wifi: Split non-OFDMA and OFDMA in two TX events for HE TB PPDUs

This commit is contained in:
Sébastien Deronne
2019-07-25 09:49:48 +02:00
parent cbb97e5baf
commit a3b1286856
4 changed files with 139 additions and 15 deletions

View File

@@ -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<SpectrumSignalParameters> rxParams)
NS_LOG_INFO ("Received Wi-Fi signal");
Ptr<WifiPpdu> 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<WifiNetDevice> device = DynamicCast<WifiNetDevice> (GetDevice ());
bool isAp = (DynamicCast<ApWifiMac> (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<AntennaModel>
@@ -382,7 +404,7 @@ SpectrumWifiPhy::CreateWifiSpectrumPhyInterface (Ptr<NetDevice> device)
}
Ptr<SpectrumValue>
SpectrumWifiPhy::GetTxPowerSpectralDensity (double txPowerW, Ptr<WifiPpdu> ppdu)
SpectrumWifiPhy::GetTxPowerSpectralDensity (double txPowerW, Ptr<WifiPpdu> ppdu, bool isOfdma)
{
WifiTxVector txVector = ppdu->GetTxVector ();
uint16_t centerFrequency = GetCenterFrequencyForChannelWidth (txVector);
@@ -407,7 +429,7 @@ SpectrumWifiPhy::GetTxPowerSpectralDensity (double txPowerW, Ptr<WifiPpdu> 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<WifiPpdu> ppdu)
double txPowerDbm = GetTxPowerForTransmission (txVector) + GetTxGain ();
NS_LOG_DEBUG ("Start transmission: signal power before antenna gain=" << txPowerDbm << "dBm");
double txPowerWatts = DbmToW (txPowerDbm);
Ptr<SpectrumValue> txPowerSpectrum = GetTxPowerSpectralDensity (txPowerWatts, ppdu);
Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();
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<SpectrumValue> txPowerSpectrum = GetTxPowerSpectralDensity (txPowerWatts, ppdu);
Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();
txParams->duration = nonOfdmaDuration;
txParams->psd = txPowerSpectrum;
txParams->txPhy = m_wifiSpectrumPhyInterface->GetObject<SpectrumPhy> ();
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<SpectrumValue> txPowerSpectrum = GetTxPowerSpectralDensity (txPowerWatts, ppdu);
Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();
txParams->duration = ppdu->GetTxDuration ();
txParams->psd = txPowerSpectrum;
txParams->txPhy = m_wifiSpectrumPhyInterface->GetObject<SpectrumPhy> ();
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<WifiPpdu> ppdu, double txPowerWatts)
{
NS_LOG_FUNCTION (this << ppdu << txPowerWatts);
NS_ASSERT (ppdu->IsUlMu ());
Ptr<SpectrumValue> txPowerSpectrum = GetTxPowerSpectralDensity (txPowerWatts, ppdu, true);
Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();
WifiTxVector txVector = ppdu->GetTxVector ();
txParams->duration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
txParams->psd = txPowerSpectrum;
txParams->txPhy = m_wifiSpectrumPhyInterface->GetObject<SpectrumPhy> ();
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<WifiSpectrumSignalParameters> txParams)
{
NS_LOG_FUNCTION (this << txParams);
m_channel->StartTx (txParams);
}

View File

@@ -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<SpectrumValue> GetTxPowerSpectralDensity (double txPowerW, Ptr<WifiPpdu> ppdu);
Ptr<SpectrumValue> GetTxPowerSpectralDensity (double txPowerW, Ptr<WifiPpdu> 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<WifiPpdu> 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<WifiSpectrumSignalParameters> txParams);
/**
* Perform run-time spectrum model change
*/

View File

@@ -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> 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<WifiPpdu> 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<WifiPpdu> 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<WifiSpectrumBand, double>& p1, const std::pair<WifiSpectrumBand, double>& 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> 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> event)
{
@@ -3317,7 +3336,7 @@ WifiPhy::StartReceivePayload (Ptr<Event> 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> 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
{

View File

@@ -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<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxPowersW);
@@ -236,6 +236,15 @@ public:
*/
void StartReceivePayload (Ptr<Event> 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<WifiPpdu> 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