diff --git a/src/wifi/model/interference-helper.h b/src/wifi/model/interference-helper.h index 7b1a97f42..ff7a6328c 100644 --- a/src/wifi/model/interference-helper.h +++ b/src/wifi/model/interference-helper.h @@ -190,7 +190,7 @@ public: * \param txVector the TXVECTOR * \param duration the PPDU duration * \param rxPower received power per band (W) - * \param isStartOfdmaRxing flag whether the event corresponds to the start of the OFDMA payload reception (only used for UL-OFDMA) + * \param isStartOfdmaRxing flag whether the event corresponds to the start of the OFDMA payload reception (only used for UL-OFDMA) //TODO simplify this once WifiPpdu is subclassed by adding an attribute * * \return Event */ diff --git a/src/wifi/model/spectrum-wifi-phy.cc b/src/wifi/model/spectrum-wifi-phy.cc index 05283a02e..9102487da 100644 --- a/src/wifi/model/spectrum-wifi-phy.cc +++ b/src/wifi/model/spectrum-wifi-phy.cc @@ -360,49 +360,7 @@ SpectrumWifiPhy::StartRx (Ptr rxParams) NS_LOG_INFO ("Received Wi-Fi signal"); Ptr ppdu = wifiRxParams->ppdu->Copy (); - WifiTxVector txVector = ppdu->GetTxVector (); - if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB - && wifiRxParams->txPsdFlag == PSD_HE_TB_OFDMA_PORTION) - { - if (DynamicCast (GetPhyEntity (WIFI_MOD_CLASS_HE))->GetCurrentHeTbPpduUid () == ppdu->GetUid () - && m_currentEvent != 0) - { - //AP or STA has already received non-OFDMA part, switch to OFDMA part, and schedule reception of payload (will be canceled for STAs by StartPayloadStart) - bool ofdmaStarted = !m_beginOfdmaPayloadRxEvents.empty (); - NS_LOG_INFO ("Switch to OFDMA part (already started? " << (ofdmaStarted ? "Y" : "N") << ") " - << "and schedule OFDMA payload reception in " << GetPpduFieldDuration (WIFI_PPDU_FIELD_TRAINING, txVector).As (Time::NS)); - Ptr event = m_interference.Add (ppdu, txVector, rxDuration, rxPowerW, !ofdmaStarted); - uint16_t staId = GetStaId (ppdu); - NS_ASSERT (m_beginOfdmaPayloadRxEvents.find (staId) == m_beginOfdmaPayloadRxEvents.end ()); - m_beginOfdmaPayloadRxEvents[staId] = Simulator::Schedule (GetPpduFieldDuration (WIFI_PPDU_FIELD_TRAINING, txVector), - &WifiPhy::StartReceiveOfdmaPayload, this, event); - } - else - { - //PHY receives the OFDMA payload while having dropped the preamble - NS_LOG_INFO ("Consider OFDMA part of the HE TB PPDU as interference since device dropped the preamble"); - m_interference.Add (ppdu, txVector, rxDuration, rxPowerW); - auto it = m_currentPreambleEvents.find (std::make_pair(ppdu->GetUid (), ppdu->GetPreamble ())); - if (it != m_currentPreambleEvents.end ()) - { - m_currentPreambleEvents.erase (it); - } - if (m_currentPreambleEvents.empty ()) - { - Reset (); - } - - if (rxDuration > m_state->GetDelayUntilIdle ()) - { - //that packet will be noise _after_ the completion of the OFDMA part of the HE TB PPDUs - SwitchMaybeToCcaBusy (GetMeasurementChannelWidth (ppdu)); - } - } - } - else - { - StartReceivePreamble (ppdu, rxPowerW); - } + StartReceivePreamble (ppdu, rxPowerW, rxDuration, wifiRxParams->txPsdFlag); } Ptr @@ -455,7 +413,9 @@ SpectrumWifiPhy::GetTxPowerSpectralDensity (double txPowerW, Ptr ppdu, case WIFI_MOD_CLASS_HE: if (flag == PSD_HE_TB_OFDMA_PORTION) { - WifiSpectrumBand band = GetRuBand (txVector, GetStaId (ppdu)); + //TODO Move this to HePhy + const auto hePhy = DynamicCast (GetPhyEntity (WIFI_MOD_CLASS_HE)); + WifiSpectrumBand band = hePhy->GetRuBand (txVector, GetStaId (ppdu)); v = WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity (centerFrequency, channelWidth, txPowerW, GetGuardBandwidth (channelWidth), band); } else diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index 2909a427b..0e8a88db5 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -563,21 +563,10 @@ WifiPhy::DoDispose (void) NS_LOG_FUNCTION (this); m_endTxEvent.Cancel (); m_endPhyRxEvent.Cancel (); - for (auto & endRxEvent : m_endRxEvents) + for (auto & phyEntity : m_phyEntities) { - endRxEvent.Cancel (); + phyEntity.second->CancelAllEvents (); } - m_endRxEvents.clear (); - for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) - { - endPreambleDetectionEvent.Cancel (); - } - m_endPreambleDetectionEvents.clear (); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - beginOfdmaPayloadRxEvent.second.Cancel (); - } - m_beginOfdmaPayloadRxEvents.clear (); m_device = 0; m_mobility = 0; m_state = 0; @@ -1621,21 +1610,10 @@ WifiPhy::DoChannelSwitch (uint8_t nch) case WifiPhyState::RX: NS_LOG_DEBUG ("drop packet because of channel switching while reception"); m_endPhyRxEvent.Cancel (); - for (auto & endRxEvent : m_endRxEvents) + for (auto & phyEntity : m_phyEntities) { - endRxEvent.Cancel (); + phyEntity.second->CancelAllEvents (); } - m_endRxEvents.clear (); - for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) - { - endPreambleDetectionEvent.Cancel (); - } - m_endPreambleDetectionEvents.clear (); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - beginOfdmaPayloadRxEvent.second.Cancel (); - } - m_beginOfdmaPayloadRxEvents.clear (); goto switchChannel; break; case WifiPhyState::TX: @@ -1644,22 +1622,9 @@ WifiPhy::DoChannelSwitch (uint8_t nch) break; case WifiPhyState::CCA_BUSY: case WifiPhyState::IDLE: + for (auto & phyEntity : m_phyEntities) { - for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) - { - endPreambleDetectionEvent.Cancel (); - } - m_endPreambleDetectionEvents.clear (); - for (auto & endRxEvent : m_endRxEvents) - { - endRxEvent.Cancel (); - } - m_endRxEvents.clear (); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - beginOfdmaPayloadRxEvent.second.Cancel (); - } - m_beginOfdmaPayloadRxEvents.clear (); + phyEntity.second->CancelAllEvents (); } goto switchChannel; break; @@ -1708,21 +1673,10 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency) case WifiPhyState::RX: NS_LOG_DEBUG ("drop packet because of channel/frequency switching while reception"); m_endPhyRxEvent.Cancel (); - for (auto & endRxEvent : m_endRxEvents) + for (auto & phyEntity : m_phyEntities) { - endRxEvent.Cancel (); + phyEntity.second->CancelAllEvents (); } - m_endRxEvents.clear (); - for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) - { - endPreambleDetectionEvent.Cancel (); - } - m_endPreambleDetectionEvents.clear (); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - beginOfdmaPayloadRxEvent.second.Cancel (); - } - m_beginOfdmaPayloadRxEvents.clear (); goto switchFrequency; break; case WifiPhyState::TX: @@ -1731,22 +1685,11 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency) break; case WifiPhyState::CCA_BUSY: case WifiPhyState::IDLE: - for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) + for (auto & phyEntity : m_phyEntities) { - endPreambleDetectionEvent.Cancel (); + phyEntity.second->CancelAllEvents (); } - m_endPreambleDetectionEvents.clear (); - for (auto & endRxEvent : m_endRxEvents) - { - endRxEvent.Cancel (); - } - m_endRxEvents.clear (); goto switchFrequency; - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - beginOfdmaPayloadRxEvent.second.Cancel (); - } - m_beginOfdmaPayloadRxEvents.clear (); break; case WifiPhyState::SLEEP: NS_LOG_DEBUG ("frequency switching ignored in sleep mode"); @@ -1815,21 +1758,10 @@ WifiPhy::SetOffMode (void) m_channelAccessRequested = false; m_endPhyRxEvent.Cancel (); m_endTxEvent.Cancel (); - for (auto & endRxEvent : m_endRxEvents) + for (auto & phyEntity : m_phyEntities) { - endRxEvent.Cancel (); + phyEntity.second->CancelAllEvents (); } - m_endRxEvents.clear (); - for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) - { - endPreambleDetectionEvent.Cancel (); - } - m_endPreambleDetectionEvents.clear (); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - beginOfdmaPayloadRxEvent.second.Cancel (); - } - m_beginOfdmaPayloadRxEvents.clear (); m_state->SwitchToOff (); } @@ -1975,7 +1907,7 @@ WifiPhy::CalculateTxDuration (WifiConstPsduMap psduMap, WifiTxVector txVector, W //TODO: Move this logic to HePhy if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB) { - return ConvertLSigLengthToHeTbPpduDuration (txVector.GetLength (), txVector, band); + return HePhy::ConvertLSigLengthToHeTbPpduDuration (txVector.GetLength (), txVector, band); } Time maxDuration = Seconds (0); @@ -2164,30 +2096,23 @@ WifiPhy::Send (WifiConstPsduMap psdus, WifiTxVector txVector) return; } - Time txDuration; - if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB) - { - NS_ASSERT (txVector.GetLength () > 0); - txDuration = ConvertLSigLengthToHeTbPpduDuration (txVector.GetLength (), txVector, GetPhyBand ()); - } - else - { - txDuration = CalculateTxDuration (psdus, txVector, GetPhyBand ()); - } + Time txDuration = CalculateTxDuration (psdus, txVector, GetPhyBand ()); - if (!m_endPreambleDetectionEvents.empty () || ((m_currentEvent != 0) && (m_currentEvent->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ())))) + bool noEndPreambleDetectionEvent = true; + for (const auto & it : m_phyEntities) + { + noEndPreambleDetectionEvent &= it.second->NoEndPreambleDetectionEvents (); + } + if (!noEndPreambleDetectionEvent || ((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 (GetMeasurementChannelWidth (m_currentEvent != 0 ? m_currentEvent->GetPpdu () : nullptr)); } - for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) + for (auto & it : m_phyEntities) { - if (endPreambleDetectionEvent.IsRunning ()) - { - endPreambleDetectionEvent.Cancel (); - } + it.second->CancelRunningEndPreambleDetectionEvents (); } m_currentPreambleEvents.clear (); @@ -2252,190 +2177,30 @@ WifiPhy::Reset (void) NS_LOG_FUNCTION (this); m_currentPreambleEvents.clear (); m_currentEvent = 0; - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) + for (auto & phyEntity : m_phyEntities) { - beginOfdmaPayloadRxEvent.second.Cancel (); + phyEntity.second->CancelAllEvents (); } - m_beginOfdmaPayloadRxEvents.clear (); } void -WifiPhy::StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxPowersW) +WifiPhy::StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxPowersW, + Time rxDuration, TxPsdFlag psdFlag /* = PSD_NON_HE_TB */) { - //The total RX power corresponds to the maximum over all the bands - auto it = std::max_element (rxPowersW.begin (), rxPowersW.end (), - [] (const std::pair& p1, const std::pair& p2) { - return p1.second < p2.second; - }); - NS_LOG_FUNCTION (this << ppdu << it->second); - WifiTxVector txVector = ppdu->GetTxVector (); - Time rxDuration = ppdu->GetTxDuration (); - - 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->GetType () == WIFI_PPDU_TYPE_UL_MU) + WifiModulationClass modulation = ppdu->GetTxVector ().GetModulationClass (); + auto it = m_phyEntities.find (modulation); + if (it != m_phyEntities.end ()) { - rxDuration = CalculateNonOfdmaDurationForHeTb (txVector); //the OFDMA part of the transmission will be added later on - 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}); - } + it->second->StartReceivePreamble (ppdu, rxPowersW, rxDuration, psdFlag); } 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"); - if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ())) + //TODO find a fallback PHY for receiving the PPDU (e.g. 11a for 11ax due to preamble structure) + NS_LOG_DEBUG ("Unsupported modulation received (" << modulation << "), consider as noise"); + if (ppdu->GetTxDuration () > m_state->GetDelayUntilIdle ()) { MaybeCcaBusyDuration (GetMeasurementChannelWidth (nullptr)); } - return; - } - - if (ppdu->IsTruncatedTx ()) - { - NS_LOG_DEBUG ("Packet reception stopped because transmitter has been switched off"); - if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ())) - { - MaybeCcaBusyDuration (GetMeasurementChannelWidth (ppdu)); - } - return; - } - - switch (m_state->GetState ()) - { - case WifiPhyState::SWITCHING: - NS_LOG_DEBUG ("Drop packet because of channel switching"); - /* - * Packets received on the upcoming channel are added to the event list - * during the switching state. This way the medium can be correctly sensed - * when the device listens to the channel for the first time after the - * switching e.g. after channel switching, the channel may be sensed as - * busy due to other devices' transmissions started before the end of - * the switching. - */ - DropPreambleEvent (ppdu, CHANNEL_SWITCHING, endRx, GetMeasurementChannelWidth (ppdu)); - break; - case WifiPhyState::RX: - if (m_frameCaptureModel != 0 - && m_frameCaptureModel->IsInCaptureWindow (m_timeLastPreambleDetected) - && m_frameCaptureModel->CaptureNewFrame (m_currentEvent, event)) - { - AbortCurrentReception (FRAME_CAPTURE_PACKET_SWITCH); - NS_LOG_DEBUG ("Switch to new packet"); - StartRx (event); - } - else - { - NS_LOG_DEBUG ("Drop packet because already in Rx"); - DropPreambleEvent (ppdu, RXING, endRx, GetMeasurementChannelWidth (ppdu)); - 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 (); - } - } - break; - case WifiPhyState::TX: - NS_LOG_DEBUG ("Drop packet because already in Tx"); - DropPreambleEvent (ppdu, TXING, endRx, GetMeasurementChannelWidth (ppdu)); - break; - case WifiPhyState::CCA_BUSY: - if (m_currentEvent != 0) - { - if (m_frameCaptureModel != 0 - && m_frameCaptureModel->IsInCaptureWindow (m_timeLastPreambleDetected) - && m_frameCaptureModel->CaptureNewFrame (m_currentEvent, event)) - { - AbortCurrentReception (FRAME_CAPTURE_PACKET_SWITCH); - NS_LOG_DEBUG ("Switch to new packet"); - StartRx (event); - } - else - { - NS_LOG_DEBUG ("Drop packet because already decoding preamble"); - DropPreambleEvent (ppdu, BUSY_DECODING_PREAMBLE, endRx, GetMeasurementChannelWidth (ppdu)); - } - } - else - { - StartRx (event); - } - break; - case WifiPhyState::IDLE: - NS_ASSERT (m_currentEvent == 0); - StartRx (event); - break; - case WifiPhyState::SLEEP: - NS_LOG_DEBUG ("Drop packet because in sleep mode"); - DropPreambleEvent (ppdu, SLEEPING, endRx, GetMeasurementChannelWidth (nullptr)); - break; - default: - NS_FATAL_ERROR ("Invalid WifiPhy state."); - break; - } -} - -void -WifiPhy::DropPreambleEvent (Ptr ppdu, WifiPhyRxfailureReason reason, Time endRx, uint16_t measurementChannelWidth) -{ - 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 ()) - { - m_currentPreambleEvents.erase (it); - } - if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ())) - { - //that PPDU will be noise _after_ the end of the current event. - MaybeCcaBusyDuration (measurementChannelWidth); } } @@ -2453,347 +2218,6 @@ WifiPhy::MaybeCcaBusyDuration (uint16_t channelWidth) } } -void -WifiPhy::StartReceiveOfdmaPayload (Ptr event) -{ - Ptr ppdu = event->GetPpdu (); - RxPowerWattPerChannelBand rxPowersW = event->GetRxPowerWPerBand (); - //The total RX power corresponds to the maximum over all the bands - auto it = std::max_element (rxPowersW.begin (), rxPowersW.end (), - [] (const std::pair& p1, const std::pair& p2) { - return p1.second < p2.second; - }); - NS_LOG_FUNCTION (this << event << ppdu << it->second); - NS_ASSERT (m_currentEvent != 0); - auto itEvent = m_beginOfdmaPayloadRxEvents.find (GetStaId (ppdu)); - /** - * m_beginOfdmaPayloadRxEvents should still be running only for APs, since canceled in StartReceivePayload for STAs. - * This is because SpectrumWifiPhy does not have access to the device type and thus blindly schedules things, letting - * the parent WifiPhy class take into account device type. - */ - NS_ASSERT (itEvent != m_beginOfdmaPayloadRxEvents.end () && itEvent->second.IsExpired ()); - m_beginOfdmaPayloadRxEvents.erase (itEvent); - - Time payloadDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (ppdu->GetTxVector ()); - Ptr psdu = GetAddressedPsduInPpdu (ppdu); - ScheduleEndOfMpdus (event); - m_endRxEvents.push_back (Simulator::Schedule (payloadDuration, &WifiPhy::EndReceive, this, event)); - m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), ppdu->GetStaId ()), SignalNoiseDbm ()}); - m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), ppdu->GetStaId ()), std::vector ()}); -} - -void -WifiPhy::StartReceivePayload (Ptr event) -{ - NS_LOG_FUNCTION (this << *event); - NS_ASSERT (m_endPhyRxEvent.IsExpired ()); - Ptr ppdu = event->GetPpdu (); - WifiTxVector txVector = event->GetTxVector (); - Time payloadDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector); - m_state->SwitchToRx (payloadDuration); - m_phyRxPayloadBeginTrace (txVector, payloadDuration); //this callback (equivalent to PHY-RXSTART primitive) is triggered only if headers have been correctly decoded and that the mode within is supported - - Ptr device = DynamicCast (GetDevice ()); - bool isAp = device != 0 && (DynamicCast (device->GetMac ()) != 0); - if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB && !isAp) - { - NS_LOG_DEBUG ("Ignore HE TB PPDU payload received by STA but keep state in Rx"); - m_endRxEvents.push_back (Simulator::Schedule (payloadDuration, - &WifiPhy::ResetReceive, this, event)); - //Cancel all scheduled events for OFDMA payload reception - NS_ASSERT (!m_beginOfdmaPayloadRxEvents.empty () && m_beginOfdmaPayloadRxEvents.begin ()->second.IsRunning ()); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - beginOfdmaPayloadRxEvent.second.Cancel (); - } - m_beginOfdmaPayloadRxEvents.clear (); - } - else - { - NS_LOG_DEBUG ("Receiving PSDU"); - uint16_t staId = GetStaId (ppdu); - m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), staId), SignalNoiseDbm ()}); - m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), staId), std::vector ()}); - if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB) - { - //for HE TB PPDUs, ScheduleEndOfMpdus and EndReceive are scheduled by StartReceiveOfdmaPayload - NS_ASSERT (isAp); - NS_ASSERT (!m_beginOfdmaPayloadRxEvents.empty ()); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - NS_ASSERT (beginOfdmaPayloadRxEvent.second.IsRunning ()); - } - } - else - { - ScheduleEndOfMpdus (event); - m_endRxEvents.push_back (Simulator::Schedule (payloadDuration, &WifiPhy::EndReceive, this, event)); - } - } -} - -void -WifiPhy::ScheduleEndOfMpdus (Ptr event) -{ - NS_LOG_FUNCTION (this << *event); - Ptr ppdu = event->GetPpdu (); - Ptr psdu = GetAddressedPsduInPpdu (ppdu); - WifiTxVector txVector = event->GetTxVector (); - uint16_t staId = GetStaId (ppdu); - Time endOfMpduDuration = NanoSeconds (0); - Time relativeStart = NanoSeconds (0); - Time psduDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector); - Time remainingAmpduDuration = psduDuration; - size_t nMpdus = psdu->GetNMpdus (); - MpduType mpduType = (nMpdus > 1) ? FIRST_MPDU_IN_AGGREGATE : (psdu->IsSingle () ? SINGLE_MPDU : NORMAL_MPDU); - uint32_t totalAmpduSize = 0; - double totalAmpduNumSymbols = 0.0; - auto mpdu = psdu->begin (); - for (size_t i = 0; i < nMpdus && mpdu != psdu->end (); ++mpdu) - { - uint32_t size = (mpduType == NORMAL_MPDU) ? psdu->GetSize () : psdu->GetAmpduSubframeSize (i); - Time mpduDuration = GetPayloadDuration (size, txVector, - GetPhyBand (), mpduType, true, totalAmpduSize, - totalAmpduNumSymbols, staId); - - remainingAmpduDuration -= mpduDuration; - if (i == (nMpdus - 1) && !remainingAmpduDuration.IsZero ()) //no more MPDUs coming - { - if (remainingAmpduDuration < NanoSeconds (txVector.GetGuardInterval ())) //enables to ignore padding - { - mpduDuration += remainingAmpduDuration; //apply a correction just in case rounding had induced slight shift - } - } - - endOfMpduDuration += mpduDuration; - NS_LOG_INFO ("Schedule end of MPDU #" << i << " in " << endOfMpduDuration.As (Time::NS) - << " (relativeStart=" << relativeStart.As (Time::NS) << ", mpduDuration=" << mpduDuration.As (Time::NS) - << ", remainingAmdpuDuration=" << remainingAmpduDuration.As (Time::NS) << ")"); - m_endOfMpduEvents.push_back (Simulator::Schedule (endOfMpduDuration, &WifiPhy::EndOfMpdu, this, event, Create (*mpdu, false), i, relativeStart, mpduDuration)); - - //Prepare next iteration - ++i; - relativeStart += mpduDuration; - mpduType = (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE; - } -} - -void -WifiPhy::EndOfMpdu (Ptr event, Ptr psdu, size_t mpduIndex, Time relativeStart, Time mpduDuration) -{ - NS_LOG_FUNCTION (this << *event << mpduIndex << relativeStart << mpduDuration); - Ptr ppdu = event->GetPpdu (); - WifiTxVector txVector = event->GetTxVector (); - uint16_t staId = GetStaId (ppdu); - - uint16_t channelWidth = std::min (GetChannelWidth (), event->GetTxVector ().GetChannelWidth ()); - WifiSpectrumBand band; - if (txVector.IsMu ()) - { - band = GetRuBand (txVector, staId); - channelWidth = HeRu::GetBandwidth (txVector.GetRu (staId).ruType); - } - else - { - band = GetBand (channelWidth); - } - double snr = m_interference.CalculateSnr (event, channelWidth, txVector.GetNss (staId), band); - - std::pair rxInfo = GetReceptionStatus (psdu, event, staId, relativeStart, mpduDuration); - NS_LOG_DEBUG ("Extracted MPDU #" << mpduIndex << ": duration: " << mpduDuration.GetNanoSeconds () << "ns" << - ", correct reception: " << rxInfo.first << ", Signal/Noise: " << rxInfo.second.signal << "/" << rxInfo.second.noise << "dBm"); - - auto signalNoiseIt = m_signalNoiseMap.find (std::make_pair (ppdu->GetUid (), staId)); - NS_ASSERT (signalNoiseIt != m_signalNoiseMap.end ()); - signalNoiseIt->second = rxInfo.second; - - RxSignalInfo rxSignalInfo; - rxSignalInfo.snr = snr; - rxSignalInfo.rssi = rxInfo.second.signal; - - auto statusPerMpduIt = m_statusPerMpduMap.find (std::make_pair (ppdu->GetUid (), staId)); - NS_ASSERT (statusPerMpduIt != m_statusPerMpduMap.end ()); - statusPerMpduIt->second.push_back (rxInfo.first); - - if (rxInfo.first && GetAddressedPsduInPpdu (ppdu)->GetNMpdus () > 1) - { - //only done for correct MPDU that is part of an A-MPDU - m_state->ContinueRxNextMpdu (Copy (psdu), rxSignalInfo, txVector); - } -} - -void -WifiPhy::EndReceive (Ptr event) -{ - Ptr ppdu = event->GetPpdu (); - WifiTxVector txVector = event->GetTxVector (); - Time psduDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector); - NS_LOG_FUNCTION (this << *event << psduDuration); - if (ppdu->GetType () != WIFI_PPDU_TYPE_UL_MU) - { - NS_ASSERT (GetLastRxEndTime () == Simulator::Now ()); - } - NS_ASSERT (event->GetEndTime () == Simulator::Now ()); - - uint16_t staId = GetStaId (ppdu); - WifiSpectrumBand band; - uint16_t channelWidth = std::min (GetChannelWidth (), txVector.GetChannelWidth ()); - if (txVector.IsMu ()) - { - band = GetRuBand (txVector, staId); - channelWidth = HeRu::GetBandwidth (txVector.GetRu (staId).ruType); - } - else - { - band = GetBand (channelWidth); - } - double snr = m_interference.CalculateSnr (event, channelWidth, txVector.GetNss (staId), band); - - Ptr psdu = GetAddressedPsduInPpdu (ppdu); - NotifyRxEnd (psdu); - - auto signalNoiseIt = m_signalNoiseMap.find (std::make_pair (ppdu->GetUid (), staId)); - NS_ASSERT (signalNoiseIt != m_signalNoiseMap.end ()); - auto statusPerMpduIt = m_statusPerMpduMap.find (std::make_pair (ppdu->GetUid (), staId)); - NS_ASSERT (statusPerMpduIt != m_statusPerMpduMap.end ()); - - if (std::count (statusPerMpduIt->second.begin (), statusPerMpduIt->second.end (), true)) - { - //At least one MPDU has been successfully received - NotifyMonitorSniffRx (psdu, GetFrequency (), txVector, signalNoiseIt->second, statusPerMpduIt->second, staId); - RxSignalInfo rxSignalInfo; - rxSignalInfo.snr = snr; - rxSignalInfo.rssi = signalNoiseIt->second.signal; //same information for all MPDUs - m_state->SwitchFromRxEndOk (Copy (psdu), rxSignalInfo, txVector, staId, statusPerMpduIt->second); - m_previouslyRxPpduUid = event->GetPpdu ()->GetUid (); //store UID only if reception is successful (because otherwise trigger won't be read by MAC layer) - } - else - { - m_state->SwitchFromRxEndError (Copy (psdu), snr); - } - - if (ppdu->GetType () == WIFI_PPDU_TYPE_UL_MU) - { - for (auto it = m_endRxEvents.begin (); it != m_endRxEvents.end (); ) - { - if (it->IsExpired ()) - { - it = m_endRxEvents.erase (it); - } - else - { - it++; - } - } - if (m_endRxEvents.empty ()) - { - //We got the last PPDU of the UL-OFDMA transmission - m_interference.NotifyRxEnd (Simulator::Now ()); - m_signalNoiseMap.clear (); - m_statusPerMpduMap.clear (); - for (const auto & endOfMpduEvent : m_endOfMpduEvents) - { - NS_ASSERT (endOfMpduEvent.IsExpired ()); - } - m_endOfMpduEvents.clear (); - Reset (); - } - } - else - { - m_interference.NotifyRxEnd (Simulator::Now ()); - MaybeCcaBusyDuration (GetMeasurementChannelWidth (ppdu)); - m_currentEvent = 0; - m_currentPreambleEvents.clear (); - m_endRxEvents.clear (); - m_signalNoiseMap.clear (); - m_statusPerMpduMap.clear (); - for (const auto & endOfMpduEvent : m_endOfMpduEvents) - { - NS_ASSERT (endOfMpduEvent.IsExpired ()); - } - m_endOfMpduEvents.clear (); - } - MaybeCcaBusyDuration (GetMeasurementChannelWidth (ppdu)); -} - -std::pair -WifiPhy::GetReceptionStatus (Ptr psdu, Ptr event, uint16_t staId, - Time relativeMpduStart, Time mpduDuration) -{ - NS_LOG_FUNCTION (this << *psdu << *event << staId << relativeMpduStart << mpduDuration); - uint16_t channelWidth = std::min (GetChannelWidth (), event->GetTxVector ().GetChannelWidth ()); - WifiTxVector txVector = event->GetTxVector (); - WifiSpectrumBand band; - if (txVector.IsMu ()) - { - band = GetRuBand (txVector, staId); - channelWidth = HeRu::GetBandwidth (txVector.GetRu (staId).ruType); - } - else - { - band = GetBand (channelWidth); - } - PhyEntity::SnrPer snrPer = m_interference.CalculatePayloadSnrPer (event, channelWidth, band, staId, std::make_pair (relativeMpduStart, relativeMpduStart + mpduDuration)); - - WifiMode mode = event->GetTxVector ().GetMode (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)); - - // There are two error checks: PER and receive error model check. - // PER check models is typical for Wi-Fi and is based on signal modulation; - // Receive error model is optional, if we have an error model and - // it indicates that the packet is corrupt, drop the packet. - SignalNoiseDbm signalNoise; - signalNoise.signal = WToDbm (event->GetRxPowerW (band)); - signalNoise.noise = WToDbm (event->GetRxPowerW (band) / snrPer.snr); - if (m_random->GetValue () > snrPer.per && - !(m_postReceptionErrorModel && m_postReceptionErrorModel->IsCorrupt (psdu->GetPacket ()->Copy ()))) - { - NS_LOG_DEBUG ("Reception succeeded: " << psdu); - return std::make_pair (true, signalNoise); - } - else - { - NS_LOG_DEBUG ("Reception failed: " << psdu); - return std::make_pair (false, signalNoise); - } -} - -WifiSpectrumBand -WifiPhy::GetRuBand (WifiTxVector txVector, uint16_t staId) const -{ - NS_ASSERT (txVector.IsMu ()); - WifiSpectrumBand band; - HeRu::RuSpec ru = txVector.GetRu (staId); - uint16_t channelWidth = txVector.GetChannelWidth (); - NS_ASSERT (channelWidth <= GetChannelWidth ()); - HeRu::SubcarrierGroup group = HeRu::GetSubcarrierGroup (channelWidth, ru.ruType, ru.index); - HeRu::SubcarrierRange range = std::make_pair (group.front ().first, group.back ().second); - band = ConvertHeRuSubcarriers (channelWidth, range); - return band; -} - -WifiSpectrumBand -WifiPhy::GetNonOfdmaBand (WifiTxVector txVector, uint16_t staId) const -{ - NS_ASSERT (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB); - uint16_t channelWidth = txVector.GetChannelWidth (); - NS_ASSERT (channelWidth <= GetChannelWidth ()); - - HeRu::RuSpec ru = txVector.GetRu (staId); - uint16_t ruWidth = HeRu::GetBandwidth (ru.ruType); - uint16_t nonOfdmaWidth = ruWidth < 20 ? 20 : ruWidth; - - // Find the RU that encompasses the non-OFDMA part of the HE TB PPDU for the STA-ID - HeRu::RuSpec nonOfdmaRu = HeRu::FindOverlappingRu (channelWidth, ru, HeRu::GetRuType (nonOfdmaWidth)); - - HeRu::SubcarrierGroup groupPreamble = HeRu::GetSubcarrierGroup (channelWidth, nonOfdmaRu.ruType, nonOfdmaRu.index); - HeRu::SubcarrierRange range = std::make_pair (groupPreamble.front ().first, groupPreamble.back ().second); - return ConvertHeRuSubcarriers (channelWidth, range); -} - WifiSpectrumBand WifiPhy::ConvertHeRuSubcarriers (uint16_t channelWidth, HeRu::SubcarrierRange range) const { @@ -2816,23 +2240,11 @@ void WifiPhy::ResetReceive (Ptr event) { NS_LOG_FUNCTION (this << *event); - Ptr ppdu = event->GetPpdu (); - if (ppdu->GetType () != WIFI_PPDU_TYPE_UL_MU) - { - NS_ASSERT (event->GetEndTime () == Simulator::Now ()); - } NS_ASSERT (!IsStateRx ()); - NS_ASSERT (m_endRxEvents.size () == 1 && m_endRxEvents.front ().IsExpired ()); - m_endRxEvents.clear (); m_interference.NotifyRxEnd (Simulator::Now ()); m_currentEvent = 0; m_currentPreambleEvents.clear (); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - beginOfdmaPayloadRxEvent.second.Cancel (); - } - m_beginOfdmaPayloadRxEvents.clear (); - MaybeCcaBusyDuration (GetMeasurementChannelWidth (ppdu)); + MaybeCcaBusyDuration (GetMeasurementChannelWidth (event->GetPpdu ())); } void @@ -3054,33 +2466,14 @@ WifiPhy::AbortCurrentReception (WifiPhyRxfailureReason reason) NS_LOG_FUNCTION (this << reason); if (reason != OBSS_PD_CCA_RESET || m_currentEvent) //Otherwise abort has already been called just before with FILTERED reason { - for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents) + for (auto & phyEntity : m_phyEntities) { - if (endPreambleDetectionEvent.IsRunning ()) - { - endPreambleDetectionEvent.Cancel (); - } + phyEntity.second->CancelAllEvents (); } - m_endPreambleDetectionEvents.clear (); if (m_endPhyRxEvent.IsRunning ()) { m_endPhyRxEvent.Cancel (); } - for (auto & endMpduEvent : m_endOfMpduEvents) - { - endMpduEvent.Cancel (); - } - m_endOfMpduEvents.clear (); - for (auto & endRxEvent : m_endRxEvents) - { - endRxEvent.Cancel (); - } - m_endRxEvents.clear (); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - beginOfdmaPayloadRxEvent.second.Cancel (); - } - m_beginOfdmaPayloadRxEvents.clear (); m_interference.NotifyRxEnd (Simulator::Now ()); if (!m_currentEvent) { @@ -3158,26 +2551,6 @@ WifiPhy::GetTxPowerForTransmission (WifiTxVector txVector, uint16_t staId /* = S return txPowerDbm; } -void -WifiPhy::StartRx (Ptr event) -{ - //TODO: To move to StartReceivePreamble (and include the logic therein) - WifiModulationClass modulation = event->GetTxVector ().GetModulationClass (); - auto it = m_phyEntities.find (modulation); - if (it != m_phyEntities.end ()) - { - it->second->StartReceiveField (WIFI_PPDU_FIELD_PREAMBLE, event); - } - else - { - NS_LOG_DEBUG ("Unsupported modulation received (" << modulation << "), consider as noise"); - if (event->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ())) - { - MaybeCcaBusyDuration (GetMeasurementChannelWidth (nullptr)); - } - } -} - Ptr WifiPhy::GetAddressedPsduInPpdu (Ptr ppdu) const { @@ -3188,24 +2561,8 @@ WifiPhy::GetAddressedPsduInPpdu (Ptr ppdu) const uint16_t WifiPhy::GetStaId (const Ptr ppdu) const { - uint16_t staId = SU_STA_ID; - if (ppdu->GetType () == WIFI_PPDU_TYPE_UL_MU) - { - staId = ppdu->GetStaId (); - } - else if (ppdu->GetType () == WIFI_PPDU_TYPE_DL_MU) - { - Ptr device = DynamicCast (GetDevice ()); - if (device) - { - Ptr mac = DynamicCast (device->GetMac ()); - if (mac && mac->IsAssociated ()) - { - return mac->GetAssociationId (); - } - } - } - return staId; + //TODO: wrapper. See if still needed + return GetPhyEntity (ppdu->GetModulation ())->GetStaId (ppdu); } uint16_t @@ -3243,20 +2600,6 @@ WifiPhy::GetBand (uint16_t /*bandWidth*/, uint8_t /*bandIndex*/) return band; } -uint16_t -WifiPhy::ConvertHeTbPpduDurationToLSigLength (Time ppduDuration, WifiPhyBand band) -{ - return DynamicCast (GetStaticPhyEntity (WIFI_MOD_CLASS_HE))->ConvertHeTbPpduDurationToLSigLength (ppduDuration, band); -} - -Time -WifiPhy::ConvertLSigLengthToHeTbPpduDuration (uint16_t length, WifiTxVector txVector, WifiPhyBand band) -{ - NS_ASSERT (txVector.GetModulationClass () == WIFI_MOD_CLASS_HE); - auto hePhy = DynamicCast (GetStaticPhyEntity (txVector.GetModulationClass ())); - return (hePhy ? hePhy->ConvertLSigLengthToHeTbPpduDuration (length, txVector, band) : NanoSeconds (0)); -} - int64_t WifiPhy::AssignStreams (int64_t stream) { diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index e1753499d..5c1cce501 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -121,30 +121,11 @@ public: * * \param ppdu the arriving PPDU * \param rxPowersW the receive power in W per band + * \param rxDuration the duration of the PPDU + * \param psdFlag the flag indicating the type of Tx PSD to build */ - void StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxPowersW); - - /** - * Start receiving the PSDU (i.e. the first symbol of the PSDU has arrived). - * - * \param event the event holding incoming PPDU's information - */ - void StartReceivePayload (Ptr event); - - /** - * Start receiving the PSDU (i.e. the first symbol of the PSDU has arrived) of an UL-OFDMA transmission. - * This function is called upon the RX event corresponding to the OFDMA part of the UL MU PPDU. - * - * \param event the event holding incoming OFDMA part of the PPDU's information - */ - void StartReceiveOfdmaPayload (Ptr event); - - /** - * The last symbol of the PPDU has arrived. - * - * \param event the event holding incoming PPDU's information - */ - void EndReceive (Ptr event); + void StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxPowersW, + Time rxDuration, TxPsdFlag psdFlag = PSD_NON_HE_TB); /** * Reset PHY at the end of the packet under reception after it has failed the PHY header. @@ -251,23 +232,6 @@ public: */ Time GetLastRxEndTime (void) const; - /** - * \param ppduDuration the duration of the HE TB PPDU - * \param band the frequency band being used - * - * \return the L-SIG length value corresponding to that HE TB PPDU duration. - */ - static uint16_t ConvertHeTbPpduDurationToLSigLength (Time ppduDuration, WifiPhyBand band); - - /** - * \param length the L-SIG length value - * \param txVector the TXVECTOR used for the transmission of this HE TB PPDU - * \param band the frequency band being used - * - * \return the duration of the HE TB PPDU corresponding to that L-SIG length value. - */ - static Time ConvertLSigLengthToHeTbPpduDuration (uint16_t length, WifiTxVector txVector, WifiPhyBand band); - /** * \param size the number of bytes in the packet to send * \param txVector the TXVECTOR used for the transmission of this packet @@ -1042,24 +1006,6 @@ public: */ void NotifyChannelAccessRequested (void); - /** - * Get the RU band used to transmit a PSDU to a given STA in a HE MU PPDU - * - * \param txVector the TXVECTOR used for the transmission - * \param staId the STA-ID of the recipient - * - * \return the RU band used to transmit a PSDU to a given STA in a HE MU PPDU - */ - WifiSpectrumBand GetRuBand (WifiTxVector txVector, uint16_t staId) const; - /** - * Get the band used to transmit the non-OFDMA part of an HE TB PPDU. - * - * \param txVector the TXVECTOR used for the transmission - * \param staId the STA-ID of the station taking part of the UL MU - * - * \return the spectrum band used to transmit the non-OFDMA part of an HE TB PPDU - */ - WifiSpectrumBand GetNonOfdmaBand (WifiTxVector txVector, uint16_t staId) const; /** * \param channelWidth the total channel width (MHz) used for the OFDMA transmission @@ -1141,6 +1087,7 @@ protected: * \param channelWidth the channel width in MHz used for RSSI measurement */ void SwitchMaybeToCcaBusy (uint16_t channelWidth); + /** * Return the STA ID that has been assigned to the station this PHY belongs to. * This is typically called for MU PPDUs, in order to pick the correct PSDU. @@ -1149,6 +1096,7 @@ protected: * \return the STA ID */ 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 @@ -1202,11 +1150,6 @@ protected: EventId m_endPhyRxEvent; //!< the end of PHY receive event EventId m_endTxEvent; //!< the end of transmit event - std::vector m_endRxEvents; //!< the end of receive events (only one unless UL MU reception) - std::vector m_endPreambleDetectionEvents; //!< the end of preamble detection events - - std::map m_beginOfdmaPayloadRxEvents; //!< the beginning of the OFDMA payload reception events (indexed by STA-ID) - Ptr m_currentEvent; //!< Hold the current event std::map , Ptr > m_currentPreambleEvents; //!< store event associated to a PPDU (that has a unique ID and preamble combination) whose preamble is being received @@ -1345,45 +1288,6 @@ private: */ void MaybeCcaBusyDuration (uint16_t channelWidth); - /** - * Starting receiving the PPDU after having detected the medium is idle or after a reception switch. - * - * \param event the event holding incoming PPDU's information - */ - void StartRx (Ptr event); - /** - * Get the reception status for the provided MPDU and notify. - * - * \param psdu the arriving MPDU formatted as a PSDU - * \param event the event holding incoming PPDU's information - * \param staId the station ID of the PSDU (only used for MU) - * \param relativeMpduStart the relative start time of the MPDU within the A-MPDU. 0 for normal MPDUs - * \param mpduDuration the duration of the MPDU - * - * \return information on MPDU reception: status, signal power (dBm), and noise power (in dBm) - */ - std::pair GetReceptionStatus (Ptr psdu, - Ptr event, uint16_t staId, - Time relativeMpduStart, - Time mpduDuration); - /** - * The last symbol of an MPDU in an A-MPDU has arrived. - * - * \param event the event holding incoming PPDU's information - * \param psdu the arriving MPDU formatted as a PSDU containing a normal MPDU - * \param mpduIndex the index of the MPDU within the A-MPDU - * \param relativeMpduStart the relative start time of the MPDU within the A-MPDU. - * \param mpduDuration the duration of the MPDU - */ - void EndOfMpdu (Ptr event, Ptr psdu, size_t mpduIndex, Time relativeStart, Time mpduDuration); - - /** - * Schedule end of MPDUs events. - * - * \param event the event holding incoming PPDU's information - */ - void ScheduleEndOfMpdus (Ptr event); - /** * Get the PSDU addressed to that PHY in a PPDU (useful for MU PPDU). * @@ -1392,17 +1296,6 @@ private: */ Ptr GetAddressedPsduInPpdu (Ptr ppdu) const; - /** - * Drop the PPDU and the corresponding preamble detection event, but keep CCA busy - * state after the completion of the currently processed event. - * - * \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, uint16_t measurementChannelWidth); - /** * The trace source fired when a packet begins the transmission process on * the medium. @@ -1567,16 +1460,6 @@ private: Ptr m_postReceptionErrorModel; //!< Error model for receive packet events Time m_timeLastPreambleDetected; //!< Record the time the last preamble was detected - std::vector m_endOfMpduEvents; //!< the end of MPDU events (only used for A-MPDUs) - - /** - * A pair of a UID and STA_ID - */ - typedef std::pair UidStaIdPair; - - std::map > m_statusPerMpduMap; //!< Map of the current reception status per MPDU that is filled in as long as MPDUs are being processed by the PHY in case of an A-MPDU - std::map m_signalNoiseMap; //!< Map of the latest signal power and noise power in dBm (noise power includes the noise figure) - Callback m_capabilitiesChangedCallback; //!< Callback when PHY capabilities changed }; diff --git a/src/wifi/model/yans-wifi-channel.cc b/src/wifi/model/yans-wifi-channel.cc index 41d711fd2..ecb841d41 100644 --- a/src/wifi/model/yans-wifi-channel.cc +++ b/src/wifi/model/yans-wifi-channel.cc @@ -135,7 +135,7 @@ YansWifiChannel::Receive (Ptr phy, Ptr ppdu, double rxPow } RxPowerWattPerChannelBand rxPowerW; rxPowerW.insert ({std::make_pair (0, 0), (DbmToW (rxPowerDbm + phy->GetRxGain ()))}); //dummy band for YANS - phy->StartReceivePreamble (ppdu, rxPowerW); + phy->StartReceivePreamble (ppdu, rxPowerW, ppdu->GetTxDuration ()); } std::size_t diff --git a/src/wifi/test/wifi-phy-ofdma-test.cc b/src/wifi/test/wifi-phy-ofdma-test.cc index 836104a7a..1b30e8d4a 100644 --- a/src/wifi/test/wifi-phy-ofdma-test.cc +++ b/src/wifi/test/wifi-phy-ofdma-test.cc @@ -56,6 +56,58 @@ 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) +/** + * HE PHY slightly modified so as to return a given + * STA-ID in case of DL MU for OfdmaSpectrumWifiPhy. + */ +class OfdmaTestHePhy : public HePhy +{ +public: + /** + * Constructor + * + * \param staId the ID of the STA to which this PHY belongs to + */ + OfdmaTestHePhy (uint16_t staId); + virtual ~OfdmaTestHePhy (); + + /** + * Return the STA ID that has been assigned to the station this PHY belongs to. + * This is typically called for MU PPDUs, in order to pick the correct PSDU. + * + * \param ppdu the PPDU for which the STA ID is requested + * \return the STA ID + */ + uint16_t GetStaId (const Ptr ppdu) const override; + + +private: + uint16_t m_staId; ///< ID of the STA to which this PHY belongs to +}; //class OfdmaTestHePhy + +OfdmaTestHePhy::OfdmaTestHePhy (uint16_t staId) + : HePhy (), + m_staId (staId) +{ +} + +OfdmaTestHePhy::~OfdmaTestHePhy () +{ +} + +uint16_t +OfdmaTestHePhy::GetStaId (const Ptr ppdu) const +{ + if (ppdu->GetType () == WIFI_PPDU_TYPE_DL_MU) + { + return m_staId; + } + return HePhy::GetStaId (ppdu); +} + +/** + * SpectrumWifiPhy used for testing OFDMA. + */ class OfdmaSpectrumWifiPhy : public SpectrumWifiPhy { public: @@ -72,6 +124,9 @@ public: OfdmaSpectrumWifiPhy (uint16_t staId); virtual ~OfdmaSpectrumWifiPhy (); + // Inherited + virtual void DoInitialize (void) override; + using WifiPhy::Reset; /** @@ -125,13 +180,15 @@ public: */ Time GetEnergyDuration (double energyW, WifiSpectrumBand band); -private: - // Inherited - uint16_t GetStaId (const Ptr ppdu) const override; + /** + * \return a const pointer to the HE PHY instance + */ + Ptr GetHePhy (void) const; +private: uint16_t m_staId; ///< ID of the STA to which this PHY belongs to TracedCallback m_phyTxPpduUidTrace; //!< Callback providing UID of the PPDU that is about to be transmitted -}; +}; //class OfdmaSpectrumWifiPhy TypeId OfdmaSpectrumWifiPhy::GetTypeId (void) @@ -157,14 +214,14 @@ OfdmaSpectrumWifiPhy::~OfdmaSpectrumWifiPhy() { } -uint16_t -OfdmaSpectrumWifiPhy::GetStaId (const Ptr ppdu) const +void +OfdmaSpectrumWifiPhy::DoInitialize (void) { - if (ppdu->GetType () == WIFI_PPDU_TYPE_DL_MU) - { - return m_staId; - } - return SpectrumWifiPhy::GetStaId (ppdu); + //Replace HE PHY instance with test instance + Ptr hePhy = Create (m_staId); + hePhy->SetOwner (this); + m_phyEntities[WIFI_MOD_CLASS_HE] = hePhy; + SpectrumWifiPhy::DoInitialize (); } void @@ -213,6 +270,12 @@ OfdmaSpectrumWifiPhy::GetEnergyDuration (double energyW, WifiSpectrumBand band) return m_interference.GetEnergyDuration (energyW, band); } +Ptr +OfdmaSpectrumWifiPhy::GetHePhy (void) const +{ + return DynamicCast (GetPhyEntity (WIFI_MOD_CLASS_HE)); +} + /** * \ingroup wifi-test * \ingroup tests @@ -1152,8 +1215,8 @@ TestUlOfdmaPpduUid::SendTbPpdu (void) m_phySta1->GetPhyBand (), rxStaId2); Time txDuration = std::max (txDuration1, txDuration2); - txVector1.SetLength (m_phySta1->ConvertHeTbPpduDurationToLSigLength (txDuration, m_phySta1->GetPhyBand ())); - txVector2.SetLength (m_phySta2->ConvertHeTbPpduDurationToLSigLength (txDuration, m_phySta2->GetPhyBand ())); + txVector1.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, m_phySta1->GetPhyBand ())); + txVector2.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, m_phySta2->GetPhyBand ())); m_phySta1->Send (psdus1, txVector1); m_phySta2->Send (psdus2, txVector2); @@ -1390,7 +1453,7 @@ TestMultipleHeTbPreambles::RxHeTbPpdu (uint64_t uid, uint16_t staId, double txPo m_phy->StartRx (rxParams); //Schedule OFDMA part - WifiSpectrumBand band = m_phy->GetRuBand (txVector, staId); + WifiSpectrumBand band = m_phy->GetHePhy ()->GetRuBand (txVector, staId); Ptr rxPsdOfdma = WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity (DEFAULT_FREQUENCY, DEFAULT_CHANNEL_WIDTH, txPowerWatts, DEFAULT_GUARD_WIDTH, band); Ptr rxParamsOfdma = Create (); rxParamsOfdma->psd = rxPsd; @@ -1861,7 +1924,7 @@ TestUlOfdmaPhyTransmission::SendHeTbPpdu (uint16_t txStaId, std::size_t index, s } Time txDuration = phy->CalculateTxDuration (psdu->GetSize (), txVector, phy->GetPhyBand (), txStaId); - txVector.SetLength (phy->ConvertHeTbPpduDurationToLSigLength (txDuration, phy->GetPhyBand ())); + txVector.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, phy->GetPhyBand ())); phy->SetPpduUid (uid); phy->Send (psdus, txVector); @@ -2182,10 +2245,12 @@ TestUlOfdmaPhyTransmission::SchedulePowerMeasurementChecks (Time delay, double r Time nonOfdmaDuration = m_phyAp->CalculateNonOfdmaDurationForHeTb (txVectorSta2); NS_ASSERT (nonOfdmaDuration == m_phyAp->CalculateNonOfdmaDurationForHeTb (txVectorSta1)); + Ptr hePhy = m_phyAp->GetHePhy (); + std::vector rxPowerNonOfdma { rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2 }; - std::vector nonOfdmaBand { m_phyAp->GetNonOfdmaBand (txVectorSta1, 1), m_phyAp->GetNonOfdmaBand (txVectorSta2, 2) }; + std::vector nonOfdmaBand { hePhy->GetNonOfdmaBand (txVectorSta1, 1), hePhy->GetNonOfdmaBand (txVectorSta2, 2) }; std::vector rxPowerOfdma { rxPowerOfdmaRu1, rxPowerOfdmaRu2 }; - std::vector ofdmaBand { m_phyAp->GetRuBand (txVectorSta1, 1), m_phyAp->GetRuBand (txVectorSta2, 2) }; + std::vector ofdmaBand { hePhy->GetRuBand (txVectorSta1, 1), hePhy->GetRuBand (txVectorSta2, 2) }; for (uint8_t i = 0; i < 2; ++i) { @@ -2824,7 +2889,7 @@ TestPhyPaddingExclusion::SendHeTbPpdu (uint16_t txStaId, std::size_t index, std: phy = m_phySta2; } - txVector.SetLength (phy->ConvertHeTbPpduDurationToLSigLength (txDuration, phy->GetPhyBand ())); + txVector.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, phy->GetPhyBand ())); phy->SetPpduUid (0); phy->Send (psdus, txVector); @@ -3200,7 +3265,7 @@ TestUlOfdmaPowerControl::SendMuBar (std::vector staIds) //Build MU-BAR trigger frame CtrlTriggerHeader muBar; muBar.SetType (MU_BAR_TRIGGER); - muBar.SetUlLength (WifiPhy::ConvertHeTbPpduDurationToLSigLength (MicroSeconds (120), WIFI_PHY_BAND_5GHZ)); + muBar.SetUlLength (HePhy::ConvertHeTbPpduDurationToLSigLength (MicroSeconds (128), WIFI_PHY_BAND_5GHZ)); muBar.SetMoreTF (true); muBar.SetCsRequired (true); muBar.SetUlBandwidth (DEFAULT_CHANNEL_WIDTH);