wifi: (merges !642) Extend ErrorRateModel API for link-to-system models

Incorporates improvements from Rediet's code review.
This commit is contained in:
Sébastien Deronne
2021-06-04 10:42:01 -07:00
committed by Tom Henderson
parent f0b7deab3d
commit 4d7983d4e0
12 changed files with 110 additions and 58 deletions

View File

@@ -19,7 +19,7 @@
*/
#include "error-rate-model.h"
#include "non-ht/dsss-error-rate-model.h"
#include "ns3/dsss-error-rate-model.h"
#include "wifi-tx-vector.h"
namespace ns3 {
@@ -60,7 +60,7 @@ ErrorRateModel::CalculateSnr (const WifiTxVector& txVector, double ber) const
}
double
ErrorRateModel::GetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint16_t staId) const
ErrorRateModel::GetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint8_t numRxAntennas, WifiPpduField field, uint16_t staId) const
{
if (mode.GetModulationClass () == WIFI_MOD_CLASS_DSSS || mode.GetModulationClass () == WIFI_MOD_CLASS_HR_DSSS)
{
@@ -80,9 +80,22 @@ ErrorRateModel::GetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector
}
else
{
return DoGetChunkSuccessRate (mode, txVector, snr, nbits, staId);
return DoGetChunkSuccessRate (mode, txVector, snr, nbits, numRxAntennas, field, staId);
}
return 0;
}
bool
ErrorRateModel::IsAwgn (void) const
{
return true;
}
int64_t
ErrorRateModel::AssignStreams (int64_t stream)
{
// Override this method if the error model uses random variables
return 0;
}
} //namespace ns3

View File

@@ -48,6 +48,12 @@ public:
*/
double CalculateSnr (const WifiTxVector& txVector, double ber) const;
/**
* \return true if the model is for AWGN channels,
* false otherwise
*/
virtual bool IsAwgn (void) const;
/**
* This method returns the probability that the given 'chunk' of the
* packet will be successfully received by the PHY.
@@ -70,11 +76,25 @@ public:
* \param txVector TXVECTOR of the overall transmission
* \param snr the SNR of the chunk
* \param nbits the number of bits in this chunk
* \param numRxAntennas the number of active RX antennas (1 if not provided)
* \param field the PPDU field to which the chunk belongs to (assumes this is for the payload part if not provided)
* \param staId the station ID for MU
*
* \return probability of successfully receiving the chunk
*/
double GetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint16_t staId = SU_STA_ID) const;
double GetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits,
uint8_t numRxAntennas = 1, WifiPpduField field = WIFI_PPDU_FIELD_DATA,
uint16_t staId = SU_STA_ID) const;
/**
* Assign a fixed random variable stream number to the random variables
* used by this model. Return the number of streams (possibly zero) that
* have been assigned.
*
* \param stream first stream index to use
* \return the number of stream indices assigned by this model
*/
virtual int64_t AssignStreams (int64_t stream);
private:
@@ -85,11 +105,14 @@ private:
* \param txVector TXVECTOR of the overall transmission
* \param snr the SNR of the chunk
* \param nbits the number of bits in this chunk
* \param numRxAntennas the number of active RX antennas
* \param field the PPDU field to which the chunk belongs to
* \param staId the station ID for MU
*
* \return probability of successfully receiving the chunk
*/
virtual double DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint16_t staId) const = 0;
virtual double DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits,
uint8_t numRxAntennas, WifiPpduField field, uint16_t staId) const = 0;
};
} //namespace ns3

View File

@@ -344,13 +344,16 @@ InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint1
double noise = noiseFloor + noiseInterference;
double snr = signal / noise; //linear scale
NS_LOG_DEBUG ("bandwidth(MHz)=" << channelWidth << ", signal(W)= " << signal << ", noise(W)=" << noiseFloor << ", interference(W)=" << noiseInterference << ", snr=" << RatioToDb(snr) << "dB");
double gain = 1;
if (m_numRxAntennas > nss)
if (m_errorRateModel->IsAwgn ())
{
gain = static_cast<double>(m_numRxAntennas) / nss; //compute gain offered by diversity for AWGN
double gain = 1;
if (m_numRxAntennas > nss)
{
gain = static_cast<double> (m_numRxAntennas) / nss; //compute gain offered by diversity for AWGN
}
NS_LOG_DEBUG ("SNR improvement thanks to diversity: " << 10 * std::log10 (gain) << "dB");
snr *= gain;
}
NS_LOG_DEBUG ("SNR improvement thanks to diversity: " << 10 * std::log10 (gain) << "dB");
snr *= gain;
return snr;
}
@@ -384,7 +387,7 @@ InterferenceHelper::CalculateNoiseInterferenceW (Ptr<Event> event, NiChangesPerB
}
double
InterferenceHelper::CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode, const WifiTxVector& txVector) const
InterferenceHelper::CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode, const WifiTxVector& txVector, WifiPpduField field) const
{
if (duration.IsZero ())
{
@@ -392,7 +395,7 @@ InterferenceHelper::CalculateChunkSuccessRate (double snir, Time duration, WifiM
}
uint64_t rate = mode.GetDataRate (txVector.GetChannelWidth ());
uint64_t nbits = static_cast<uint64_t> (rate * duration.GetSeconds ());
double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits);
double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits, m_numRxAntennas, field);
return csr;
}
@@ -407,7 +410,7 @@ InterferenceHelper::CalculatePayloadChunkSuccessRate (double snir, Time duration
uint64_t rate = mode.GetDataRate (txVector, staId);
uint64_t nbits = static_cast<uint64_t> (rate * duration.GetSeconds ());
nbits /= txVector.GetNss (staId); //divide effective number of bits by NSS to achieve same chunk error rate as SISO for AWGN
double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits, staId);
double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits, m_numRxAntennas, WIFI_PPDU_FIELD_DATA, staId);
return csr;
}
@@ -417,7 +420,7 @@ InterferenceHelper::CalculatePayloadPer (Ptr<const Event> event, uint16_t channe
uint16_t staId, std::pair<Time, Time> window) const
{
NS_LOG_FUNCTION (this << channelWidth << band.first << band.second << staId << window.first << window.second);
const WifiTxVector& txVector = event->GetTxVector ();
const WifiTxVector txVector = event->GetTxVector ();
double psr = 1.0; /* Packet Success Rate */
auto ni_it = nis->find (band)->second;
auto j = ni_it.begin ();
@@ -468,7 +471,7 @@ InterferenceHelper::CalculatePhyHeaderSectionPsr (Ptr<const Event> event, NiChan
PhyEntity::PhyHeaderSections phyHeaderSections) const
{
NS_LOG_FUNCTION (this << band.first << band.second);
const WifiTxVector& txVector = event->GetTxVector ();
const WifiTxVector txVector = event->GetTxVector ();
double psr = 1.0; /* Packet Success Rate */
auto ni_it = nis->find (band)->second;
auto j = ni_it.begin ();
@@ -500,7 +503,15 @@ InterferenceHelper::CalculatePhyHeaderSectionPsr (Ptr<const Event> event, NiChan
if (duration.IsStrictlyPositive ())
{
WifiMode mode = section.second.second;
psr *= CalculateChunkSuccessRate (snr, duration, mode, txVector);
if (mode.GetModulationClass () < WIFI_MOD_CLASS_OFDM)
{
psr *= CalculateChunkSuccessRate (snr, duration, mode, txVector, WIFI_PPDU_FIELD_NON_HT_HEADER);
}
else
{
//FIXME: this will be directly available with PHY refactoring, hence assume HT-SIG for now since error rate model do not differentiate these non-HT PHY headers yet
psr *= CalculateChunkSuccessRate (snr, duration, mode, txVector, WIFI_PPDU_FIELD_HT_SIG);
}
NS_LOG_DEBUG ("Current NI change in " << section.first << " [" << start << ", " << stop << "] for "
<< duration.As (Time::NS) << ": mode=" << mode << ", psr=" << psr);
}
@@ -523,7 +534,7 @@ InterferenceHelper::CalculatePhyHeaderPer (Ptr<const Event> event, NiChangesPerB
WifiPpduField header) const
{
NS_LOG_FUNCTION (this << band.first << band.second << header);
const WifiTxVector& txVector = event->GetTxVector ();
const WifiTxVector txVector = event->GetTxVector ();
auto ni_it = nis->find (band)->second;
auto phyEntity = WifiPhy::GetStaticPhyEntity (txVector.GetModulationClass ());

View File

@@ -281,18 +281,30 @@ protected:
*/
double CalculateSnr (double signal, double noiseInterference, uint16_t channelWidth, uint8_t nss) const;
/**
* Calculate the success rate of the chunk given the SINR, duration, and Wi-Fi mode.
* The duration and mode are used to calculate how many bits are present in the chunk.
* Calculate the success rate of the chunk given the SINR, duration, and TXVECTOR.
* The duration and TXVECTOR are used to calculate how many bits are present in the chunk.
*
* \param snir the SINR
* \param duration the duration of the chunk
* \param mode the WifiMode
* \param txVector the TXVECTOR
* \param field the PPDU field to which the chunk belongs to
*
* \return the success rate
*/
double CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode, const WifiTxVector& txVector) const;
double CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode, const WifiTxVector& txVector, WifiPpduField field) const;
/**
* Calculate the success rate of the payload chunk given the SINR, duration, and TXVECTOR.
* The duration and TXVECTOR are used to calculate how many bits are present in the payload chunk.
*
* \param snir the SINR
* \param duration the duration of the chunk
* \param txVector the TXVECTOR
* \param staId the station ID of the PSDU (only used for MU)
*
* \return the success rate
*/
double CalculatePayloadChunkSuccessRate (double snir, Time duration, const WifiTxVector& txVector, uint16_t staId = SU_STA_ID) const;
private:
/**
@@ -362,18 +374,6 @@ private:
* \return noise and interference power
*/
double CalculateNoiseInterferenceW (Ptr<Event> event, NiChangesPerBand *nis, WifiSpectrumBand band) const;
/**
* Calculate the success rate of the payload chunk given the SINR, duration, and Wi-Fi mode.
* The duration and mode are used to calculate how many bits are present in the chunk.
*
* \param snir the SINR
* \param duration the duration of the chunk
* \param txVector the TXVECTOR
* \param staId the station ID of the PSDU (only used for MU)
*
* \return the success rate
*/
double CalculatePayloadChunkSuccessRate (double snir, Time duration, const WifiTxVector& txVector, uint16_t staId) const;
/**
* Calculate the error rate of the given PHY payload only in the provided time
* window (thus enabling per MPDU PER information). The PHY payload can be divided into

View File

@@ -217,9 +217,9 @@ NistErrorRateModel::GetBValue (WifiCodeRate codeRate) const
}
double
NistErrorRateModel::DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint16_t staId) const
NistErrorRateModel::DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint8_t numRxAntennas, WifiPpduField field, uint16_t staId) const
{
NS_LOG_FUNCTION (this << mode << snr << nbits << staId);
NS_LOG_FUNCTION (this << mode << snr << nbits << +numRxAntennas << field << staId);
if (mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM
|| mode.GetModulationClass () == WIFI_MOD_CLASS_OFDM
|| mode.GetModulationClass () == WIFI_MOD_CLASS_HT

View File

@@ -47,7 +47,8 @@ public:
private:
double DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint16_t staId) const override;
double DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits,
uint8_t numRxAntennas, WifiPpduField field, uint16_t staId) const override;
/**
* Return the bValue such that coding rate = bValue / (bValue + 1).
*

View File

@@ -141,9 +141,9 @@ TableBasedErrorRateModel::GetMcsForMode (WifiMode mode)
}
double
TableBasedErrorRateModel::DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint16_t staId) const
TableBasedErrorRateModel::DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint8_t numRxAntennas, WifiPpduField field, uint16_t staId) const
{
NS_LOG_FUNCTION (this << mode << txVector << snr << nbits << staId);
NS_LOG_FUNCTION (this << mode << txVector << snr << nbits << +numRxAntennas << field << staId);
uint64_t size = std::max<uint64_t> (1, (nbits / 8));
double roundedSnr = RoundSnr (RatioToDb (snr), SNR_PRECISION);
uint8_t mcs = GetMcsForMode (mode);

View File

@@ -47,8 +47,6 @@ public:
TableBasedErrorRateModel ();
~TableBasedErrorRateModel ();
double DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint16_t staId) const override;
/**
* \brief Utility function to convert WifiMode to an MCS value
* \param mode the WifiMode
@@ -58,6 +56,9 @@ public:
private:
double DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits,
uint8_t numRxAntennas, WifiPpduField field, uint16_t staId) const override;
/**
* Round SNR (in dB) to the specified precision
*

View File

@@ -2294,8 +2294,10 @@ int64_t
WifiPhy::AssignStreams (int64_t stream)
{
NS_LOG_FUNCTION (this << stream);
m_random->SetStream (stream);
return 1;
int64_t currentStream = stream;
m_random->SetStream (currentStream++);
currentStream += m_interference.GetErrorRateModel ()->AssignStreams (currentStream);
return (currentStream - stream);
}
std::ostream& operator<< (std::ostream& os, RxSignalInfo rxSignalInfo)

View File

@@ -179,9 +179,9 @@ YansErrorRateModel::GetFecQamBer (double snr, uint64_t nbits,
}
double
YansErrorRateModel::DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint16_t staId) const
YansErrorRateModel::DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint8_t numRxAntennas, WifiPpduField field, uint16_t staId) const
{
NS_LOG_FUNCTION (this << mode << txVector.GetMode () << snr << nbits << staId);
NS_LOG_FUNCTION (this << mode << txVector << snr << nbits << +numRxAntennas << field << staId);
if (mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM
|| mode.GetModulationClass () == WIFI_MOD_CLASS_OFDM
|| mode.GetModulationClass () == WIFI_MOD_CLASS_HT

View File

@@ -63,7 +63,8 @@ public:
private:
double DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits, uint16_t staId) const override;
double DoGetChunkSuccessRate (WifiMode mode, const WifiTxVector& txVector, double snr, uint64_t nbits,
uint8_t numRxAntennas, WifiPpduField field, uint16_t staId) const override;
/**
* Return BER of BPSK with the given parameters.
*

View File

@@ -300,7 +300,7 @@ class TestInterferenceHelper : public InterferenceHelper
{
public:
using InterferenceHelper::InterferenceHelper;
using InterferenceHelper::CalculateChunkSuccessRate;
using InterferenceHelper::CalculatePayloadChunkSuccessRate;
using InterferenceHelper::CalculateSnr;
};
@@ -352,7 +352,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
double snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr, 0.1, "Attempt to set initial SNR to known value failed");
Time duration = MilliSeconds (2);
double chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
double chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_EQ_TOL (chunkSuccess, 0.905685, 0.000001, "CSR not within tolerance for SISO");
double sisoChunkSuccess = chunkSuccess;
@@ -361,7 +361,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
txVector.SetNTx (2);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr, 0.1, "SNR not within tolerance for 2x1:2 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_EQ_TOL (chunkSuccess, 0.905685, 0.000001, "CSR not within tolerance for SISO");
// MIMO 1x2:1: expect that SNR is increased by a factor of 3 dB (10 log 2/1) compared to SISO thanks to RX diversity
@@ -370,7 +370,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
interference.SetNumberOfReceiveAntennas (2);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr + 3, 0.1, "SNR not within tolerance for 1x2:1 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_GT (chunkSuccess, sisoChunkSuccess, "CSR not within tolerance for 1x2:1 MIMO");
// MIMO 2x2:1: expect that SNR is increased by a factor of 3 dB (10 log 2/1) compared to SISO thanks to RX diversity
@@ -379,7 +379,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
interference.SetNumberOfReceiveAntennas (2);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr + 3, 0.1, "SNR not equal within tolerance for 2x2:1 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_GT (chunkSuccess, sisoChunkSuccess, "CSR not within tolerance for 2x2:1 MIMO");
// MIMO 2x2:2: expect no SNR gain in AWGN channel
@@ -388,7 +388,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
interference.SetNumberOfReceiveAntennas (2);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr, 0.1, "SNR not equal within tolerance for 2x2:2 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_EQ_TOL (chunkSuccess, sisoChunkSuccess, 0.000001, "CSR not within tolerance for 2x2:2 MIMO");
// MIMO 3x3:1: expect that SNR is increased by a factor of 4.8 dB (10 log 3/1) compared to SISO thanks to RX diversity
@@ -397,7 +397,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
interference.SetNumberOfReceiveAntennas (3);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr + 4.8, 0.1, "SNR not within tolerance for 3x3:1 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_GT (chunkSuccess, sisoChunkSuccess, "CSR not within tolerance for 3x3:1 MIMO");
// MIMO 3x3:2: expect that SNR is increased by a factor of 1.8 dB (10 log 3/2) compared to SISO thanks to RX diversity
@@ -406,7 +406,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
interference.SetNumberOfReceiveAntennas (3);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr + 1.8, 0.1, "SNR not within tolerance for 3x3:2 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_GT (chunkSuccess, sisoChunkSuccess, "CSR not within tolerance for 3x3:2 MIMO");
// MIMO 3x3:3: expect no SNR gain in AWGN channel
@@ -415,7 +415,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
interference.SetNumberOfReceiveAntennas (3);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr, 0.1, "SNR not within tolerance for 3x3:3 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_EQ_TOL (chunkSuccess, sisoChunkSuccess, 0.000001, "CSR not equal within tolerance for 3x3:3 MIMO");
// MIMO 4x4:1: expect that SNR is increased by a factor of 6 dB (10 log 4/1) compared to SISO thanks to RX diversity
@@ -424,7 +424,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
interference.SetNumberOfReceiveAntennas (4);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr + 6, 0.1, "SNR not within tolerance for 4x4:1 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_GT (chunkSuccess, sisoChunkSuccess, "CSR not within tolerance for 4x4:1 MIMO");
// MIMO 4x4:2: expect that SNR is increased by a factor of 3 dB (10 log 4/2) compared to SISO thanks to RX diversity
@@ -433,7 +433,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
interference.SetNumberOfReceiveAntennas (4);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr + 3, 0.1, "SNR not within tolerance for 4x4:2 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_GT (chunkSuccess, sisoChunkSuccess, "CSR not within tolerance for 4x4:2 MIMO");
// MIMO 4x4:3: expect that SNR is increased by a factor of 1.2 dB (10 log 4/3) compared to SISO thanks to RX diversity
@@ -442,7 +442,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
interference.SetNumberOfReceiveAntennas (4);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr + 1.2, 0.1, "SNR not within tolerance for 4x4:3 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_GT (chunkSuccess, sisoChunkSuccess, "CSR not within tolerance for 4x4:1 MIMO");
// MIMO 4x4:4: expect no SNR gain in AWGN channel
@@ -451,7 +451,7 @@ WifiErrorRateModelsTestCaseMimo::DoRun (void)
interference.SetNumberOfReceiveAntennas (4);
snr = interference.CalculateSnr (0.001, 0.001 / DbToRatio (initialSnr), txVector.GetChannelWidth (), txVector.GetNss ());
NS_TEST_ASSERT_MSG_EQ_TOL (RatioToDb (snr), initialSnr, 0.1, "SNR not within tolerance for 4x4:4 MIMO");
chunkSuccess = interference.CalculateChunkSuccessRate (snr, duration, mode, txVector);
chunkSuccess = interference.CalculatePayloadChunkSuccessRate (snr, duration, txVector);
NS_TEST_ASSERT_MSG_EQ_TOL (chunkSuccess, sisoChunkSuccess, 0.000001, "CSR not within tolerance for 4x4:4 MIMO");
}