wifi: PHY logic changes to handle HE TB PPDUs reception

This commit is contained in:
Sébastien Deronne
2019-08-08 12:41:42 +02:00
parent a3b1286856
commit e4bc5ff260
8 changed files with 299 additions and 129 deletions

View File

@@ -181,10 +181,10 @@ InterferenceHelper::~InterferenceHelper ()
}
Ptr<Event>
InterferenceHelper::Add (Ptr<const WifiPpdu> ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPowerW)
InterferenceHelper::Add (Ptr<const WifiPpdu> ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPowerW, bool isStartOfdmaRxing)
{
Ptr<Event> event = Create<Event> (ppdu, txVector, duration, rxPowerW);
AppendEvent (event);
AppendEvent (event, isStartOfdmaRxing);
return event;
}
@@ -265,9 +265,9 @@ InterferenceHelper::GetEnergyDuration (double energyW, WifiSpectrumBand band)
}
void
InterferenceHelper::AppendEvent (Ptr<Event> event)
InterferenceHelper::AppendEvent (Ptr<Event> event, bool isStartOfdmaRxing)
{
NS_LOG_FUNCTION (this << event);
NS_LOG_FUNCTION (this << event << isStartOfdmaRxing);
RxPowerWattPerChannelBand rxPowerWattPerChannelBand = event->GetRxPowerWPerBand ();
for (auto const& it : rxPowerWattPerChannelBand)
{
@@ -284,6 +284,13 @@ InterferenceHelper::AppendEvent (Ptr<Event> event)
// Always leave the first zero power noise event in the list
ni_it->second.erase (++(ni_it->second.begin ()), GetNextPosition (event->GetStartTime (), band));
}
else if (isStartOfdmaRxing)
{
//When the first UL-OFDMA payload is received, we need to set m_firstPowerPerBand
//so that it takes into account interferences that arrived between the start of the
//UL MU transmission and the start of UL-OFDMA payload.
m_firstPowerPerBand.find (band)->second = previousPowerStart;
}
auto first = AddNiChangeEvent (event->GetStartTime (), NiChange (previousPowerStart, event), band);
auto last = AddNiChangeEvent (event->GetEndTime (), NiChange (previousPowerEnd, event), band);
for (auto i = first; i != last; ++i)
@@ -406,10 +413,19 @@ InterferenceHelper::CalculatePayloadPer (Ptr<const Event> event, uint16_t channe
Time previous = j->first;
WifiMode payloadMode = txVector.GetMode (staId);
WifiPreamble preamble = txVector.GetPreambleType ();
Time phyHeaderStart = j->first + WifiPhy::GetPhyPreambleDuration (txVector); //PPDU start time + preamble
Time phyHtSigHeaderStart = phyHeaderStart + WifiPhy::GetPhyHeaderDuration (txVector); //PPDU start time + preamble + L-SIG
Time phyTrainingSymbolsStart = phyHtSigHeaderStart + WifiPhy::GetPhyHtSigHeaderDuration (preamble) + WifiPhy::GetPhySigA1Duration (preamble) + WifiPhy::GetPhySigA2Duration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A
Time phyPayloadStart = phyTrainingSymbolsStart + WifiPhy::GetPhyTrainingSymbolDuration (txVector) + WifiPhy::GetPhySigBDuration (txVector); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
Time phyPayloadStart;
if (!event->GetPpdu ()->IsUlMu ())
{
Time phyHeaderStart = j->first + WifiPhy::GetPhyPreambleDuration (txVector); //PPDU start time + preamble
Time phyHtSigHeaderStart = phyHeaderStart + WifiPhy::GetPhyHeaderDuration (txVector); //PPDU start time + preamble + L-SIG
Time phyTrainingSymbolsStart = phyHtSigHeaderStart + WifiPhy::GetPhyHtSigHeaderDuration (preamble) + WifiPhy::GetPhySigA1Duration (preamble) + WifiPhy::GetPhySigA2Duration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A
phyPayloadStart = phyTrainingSymbolsStart + WifiPhy::GetPhyTrainingSymbolDuration (txVector) + WifiPhy::GetPhySigBDuration (txVector); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
}
else
{
//j->first corresponds to the start of the UL-OFDMA payload
phyPayloadStart = j->first;
}
Time windowStart = phyPayloadStart + window.first;
Time windowEnd = phyPayloadStart + window.second;
double noiseInterferenceW = m_firstPowerPerBand.find (band)->second;

View File

@@ -211,10 +211,11 @@ 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)
*
* \return Event
*/
Ptr<Event> Add (Ptr<const WifiPpdu> ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPower);
Ptr<Event> Add (Ptr<const WifiPpdu> ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPower, bool isStartOfdmaRxing = false);
/**
* Add a non-Wifi signal to interference helper.
@@ -373,9 +374,10 @@ private:
/**
* Append the given Event.
*
* \param event
* \param event the event to be appended
* \param isStartOfdmaRxing flag whether event corresponds to the start of the OFDMA payload reception (only used for UL-OFDMA)
*/
void AppendEvent (Ptr<Event> event);
void AppendEvent (Ptr<Event> event, bool isStartOfdmaRxing);
/**
* Calculate noise and interference power in W.

View File

@@ -34,8 +34,6 @@
#include "wifi-utils.h"
#include "wifi-ppdu.h"
#include "wifi-psdu.h"
#include "ap-wifi-mac.h"
#include "wifi-net-device.h"
namespace ns3 {
@@ -360,19 +358,33 @@ SpectrumWifiPhy::StartRx (Ptr<SpectrumSignalParameters> rxParams)
NS_LOG_INFO ("Received Wi-Fi signal");
Ptr<WifiPpdu> ppdu = Copy (wifiRxParams->ppdu);
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)
&& wifiRxParams->txPsdFlag == PSD_HE_TB_OFDMA_PORTION)
{
if (m_currentHeTbPpduUid == ppdu->GetUid () && m_currentEvent != 0)
{
//AP and STA already received non-OFDMA part, handle OFDMA payload reception
StartReceiveOfdmaPayload (ppdu, rxPowerW);
}
else
{
NS_LOG_INFO ("Ignore UL-OFDMA since device is not AP");
m_currentPreambleEvents.clear ();
//PHY receives the OFDMA payload while having dropped the preamble
NS_LOG_INFO ("Consider UL-OFDMA part of the HE TB PPDU as interference since device dropped the preamble");
m_interference.Add (ppdu, ppdu->GetTxVector (), 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 ();
}
}
}
else

View File

@@ -477,10 +477,11 @@ WifiPhyStateHelper::ContinueRxNextMpdu (Ptr<WifiPsdu> psdu, double snr, WifiTxVe
void
WifiPhyStateHelper::SwitchFromRxEndOk (Ptr<WifiPsdu> psdu, double snr, WifiTxVector txVector, uint16_t staId, std::vector<bool> statusPerMpdu)
{
NS_LOG_FUNCTION (this << *psdu << snr << txVector << statusPerMpdu.size () <<
NS_LOG_FUNCTION (this << *psdu << snr << txVector << staId << statusPerMpdu.size () <<
std::all_of(statusPerMpdu.begin(), statusPerMpdu.end(), [](bool v) { return v; })); //returns true if all true
NS_ASSERT (statusPerMpdu.size () != 0);
NS_ASSERT (m_endRx == Simulator::Now ());
NS_ASSERT (Abs (m_endRx - Simulator::Now ()) < MicroSeconds (1)); //1us corresponds to the maximum propagation delay (delay spread)
//TODO: a better fix would be to call the function once all HE TB PPDUs are received
m_rxOkTrace (psdu->GetPacket (), snr, txVector.GetMode (staId), txVector.GetPreambleType ());
NotifyRxEndOk ();
DoSwitchFromRx ();
@@ -494,7 +495,8 @@ void
WifiPhyStateHelper::SwitchFromRxEndError (Ptr<WifiPsdu> psdu, double snr)
{
NS_LOG_FUNCTION (this << *psdu << snr);
NS_ASSERT (m_endRx == Simulator::Now ());
NS_ASSERT (Abs (m_endRx - Simulator::Now ()) < MicroSeconds (1)); //1us corresponds to the maximum propagation delay (delay spread)
//TODO: a better fix would be to call the function once all HE TB PPDUs are received
m_rxErrorTrace (psdu->GetPacket (), snr);
NotifyRxEndError ();
DoSwitchFromRx ();

View File

@@ -39,6 +39,7 @@
#include "he-configuration.h"
#include "mpdu-aggregator.h"
#include "wifi-psdu.h"
#include "ap-wifi-mac.h"
namespace ns3 {
@@ -508,9 +509,9 @@ WifiPhy::GetTypeId (void)
WifiPhy::WifiPhy ()
: m_txMpduReferenceNumber (0xffffffff),
m_rxMpduReferenceNumber (0xffffffff),
m_endRxEvent (),
m_endPhyRxEvent (),
m_endTxEvent (),
m_currentEvent (0),
m_previouslyRxPpduUid (UINT64_MAX),
m_currentHeTbPpduUid (UINT64_MAX),
m_standard (WIFI_PHY_STANDARD_UNSPECIFIED),
@@ -531,9 +532,9 @@ WifiPhy::WifiPhy ()
m_rxSpatialStreams (0),
m_channelNumber (0),
m_initialChannelNumber (0),
m_currentEvent (0),
m_wifiRadioEnergyModel (0),
m_timeLastPreambleDetected (Seconds (0))
m_timeLastPreambleDetected (Seconds (0)),
m_ofdmaStarted (false)
{
NS_LOG_FUNCTION (this);
m_random = CreateObject<UniformRandomVariable> ();
@@ -550,8 +551,12 @@ WifiPhy::DoDispose (void)
{
NS_LOG_FUNCTION (this);
m_endTxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_endPhyRxEvent.Cancel ();
for (auto & endRxEvent : m_endRxEvents)
{
endRxEvent.Cancel ();
}
m_endRxEvents.clear ();
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
@@ -1697,7 +1702,11 @@ WifiPhy::DoChannelSwitch (uint8_t nch)
case WifiPhyState::RX:
NS_LOG_DEBUG ("drop packet because of channel switching while reception");
m_endPhyRxEvent.Cancel ();
m_endRxEvent.Cancel ();
for (auto & endRxEvent : m_endRxEvents)
{
endRxEvent.Cancel ();
}
m_endRxEvents.clear ();
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
@@ -1717,7 +1726,11 @@ WifiPhy::DoChannelSwitch (uint8_t nch)
endPreambleDetectionEvent.Cancel ();
}
m_endPreambleDetectionEvents.clear ();
m_endRxEvent.Cancel ();
for (auto & endRxEvent : m_endRxEvents)
{
endRxEvent.Cancel ();
}
m_endRxEvents.clear ();
}
goto switchChannel;
break;
@@ -1766,7 +1779,11 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency)
case WifiPhyState::RX:
NS_LOG_DEBUG ("drop packet because of channel/frequency switching while reception");
m_endPhyRxEvent.Cancel ();
m_endRxEvent.Cancel ();
for (auto & endRxEvent : m_endRxEvents)
{
endRxEvent.Cancel ();
}
m_endRxEvents.clear ();
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
@@ -1785,7 +1802,11 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency)
endPreambleDetectionEvent.Cancel ();
}
m_endPreambleDetectionEvents.clear ();
m_endRxEvent.Cancel ();
for (auto & endRxEvent : m_endRxEvents)
{
endRxEvent.Cancel ();
}
m_endRxEvents.clear ();
goto switchFrequency;
break;
case WifiPhyState::SLEEP:
@@ -1854,8 +1875,12 @@ WifiPhy::SetOffMode (void)
m_powerRestricted = false;
m_channelAccessRequested = false;
m_endPhyRxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_endTxEvent.Cancel ();
for (auto & endRxEvent : m_endRxEvents)
{
endRxEvent.Cancel ();
}
m_endRxEvents.clear ();
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
@@ -2936,6 +2961,7 @@ WifiPhy::Reset (void)
NS_LOG_FUNCTION (this);
m_currentPreambleEvents.clear ();
m_currentEvent = 0;
m_ofdmaStarted = false;
}
void
@@ -2945,10 +2971,12 @@ WifiPhy::StartReceiveHeader (Ptr<Event> event)
NS_ASSERT (!IsStateRx ());
NS_ASSERT (m_endPhyRxEvent.IsExpired ());
//calculate PER on the 20 MHz primary channel for PHY headers
uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth ();
auto primaryBand = GetBand (primaryChannelWidth);
double maxRxPowerW = 0;
Ptr<Event> maxEvent;
NS_ASSERT (!m_currentPreambleEvents.empty ());
for (auto preambleEvent : m_currentPreambleEvents)
{
double rxPowerW = preambleEvent.second->GetRxPowerW (primaryBand);
@@ -2974,24 +3002,13 @@ WifiPhy::StartReceiveHeader (Ptr<Event> event)
}
m_currentEvent = event;
uint16_t channelWidth;
if (m_currentEvent->GetTxVector ().GetChannelWidth () >= 40)
{
channelWidth = 20; //calculate PER on the 20 MHz primary channel for PHY headers
}
else
{
channelWidth = m_currentEvent->GetTxVector ().GetChannelWidth ();
}
auto band = GetBand (channelWidth);
InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (m_currentEvent, band);
double snr = snrPer.snr;
NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr));
double snr = m_interference.CalculateSnr (m_currentEvent, primaryChannelWidth, 1, primaryBand);
NS_LOG_DEBUG ("SNR(dB)=" << RatioToDb (snr) << " at start of legacy PHY header");
Time headerPayloadDuration = m_currentEvent->GetStartTime () + m_currentEvent->GetPpdu ()->GetTxDuration () - Simulator::Now ();
if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (m_currentEvent->GetRxPowerW (band), snr, m_channelWidth)))
if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (m_currentEvent->GetRxPowerW (primaryBand), snr, primaryChannelWidth)))
{
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
@@ -3079,7 +3096,7 @@ WifiPhy::ContinueReceiveHeader (Ptr<Event> event)
}
InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (event, GetBand (channelWidth));
NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per);
NS_LOG_DEBUG ("SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per);
if (m_random->GetValue () > snrPer.per) //non-HT PHY header reception succeeded
{
NS_LOG_DEBUG ("Received non-HT PHY header");
@@ -3303,13 +3320,28 @@ WifiPhy::StartReceiveOfdmaPayload (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand
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);
Ptr<Event> event = m_interference.Add (ppdu, txVector, payloadDuration, rxPowersW, !m_ofdmaStarted);
m_ofdmaStarted = true;
Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (GetDevice ());
bool isAp = (DynamicCast<ApWifiMac> (device->GetMac ()) != 0);
if (isAp)
{
Ptr<const WifiPsdu> psdu = GetAddressedPsduInPpdu (ppdu);
if (psdu->GetNMpdus () > 1)
{
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<bool> ()});
}
else
{
//Don't do anything special for STAs since ResetReceive has already been scheduled by StartReceivePayload
NS_ASSERT (m_endRxEvents.size () == 1 && m_endRxEvents.front ().IsRunning ());
}
}
void
@@ -3317,17 +3349,17 @@ WifiPhy::StartReceivePayload (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
NS_ASSERT (m_endPhyRxEvent.IsExpired ());
NS_ASSERT (m_endRxEvent.IsExpired ());
bool canReceivePayload = false;
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
WifiModulationClass modulation = ppdu->GetModulation ();
//calculate PER on the primary 20 MHz channel for PHY headers
uint16_t primaryChannelWidth = std::min (event->GetTxVector ().GetChannelWidth (), static_cast<uint16_t> (20));
auto primaryBand = GetBand (primaryChannelWidth);
if (modulation >= WIFI_MOD_CLASS_HT)
{
InterferenceHelper::SnrPer snrPer = m_interference.CalculateHtPhyHeaderSnrPer (event, primaryBand);
NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per);
NS_LOG_DEBUG ("SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per);
canReceivePayload = (m_random->GetValue () > snrPer.per);
}
else
@@ -3357,6 +3389,7 @@ WifiPhy::StartReceivePayload (Ptr<Event> event)
}
}
}
if (nss > GetMaxSupportedRxSpatialStreams ())
{
NS_LOG_DEBUG ("Packet reception could not be started because not enough RX antennas");
@@ -3369,23 +3402,37 @@ WifiPhy::StartReceivePayload (Ptr<Event> event)
}
else if (IsModeSupported (txMode) || IsMcsSupported (txMode))
{
m_statusPerMpdu.clear();
if (psdu->GetNMpdus () > 1)
{
ScheduleEndOfMpdus (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
success = true;
NS_LOG_DEBUG ("Receiving PSDU");
if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB)
Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (GetDevice ());
bool isAp = device != 0 && (DynamicCast<ApWifiMac> (device->GetMac ()) != 0);
if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB && !isAp)
{
NS_LOG_DEBUG ("Ignore UL-OFDMA (OFDMA part of HE TB PPDU) received by STA but keep state in Rx");
m_currentHeTbPpduUid = ppdu->GetUid ();
//EndReceive is scheduled by StartReceiveOfdmaPayload
//ResetReceive is scheduled below at end of PSDU
}
else
{
m_endRxEvent = Simulator::Schedule (payloadDuration, &WifiPhy::EndReceive, this, event);
success = true;
NS_LOG_DEBUG ("Receiving PSDU");
m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), staId), SignalNoiseDbm ()});
m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), staId), std::vector<bool> ()});
if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB)
{
//for HE TB PPDUs, ScheduleEndOfMpdus and EndReceive are scheduled by StartReceiveOfdmaPayload
NS_ASSERT (isAp);
m_currentHeTbPpduUid = ppdu->GetUid ();
}
else
{
if (psdu->GetNMpdus () > 1)
{
ScheduleEndOfMpdus (event);
}
m_endRxEvents.push_back (Simulator::Schedule (payloadDuration, &WifiPhy::EndReceive, this, event));
}
}
}
else //mode is not allowed
@@ -3418,7 +3465,7 @@ WifiPhy::StartReceivePayload (Ptr<Event> event)
{
if (payloadDuration.IsStrictlyPositive ())
{
m_endRxEvent = Simulator::Schedule (payloadDuration, &WifiPhy::ResetReceive, this, event);
m_endRxEvents.push_back (Simulator::Schedule (payloadDuration, &WifiPhy::ResetReceive, this, event));
}
else
{
@@ -3436,7 +3483,9 @@ WifiPhy::ScheduleEndOfMpdus (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
Ptr<const WifiPsdu> 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);
@@ -3444,9 +3493,7 @@ WifiPhy::ScheduleEndOfMpdus (Ptr<Event> event)
MpduType mpdutype = FIRST_MPDU_IN_AGGREGATE;
uint32_t totalAmpduSize = 0;
double totalAmpduNumSymbols = 0.0;
Ptr<const WifiPsdu> psdu = GetAddressedPsduInPpdu (ppdu);
size_t nMpdus = psdu->GetNMpdus ();
uint16_t staId = SU_STA_ID;
auto mpdu = psdu->begin ();
for (size_t i = 0; i < nMpdus && mpdu != psdu->end (); ++mpdu)
{
@@ -3476,49 +3523,10 @@ WifiPhy::EndOfMpdu (Ptr<Event> event, Ptr<const WifiPsdu> psdu, size_t mpduIndex
{
NS_LOG_FUNCTION (this << *event << mpduIndex << relativeStart << mpduDuration);
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
uint16_t staId = GetStaId (ppdu);
WifiTxVector txVector = event->GetTxVector ();
uint16_t channelWidth = std::min (GetChannelWidth (), txVector.GetChannelWidth ());
double snr = m_interference.CalculateSnr (event, channelWidth, txVector.GetNss (staId), GetBand (channelWidth));
std::pair<bool, SignalNoiseDbm> 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");
m_signalNoise = rxInfo.second;
m_statusPerMpdu.push_back (rxInfo.first);
if (rxInfo.first)
{
m_state->ContinueRxNextMpdu (Copy (psdu), snr, event->GetTxVector ());
}
}
void
WifiPhy::EndReceive (Ptr<Event> event)
{
Time psduDuration = event->GetEndTime () - event->GetStartTime ();
NS_LOG_FUNCTION (this << *event << psduDuration);
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
if (!ppdu->IsUlMu ())
{
NS_ASSERT (GetLastRxEndTime () == Simulator::Now ());
}
NS_ASSERT (event->GetEndTime () == Simulator::Now ());
uint16_t staId = GetStaId (ppdu);
Ptr<const WifiPsdu> psdu = GetAddressedPsduInPpdu (ppdu);
if (psdu->GetNMpdus () == 1)
{
//We do not enter here for A-MPDU since this is done in WifiPhy::EndOfMpdu
std::pair<bool, SignalNoiseDbm> rxInfo = GetReceptionStatus (psdu, event, staId, NanoSeconds (0), psduDuration);
m_signalNoise = rxInfo.second;
m_statusPerMpdu.push_back (rxInfo.first);
}
NotifyRxEnd (psdu);
WifiTxVector txVector = event->GetTxVector ();
uint16_t channelWidth = std::min (GetChannelWidth (), txVector.GetChannelWidth ());
uint16_t channelWidth = std::min (GetChannelWidth (), event->GetTxVector ().GetChannelWidth ());
WifiSpectrumBand band;
if (txVector.IsMu ())
{
@@ -3530,12 +3538,72 @@ WifiPhy::EndReceive (Ptr<Event> event)
band = GetBand (channelWidth);
}
double snr = m_interference.CalculateSnr (event, channelWidth, txVector.GetNss (staId), band);
if (std::count (m_statusPerMpdu.begin (), m_statusPerMpdu.end (), true))
std::pair<bool, SignalNoiseDbm> 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;
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)
{
m_state->ContinueRxNextMpdu (Copy (psdu), snr, txVector);
}
}
void
WifiPhy::EndReceive (Ptr<Event> event)
{
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
WifiTxVector txVector = event->GetTxVector ();
Time psduDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
NS_LOG_FUNCTION (this << *event << psduDuration);
if (!ppdu->IsUlMu ())
{
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<const WifiPsdu> 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 (psdu->GetNMpdus () == 1)
{
//We do not enter here for A-MPDU since this is done in WifiPhy::EndOfMpdu
std::pair<bool, SignalNoiseDbm> rxInfo = GetReceptionStatus (psdu, event, staId, NanoSeconds (0), psduDuration);
signalNoiseIt->second = rxInfo.second;
statusPerMpduIt->second.push_back (rxInfo.first);
}
if (std::count (statusPerMpduIt->second.begin (), statusPerMpduIt->second.end (), true))
{
//At least one MPDU has been successfully received
WifiTxVector txVector = event->GetTxVector ();
NotifyMonitorSniffRx (psdu, GetFrequency (), txVector, m_signalNoise, m_statusPerMpdu, staId);
m_state->SwitchFromRxEndOk (Copy (psdu), snr, txVector, staId, m_statusPerMpdu);
NotifyMonitorSniffRx (psdu, GetFrequency (), txVector, signalNoiseIt->second, statusPerMpduIt->second, staId);
m_state->SwitchFromRxEndOk (Copy (psdu), snr, 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
@@ -3543,9 +3611,48 @@ WifiPhy::EndReceive (Ptr<Event> event)
m_state->SwitchFromRxEndError (Copy (psdu), snr);
}
m_interference.NotifyRxEnd (Simulator::Now ());
m_currentEvent = 0;
m_currentPreambleEvents.clear ();
if (ppdu->IsUlMu ())
{
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 ();
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 ();
}
@@ -3570,7 +3677,7 @@ WifiPhy::GetReceptionStatus (Ptr<const WifiPsdu> psdu, Ptr<Event> event, uint16_
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 () <<
", 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.
@@ -3635,6 +3742,8 @@ WifiPhy::ResetReceive (Ptr<Event> event)
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 ();
@@ -4907,10 +5016,11 @@ WifiPhy::AbortCurrentReception (WifiPhyRxfailureReason reason)
{
m_endPhyRxEvent.Cancel ();
}
if (m_endRxEvent.IsRunning ())
for (auto & endRxEvent : m_endRxEvents)
{
m_endRxEvent.Cancel ();
endRxEvent.Cancel ();
}
m_endRxEvents.clear ();
m_interference.NotifyRxEnd (Simulator::Now ());
if (!m_currentEvent)
{
@@ -4979,11 +5089,27 @@ Ptr<const WifiPsdu>
WifiPhy::GetAddressedPsduInPpdu (Ptr<const WifiPpdu> ppdu) const
{
Ptr<const WifiPsdu> psdu;
if (!ppdu->IsDlMu ())
if (!ppdu->IsMu ())
{
psdu = ppdu->GetPsdu ();
}
else
else if (ppdu->IsUlMu ())
{
uint8_t bssColor = 0;
Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (GetDevice ());
if (device)
{
Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration ();
if (heConfiguration)
{
UintegerValue bssColorAttribute;
heConfiguration->GetAttribute ("BssColor", bssColorAttribute);
bssColor = bssColorAttribute.Get ();
}
}
psdu = ppdu->GetPsdu (bssColor);
}
else //DL MU
{
uint8_t bssColor = 0;
Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (GetDevice ());

View File

@@ -1864,11 +1864,12 @@ protected:
uint32_t m_txMpduReferenceNumber; //!< A-MPDU reference number to identify all transmitted subframes belonging to the same received A-MPDU
uint32_t m_rxMpduReferenceNumber; //!< A-MPDU reference number to identify all received subframes belonging to the same received A-MPDU
EventId m_endRxEvent; //!< the end of receive event
EventId m_endPhyRxEvent; //!< the end of PHY receive event
EventId m_endTxEvent; //!< the end of transmit event
std::vector <EventId> m_endRxEvents; //!< the end of receive events (only one unless UL MU reception)
std::vector <EventId> m_endPreambleDetectionEvents; //!< the end of preamble detection events
Ptr<Event> m_currentEvent; //!< Hold the current event
std::map <std::pair<uint64_t /* UID*/, WifiPreamble>, Ptr<Event> > m_currentPreambleEvents; //!< store event associated to a PPDU (that has a unique ID and preamble combination) whose preamble is being received
uint64_t m_previouslyRxPpduUid; //!< UID of the previously received PPDU (reused by HE TB PPDUs), reset to UINT64_MAX upon transmission
@@ -2236,17 +2237,25 @@ private:
Ptr<NetDevice> m_device; //!< Pointer to the device
Ptr<MobilityModel> m_mobility; //!< Pointer to the mobility model
Ptr<Event> m_currentEvent; //!< Hold the current event
Ptr<FrameCaptureModel> m_frameCaptureModel; //!< Frame capture model
Ptr<PreambleDetectionModel> m_preambleDetectionModel; //!< Preamble detection model
Ptr<WifiRadioEnergyModel> m_wifiRadioEnergyModel; //!< Wifi radio energy model
Ptr<ErrorModel> m_postReceptionErrorModel; //!< Error model for receive packet events
Time m_timeLastPreambleDetected; //!< Record the time the last preamble was detected
std::vector<bool> m_statusPerMpdu; //!< 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
SignalNoiseDbm m_signalNoise; //!< latest signal power and noise power in dBm (noise power includes the noise figure)
std::vector <EventId> m_endOfMpduEvents; //!< the end of MPDU events (only used for A-MPDUs)
Callback<void> m_capabilitiesChangedCallback; //!< Callback when PHY capabilities changed
/**
* A pair of a UID and STA_ID
*/
typedef std::pair <uint64_t /* uid */, uint16_t /* staId */> UidStaIdPair;
std::map<UidStaIdPair, std::vector<bool> > 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<UidStaIdPair, SignalNoiseDbm> m_signalNoiseMap; //!< Map of the latest signal power and noise power in dBm (noise power includes the noise figure)
bool m_ofdmaStarted; //!< Flag whether the reception of the OFDMA part has started (only used for UL-OFDMA)
Callback<void> m_capabilitiesChangedCallback; //!< Callback when PHY capabilities changed
};
} //namespace ns3

View File

@@ -382,11 +382,14 @@ WifiPpdu::GetPsdu (uint8_t bssColor, uint16_t staId) const
else if (IsUlMu ())
{
NS_ASSERT (m_psdus.size () == 1);
return m_psdus.begin ()->second;
if (bssColor == 0 || (bssColor == m_heSig.GetBssColor ()))
{
return m_psdus.begin ()->second;
}
}
else
{
if (bssColor == m_heSig.GetBssColor ())
if (bssColor == 0 || (bssColor == m_heSig.GetBssColor ()))
{
auto it = m_psdus.find (staId);
if (it != m_psdus.end ())

View File

@@ -79,7 +79,7 @@ public:
* \param staId the staId of the PHY calling this function.
* \return the PSDU
*/
Ptr<const WifiPsdu> GetPsdu (uint8_t bssColor = 64, uint16_t staId = SU_STA_ID) const;
Ptr<const WifiPsdu> GetPsdu (uint8_t bssColor = 0, uint16_t staId = SU_STA_ID) const;
/**
* Return true if the PPDU's transmission was aborted due to transmitter switch off