wifi: Consider correct measurement channel width for solicited HE TB PPDUs

This commit is contained in:
Sébastien Deronne
2021-01-03 20:52:28 +01:00
parent af3ca8e915
commit e2e36c71bd
7 changed files with 137 additions and 104 deletions

View File

@@ -461,11 +461,11 @@ InterferenceHelper::CalculatePayloadPer (Ptr<const Event> event, uint16_t channe
}
double
InterferenceHelper::CalculateNonHtPhyHeaderPer (Ptr<const Event> event, NiChangesPerBand *nis, WifiSpectrumBand band) const
InterferenceHelper::CalculateNonHtPhyHeaderPer (Ptr<const Event> event, NiChangesPerBand *nis,
uint16_t channelWidth, WifiSpectrumBand band) const
{
NS_LOG_FUNCTION (this << band.first << band.second);
const WifiTxVector txVector = event->GetTxVector ();
uint16_t channelWidth = txVector.GetChannelWidth () >= 40 ? 20 : txVector.GetChannelWidth (); //calculate PER on the 20 MHz primary channel for L-SIG
double psr = 1.0; /* Packet Success Rate */
auto ni_it = nis->find (band)->second;
auto j = ni_it.begin ();
@@ -576,11 +576,11 @@ InterferenceHelper::CalculateNonHtPhyHeaderPer (Ptr<const Event> event, NiChange
}
double
InterferenceHelper::CalculateHtPhyHeaderPer (Ptr<const Event> event, NiChangesPerBand *nis, WifiSpectrumBand band) const
InterferenceHelper::CalculateHtPhyHeaderPer (Ptr<const Event> event, NiChangesPerBand *nis,
uint16_t channelWidth, WifiSpectrumBand band) const
{
NS_LOG_FUNCTION (this << band.first << band.second);
const WifiTxVector txVector = event->GetTxVector ();
uint16_t channelWidth = txVector.GetChannelWidth () >= 40 ? 20 : txVector.GetChannelWidth (); //calculate PER on the 20 MHz primary channel for PHY headers
double psr = 1.0; /* Packet Success Rate */
auto ni_it = nis->find (band)->second;
auto j = ni_it.begin ();
@@ -879,19 +879,10 @@ InterferenceHelper::CalculateSnr (Ptr<Event> event, uint16_t channelWidth, uint8
}
struct InterferenceHelper::SnrPer
InterferenceHelper::CalculateNonHtPhyHeaderSnrPer (Ptr<Event> event, WifiSpectrumBand band) const
InterferenceHelper::CalculateNonHtPhyHeaderSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band) const
{
NS_LOG_FUNCTION (this << band.first << band.second);
NS_LOG_FUNCTION (this << channelWidth << band.first << band.second);
NiChangesPerBand ni;
uint16_t channelWidth;
if (event->GetTxVector ().GetChannelWidth () >= 40)
{
channelWidth = 20; //calculate PER on the 20 MHz primary channel for L-SIG
}
else
{
channelWidth = event->GetTxVector ().GetChannelWidth ();
}
double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
double snr = CalculateSnr (event->GetRxPowerW (band),
noiseInterferenceW,
@@ -901,7 +892,7 @@ InterferenceHelper::CalculateNonHtPhyHeaderSnrPer (Ptr<Event> event, WifiSpectru
/* calculate the SNIR at the start of the PHY header and accumulate
* all SNIR changes in the SNIR vector.
*/
double per = CalculateNonHtPhyHeaderPer (event, &ni, band);
double per = CalculateNonHtPhyHeaderPer (event, &ni, channelWidth, band);
struct SnrPer snrPer;
snrPer.snr = snr;
@@ -910,19 +901,10 @@ InterferenceHelper::CalculateNonHtPhyHeaderSnrPer (Ptr<Event> event, WifiSpectru
}
struct InterferenceHelper::SnrPer
InterferenceHelper::CalculateHtPhyHeaderSnrPer (Ptr<Event> event, WifiSpectrumBand band) const
InterferenceHelper::CalculateHtPhyHeaderSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band) const
{
NS_LOG_FUNCTION (this << band.first << band.second);
NiChangesPerBand ni;
uint16_t channelWidth;
if (event->GetTxVector ().GetChannelWidth () >= 40)
{
channelWidth = 20; //calculate PER on the 20 MHz primary channel for PHY headers
}
else
{
channelWidth = event->GetTxVector ().GetChannelWidth ();
}
double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
double snr = CalculateSnr (event->GetRxPowerW (band),
noiseInterferenceW,
@@ -932,7 +914,7 @@ InterferenceHelper::CalculateHtPhyHeaderSnrPer (Ptr<Event> event, WifiSpectrumBa
/* calculate the SNIR at the start of the PHY header and accumulate
* all SNIR changes in the SNIR vector.
*/
double per = CalculateHtPhyHeaderPer (event, &ni, band);
double per = CalculateHtPhyHeaderPer (event, &ni, channelWidth, band);
struct SnrPer snrPer;
snrPer.snr = snr;

View File

@@ -256,21 +256,23 @@ public:
* all SNIR changes in the SNIR vector.
*
* \param event the event corresponding to the first time the corresponding PPDU arrives
* \param channelWidth the channel width (in MHz) for header measurement
* \param band identify the band used by the PSDU
*
* \return struct of SNR and PER
*/
struct InterferenceHelper::SnrPer CalculateNonHtPhyHeaderSnrPer (Ptr<Event> event, WifiSpectrumBand band) const;
struct InterferenceHelper::SnrPer CalculateNonHtPhyHeaderSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band) const;
/**
* Calculate the SNIR at the start of the HT PHY header and accumulate
* all SNIR changes in the SNIR vector.
*
* \param event the event corresponding to the first time the corresponding PPDU arrives
* \param channelWidth the channel width (in MHz) for header measurement
* \param band identify the band used by the PSDU
*
* \return struct of SNR and PER
*/
struct InterferenceHelper::SnrPer CalculateHtPhyHeaderSnrPer (Ptr<Event> event, WifiSpectrumBand band) const;
struct InterferenceHelper::SnrPer CalculateHtPhyHeaderSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band) const;
/**
* Notify that RX has started.
@@ -423,22 +425,26 @@ private:
*
* \param event the event
* \param nis the NiChanges
* \param channelWidth the channel width (in MHz) for header measurement
* \param band the band
*
* \return the error rate of the non-HT PHY header
*/
double CalculateNonHtPhyHeaderPer (Ptr<const Event> event, NiChangesPerBand *nis, WifiSpectrumBand band) const;
double CalculateNonHtPhyHeaderPer (Ptr<const Event> event, NiChangesPerBand *nis,
uint16_t channelWidth, WifiSpectrumBand band) const;
/**
* Calculate the error rate of the HT PHY header. TheHT PHY header
* can be divided into multiple chunks (e.g. due to interference from other transmissions).
*
* \param event the event
* \param nis the NiChanges
* \param channelWidth the channel width (in MHz) for header measurement
* \param band the band
*
* \return the error rate of the HT PHY header
*/
double CalculateHtPhyHeaderPer (Ptr<const Event> event, NiChangesPerBand *nis, WifiSpectrumBand band) const;
double CalculateHtPhyHeaderPer (Ptr<const Event> event, NiChangesPerBand *nis,
uint16_t channelWidth, WifiSpectrumBand band) const;
double m_noiseFigure; //!< noise figure (linear)
Ptr<ErrorRateModel> m_errorRateModel; //!< error rate model

View File

@@ -344,14 +344,14 @@ SpectrumWifiPhy::StartRx (Ptr<SpectrumSignalParameters> rxParams)
{
NS_LOG_INFO ("Received non Wi-Fi signal");
m_interference.AddForeignSignal (rxDuration, rxPowerW);
SwitchMaybeToCcaBusy ();
SwitchMaybeToCcaBusy (GetMeasurementChannelWidth (nullptr));
return;
}
if (wifiRxParams && m_disableWifiReception)
{
NS_LOG_INFO ("Received Wi-Fi signal but blocked from syncing");
m_interference.AddForeignSignal (rxDuration, rxPowerW);
SwitchMaybeToCcaBusy ();
SwitchMaybeToCcaBusy (GetMeasurementChannelWidth (nullptr));
return;
}
@@ -383,7 +383,7 @@ SpectrumWifiPhy::StartRx (Ptr<SpectrumSignalParameters> rxParams)
if (rxDuration > m_state->GetDelayUntilIdle ())
{
//that packet will be noise _after_ the completion of the OFDMA part of the HE TB PPDUs
SwitchMaybeToCcaBusy ();
SwitchMaybeToCcaBusy (GetMeasurementChannelWidth (ppdu));
}
}
}

View File

@@ -140,7 +140,18 @@ public:
* to the current channel bandwidth (which can be different from devices max
* channel width).
*/
uint16_t GetGuardBandwidth (uint16_t currentChannelWidth) const;
virtual uint16_t GetGuardBandwidth (uint16_t currentChannelWidth) const;
/**
* Get the center frequency of the non-OFDMA part of the current TxVector for the
* given STA-ID.
* Note this method is only to be used for UL MU.
*
* \param txVector the TXVECTOR that has the RU allocation
* \param staId the STA-ID of the station taking part of the UL MU
* \return the center frequency in MHz corresponding to the non-OFDMA part of the HE TB PPDU
*/
uint16_t GetCenterFrequencyForNonOfdmaPart (WifiTxVector txVector, uint16_t staId) const;
/**
* Callback invoked when the PHY model starts to process a signal
@@ -176,17 +187,6 @@ protected:
*/
WifiSpectrumBand GetBand (uint16_t bandWidth, uint8_t bandIndex = 0);
/**
* Get the center frequency of the non-OFDMA part of the current TxVector for the
* given STA-ID.
* Note this method is only to be used for UL MU.
*
* \param txVector the TXVECTOR that has the RU allocation
* \param staId the STA-ID of the station taking part of the UL MU
* \return the center frequency in MHz corresponding to the non-OFDMA part of the HE TB PPDU
*/
uint16_t GetCenterFrequencyForNonOfdmaPart (WifiTxVector txVector, uint16_t staId) const;
private:
/**

View File

@@ -513,6 +513,7 @@ WifiPhy::WifiPhy ()
m_endTxEvent (),
m_currentEvent (0),
m_previouslyRxPpduUid (UINT64_MAX),
m_previouslyTxPpduUid (UINT64_MAX),
m_currentHeTbPpduUid (UINT64_MAX),
m_standard (WIFI_PHY_STANDARD_UNSPECIFIED),
m_band (WIFI_PHY_BAND_UNSPECIFIED),
@@ -1908,8 +1909,7 @@ WifiPhy::ResumeFromSleep (void)
case WifiPhyState::SLEEP:
{
NS_LOG_DEBUG ("resuming from sleep mode");
uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth ();
Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (primaryChannelWidth));
Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (GetMeasurementChannelWidth (nullptr)));
m_state->SwitchFromSleep (delayUntilCcaEnd);
break;
}
@@ -1940,8 +1940,7 @@ WifiPhy::ResumeFromOff (void)
case WifiPhyState::OFF:
{
NS_LOG_DEBUG ("resuming from off mode");
uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth ();
Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (primaryChannelWidth));
Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (GetMeasurementChannelWidth (nullptr)));
m_state->SwitchFromOff (delayUntilCcaEnd);
break;
}
@@ -2890,7 +2889,7 @@ WifiPhy::Send (WifiConstPsduMap psdus, WifiTxVector txVector)
{
AbortCurrentReception (RECEPTION_ABORTED_BY_TX);
//that packet will be noise _after_ the transmission.
MaybeCcaBusyDuration ();
MaybeCcaBusyDuration (GetMeasurementChannelWidth (m_currentEvent != 0 ? m_currentEvent->GetPpdu () : nullptr));
}
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
@@ -2938,6 +2937,7 @@ WifiPhy::Send (WifiConstPsduMap psdus, WifiTxVector txVector)
uid = m_globalPpduUid++;
}
m_previouslyRxPpduUid = UINT64_MAX; //reset to use it only once
m_previouslyTxPpduUid = uid; //to be able to identify solicited HE TB PPDUs
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdus, txVector, txDuration, GetPhyBand (), uid);
if (m_wifiRadioEnergyModel != 0 && m_wifiRadioEnergyModel->GetMaximumTimeInState (WifiPhyState::TX) < txDuration)
@@ -2971,15 +2971,15 @@ WifiPhy::StartReceiveHeader (Ptr<Event> event)
NS_ASSERT (!IsStateRx ());
NS_ASSERT (m_endPhyRxEvent.IsExpired ());
//calculate PER on the 20 MHz primary channel for PHY headers
uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth ();
auto primaryBand = GetBand (primaryChannelWidth);
double maxRxPowerW = 0;
//calculate PER on the measurement channel for PHY headers
uint16_t measurementChannelWidth = GetMeasurementChannelWidth (event->GetPpdu ());
auto measurementBand = GetBand (measurementChannelWidth);
double maxRxPowerW = -1; //in case current event may not be sent on measurement channel (rxPowerW would be equal to 0)
Ptr<Event> maxEvent;
NS_ASSERT (!m_currentPreambleEvents.empty ());
for (auto preambleEvent : m_currentPreambleEvents)
{
double rxPowerW = preambleEvent.second->GetRxPowerW (primaryBand);
double rxPowerW = preambleEvent.second->GetRxPowerW (measurementBand);
if (rxPowerW > maxRxPowerW)
{
maxRxPowerW = rxPowerW;
@@ -3003,12 +3003,13 @@ WifiPhy::StartReceiveHeader (Ptr<Event> event)
m_currentEvent = event;
double snr = m_interference.CalculateSnr (m_currentEvent, primaryChannelWidth, 1, primaryBand);
double snr = m_interference.CalculateSnr (m_currentEvent, measurementChannelWidth, 1, measurementBand);
NS_LOG_DEBUG ("SNR(dB)=" << RatioToDb (snr) << " at start of legacy PHY header");
Time headerPayloadDuration = m_currentEvent->GetStartTime () + m_currentEvent->GetPpdu ()->GetTxDuration () - Simulator::Now ();
if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (m_currentEvent->GetRxPowerW (primaryBand), snr, primaryChannelWidth)))
if ((!m_preambleDetectionModel && maxRxPowerW > 0.0)
|| (m_preambleDetectionModel && m_preambleDetectionModel->IsPreambleDetected (m_currentEvent->GetRxPowerW (measurementBand), snr, measurementChannelWidth)))
{
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
@@ -3069,7 +3070,7 @@ WifiPhy::StartReceiveHeader (Ptr<Event> event)
NS_LOG_DEBUG ("Drop packet because PHY preamble detection failed");
// Like CCA-SD, CCA-ED is governed by the 4 us CCA window to flag CCA-BUSY
// for any received signal greater than the CCA-ED threshold.
DropPreambleEvent (m_currentEvent->GetPpdu (), PREAMBLE_DETECT_FAILURE, m_currentEvent->GetEndTime ());
DropPreambleEvent (m_currentEvent->GetPpdu (), PREAMBLE_DETECT_FAILURE, m_currentEvent->GetEndTime (), GetMeasurementChannelWidth (m_currentEvent->GetPpdu ()));
if (m_currentPreambleEvents.empty())
{
//Do not erase events if there are still pending preamble events to be processed
@@ -3085,16 +3086,8 @@ WifiPhy::ContinueReceiveHeader (Ptr<Event> event)
NS_LOG_FUNCTION (this << *event);
NS_ASSERT (m_endPhyRxEvent.IsExpired ());
uint16_t channelWidth;
if (event->GetTxVector ().GetChannelWidth () >= 40)
{
channelWidth = 20; //calculate PER on the 20 MHz primary channel for PHY headers
}
else
{
channelWidth = event->GetTxVector ().GetChannelWidth ();
}
InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (event, GetBand (channelWidth));
uint16_t measurementChannelWidth = GetMeasurementChannelWidth (event->GetPpdu ());
InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (event, measurementChannelWidth, GetBand (measurementChannelWidth));
NS_LOG_DEBUG ("SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per);
if (m_random->GetValue () > snrPer.per) //non-HT PHY header reception succeeded
@@ -3112,7 +3105,7 @@ WifiPhy::ContinueReceiveHeader (Ptr<Event> event)
AbortCurrentReception (L_SIG_FAILURE);
if (event->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
{
MaybeCcaBusyDuration ();
MaybeCcaBusyDuration (GetMeasurementChannelWidth (event->GetPpdu ()));
}
}
}
@@ -3185,7 +3178,7 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
NS_LOG_DEBUG ("Cannot start RX because device is OFF");
if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
{
MaybeCcaBusyDuration ();
MaybeCcaBusyDuration (GetMeasurementChannelWidth (nullptr));
}
return;
}
@@ -3195,7 +3188,7 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
NS_LOG_DEBUG ("Packet reception stopped because transmitter has been switched off");
if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
{
MaybeCcaBusyDuration ();
MaybeCcaBusyDuration (GetMeasurementChannelWidth (ppdu));
}
return;
}
@@ -3212,7 +3205,7 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
* busy due to other devices' transmissions started before the end of
* the switching.
*/
DropPreambleEvent (ppdu, CHANNEL_SWITCHING, endRx);
DropPreambleEvent (ppdu, CHANNEL_SWITCHING, endRx, GetMeasurementChannelWidth (ppdu));
break;
case WifiPhyState::RX:
if (m_frameCaptureModel != 0
@@ -3226,7 +3219,7 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
else
{
NS_LOG_DEBUG ("Drop packet because already in Rx");
DropPreambleEvent (ppdu, RXING, endRx);
DropPreambleEvent (ppdu, RXING, endRx, GetMeasurementChannelWidth (ppdu));
if (m_currentEvent == 0)
{
/*
@@ -3241,7 +3234,7 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
break;
case WifiPhyState::TX:
NS_LOG_DEBUG ("Drop packet because already in Tx");
DropPreambleEvent (ppdu, TXING, endRx);
DropPreambleEvent (ppdu, TXING, endRx, GetMeasurementChannelWidth (ppdu));
break;
case WifiPhyState::CCA_BUSY:
if (m_currentEvent != 0)
@@ -3257,7 +3250,7 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
else
{
NS_LOG_DEBUG ("Drop packet because already decoding preamble");
DropPreambleEvent (ppdu, BUSY_DECODING_PREAMBLE, endRx);
DropPreambleEvent (ppdu, BUSY_DECODING_PREAMBLE, endRx, GetMeasurementChannelWidth (ppdu));
}
}
else
@@ -3271,7 +3264,7 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
break;
case WifiPhyState::SLEEP:
NS_LOG_DEBUG ("Drop packet because in sleep mode");
DropPreambleEvent (ppdu, SLEEPING, endRx);
DropPreambleEvent (ppdu, SLEEPING, endRx, GetMeasurementChannelWidth (nullptr));
break;
default:
NS_FATAL_ERROR ("Invalid WifiPhy state.");
@@ -3280,9 +3273,9 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
}
void
WifiPhy::DropPreambleEvent (Ptr<const WifiPpdu> ppdu, WifiPhyRxfailureReason reason, Time endRx)
WifiPhy::DropPreambleEvent (Ptr<const WifiPpdu> ppdu, WifiPhyRxfailureReason reason, Time endRx, uint16_t measurementChannelWidth)
{
NS_LOG_FUNCTION (this << *ppdu << reason << endRx);
NS_LOG_FUNCTION (this << *ppdu << reason << endRx << measurementChannelWidth);
NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), reason);
auto it = m_currentPreambleEvents.find (std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()));
if (it != m_currentPreambleEvents.end ())
@@ -3292,19 +3285,18 @@ WifiPhy::DropPreambleEvent (Ptr<const WifiPpdu> ppdu, WifiPhyRxfailureReason rea
if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
{
//that PPDU will be noise _after_ the end of the current event.
MaybeCcaBusyDuration ();
MaybeCcaBusyDuration (measurementChannelWidth);
}
}
void
WifiPhy::MaybeCcaBusyDuration ()
WifiPhy::MaybeCcaBusyDuration (uint16_t channelWidth)
{
//We are here because we have received the first bit of a packet and we are
//not going to be able to synchronize on it
//In this model, CCA becomes busy when the aggregation of all signals as
//tracked by the InterferenceHelper class is higher than the CcaBusyThreshold
uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth ();
Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (primaryChannelWidth));
Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (channelWidth));
if (!delayUntilCcaEnd.IsZero ())
{
m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd);
@@ -3352,13 +3344,13 @@ WifiPhy::StartReceivePayload (Ptr<Event> event)
bool canReceivePayload = false;
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
WifiModulationClass modulation = ppdu->GetModulation ();
//calculate PER on the primary 20 MHz channel for PHY headers
uint16_t primaryChannelWidth = std::min (event->GetTxVector ().GetChannelWidth (), static_cast<uint16_t> (20));
auto primaryBand = GetBand (primaryChannelWidth);
//calculate PER on the measurement channel for PHY headers
uint16_t measurementChannelWidth = GetMeasurementChannelWidth (ppdu);
auto measurementBand = GetBand (measurementChannelWidth);
if (modulation >= WIFI_MOD_CLASS_HT)
{
InterferenceHelper::SnrPer snrPer = m_interference.CalculateHtPhyHeaderSnrPer (event, primaryBand);
InterferenceHelper::SnrPer snrPer = m_interference.CalculateHtPhyHeaderSnrPer (event, measurementChannelWidth, measurementBand);
NS_LOG_DEBUG ("SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per);
canReceivePayload = (m_random->GetValue () > snrPer.per);
}
@@ -3451,7 +3443,7 @@ WifiPhy::StartReceivePayload (Ptr<Event> event)
if (modulation == WIFI_MOD_CLASS_HE)
{
HePreambleParameters params;
params.rssiW = event->GetRxPowerW (primaryBand);
params.rssiW = event->GetRxPowerW (measurementBand);
params.bssColor = event->GetTxVector ().GetBssColor ();
NotifyEndOfHePreamble (params);
}
@@ -3472,7 +3464,7 @@ WifiPhy::StartReceivePayload (Ptr<Event> event)
AbortCurrentReception (FILTERED); //immediately followed by PHY-RXEND (Filtered)
if (event->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
{
MaybeCcaBusyDuration ();
MaybeCcaBusyDuration (GetMeasurementChannelWidth (ppdu));
}
}
}
@@ -3641,7 +3633,7 @@ WifiPhy::EndReceive (Ptr<Event> event)
else
{
m_interference.NotifyRxEnd (Simulator::Now ());
MaybeCcaBusyDuration ();
MaybeCcaBusyDuration (GetMeasurementChannelWidth (ppdu));
m_currentEvent = 0;
m_currentPreambleEvents.clear ();
m_endRxEvents.clear ();
@@ -3653,7 +3645,7 @@ WifiPhy::EndReceive (Ptr<Event> event)
}
m_endOfMpduEvents.clear ();
}
MaybeCcaBusyDuration ();
MaybeCcaBusyDuration (GetMeasurementChannelWidth (ppdu));
}
std::pair<bool, SignalNoiseDbm>
@@ -3766,7 +3758,7 @@ WifiPhy::ResetReceive (Ptr<Event> event)
m_interference.NotifyRxEnd (Simulator::Now ());
m_currentEvent = 0;
m_currentPreambleEvents.clear ();
MaybeCcaBusyDuration ();
MaybeCcaBusyDuration (GetMeasurementChannelWidth (ppdu));
}
void
@@ -5002,16 +4994,14 @@ WifiPhy::GetLastRxEndTime (void) const
}
void
WifiPhy::SwitchMaybeToCcaBusy (void)
WifiPhy::SwitchMaybeToCcaBusy (uint16_t channelWidth)
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION (this << channelWidth);
//We are here because we have received the first bit of a packet and we are
//not going to be able to synchronize on it
//In this model, CCA becomes busy when the aggregation of all signals as
//tracked by the InterferenceHelper class is higher than the CcaBusyThreshold
uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth ();
Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (primaryChannelWidth));
Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (channelWidth));
if (!delayUntilCcaEnd.IsZero ())
{
NS_LOG_DEBUG ("Calling SwitchMaybeToCcaBusy for " << delayUntilCcaEnd.As (Time::S));
@@ -5098,8 +5088,7 @@ void
WifiPhy::StartRx (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth ();
NS_LOG_DEBUG ("sync to signal (power=" << event->GetRxPowerW (GetBand (primaryChannelWidth)) << "W)");
NS_LOG_DEBUG ("sync to signal (power=" << event->GetRxPowerW (GetBand (GetMeasurementChannelWidth (event->GetPpdu ()))) << "W)");
m_interference.NotifyRxStart (); //We need to notify it now so that it starts recording events
m_endPreambleDetectionEvents.push_back (Simulator::Schedule (GetPreambleDetectionDuration (), &WifiPhy::StartReceiveHeader, this, event));
}
@@ -5170,6 +5159,32 @@ WifiPhy::GetStaId (const Ptr<const WifiPpdu> ppdu) const
return staId;
}
uint16_t
WifiPhy::GetMeasurementChannelWidth (const Ptr<const WifiPpdu> ppdu) const
{
uint16_t channelWidth = GetChannelWidth ();
if (ppdu == nullptr)
{
// Here because PHY was not receiving anything (e.g. resuming from OFF) nor expecting anything (e.g. sleep)
// nor processing a Wi-Fi signal.
return channelWidth >= 40 ? 20 : channelWidth;
}
channelWidth = std::min (channelWidth, ppdu->GetTxVector ().GetChannelWidth ());
/**
* The PHY shall not issue a PHY-RXSTART.indication primitive in response to a PPDU that does not overlap
* the primary channel unless the PHY at an AP receives the HE TB PPDU solicited by the AP. For the HE
* TB PPDU solicited by the AP, the PHY shall issue a PHY-RXSTART.indication primitive for a PPDU
* received in the primary or at the secondary 20 MHz channel, the secondary 40 MHz channel, or the secondary
* 80 MHz channel.
*/
if (channelWidth >= 40 && ppdu->GetUid () != m_previouslyTxPpduUid)
{
channelWidth = 20;
}
return channelWidth;
}
WifiSpectrumBand
WifiPhy::GetBand (uint16_t /*bandWidth*/, uint8_t /*bandIndex*/)
{

View File

@@ -1816,8 +1816,10 @@ protected:
* state of interference tracker. In this model, CCA becomes busy when
* the aggregation of all signals as tracked by the InterferenceHelper
* class is higher than the CcaEdThreshold
*
* \param channelWidth the channel width in MHz used for RSSI measurement
*/
void SwitchMaybeToCcaBusy (void);
void SwitchMaybeToCcaBusy (uint16_t channelWidth);
/**
* Return the STA ID that has been assigned to the station this PHY belongs to.
@@ -1828,6 +1830,16 @@ protected:
*/
virtual uint16_t GetStaId (const Ptr<const WifiPpdu> ppdu) const;
/**
* Return the channel width used to measure the RSSI.
* This corresponds to the primary channel unless it corresponds to the
* HE TB PPDU solicited by the AP.
*
* \param ppdu the PPDU that is being received
* \param the channel width (in MHz) used for RSSI measurement
*/
uint16_t GetMeasurementChannelWidth (const Ptr<const WifiPpdu> ppdu) const;
/**
* Get the start band index and the stop band index for a given band
*
@@ -1883,6 +1895,7 @@ protected:
std::map <std::pair<uint64_t /* UID*/, WifiPreamble>, Ptr<Event> > m_currentPreambleEvents; //!< store event associated to a PPDU (that has a unique ID and preamble combination) whose preamble is being received
uint64_t m_previouslyRxPpduUid; //!< UID of the previously received PPDU (reused by HE TB PPDUs), reset to UINT64_MAX upon transmission
uint64_t m_previouslyTxPpduUid; //!< UID of the previously sent PPDU, used by AP to recognize response HE TB PPDUs
uint64_t m_currentHeTbPpduUid; //!< UID of the HE TB PPDU being received
@@ -1995,8 +2008,9 @@ private:
/**
* Eventually switch to CCA busy
* \param channelWidth the channel width in MHz used for RSSI measurement
*/
void MaybeCcaBusyDuration (void);
void MaybeCcaBusyDuration (uint16_t channelWidth);
/**
* Starting receiving the PPDU after having detected the medium is idle or after a reception switch.
@@ -2052,8 +2066,9 @@ private:
* \param ppdu the incoming PPDU
* \param reason the reason the PPDU is dropped
* \param endRx the end of the incoming PPDU's reception
* \param measurementChannelWidth the measurement width (in MHz) to consider for the PPDU
*/
void DropPreambleEvent (Ptr<const WifiPpdu> ppdu, WifiPhyRxfailureReason reason, Time endRx);
void DropPreambleEvent (Ptr<const WifiPpdu> ppdu, WifiPhyRxfailureReason reason, Time endRx, uint16_t measurementChannelWidth);
/**
* The trace source fired when a packet begins the transmission process on

View File

@@ -46,7 +46,6 @@ NS_LOG_COMPONENT_DEFINE ("WifiPhyOfdmaTest");
static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
static const uint32_t DEFAULT_FREQUENCY = 5180; // MHz
static const uint16_t DEFAULT_CHANNEL_WIDTH = 20; // MHz
static const uint16_t DEFAULT_GUARD_WIDTH = DEFAULT_CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
class OfdmaSpectrumWifiPhy : public SpectrumWifiPhy
{
@@ -77,6 +76,11 @@ public:
* \param ppdu the PPDU to send
*/
void StartTx (Ptr<WifiPpdu> ppdu) override;
/**
* \param currentChannelWidth channel width of the current transmission (MHz)
* \return the width of the guard band (MHz) set to 2
*/
uint16_t GetGuardBandwidth (uint16_t currentChannelWidth) const override;
/**
* Set the global PPDU UID counter.
@@ -153,6 +157,14 @@ OfdmaSpectrumWifiPhy::GetCurrentPreambleEvents (void)
return m_currentPreambleEvents;
}
uint16_t
OfdmaSpectrumWifiPhy::GetGuardBandwidth (uint16_t currentChannelWidth) const
{
// return a small enough value to avoid having too much out of band transmission
// knowing that slopes are not configurable yet.
return 1;
}
/**
* \ingroup wifi-test
* \ingroup tests
@@ -1293,7 +1305,10 @@ TestMultipleHeTbPreambles::RxHeTbPpdu (uint64_t uid, uint16_t staId, double txPo
Time ppduDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand (), staId);
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdus, txVector, ppduDuration, WIFI_PHY_BAND_5GHZ, uid);
Ptr<SpectrumValue> rxPsd = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (DEFAULT_FREQUENCY, DEFAULT_CHANNEL_WIDTH, txPowerWatts, DEFAULT_GUARD_WIDTH);
uint32_t centerFrequency = m_phy->GetCenterFrequencyForNonOfdmaPart (txVector, staId);
uint16_t ruWidth = HeRu::GetBandwidth (txVector.GetRu (staId).ruType);
uint16_t channelWidth = ruWidth < 20 ? 20 : ruWidth;
Ptr<SpectrumValue> rxPsd = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (centerFrequency, channelWidth, txPowerWatts, m_phy->GetGuardBandwidth (channelWidth));
Ptr<WifiSpectrumSignalParameters> rxParams = Create<WifiSpectrumSignalParameters> ();
rxParams->psd = rxPsd;
rxParams->txPhy = 0;