diff --git a/src/wifi/model/interference-helper.cc b/src/wifi/model/interference-helper.cc index 0781e287c..ce46f5bc0 100644 --- a/src/wifi/model/interference-helper.cc +++ b/src/wifi/model/interference-helper.cc @@ -461,11 +461,11 @@ InterferenceHelper::CalculatePayloadPer (Ptr event, uint16_t channe } double -InterferenceHelper::CalculateNonHtPhyHeaderPer (Ptr event, NiChangesPerBand *nis, WifiSpectrumBand band) const +InterferenceHelper::CalculateNonHtPhyHeaderPer (Ptr 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 event, NiChange } double -InterferenceHelper::CalculateHtPhyHeaderPer (Ptr event, NiChangesPerBand *nis, WifiSpectrumBand band) const +InterferenceHelper::CalculateHtPhyHeaderPer (Ptr 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, uint16_t channelWidth, uint8 } struct InterferenceHelper::SnrPer -InterferenceHelper::CalculateNonHtPhyHeaderSnrPer (Ptr event, WifiSpectrumBand band) const +InterferenceHelper::CalculateNonHtPhyHeaderSnrPer (Ptr 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, 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, WifiSpectru } struct InterferenceHelper::SnrPer -InterferenceHelper::CalculateHtPhyHeaderSnrPer (Ptr event, WifiSpectrumBand band) const +InterferenceHelper::CalculateHtPhyHeaderSnrPer (Ptr 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, 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; diff --git a/src/wifi/model/interference-helper.h b/src/wifi/model/interference-helper.h index d17e98efd..9fc24977d 100644 --- a/src/wifi/model/interference-helper.h +++ b/src/wifi/model/interference-helper.h @@ -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, WifiSpectrumBand band) const; + struct InterferenceHelper::SnrPer CalculateNonHtPhyHeaderSnrPer (Ptr 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, WifiSpectrumBand band) const; + struct InterferenceHelper::SnrPer CalculateHtPhyHeaderSnrPer (Ptr 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 event, NiChangesPerBand *nis, WifiSpectrumBand band) const; + double CalculateNonHtPhyHeaderPer (Ptr 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 event, NiChangesPerBand *nis, WifiSpectrumBand band) const; + double CalculateHtPhyHeaderPer (Ptr event, NiChangesPerBand *nis, + uint16_t channelWidth, WifiSpectrumBand band) const; double m_noiseFigure; //!< noise figure (linear) Ptr m_errorRateModel; //!< error rate model diff --git a/src/wifi/model/spectrum-wifi-phy.cc b/src/wifi/model/spectrum-wifi-phy.cc index 251ba988c..2b65cdb72 100644 --- a/src/wifi/model/spectrum-wifi-phy.cc +++ b/src/wifi/model/spectrum-wifi-phy.cc @@ -344,14 +344,14 @@ SpectrumWifiPhy::StartRx (Ptr 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 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)); } } } diff --git a/src/wifi/model/spectrum-wifi-phy.h b/src/wifi/model/spectrum-wifi-phy.h index 2bd501aa4..cdc8ad756 100644 --- a/src/wifi/model/spectrum-wifi-phy.h +++ b/src/wifi/model/spectrum-wifi-phy.h @@ -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: /** diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index e934282f3..605e76446 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -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 ppdu = Create (psdus, txVector, txDuration, GetPhyBand (), uid); if (m_wifiRadioEnergyModel != 0 && m_wifiRadioEnergyModel->GetMaximumTimeInState (WifiPhyState::TX) < txDuration) @@ -2971,15 +2971,15 @@ WifiPhy::StartReceiveHeader (Ptr 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 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) 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) 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) 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) AbortCurrentReception (L_SIG_FAILURE); if (event->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ())) { - MaybeCcaBusyDuration (); + MaybeCcaBusyDuration (GetMeasurementChannelWidth (event->GetPpdu ())); } } } @@ -3185,7 +3178,7 @@ WifiPhy::StartReceivePreamble (Ptr 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 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 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 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 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 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 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 ppdu, RxPowerWattPerChannelBand rxP } void -WifiPhy::DropPreambleEvent (Ptr ppdu, WifiPhyRxfailureReason reason, Time endRx) +WifiPhy::DropPreambleEvent (Ptr 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 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) bool canReceivePayload = false; Ptr 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 (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) 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) 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) 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) } m_endOfMpduEvents.clear (); } - MaybeCcaBusyDuration (); + MaybeCcaBusyDuration (GetMeasurementChannelWidth (ppdu)); } std::pair @@ -3766,7 +3758,7 @@ WifiPhy::ResetReceive (Ptr 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) { 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 ppdu) const return staId; } +uint16_t +WifiPhy::GetMeasurementChannelWidth (const Ptr 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*/) { diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 2eb1aec5b..19dde397b 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -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 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 ppdu) const; + /** * Get the start band index and the stop band index for a given band * @@ -1883,6 +1895,7 @@ protected: std::map , Ptr > 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 ppdu, WifiPhyRxfailureReason reason, Time endRx); + void DropPreambleEvent (Ptr ppdu, WifiPhyRxfailureReason reason, Time endRx, uint16_t measurementChannelWidth); /** * The trace source fired when a packet begins the transmission process on diff --git a/src/wifi/test/wifi-phy-ofdma-test.cc b/src/wifi/test/wifi-phy-ofdma-test.cc index 24595bda4..2a6faa425 100644 --- a/src/wifi/test/wifi-phy-ofdma-test.cc +++ b/src/wifi/test/wifi-phy-ofdma-test.cc @@ -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 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 ppdu = Create (psdus, txVector, ppduDuration, WIFI_PHY_BAND_5GHZ, uid); - Ptr 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 rxPsd = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (centerFrequency, channelWidth, txPowerWatts, m_phy->GetGuardBandwidth (channelWidth)); Ptr rxParams = Create (); rxParams->psd = rxPsd; rxParams->txPhy = 0;