From d3135ed514cc1e08372f5037f4097b258a5fd069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Tue, 20 Aug 2019 16:44:06 +0200 Subject: [PATCH] wifi: Forward up MPDUs from an A-MPDU under reception as long as they arrive at the PHY --- examples/wireless/examples-to-run.py | 8 +- src/wifi/model/mac-low.cc | 19 ++-- src/wifi/model/wifi-phy-state-helper.cc | 12 ++- src/wifi/model/wifi-phy-state-helper.h | 8 ++ src/wifi/model/wifi-phy.cc | 122 +++++++++++++---------- src/wifi/model/wifi-phy.h | 22 ++++ src/wifi/test/wifi-phy-reception-test.cc | 4 + 7 files changed, 133 insertions(+), 62 deletions(-) diff --git a/examples/wireless/examples-to-run.py b/examples/wireless/examples-to-run.py index 1ff15394c..9da9f3f98 100755 --- a/examples/wireless/examples-to-run.py +++ b/examples/wireless/examples-to-run.py @@ -37,12 +37,12 @@ cpp_examples = [ ("wifi-ofdm-vht-validation", "True", "True"), ("wifi-ofdm-he-validation", "True", "True"), ("wifi-80211n-mimo --simulationTime=0.1 --step=10", "True", "True"), - ("wifi-ht-network --simulationTime=0.2 --frequency=5 --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=134", "True", "True"), - ("wifi-ht-network --simulationTime=0.2 --frequency=5 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=129", "True", "True"), + ("wifi-ht-network --simulationTime=0.2 --frequency=5 --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=135", "True", "True"), + ("wifi-ht-network --simulationTime=0.2 --frequency=5 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=131", "True", "True"), ("wifi-ht-network --simulationTime=0.2 --frequency=2.4 --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=132", "True", "True"), - ("wifi-ht-network --simulationTime=0.2 --frequency=2.4 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=127", "True", "True"), + ("wifi-ht-network --simulationTime=0.2 --frequency=2.4 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=128", "True", "True"), ("wifi-vht-network --simulationTime=0.2 --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=562", "True", "True"), - ("wifi-vht-network --simulationTime=0.2 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=524", "True", "True"), + ("wifi-vht-network --simulationTime=0.2 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=525", "True", "True"), ("wifi-he-network --simulationTime=0.25 --frequency=5 --useRts=0 --minExpectedThroughput=6 --maxExpectedThroughput=844", "True", "True"), ("wifi-he-network --simulationTime=0.3 --frequency=5 --useRts=0 --useExtendedBlockAck=1 --minExpectedThroughput=6 --maxExpectedThroughput=1033", "True", "True"), ("wifi-he-network --simulationTime=0.3 --frequency=5 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=745", "True", "True"), diff --git a/src/wifi/model/mac-low.cc b/src/wifi/model/mac-low.cc index 381c8a810..558dd03e8 100644 --- a/src/wifi/model/mac-low.cc +++ b/src/wifi/model/mac-low.cc @@ -2467,9 +2467,14 @@ MacLow::DeaggregateAmpduAndReceive (Ptr psdu, double rxSnr, WifiTxVect { NS_LOG_FUNCTION (this); bool normalAck = false; - bool ampduSubframe = false; //flag indicating the packet belongs to an A-MPDU and is not a VHT/HE single MPDU - if (txVector.IsAggregation ()) + bool ampduSubframe = txVector.IsAggregation (); //flag indicating the packet belongs to an A-MPDU and is not a VHT/HE single MPDU + //statusPerMpdu is empty for intermediate MPDU forwarding. + //This function is called also once the PPDU has been fully received by the PHY, + //in that case statusPerMpdu carries the information about the received MPDUs. + if (ampduSubframe && !statusPerMpdu.empty ()) { + //We are here if a S-MPDU is received or if all MPDUs of an A-MPDU have been + //received (but have been already forwarded up, so ReceiveOk won't be called) NS_ASSERT (psdu->IsAggregate ()); ampduSubframe = true; auto n = psdu->begin (); @@ -2477,9 +2482,6 @@ MacLow::DeaggregateAmpduAndReceive (Ptr psdu, double rxSnr, WifiTxVect NS_ABORT_MSG_IF (psdu->GetNMpdus () != statusPerMpdu.size (), "Should have one receive status per MPDU"); WifiMacHeader firsthdr = (*n)->GetHeader (); - NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ()); - NotifyNav ((*n)->GetPacket (), firsthdr); - if (firsthdr.GetAddr1 () == m_self) { //Iterate over all MPDUs and notify reception only if status OK @@ -2512,7 +2514,10 @@ MacLow::DeaggregateAmpduAndReceive (Ptr psdu, double rxSnr, WifiTxVect else if (firsthdr.IsData () || firsthdr.IsQosData ()) { NS_LOG_DEBUG ("Deaggregate packet from " << firsthdr.GetAddr2 () << " with sequence=" << firsthdr.GetSequenceNumber ()); - ReceiveOk ((*n), rxSnr, txVector, ampduSubframe); + if (psdu->IsSingle ()) + { + ReceiveOk ((*n), rxSnr, txVector, ampduSubframe); + } if (firsthdr.IsQosAck ()) { NS_LOG_DEBUG ("Normal Ack"); @@ -2554,7 +2559,7 @@ MacLow::DeaggregateAmpduAndReceive (Ptr psdu, double rxSnr, WifiTxVect } else { - /* Simple MPDU */ + /* An MPDU has been received */ NS_ASSERT (!psdu->IsAggregate ()); ReceiveOk ((*psdu->begin ()), rxSnr, txVector, ampduSubframe); } diff --git a/src/wifi/model/wifi-phy-state-helper.cc b/src/wifi/model/wifi-phy-state-helper.cc index 13c6ecd39..c08903fbd 100644 --- a/src/wifi/model/wifi-phy-state-helper.cc +++ b/src/wifi/model/wifi-phy-state-helper.cc @@ -461,6 +461,17 @@ WifiPhyStateHelper::SwitchToChannelSwitching (Time switchingDuration) NS_ASSERT (IsStateSwitching ()); } +void +WifiPhyStateHelper::ContinueRxNextMpdu (Ptr psdu, double snr, WifiTxVector txVector) +{ + NS_LOG_FUNCTION (this << *psdu << snr << txVector); + std::vector statusPerMpdu; + if (!m_rxOkCallback.IsNull ()) + { + m_rxOkCallback (psdu, snr, txVector, statusPerMpdu); + } +} + void WifiPhyStateHelper::SwitchFromRxEndOk (Ptr psdu, double snr, WifiTxVector txVector, std::vector statusPerMpdu) { @@ -475,7 +486,6 @@ WifiPhyStateHelper::SwitchFromRxEndOk (Ptr psdu, double snr, WifiTxVec { m_rxOkCallback (psdu, snr, txVector, statusPerMpdu); } - } void diff --git a/src/wifi/model/wifi-phy-state-helper.h b/src/wifi/model/wifi-phy-state-helper.h index 67359a399..9474caff6 100644 --- a/src/wifi/model/wifi-phy-state-helper.h +++ b/src/wifi/model/wifi-phy-state-helper.h @@ -182,6 +182,14 @@ public: * \param switchingDuration the duration of required to switch the channel */ void SwitchToChannelSwitching (Time switchingDuration); + /** + * Continue RX after the reception of an MPDU in an A-MPDU was successful. + * + * \param psdu the successfully received PSDU + * \param snr the SNR of the received PSDU in linear scale + * \param txVector TXVECTOR of the PSDU + */ + void ContinueRxNextMpdu (Ptr psdu, double snr, WifiTxVector txVector); /** * Switch from RX after the reception was successful. * diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index 089601d6a..cd2513e08 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -3152,6 +3152,11 @@ WifiPhy::StartReceivePayload (Ptr event) } else { + m_statusPerMpdu.clear(); + if (event->GetPsdu ()->GetNMpdus () > 1) + { + ScheduleEndOfMpdus (event); + } m_state->SwitchToRx (payloadDuration); m_endRxEvent = Simulator::Schedule (payloadDuration, &WifiPhy::EndReceive, this, event); NS_LOG_DEBUG ("Receiving PSDU"); @@ -3174,6 +3179,62 @@ WifiPhy::StartReceivePayload (Ptr event) m_endRxEvent = Simulator::Schedule (payloadDuration, &WifiPhy::ResetReceive, this, event); } +void +WifiPhy::ScheduleEndOfMpdus (Ptr event) +{ + NS_LOG_FUNCTION (this << *event); + Ptr ppdu = event->GetPpdu (); + WifiTxVector txVector = event->GetTxVector (); + Time endOfMpduDuration = NanoSeconds (0); + Time relativeStart = NanoSeconds (0); + Time psduDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector); + Time remainingAmpduDuration = psduDuration; + MpduType mpdutype = FIRST_MPDU_IN_AGGREGATE; + uint32_t totalAmpduSize = 0; + double totalAmpduNumSymbols = 0.0; + Ptr psdu = event->GetPsdu (); + size_t nMpdus = psdu->GetNMpdus (); + auto mpdu = psdu->begin (); + for (size_t i = 0; i < nMpdus && mpdu != psdu->end (); ++mpdu) + { + Time mpduDuration = GetPayloadDuration (psdu->GetAmpduSubframeSize (i), txVector, + GetPhyBand (), mpdutype, true, totalAmpduSize, totalAmpduNumSymbols); + + remainingAmpduDuration -= mpduDuration; + if (i == (nMpdus - 1) && !remainingAmpduDuration.IsZero ()) //no more MPDU coming + { + mpduDuration += remainingAmpduDuration; //apply a correction just in case rounding had induced slight shift + } + + endOfMpduDuration += mpduDuration; + 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 (); + + std::pair rxInfo = GetReceptionStatus (psdu, event, 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), m_interference.CalculateSnr (event), event->GetTxVector ()); + } +} + void WifiPhy::EndReceive (Ptr event) { @@ -3182,62 +3243,23 @@ WifiPhy::EndReceive (Ptr event) NS_ASSERT (GetLastRxEndTime () == Simulator::Now ()); NS_ASSERT (event->GetEndTime () == Simulator::Now ()); - double snr = m_interference.CalculateSnr (event); - std::vector statusPerMpdu; - SignalNoiseDbm signalNoise; - Ptr psdu = event->GetPsdu (); - Time relativeStart = NanoSeconds (0); - bool receptionOkAtLeastForOneMpdu = false; - std::pair rxInfo; - WifiTxVector txVector = event->GetTxVector (); - size_t nMpdus = psdu->GetNMpdus (); - if (nMpdus > 1) + if (psdu->GetNMpdus () == 1) { - //Extract all MPDUs of the A-MPDU to compute per-MPDU PER stats - Time remainingAmpduDuration = psduDuration; - MpduType mpdutype = FIRST_MPDU_IN_AGGREGATE; - auto mpdu = psdu->begin (); - uint32_t totalAmpduSize = 0; - double totalAmpduNumSymbols = 0.0; - for (size_t i = 0; i < nMpdus && mpdu != psdu->end (); ++mpdu) - { - Time mpduDuration = GetPayloadDuration (psdu->GetAmpduSubframeSize (i), txVector, - GetPhyBand (), mpdutype, true, totalAmpduSize, totalAmpduNumSymbols); - remainingAmpduDuration -= mpduDuration; - if (i == (nMpdus - 1) && !remainingAmpduDuration.IsZero ()) //no more MPDU coming - { - mpduDuration += remainingAmpduDuration; //apply a correction just in case rounding had induced slight shift - } - rxInfo = GetReceptionStatus (Create (*mpdu, false), - event, relativeStart, mpduDuration); - NS_LOG_DEBUG ("Extracted MPDU #" << i << ": duration: " << mpduDuration.GetNanoSeconds () << "ns" << - ", correct reception: " << rxInfo.first << - ", Signal/Noise: " << rxInfo.second.signal << "/" << rxInfo.second.noise << "dBm"); - signalNoise = rxInfo.second; //same information for all MPDUs - statusPerMpdu.push_back (rxInfo.first); - receptionOkAtLeastForOneMpdu |= rxInfo.first; - - //Prepare next iteration - ++i; - relativeStart += mpduDuration; - mpdutype = (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE; - } - } - else - { - rxInfo = GetReceptionStatus (psdu, event, relativeStart, psduDuration); - signalNoise = rxInfo.second; //same information for all MPDUs - statusPerMpdu.push_back (rxInfo.first); - receptionOkAtLeastForOneMpdu = rxInfo.first; + //We do not enter here for A-MPDU since this is done in WifiPhy::EndOfMpdu + std::pair rxInfo = GetReceptionStatus (psdu, event, NanoSeconds (0), psduDuration); + m_signalNoise = rxInfo.second; + m_statusPerMpdu.push_back (rxInfo.first); } NotifyRxEnd (psdu); - - if (receptionOkAtLeastForOneMpdu) + double snr = m_interference.CalculateSnr (event); + if (std::count (m_statusPerMpdu.begin (), m_statusPerMpdu.end (), true)) { - NotifyMonitorSniffRx (psdu, GetFrequency (), txVector, signalNoise, statusPerMpdu); - m_state->SwitchFromRxEndOk (Copy (psdu), snr, txVector, statusPerMpdu); + //At least one MPDU has been successfully received + WifiTxVector txVector = event->GetTxVector (); + NotifyMonitorSniffRx (psdu, GetFrequency (), txVector, m_signalNoise, m_statusPerMpdu); + m_state->SwitchFromRxEndOk (Copy (psdu), snr, txVector, m_statusPerMpdu); } else { diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 0d93a9880..d5fbbe753 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -1936,6 +1936,23 @@ private: Ptr event, 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); /** * The trace source fired when a packet begins the transmission process on @@ -2141,6 +2158,11 @@ 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) + + std::vector 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) + Callback m_capabilitiesChangedCallback; //!< Callback when PHY capabilities changed }; diff --git a/src/wifi/test/wifi-phy-reception-test.cc b/src/wifi/test/wifi-phy-reception-test.cc index fa0f2202c..7d5778901 100644 --- a/src/wifi/test/wifi-phy-reception-test.cc +++ b/src/wifi/test/wifi-phy-reception-test.cc @@ -1513,6 +1513,10 @@ void TestAmpduReception::RxSuccess (Ptr psdu, double snr, WifiTxVector txVector, std::vector statusPerMpdu) { NS_LOG_FUNCTION (this << *psdu << snr << txVector); + if (statusPerMpdu.empty ()) //wait for the whole A-MPDU + { + return; + } NS_ABORT_MSG_IF (psdu->GetNMpdus () != statusPerMpdu.size (), "Should have one receive status per MPDU"); auto rxOkForMpdu = statusPerMpdu.begin (); for (auto mpdu = psdu->begin (); mpdu != psdu->end (); ++mpdu)