diff --git a/src/wifi/model/spectrum-wifi-phy.cc b/src/wifi/model/spectrum-wifi-phy.cc index 3b7ebe024..e012e8683 100644 --- a/src/wifi/model/spectrum-wifi-phy.cc +++ b/src/wifi/model/spectrum-wifi-phy.cc @@ -28,11 +28,14 @@ #include "ns3/boolean.h" #include "ns3/net-device.h" #include "ns3/node.h" +#include "ns3/simulator.h" #include "spectrum-wifi-phy.h" #include "wifi-spectrum-phy-interface.h" #include "wifi-utils.h" #include "wifi-ppdu.h" #include "wifi-psdu.h" +#include "ap-wifi-mac.h" +#include "wifi-net-device.h" namespace ns3 { @@ -356,7 +359,26 @@ SpectrumWifiPhy::StartRx (Ptr rxParams) NS_LOG_INFO ("Received Wi-Fi signal"); Ptr ppdu = Copy (wifiRxParams->ppdu); - StartReceivePreamble (ppdu, rxPowerW); + if (ppdu->GetTxVector ().GetPreambleType () == WIFI_PREAMBLE_HE_TB + && wifiRxParams->txPsdFlag == PSD_HE_TB_OFDMA_PORTION + && m_currentHeTbPpduUid == ppdu->GetUid ()) + { + Ptr device = DynamicCast (GetDevice ()); + bool isAp = (DynamicCast (device->GetMac ()) != 0); + if (isAp) + { + StartReceiveOfdmaPayload (ppdu, rxPowerW); + } + else + { + NS_LOG_INFO ("Ignore UL-OFDMA since device is not AP"); + m_currentPreambleEvents.clear (); + } + } + else + { + StartReceivePreamble (ppdu, rxPowerW); + } } Ptr @@ -382,7 +404,7 @@ SpectrumWifiPhy::CreateWifiSpectrumPhyInterface (Ptr device) } Ptr -SpectrumWifiPhy::GetTxPowerSpectralDensity (double txPowerW, Ptr ppdu) +SpectrumWifiPhy::GetTxPowerSpectralDensity (double txPowerW, Ptr ppdu, bool isOfdma) { WifiTxVector txVector = ppdu->GetTxVector (); uint16_t centerFrequency = GetCenterFrequencyForChannelWidth (txVector); @@ -407,7 +429,7 @@ SpectrumWifiPhy::GetTxPowerSpectralDensity (double txPowerW, Ptr ppdu) m_txMaskInnerBandMinimumRejection, m_txMaskOuterBandMinimumRejection, m_txMaskOuterBandMaximumRejection); break; case WIFI_MOD_CLASS_HE: - if (ppdu->IsUlMu ()) + if (isOfdma) { WifiSpectrumBand band = GetRuBand (txVector, GetStaId (ppdu)); v = WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity (centerFrequency, channelWidth, txPowerW, GetGuardBandwidth (channelWidth), band); @@ -448,16 +470,64 @@ SpectrumWifiPhy::StartTx (Ptr ppdu) double txPowerDbm = GetTxPowerForTransmission (txVector) + GetTxGain (); NS_LOG_DEBUG ("Start transmission: signal power before antenna gain=" << txPowerDbm << "dBm"); double txPowerWatts = DbmToW (txPowerDbm); - Ptr txPowerSpectrum = GetTxPowerSpectralDensity (txPowerWatts, ppdu); - Ptr txParams = Create (); - txParams->duration = ppdu->GetTxDuration (); - txParams->psd = txPowerSpectrum; NS_ASSERT_MSG (m_wifiSpectrumPhyInterface, "SpectrumPhy() is not set; maybe forgot to call CreateWifiSpectrumPhyInterface?"); + if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB) + { + //non-OFDMA part + Time nonOfdmaDuration = CalculatePhyPreambleAndHeaderDuration (txVector); //consider that HE-STF and HE-LTFs are also part of the non-OFDMA part + Ptr txPowerSpectrum = GetTxPowerSpectralDensity (txPowerWatts, ppdu); + Ptr txParams = Create (); + txParams->duration = nonOfdmaDuration; + txParams->psd = txPowerSpectrum; + txParams->txPhy = m_wifiSpectrumPhyInterface->GetObject (); + txParams->txAntenna = m_antenna; + txParams->ppdu = ppdu; + txParams->txPsdFlag = PSD_HE_TB_NON_OFDMA_PORTION; + NS_LOG_DEBUG ("Starting non-OFDMA transmission with power " << WToDbm (txPowerWatts) << " dBm on channel " << +GetChannelNumber () << " for " << txParams->duration.GetMicroSeconds () << " us"); + NS_LOG_DEBUG ("Starting non-OFDMA transmission with integrated spectrum power " << WToDbm (Integral (*txPowerSpectrum)) << " dBm; spectrum model Uid: " << txPowerSpectrum->GetSpectrumModel ()->GetUid ()); + Transmit (txParams); + + //OFDMA part + Simulator::Schedule (nonOfdmaDuration, &SpectrumWifiPhy::StartOfdmaTx, this, ppdu, txPowerWatts); + } + else + { + Ptr txPowerSpectrum = GetTxPowerSpectralDensity (txPowerWatts, ppdu); + Ptr txParams = Create (); + txParams->duration = ppdu->GetTxDuration (); + txParams->psd = txPowerSpectrum; + txParams->txPhy = m_wifiSpectrumPhyInterface->GetObject (); + txParams->txAntenna = m_antenna; + txParams->ppdu = ppdu; + NS_LOG_DEBUG ("Starting transmission with power " << WToDbm (txPowerWatts) << " dBm on channel " << +GetChannelNumber () << " for " << txParams->duration.GetMicroSeconds () << " us"); + NS_LOG_DEBUG ("Starting transmission with integrated spectrum power " << WToDbm (Integral (*txPowerSpectrum)) << " dBm; spectrum model Uid: " << txPowerSpectrum->GetSpectrumModel ()->GetUid ()); + Transmit (txParams); + } +} + +void +SpectrumWifiPhy::StartOfdmaTx (Ptr ppdu, double txPowerWatts) +{ + NS_LOG_FUNCTION (this << ppdu << txPowerWatts); + NS_ASSERT (ppdu->IsUlMu ()); + Ptr txPowerSpectrum = GetTxPowerSpectralDensity (txPowerWatts, ppdu, true); + Ptr txParams = Create (); + WifiTxVector txVector = ppdu->GetTxVector (); + txParams->duration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector); + txParams->psd = txPowerSpectrum; txParams->txPhy = m_wifiSpectrumPhyInterface->GetObject (); txParams->txAntenna = m_antenna; txParams->ppdu = ppdu; - NS_LOG_DEBUG ("Starting transmission with power " << WToDbm (txPowerWatts) << " dBm on channel " << +GetChannelNumber ()); - NS_LOG_DEBUG ("Starting transmission with integrated spectrum power " << WToDbm (Integral (*txPowerSpectrum)) << " dBm; spectrum model Uid: " << txPowerSpectrum->GetSpectrumModel ()->GetUid ()); + txParams->txPsdFlag = PSD_HE_TB_OFDMA_PORTION; + NS_LOG_DEBUG ("Starting OFDMA transmission with power " << WToDbm (txPowerWatts) << " dBm on channel " << +GetChannelNumber () << " for " << txParams->duration.GetMicroSeconds () << " us"); + NS_LOG_DEBUG ("Starting OFDMA transmission with integrated spectrum power " << WToDbm (Integral (*txPowerSpectrum)) << " dBm; spectrum model Uid: " << txPowerSpectrum->GetSpectrumModel ()->GetUid ()); + Transmit (txParams); +} + +void +SpectrumWifiPhy::Transmit (Ptr txParams) +{ + NS_LOG_FUNCTION (this << txParams); m_channel->StartTx (txParams); } diff --git a/src/wifi/model/spectrum-wifi-phy.h b/src/wifi/model/spectrum-wifi-phy.h index b48fcce37..910c20df4 100644 --- a/src/wifi/model/spectrum-wifi-phy.h +++ b/src/wifi/model/spectrum-wifi-phy.h @@ -181,12 +181,13 @@ private: /** * \param txPowerW power in W to spread across the bands * \param ppdu the PPDU that will be transmitted + * \param isOfdma flag whether the constructed Tx PSD is for the OFDMA part of an HE TB PPDU * \return Pointer to SpectrumValue * * This is a helper function to create the right TX PSD corresponding * to the standard in use. */ - Ptr GetTxPowerSpectralDensity (double txPowerW, Ptr ppdu); + Ptr GetTxPowerSpectralDensity (double txPowerW, Ptr ppdu, bool isOfdma = false); /** * \param channelWidth the total channel width (MHz) used for the OFDMA transmission @@ -197,6 +198,21 @@ private: */ WifiSpectrumBand ConvertHeRuSubcarriers (uint16_t channelWidth, HeRu::SubcarrierRange range) const; + /** + * This function is called to send the OFDMA part of a PPDU. + * + * \param ppdu the PPDU to send + * \param txPowerWatts the transmit power in watts + */ + void StartOfdmaTx (Ptr ppdu, double txPowerWatts); + + /** + * This function is sending the signal to the Spectrum channel + * + * \param txParams the parameters to be provided to the Spectrum channel + */ + void Transmit (Ptr txParams); + /** * Perform run-time spectrum model change */ diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index deddacb30..cb00d7692 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -512,6 +512,7 @@ WifiPhy::WifiPhy () m_endPhyRxEvent (), m_endTxEvent (), m_previouslyRxPpduUid (UINT64_MAX), + m_currentHeTbPpduUid (UINT64_MAX), m_standard (WIFI_PHY_STANDARD_UNSPECIFIED), m_band (WIFI_PHY_BAND_UNSPECIFIED), m_isConstructed (false), @@ -2988,7 +2989,7 @@ WifiPhy::StartReceiveHeader (Ptr event) double snr = snrPer.snr; NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr)); - Time headerPayloadDuration = m_currentEvent->GetDuration () - (Simulator::Now () - m_currentEvent->GetStartTime ()); //startOfPreambleDuration; + Time headerPayloadDuration = m_currentEvent->GetStartTime () + m_currentEvent->GetPpdu ()->GetTxDuration () - Simulator::Now (); if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (m_currentEvent->GetRxPowerW (band), snr, m_channelWidth))) { @@ -3150,7 +3151,7 @@ WifiPhy::StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxP 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); + event = m_interference.Add (ppdu, txVector, CalculatePhyPreambleAndHeaderDuration (txVector), rxPowersW); //the OFDMA part of the transmission will be added later on m_currentPreambleEvents.insert ({std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()), event}); } } @@ -3293,6 +3294,24 @@ WifiPhy::MaybeCcaBusyDuration () } } +void +WifiPhy::StartReceiveOfdmaPayload (Ptr ppdu, RxPowerWattPerChannelBand rxPowersW) +{ + //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 payloadDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector); + Ptr event = m_interference.Add (ppdu, txVector, payloadDuration, rxPowersW); + + NS_ASSERT (m_endRxEvent.IsExpired ()); + m_endRxEvent = Simulator::Schedule (payloadDuration, &WifiPhy::EndReceive, this, event); +} + void WifiPhy::StartReceivePayload (Ptr event) { @@ -3317,7 +3336,7 @@ WifiPhy::StartReceivePayload (Ptr event) canReceivePayload = true; } WifiTxVector txVector = event->GetTxVector (); - Time payloadDuration = event->GetEndTime () - event->GetStartTime () - CalculatePhyPreambleAndHeaderDuration (txVector); + Time payloadDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector); bool success = false; if (canReceivePayload) //PHY reception succeeded { @@ -3357,9 +3376,17 @@ WifiPhy::StartReceivePayload (Ptr event) } 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 - m_endRxEvent = Simulator::Schedule (payloadDuration, &WifiPhy::EndReceive, this, event); success = true; NS_LOG_DEBUG ("Receiving PSDU"); + if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB) + { + m_currentHeTbPpduUid = ppdu->GetUid (); + //EndReceive is scheduled by StartReceiveOfdmaPayload + } + else + { + m_endRxEvent = Simulator::Schedule (payloadDuration, &WifiPhy::EndReceive, this, event); + } } else //mode is not allowed { diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 7a5120ac9..45c7569ed 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -211,7 +211,7 @@ public: * Start receiving the PHY preamble of a PPDU (i.e. the first bit of the preamble has arrived). * * \param ppdu the arriving PPDU - * \param rxPowersW the receive power in W per 20 MHz channel band + * \param rxPowersW the receive power in W per band */ void StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxPowersW); @@ -236,6 +236,15 @@ public: */ 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 ppdu the arriving PPDU + * \param rxPowersW the receive power in W per band + */ + void StartReceiveOfdmaPayload (Ptr ppdu, RxPowerWattPerChannelBand rxPowersW); + /** * The last symbol of the PPDU has arrived. * @@ -1864,6 +1873,8 @@ protected: uint64_t m_previouslyRxPpduUid; //!< UID of the previously received PPDU (reused by HE TB PPDUs), reset to UINT64_MAX upon transmission + uint64_t m_currentHeTbPpduUid; //!< UID of the HE TB PPDU being received + static uint64_t m_globalPpduUid; //!< Global counter of the PPDU UID