From 6de4e8d7f5daaf5283e169da152b07ec667e202d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Wed, 31 Jul 2019 20:33:06 +0200 Subject: [PATCH] wifi: Handle multiple HE TB preambles --- src/wifi/model/interference-helper.cc | 56 +++- src/wifi/model/interference-helper.h | 26 +- src/wifi/model/wifi-phy.cc | 315 +++++++++++++++++------ src/wifi/model/wifi-phy.h | 14 +- src/wifi/model/wifi-ppdu.cc | 6 + src/wifi/model/wifi-ppdu.h | 6 + src/wifi/test/spectrum-wifi-phy-test.cc | 7 +- src/wifi/test/wifi-phy-reception-test.cc | 43 +++- 8 files changed, 358 insertions(+), 115 deletions(-) diff --git a/src/wifi/model/interference-helper.cc b/src/wifi/model/interference-helper.cc index 47d2b70cb..39516a63d 100644 --- a/src/wifi/model/interference-helper.cc +++ b/src/wifi/model/interference-helper.cc @@ -108,6 +108,22 @@ Event::GetTxVector (void) const return m_txVector; } +void +Event::UpdateRxPowerW (RxPowerWattPerChannelBand rxPower) +{ + NS_ASSERT (rxPower.size () == m_rxPowerW.size ()); + //Update power band per band + for (auto & currentRxPowerW : m_rxPowerW) + { + auto band = currentRxPowerW.first; + auto it = rxPower.find (band); + if (it != rxPower.end ()) + { + currentRxPowerW.second += it->second; + } + } +} + std::ostream & operator << (std::ostream &os, const Event &event) { os << "start=" << event.GetStartTime () << ", end=" << event.GetEndTime () @@ -229,7 +245,7 @@ InterferenceHelper::SetNumberOfReceiveAntennas (uint8_t rx) } Time -InterferenceHelper::GetEnergyDuration (double energyW, WifiSpectrumBand band) const +InterferenceHelper::GetEnergyDuration (double energyW, WifiSpectrumBand band) { Time now = Simulator::Now (); auto i = GetPreviousPosition (now, band); @@ -251,7 +267,7 @@ InterferenceHelper::GetEnergyDuration (double energyW, WifiSpectrumBand band) co void InterferenceHelper::AppendEvent (Ptr event) { - NS_LOG_FUNCTION (this); + NS_LOG_FUNCTION (this << event); RxPowerWattPerChannelBand rxPowerWattPerChannelBand = event->GetRxPowerWPerBand (); for (auto const& it : rxPowerWattPerChannelBand) { @@ -277,6 +293,26 @@ InterferenceHelper::AppendEvent (Ptr event) } } +void +InterferenceHelper::UpdateEvent (Ptr event, RxPowerWattPerChannelBand rxPower) +{ + NS_LOG_FUNCTION (this << event); + //This is called for UL MU events, in order to scale power as long as UL MU PPDUs arrive + for (auto const& it : rxPower) + { + WifiSpectrumBand band = it.first; + auto ni_it = m_niChangesPerBand.find (band); + NS_ASSERT (ni_it != m_niChangesPerBand.end ()); + auto first = GetPreviousPosition (event->GetStartTime (), band); + auto last = GetPreviousPosition (event->GetEndTime (), band); + for (auto i = first; i != last; ++i) + { + i->second.AddPower (it.second); + } + } + event->UpdateRxPowerW (rxPower); +} + double InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint16_t channelWidth, uint8_t nss) const { @@ -901,16 +937,16 @@ InterferenceHelper::EraseEvents (void) m_rxing = false; } -InterferenceHelper::NiChanges::const_iterator -InterferenceHelper::GetNextPosition (Time moment, WifiSpectrumBand band) const +InterferenceHelper::NiChanges::iterator +InterferenceHelper::GetNextPosition (Time moment, WifiSpectrumBand band) { auto it = m_niChangesPerBand.find (band); NS_ASSERT (it != m_niChangesPerBand.end ()); return it->second.upper_bound (moment); } -InterferenceHelper::NiChanges::const_iterator -InterferenceHelper::GetPreviousPosition (Time moment, WifiSpectrumBand band) const +InterferenceHelper::NiChanges::iterator +InterferenceHelper::GetPreviousPosition (Time moment, WifiSpectrumBand band) { auto it = GetNextPosition (moment, band); // This is safe since there is always an NiChange at time 0, @@ -935,15 +971,15 @@ InterferenceHelper::NotifyRxStart () } void -InterferenceHelper::NotifyRxEnd () +InterferenceHelper::NotifyRxEnd (Time endTime) { - NS_LOG_FUNCTION (this); + NS_LOG_FUNCTION (this << endTime); m_rxing = false; - //Update m_firstPower for frame capture + //Update m_firstPowerPerBand for frame capture for (auto ni : m_niChangesPerBand) { NS_ASSERT (ni.second.size () > 1); - auto it = GetPreviousPosition (Simulator::Now (), ni.first); + auto it = GetPreviousPosition (endTime, ni.first); it--; m_firstPowerPerBand.find (ni.first)->second = it->second.GetPower (); } diff --git a/src/wifi/model/interference-helper.h b/src/wifi/model/interference-helper.h index d346ce27a..3704dd6f4 100644 --- a/src/wifi/model/interference-helper.h +++ b/src/wifi/model/interference-helper.h @@ -105,6 +105,13 @@ public: * \return the TXVECTOR of the PPDU */ WifiTxVector GetTxVector (void) const; + /** + * Update the received power (W) for all bands, i.e. add up the received power + * to the current received power, for each band. + * + * \param the received power (W) for all bands. + */ + void UpdateRxPowerW (RxPowerWattPerChannelBand rxPower); private: @@ -195,7 +202,7 @@ public: * energy on the medium for a given band will * be higher than the requested threshold. */ - Time GetEnergyDuration (double energyW, WifiSpectrumBand band) const; + Time GetEnergyDuration (double energyW, WifiSpectrumBand band); /** * Add the PPDU-related signal to interference helper. @@ -270,13 +277,23 @@ public: void NotifyRxStart (); /** * Notify that RX has ended. + * + * \param endTime the end time of the signal */ - void NotifyRxEnd (); + void NotifyRxEnd (Time endTime); /** * Erase all events. */ void EraseEvents (void); + /** + * Update event to scale its received power (W) per band. + * + * \param event the event to be updated + * \param rxPower the received power (W) per band to be added to the current event + */ + void UpdateEvent (Ptr event, RxPowerWattPerChannelBand rxPower); + protected: /** @@ -359,6 +376,7 @@ private: * \param event */ void AppendEvent (Ptr event); + /** * Calculate noise and interference power in W. * @@ -434,7 +452,7 @@ private: * \param band identify the band to check * \returns an iterator to the list of NiChanges */ - NiChanges::const_iterator GetNextPosition (Time moment, WifiSpectrumBand band) const; + NiChanges::iterator GetNextPosition (Time moment, WifiSpectrumBand band); /** * Returns an iterator to the last NiChange that is before than moment * @@ -442,7 +460,7 @@ private: * \param band identify the band to check * \returns an iterator to the list of NiChanges */ - NiChanges::const_iterator GetPreviousPosition (Time moment, WifiSpectrumBand band) const; + NiChanges::iterator GetPreviousPosition (Time moment, WifiSpectrumBand band); /** * Add NiChange to the list at the appropriate position and diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index 256766daa..558edb5f4 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -510,7 +510,6 @@ WifiPhy::WifiPhy () m_rxMpduReferenceNumber (0xffffffff), m_endRxEvent (), m_endPhyRxEvent (), - m_endPreambleDetectionEvent (), m_endTxEvent (), m_standard (WIFI_PHY_STANDARD_UNSPECIFIED), m_band (WIFI_PHY_BAND_UNSPECIFIED), @@ -552,7 +551,11 @@ WifiPhy::DoDispose (void) m_endTxEvent.Cancel (); m_endRxEvent.Cancel (); m_endPhyRxEvent.Cancel (); - m_endPreambleDetectionEvent.Cancel (); + for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) + { + endPreambleDetectionEvent.Cancel (); + } + m_endPreambleDetectionEvents.clear (); m_device = 0; m_mobility = 0; m_state = 0; @@ -561,6 +564,7 @@ WifiPhy::DoDispose (void) m_deviceRateSet.clear (); m_deviceMcsSet.clear (); m_mcsIndexMap.clear (); + m_currentPreambleEvents.clear (); } void @@ -1677,6 +1681,8 @@ WifiPhy::DoChannelSwitch (uint8_t nch) { m_powerRestricted = false; m_channelAccessRequested = false; + m_currentEvent = 0; + m_currentPreambleEvents.clear (); if (!IsInitialized ()) { //this is not channel switch, this is initialization @@ -1691,7 +1697,11 @@ WifiPhy::DoChannelSwitch (uint8_t nch) NS_LOG_DEBUG ("drop packet because of channel switching while reception"); m_endPhyRxEvent.Cancel (); m_endRxEvent.Cancel (); - m_endPreambleDetectionEvent.Cancel (); + for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) + { + endPreambleDetectionEvent.Cancel (); + } + m_endPreambleDetectionEvents.clear (); goto switchChannel; break; case WifiPhyState::TX: @@ -1700,9 +1710,12 @@ WifiPhy::DoChannelSwitch (uint8_t nch) break; case WifiPhyState::CCA_BUSY: case WifiPhyState::IDLE: - if (m_endPreambleDetectionEvent.IsRunning ()) { - m_endPreambleDetectionEvent.Cancel (); + for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) + { + endPreambleDetectionEvent.Cancel (); + } + m_endPreambleDetectionEvents.clear (); m_endRxEvent.Cancel (); } goto switchChannel; @@ -1737,6 +1750,8 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency) { m_powerRestricted = false; m_channelAccessRequested = false; + m_currentEvent = 0; + m_currentPreambleEvents.clear (); if (!IsInitialized ()) { //this is not channel switch, this is initialization @@ -1751,7 +1766,11 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency) NS_LOG_DEBUG ("drop packet because of channel/frequency switching while reception"); m_endPhyRxEvent.Cancel (); m_endRxEvent.Cancel (); - m_endPreambleDetectionEvent.Cancel (); + for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) + { + endPreambleDetectionEvent.Cancel (); + } + m_endPreambleDetectionEvents.clear (); goto switchFrequency; break; case WifiPhyState::TX: @@ -1760,11 +1779,12 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency) break; case WifiPhyState::CCA_BUSY: case WifiPhyState::IDLE: - if (m_endPreambleDetectionEvent.IsRunning ()) + for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) { - m_endPreambleDetectionEvent.Cancel (); - m_endRxEvent.Cancel (); + endPreambleDetectionEvent.Cancel (); } + m_endPreambleDetectionEvents.clear (); + m_endRxEvent.Cancel (); goto switchFrequency; break; case WifiPhyState::SLEEP: @@ -1834,8 +1854,12 @@ WifiPhy::SetOffMode (void) m_channelAccessRequested = false; m_endPhyRxEvent.Cancel (); m_endRxEvent.Cancel (); - m_endPreambleDetectionEvent.Cancel (); m_endTxEvent.Cancel (); + for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) + { + endPreambleDetectionEvent.Cancel (); + } + m_endPreambleDetectionEvents.clear (); m_state->SwitchToOff (); } @@ -1843,6 +1867,7 @@ void WifiPhy::ResumeFromSleep (void) { NS_LOG_FUNCTION (this); + m_currentPreambleEvents.clear (); switch (m_state->GetState ()) { case WifiPhyState::TX: @@ -2835,16 +2860,21 @@ WifiPhy::Send (WifiConstPsduMap psdus, WifiTxVector txVector) txDuration = CalculateTxDuration (psdus, txVector, GetPhyBand ()); } - if ((m_currentEvent != 0) && (m_currentEvent->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ()))) + if (!m_endPreambleDetectionEvents.empty () || ((m_currentEvent != 0) && (m_currentEvent->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ())))) { + AbortCurrentReception (RECEPTION_ABORTED_BY_TX); //that packet will be noise _after_ the transmission. MaybeCcaBusyDuration (); } - if (m_currentEvent != 0) + for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) { - AbortCurrentReception (RECEPTION_ABORTED_BY_TX); + if (endPreambleDetectionEvent.IsRunning ()) + { + endPreambleDetectionEvent.Cancel (); + } } + m_currentPreambleEvents.clear (); if (m_powerRestricted) { @@ -2895,6 +2925,16 @@ WifiPhy::Send (WifiConstPsduMap psdus, WifiTxVector txVector) m_channelAccessRequested = false; m_powerRestricted = false; + + Simulator::Schedule (txDuration, &WifiPhy::Reset, this); +} + +void +WifiPhy::Reset (void) +{ + NS_LOG_FUNCTION (this); + m_currentPreambleEvents.clear (); + m_currentEvent = 0; } void @@ -2903,51 +2943,122 @@ WifiPhy::StartReceiveHeader (Ptr event) NS_LOG_FUNCTION (this << *event); NS_ASSERT (!IsStateRx ()); NS_ASSERT (m_endPhyRxEvent.IsExpired ()); - NS_ASSERT (m_currentEvent != 0); - NS_ASSERT (event->GetStartTime () == m_currentEvent->GetStartTime ()); - NS_ASSERT (event->GetEndTime () == m_currentEvent->GetEndTime ()); + + uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth (); + auto primaryBand = GetBand (primaryChannelWidth); + double maxRxPowerW = 0; + Ptr maxEvent; + for (auto preambleEvent : m_currentPreambleEvents) + { + double rxPowerW = preambleEvent.second->GetRxPowerW (primaryBand); + if (rxPowerW > maxRxPowerW) + { + maxRxPowerW = rxPowerW; + maxEvent = preambleEvent.second; + } + } + + NS_ASSERT (maxEvent != 0); + if (maxEvent != event) + { + NS_LOG_DEBUG ("Receiver got a stronger packet with UID " << maxEvent->GetPpdu ()->GetUid () << " during preamble detection: drop packet with UID " << event->GetPpdu ()->GetUid ()); + NotifyRxDrop (GetAddressedPsduInPpdu (event->GetPpdu ()), BUSY_DECODING_PREAMBLE); + auto it = m_currentPreambleEvents.find (std::make_pair (event->GetPpdu ()->GetUid (), event->GetPpdu ()->GetPreamble ())); + m_currentPreambleEvents.erase (it); + //This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to the power at the start of the PPDU + m_interference.NotifyRxEnd (maxEvent->GetStartTime ()); + //Make sure InterferenceHelper keeps recording events + m_interference.NotifyRxStart (); + return; + } + + m_currentEvent = event; uint16_t channelWidth; - if (event->GetTxVector ().GetChannelWidth () >= 40) + if (m_currentEvent->GetTxVector ().GetChannelWidth () >= 40) { channelWidth = 20; //calculate PER on the 20 MHz primary channel for PHY headers } else { - channelWidth = event->GetTxVector ().GetChannelWidth (); + channelWidth = m_currentEvent->GetTxVector ().GetChannelWidth (); } auto band = GetBand (channelWidth); - InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (event, band); + InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (m_currentEvent, band); double snr = snrPer.snr; - NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per); + NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr)); - if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (event->GetRxPowerW (band), snr, m_channelWidth))) + Time headerPayloadDuration = m_currentEvent->GetDuration () - (Simulator::Now () - m_currentEvent->GetStartTime ()); //startOfPreambleDuration; + + if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (m_currentEvent->GetRxPowerW (band), snr, m_channelWidth))) { - NotifyRxBegin (GetAddressedPsduInPpdu (event->GetPpdu ()), event->GetRxPowerWPerBand ()); + for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) + { + endPreambleDetectionEvent.Cancel (); + } + m_endPreambleDetectionEvents.clear (); + + for (auto it = m_currentPreambleEvents.begin (); it != m_currentPreambleEvents.end (); ) + { + if (it->second != m_currentEvent) + { + NS_LOG_DEBUG ("Drop packet with UID " << it->first.first << " and preamble " << it->first.second << " arrived at time " << it->second->GetStartTime ()); + WifiPhyRxfailureReason reason; + if (m_currentEvent->GetPpdu ()->GetUid () > it->first.first) + { + reason = PREAMBLE_DETECTION_PACKET_SWITCH; + //This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to the power at the start of the PPDU + m_interference.NotifyRxEnd (m_currentEvent->GetStartTime ()); + } + else + { + reason = BUSY_DECODING_PREAMBLE; + } + NotifyRxDrop (GetAddressedPsduInPpdu (it->second->GetPpdu ()), reason); + it = m_currentPreambleEvents.erase (it); + } + else + { + it++; + } + } + + //Make sure InterferenceHelper keeps recording events + m_interference.NotifyRxStart (); + + NotifyRxBegin (GetAddressedPsduInPpdu (m_currentEvent->GetPpdu ()), m_currentEvent->GetRxPowerWPerBand ()); m_timeLastPreambleDetected = Simulator::Now (); - WifiTxVector txVector = event->GetTxVector (); + WifiTxVector txVector = m_currentEvent->GetTxVector (); if (txVector.GetPreambleType () == WIFI_PREAMBLE_HT_GF) { //No non-HT PHY header for HT GF - Time remainingPreambleHeaderDuration = CalculatePhyPreambleAndHeaderDuration (txVector) - GetPreambleDetectionDuration (); + Time remainingPreambleHeaderDuration = CalculatePhyPreambleAndHeaderDuration (txVector) - (Simulator::Now () - m_currentEvent->GetStartTime ()); m_state->SwitchMaybeToCcaBusy (remainingPreambleHeaderDuration); - m_endPhyRxEvent = Simulator::Schedule (remainingPreambleHeaderDuration, &WifiPhy::StartReceivePayload, this, event); + m_endPhyRxEvent = Simulator::Schedule (remainingPreambleHeaderDuration, &WifiPhy::StartReceivePayload, this, m_currentEvent); } else { //Schedule end of non-HT PHY header - Time remainingPreambleAndNonHtHeaderDuration = GetPhyPreambleDuration (txVector) + GetPhyHeaderDuration (txVector) - GetPreambleDetectionDuration (); + Time remainingPreambleAndNonHtHeaderDuration = GetPhyPreambleDuration (txVector) + GetPhyHeaderDuration (txVector) - (Simulator::Now () - m_currentEvent->GetStartTime ()); m_state->SwitchMaybeToCcaBusy (remainingPreambleAndNonHtHeaderDuration); - m_endPhyRxEvent = Simulator::Schedule (remainingPreambleAndNonHtHeaderDuration, &WifiPhy::ContinueReceiveHeader, this, event); + m_endPhyRxEvent = Simulator::Schedule (remainingPreambleAndNonHtHeaderDuration, &WifiPhy::ContinueReceiveHeader, this, m_currentEvent); } } else { NS_LOG_DEBUG ("Drop packet because PHY preamble detection failed"); - NotifyRxDrop (GetAddressedPsduInPpdu (event->GetPpdu ()), PREAMBLE_DETECT_FAILURE); - m_interference.NotifyRxEnd (); + NotifyRxDrop (GetAddressedPsduInPpdu (m_currentEvent->GetPpdu ()), PREAMBLE_DETECT_FAILURE); + m_interference.NotifyRxEnd (Simulator::Now ()); + for (auto it = m_currentPreambleEvents.begin (); it != m_currentPreambleEvents.end (); ++it) + { + if (it->second == m_currentEvent) + { + it = m_currentPreambleEvents.erase (it); + break; + } + } m_currentEvent = 0; // Like CCA-SD, CCA-ED is governed by the 4μs CCA window to flag CCA-BUSY @@ -2990,6 +3101,7 @@ WifiPhy::ContinueReceiveHeader (Ptr event) { NS_LOG_DEBUG ("Abort reception because non-HT PHY header reception failed"); AbortCurrentReception (L_SIG_FAILURE); + m_currentPreambleEvents.clear (); if (event->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ())) { MaybeCcaBusyDuration (); @@ -3008,9 +3120,58 @@ WifiPhy::StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxP NS_LOG_FUNCTION (this << *ppdu << it->second); WifiTxVector txVector = ppdu->GetTxVector (); Time rxDuration = ppdu->GetTxDuration (); - Ptr event = m_interference.Add (ppdu, txVector, rxDuration, rxPowersW); - Time endRx = Simulator::Now () + rxDuration; + Ptr event; + //We store all incoming preamble events, and a decision is made at the end of the preamble detection window. + //If a preamble is received after the preamble detection window, it is stored anyway because this is needed for HE TB PPDUs in + //order to properly update the received power in InterferenceHelper. The map is cleaned anyway at the end of the current reception. + auto uidPreamblePair = std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()); + if (ppdu->IsUlMu ()) + { + auto it = m_currentPreambleEvents.find (uidPreamblePair); + if (it != m_currentPreambleEvents.end ()) + { + NS_LOG_DEBUG ("Received another HE TB PPDU for UID " << ppdu->GetUid () << " from STA-ID " << ppdu->GetStaId () << " and BSS color " << +txVector.GetBssColor ()); + event = it->second; + if (Simulator::Now () - event->GetStartTime () > NanoSeconds (400)) + { + //Section 27.3.14.3 from 802.11ax Draft 4.0: Pre-correction accuracy requirements. + //A STA that transmits an HE TB PPDU, non-HT PPDU, or non-HT duplicate PPDU in response to a triggering PPDU + //shall ensure that the transmission start time of the HE TB PPDU, non-HT PPDU, or non-HT duplicate PPDU is + //within ±0.4 µs + 16 µs from the end, at the STA’s antenna connector, of the last OFDM symbol of the triggering + //PPDU (if it contains no PE field) or of the PE field of the triggering PPDU (if the PE field is present). + //As a result, if an HE TB PPDU arrives later than 0.4 µs, it is added as an interference but PPDU is dropped. + event = m_interference.Add (ppdu, txVector, rxDuration, rxPowersW); + NS_LOG_DEBUG ("Drop packet because not received within the 400ns window"); + NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), HE_TB_PPDU_TOO_LATE); + } + else + { + //Update received power of the event associated to that UL MU transmission + m_interference.UpdateEvent (event, rxPowersW); + } + if ((m_currentEvent != 0) && (m_currentEvent->GetPpdu ()->GetUid () != ppdu->GetUid ())) + { + NS_LOG_DEBUG ("Drop packet because already receiving another HE TB PPDU"); + NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), RXING); + } + return; + } + else + { + NS_LOG_DEBUG ("Received a new HE TB PPDU for UID " << ppdu->GetUid () << " from STA-ID " << ppdu->GetStaId () << " and BSS color " << +txVector.GetBssColor ()); + event = m_interference.Add (ppdu, txVector, rxDuration, rxPowersW); + m_currentPreambleEvents.insert ({std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()), event}); + } + } + else + { + event = m_interference.Add (ppdu, txVector, rxDuration, rxPowersW); + NS_ASSERT (m_currentPreambleEvents.find (uidPreamblePair) == m_currentPreambleEvents.end ()); + m_currentPreambleEvents.insert ({uidPreamblePair, event}); + } + + Time endRx = Simulator::Now () + rxDuration; if (m_state->GetState () == WifiPhyState::OFF) { NS_LOG_DEBUG ("Cannot start RX because device is OFF"); @@ -3031,18 +3192,6 @@ WifiPhy::StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxP return; } - if (!txVector.GetModeInitialized ()) - { - //If SetRate method was not called above when filling in txVector, this means the PHY does support the rate indicated in PHY SIG headers - NS_LOG_DEBUG ("drop packet because of unsupported RX mode"); - NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), UNSUPPORTED_SETTINGS); - if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ())) - { - MaybeCcaBusyDuration (); - } - return; - } - switch (m_state->GetState ()) { case WifiPhyState::SWITCHING: @@ -3063,7 +3212,6 @@ WifiPhy::StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxP } break; case WifiPhyState::RX: - NS_ASSERT (m_currentEvent != 0); if (m_frameCaptureModel != 0 && m_frameCaptureModel->IsInCaptureWindow (m_timeLastPreambleDetected) && m_frameCaptureModel->CaptureNewFrame (m_currentEvent, event)) @@ -3076,6 +3224,16 @@ WifiPhy::StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxP { NS_LOG_DEBUG ("Drop packet because already in Rx"); NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), RXING); + if (m_currentEvent == 0) + { + /* + * We are here because the non-legacy PHY header has not been successfully received. + * The PHY is kept in RX state for the duration of the PPDU, but EndReceive function is + * not called when the reception of the PPDU is finished, which is responsible to clear + * m_currentPreambleEvents. As a result, m_currentPreambleEvents should be cleared here. + */ + m_currentPreambleEvents.clear (); + } if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ())) { //that packet will be noise _after_ the reception of the currently-received packet. @@ -3105,8 +3263,8 @@ WifiPhy::StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxP } else { - NS_LOG_DEBUG ("Drop packet because already in Rx"); - NotifyRxDrop (ppdu->GetPsdu (), RXING); + NS_LOG_DEBUG ("Drop packet because already decoding preamble"); + NotifyRxDrop (ppdu->GetPsdu (), BUSY_DECODING_PREAMBLE); if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ())) { //that packet will be noise _after_ the reception of the currently-received packet. @@ -3223,7 +3381,7 @@ WifiPhy::StartReceivePayload (Ptr event) else //mode is not allowed { NS_LOG_DEBUG ("Drop packet because it was sent using an unsupported mode (" << txMode << ")"); - NotifyRxDrop (psdu, UNSUPPORTED_SETTINGS); + NotifyRxDrop (GetAddressedPsduInPpdu (event->GetPpdu ()), UNSUPPORTED_SETTINGS); } } else @@ -3375,8 +3533,9 @@ WifiPhy::EndReceive (Ptr event) m_state->SwitchFromRxEndError (Copy (psdu), snr); } - m_interference.NotifyRxEnd (); + m_interference.NotifyRxEnd (Simulator::Now ()); m_currentEvent = 0; + m_currentPreambleEvents.clear (); MaybeCcaBusyDuration (); } @@ -3400,7 +3559,7 @@ WifiPhy::GetReceptionStatus (Ptr psdu, Ptr event, uint16_ InterferenceHelper::SnrPer snrPer = m_interference.CalculatePayloadSnrPer (event, channelWidth, band, staId, std::make_pair (relativeMpduStart, relativeMpduStart + mpduDuration)); WifiMode mode = event->GetTxVector ().GetMode (staId); - NS_LOG_DEBUG ("mode=" << (mode.GetDataRate (event->GetTxVector (), staId)) << + NS_LOG_DEBUG ("rate=" << (mode.GetDataRate (event->GetTxVector (), staId)) << ", snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per << ", size=" << psdu->GetSize () << ", relativeStart = " << relativeMpduStart.As (Time::NS) << ", duration = " << mpduDuration.As (Time::NS)); @@ -3466,8 +3625,9 @@ WifiPhy::ResetReceive (Ptr event) NS_ASSERT (event->GetEndTime () == Simulator::Now ()); } NS_ASSERT (!IsStateRx ()); - m_interference.NotifyRxEnd (); + m_interference.NotifyRxEnd (Simulator::Now ()); m_currentEvent = 0; + m_currentPreambleEvents.clear (); MaybeCcaBusyDuration (); } @@ -4725,10 +4885,14 @@ void WifiPhy::AbortCurrentReception (WifiPhyRxfailureReason reason) { NS_LOG_FUNCTION (this << reason); - if (m_endPreambleDetectionEvent.IsRunning ()) + for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) { - m_endPreambleDetectionEvent.Cancel (); + if (endPreambleDetectionEvent.IsRunning ()) + { + endPreambleDetectionEvent.Cancel (); + } } + m_endPreambleDetectionEvents.clear (); if (m_endPhyRxEvent.IsRunning ()) { m_endPhyRxEvent.Cancel (); @@ -4737,12 +4901,24 @@ WifiPhy::AbortCurrentReception (WifiPhyRxfailureReason reason) { m_endRxEvent.Cancel (); } + m_interference.NotifyRxEnd (Simulator::Now ()); + if (!m_currentEvent) + { + return; + } NotifyRxDrop (GetAddressedPsduInPpdu (m_currentEvent->GetPpdu ()), reason); - m_interference.NotifyRxEnd (); if (reason == OBSS_PD_CCA_RESET) { m_state->SwitchFromRxAbort (); } + for (auto it = m_currentPreambleEvents.begin (); it != m_currentPreambleEvents.end (); ++it) + { + if (it->second == m_currentEvent) + { + it = m_currentPreambleEvents.erase (it); + break; + } + } m_currentEvent = 0; } @@ -4782,38 +4958,11 @@ WifiPhy::GetTxPowerForTransmission (WifiTxVector txVector) const void WifiPhy::StartRx (Ptr event) { + NS_LOG_FUNCTION (this << *event); uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth (); - auto primaryBand = GetBand (primaryChannelWidth); - double rxPowerW = event->GetRxPowerW (primaryBand); - NS_LOG_FUNCTION (this << *event << rxPowerW); - - NS_LOG_DEBUG ("sync to signal (power=" << rxPowerW << "W)"); + NS_LOG_DEBUG ("sync to signal (power=" << event->GetRxPowerW (GetBand (primaryChannelWidth)) << "W)"); m_interference.NotifyRxStart (); //We need to notify it now so that it starts recording events - - if (!m_endPreambleDetectionEvent.IsRunning ()) - { - Time startOfPreambleDuration = GetPreambleDetectionDuration (); - Time remainingRxDuration = event->GetDuration () - startOfPreambleDuration; - m_endPreambleDetectionEvent = Simulator::Schedule (startOfPreambleDuration, &WifiPhy::StartReceiveHeader, this, event); - } - else if ((m_frameCaptureModel != 0) && (rxPowerW > m_currentEvent->GetRxPowerW (primaryBand))) - { - NS_LOG_DEBUG ("Received a stronger signal during preamble detection: drop current packet and switch to new packet"); - NotifyRxDrop (GetAddressedPsduInPpdu (m_currentEvent->GetPpdu ()), PREAMBLE_DETECTION_PACKET_SWITCH); - m_interference.NotifyRxEnd (); - m_endPreambleDetectionEvent.Cancel (); - m_interference.NotifyRxStart (); - Time startOfPreambleDuration = GetPreambleDetectionDuration (); - Time remainingRxDuration = event->GetDuration () - startOfPreambleDuration; - m_endPreambleDetectionEvent = Simulator::Schedule (startOfPreambleDuration, &WifiPhy::StartReceiveHeader, this, event); - } - else - { - NS_LOG_DEBUG ("Drop packet because RX is already decoding preamble"); - NotifyRxDrop (GetAddressedPsduInPpdu (event->GetPpdu ()), BUSY_DECODING_PREAMBLE); - return; - } - m_currentEvent = event; + m_endPreambleDetectionEvents.push_back (Simulator::Schedule (GetPreambleDetectionDuration (), &WifiPhy::StartReceiveHeader, this, event)); } Ptr diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 5d9b101ca..51863f854 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -65,7 +65,8 @@ enum WifiPhyRxfailureReason PREAMBLE_DETECTION_PACKET_SWITCH, FRAME_CAPTURE_PACKET_SWITCH, OBSS_PD_CCA_RESET, - FILTERED + FILTERED, + HE_TB_PPDU_TOO_LATE }; /** @@ -107,6 +108,8 @@ inline std::ostream& operator<< (std::ostream& os, WifiPhyRxfailureReason reason return (os << "OBSS_PD_CCA_RESET"); case FILTERED: return (os << "FILTERED"); + case HE_TB_PPDU_TOO_LATE: + return (os << "HE_TB_PPDU_TOO_LATE"); case UNKNOWN: default: NS_FATAL_ERROR ("Unknown reason"); @@ -1773,6 +1776,11 @@ protected: virtual void DoInitialize (void); virtual void DoDispose (void); + /* + * Reset data upon end of TX or RX + */ + void Reset (void); + /** * The default implementation does nothing and returns true. This method * is typically called internally by SetChannelNumber (). @@ -1839,9 +1847,11 @@ protected: EventId m_endRxEvent; //!< the end of receive event EventId m_endPhyRxEvent; //!< the end of PHY receive event - EventId m_endPreambleDetectionEvent; //!< the end of preamble detection event EventId m_endTxEvent; //!< the end of transmit event + std::vector m_endPreambleDetectionEvents; //!< the end of preamble detection events + std::map , Ptr > m_currentPreambleEvents; //!< store event associated to a PPDU (that has a unique ID and preamble combination) whose preamble is being received + static uint64_t m_globalPpduUid; //!< Global counter of the PPDU UID diff --git a/src/wifi/model/wifi-ppdu.cc b/src/wifi/model/wifi-ppdu.cc index cb1737727..5d5a0209a 100644 --- a/src/wifi/model/wifi-ppdu.cc +++ b/src/wifi/model/wifi-ppdu.cc @@ -510,6 +510,12 @@ WifiPpdu::GetUid (void) const return m_uid; } +WifiPreamble +WifiPpdu::GetPreamble (void) const +{ + return m_preamble; +} + void WifiPpdu::Print (std::ostream& os) const { diff --git a/src/wifi/model/wifi-ppdu.h b/src/wifi/model/wifi-ppdu.h index 566c7bfc3..6f237fb2a 100644 --- a/src/wifi/model/wifi-ppdu.h +++ b/src/wifi/model/wifi-ppdu.h @@ -132,6 +132,12 @@ public: */ uint64_t GetUid (void) const; + /** + * Get the preamble of the PPDU. + * \return the preamble of the PPDU + */ + WifiPreamble GetPreamble (void) const; + /** * \brief Print the PPDU contents. * \param os output stream in which the data should be printed. diff --git a/src/wifi/test/spectrum-wifi-phy-test.cc b/src/wifi/test/spectrum-wifi-phy-test.cc index 4e92b84a9..20cd93c21 100644 --- a/src/wifi/test/spectrum-wifi-phy-test.cc +++ b/src/wifi/test/spectrum-wifi-phy-test.cc @@ -97,6 +97,8 @@ protected: private: virtual void DoRun (void); + + uint64_t m_uid; }; SpectrumWifiPhyBasicTest::SpectrumWifiPhyBasicTest () @@ -107,7 +109,8 @@ SpectrumWifiPhyBasicTest::SpectrumWifiPhyBasicTest () SpectrumWifiPhyBasicTest::SpectrumWifiPhyBasicTest (std::string name) : TestCase (name), - m_count (0) + m_count (0), + m_uid (0) { } @@ -126,7 +129,7 @@ SpectrumWifiPhyBasicTest::MakeSignal (double txPowerWatts) Ptr psdu = Create (pkt, hdr); Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ()); - Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0); + Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++); Ptr txPowerSpectrum = WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, txPowerWatts, GUARD_WIDTH); Ptr txParams = Create (); diff --git a/src/wifi/test/wifi-phy-reception-test.cc b/src/wifi/test/wifi-phy-reception-test.cc index 7350eedb8..7be18581f 100644 --- a/src/wifi/test/wifi-phy-reception-test.cc +++ b/src/wifi/test/wifi-phy-reception-test.cc @@ -102,12 +102,15 @@ private: * \param expectedFailureCount the number of unsuccessfully received packets */ void CheckRxPacketCount (uint32_t expectedSuccessCount, uint32_t expectedFailureCount); + + uint64_t m_uid; }; TestThresholdPreambleDetectionWithoutFrameCapture::TestThresholdPreambleDetectionWithoutFrameCapture () : TestCase ("Threshold preamble detection model test when no frame capture model is applied"), m_countRxSuccess (0), - m_countRxFailure (0) + m_countRxFailure (0), + m_uid (0) { } @@ -125,7 +128,7 @@ TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket (double rxPowerDbm Ptr psdu = Create (pkt, hdr); Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ()); - Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0); + Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++); Ptr txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (rxPowerDbm), GUARD_WIDTH); @@ -289,9 +292,9 @@ TestThresholdPreambleDetectionWithoutFrameCapture::DoRun (void) Simulator::Schedule (Seconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, rxPowerDbm); Simulator::Schedule (Seconds (5.0) + MicroSeconds (2.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, rxPowerDbm + 3); - // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to CCA_BUSY - Simulator::Schedule (Seconds (5.0) + NanoSeconds (3999), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE); - Simulator::Schedule (Seconds (5.0) + NanoSeconds (4000), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::CCA_BUSY); + // At 6us (hence 4us after the last signal is received), no preamble is successfully detected, hence STA PHY STATE should move from IDLE to CCA_BUSY + Simulator::Schedule (Seconds (5.0) + NanoSeconds (5999), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE); + Simulator::Schedule (Seconds (5.0) + NanoSeconds (6000), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::CCA_BUSY); // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2 = 154.8us Simulator::Schedule (Seconds (5.0) + NanoSeconds (154799), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::CCA_BUSY); Simulator::Schedule (Seconds (5.0) + NanoSeconds (154800), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE); @@ -454,12 +457,15 @@ private: * \param expectedFailureCount the number of unsuccessfully received packets */ void CheckRxPacketCount (uint32_t expectedSuccessCount, uint32_t expectedFailureCount); + + uint64_t m_uid; }; TestThresholdPreambleDetectionWithFrameCapture::TestThresholdPreambleDetectionWithFrameCapture () : TestCase ("Threshold preamble detection model test when simple frame capture model is applied"), -m_countRxSuccess (0), -m_countRxFailure (0) + m_countRxSuccess (0), + m_countRxFailure (0), + m_uid (0) { } @@ -477,7 +483,7 @@ TestThresholdPreambleDetectionWithFrameCapture::SendPacket (double rxPowerDbm) Ptr psdu = Create (pkt, hdr); Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ()); - Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0); + Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++); Ptr txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (rxPowerDbm), GUARD_WIDTH); @@ -957,6 +963,8 @@ private: bool m_rxSuccess1500B; ///< count received packets with 1500B payload bool m_rxDropped1000B; ///< count dropped packets with 1000B payload bool m_rxDropped1500B; ///< count dropped packets with 1500B payload + + uint64_t m_uid; }; TestSimpleFrameCaptureModel::TestSimpleFrameCaptureModel () @@ -964,7 +972,8 @@ TestSimpleFrameCaptureModel::TestSimpleFrameCaptureModel () m_rxSuccess1000B (false), m_rxSuccess1500B (false), m_rxDropped1000B (false), - m_rxDropped1500B (false) + m_rxDropped1500B (false), + m_uid (0) { } @@ -982,7 +991,7 @@ TestSimpleFrameCaptureModel::SendPacket (double rxPowerDbm, uint32_t packetSize) Ptr psdu = Create (pkt, hdr); Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ()); - Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0); + Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++); Ptr txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (rxPowerDbm), GUARD_WIDTH); @@ -1165,10 +1174,13 @@ private: * \param expectedState the expected PHY state */ void DoCheckPhyState (WifiPhyState expectedState); + + uint64_t m_uid; }; TestPhyHeadersReception::TestPhyHeadersReception () -: TestCase ("PHY headers reception test") +: TestCase ("PHY headers reception test"), + m_uid (0) { } @@ -1186,7 +1198,7 @@ TestPhyHeadersReception::SendPacket (double rxPowerDbm) Ptr psdu = Create (pkt, hdr); Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ()); - Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0); + Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++); Ptr txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (rxPowerDbm), GUARD_WIDTH); @@ -1479,6 +1491,8 @@ private: uint8_t m_rxDroppedBitmapAmpdu1; ///< bitmap of dropped MPDUs in A-MPDU #1 uint8_t m_rxDroppedBitmapAmpdu2; ///< bitmap of dropped MPDUs in A-MPDU #2 + + uint64_t m_uid; ///< UID }; TestAmpduReception::TestAmpduReception () @@ -1488,7 +1502,8 @@ TestAmpduReception::TestAmpduReception () m_rxFailureBitmapAmpdu1 (0), m_rxFailureBitmapAmpdu2 (0), m_rxDroppedBitmapAmpdu1 (0), - m_rxDroppedBitmapAmpdu2 (0) + m_rxDroppedBitmapAmpdu2 (0), + m_uid (0) { } @@ -1696,7 +1711,7 @@ TestAmpduReception::SendAmpduWithThreeMpdus (double rxPowerDbm, uint32_t referen Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ()); - Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0); + Ptr ppdu = Create (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++); Ptr txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (rxPowerDbm), GUARD_WIDTH);