wifi: Forward up MPDUs from an A-MPDU under reception as long as they arrive at the PHY

This commit is contained in:
Sébastien Deronne
2019-08-20 16:44:06 +02:00
parent 559241241c
commit d3135ed514
7 changed files with 133 additions and 62 deletions

View File

@@ -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"),

View File

@@ -2467,9 +2467,14 @@ MacLow::DeaggregateAmpduAndReceive (Ptr<WifiPsdu> 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<WifiPsdu> 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<WifiPsdu> 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<WifiPsdu> psdu, double rxSnr, WifiTxVect
}
else
{
/* Simple MPDU */
/* An MPDU has been received */
NS_ASSERT (!psdu->IsAggregate ());
ReceiveOk ((*psdu->begin ()), rxSnr, txVector, ampduSubframe);
}

View File

@@ -461,6 +461,17 @@ WifiPhyStateHelper::SwitchToChannelSwitching (Time switchingDuration)
NS_ASSERT (IsStateSwitching ());
}
void
WifiPhyStateHelper::ContinueRxNextMpdu (Ptr<WifiPsdu> psdu, double snr, WifiTxVector txVector)
{
NS_LOG_FUNCTION (this << *psdu << snr << txVector);
std::vector<bool> statusPerMpdu;
if (!m_rxOkCallback.IsNull ())
{
m_rxOkCallback (psdu, snr, txVector, statusPerMpdu);
}
}
void
WifiPhyStateHelper::SwitchFromRxEndOk (Ptr<WifiPsdu> psdu, double snr, WifiTxVector txVector, std::vector<bool> statusPerMpdu)
{
@@ -475,7 +486,6 @@ WifiPhyStateHelper::SwitchFromRxEndOk (Ptr<WifiPsdu> psdu, double snr, WifiTxVec
{
m_rxOkCallback (psdu, snr, txVector, statusPerMpdu);
}
}
void

View File

@@ -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<WifiPsdu> psdu, double snr, WifiTxVector txVector);
/**
* Switch from RX after the reception was successful.
*

View File

@@ -3152,6 +3152,11 @@ WifiPhy::StartReceivePayload (Ptr<Event> 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> event)
m_endRxEvent = Simulator::Schedule (payloadDuration, &WifiPhy::ResetReceive, this, event);
}
void
WifiPhy::ScheduleEndOfMpdus (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
Ptr<const WifiPpdu> 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<const WifiPsdu> 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<WifiPsdu> (*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> event, Ptr<const WifiPsdu> psdu, size_t mpduIndex, Time relativeStart, Time mpduDuration)
{
NS_LOG_FUNCTION (this << *event << mpduIndex << relativeStart << mpduDuration);
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
std::pair<bool, SignalNoiseDbm> 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> event)
{
@@ -3182,62 +3243,23 @@ WifiPhy::EndReceive (Ptr<Event> event)
NS_ASSERT (GetLastRxEndTime () == Simulator::Now ());
NS_ASSERT (event->GetEndTime () == Simulator::Now ());
double snr = m_interference.CalculateSnr (event);
std::vector<bool> statusPerMpdu;
SignalNoiseDbm signalNoise;
Ptr<const WifiPsdu> psdu = event->GetPsdu ();
Time relativeStart = NanoSeconds (0);
bool receptionOkAtLeastForOneMpdu = false;
std::pair<bool, SignalNoiseDbm> 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<WifiPsdu> (*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<bool, SignalNoiseDbm> 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
{

View File

@@ -1936,6 +1936,23 @@ private:
Ptr<Event> 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> event, Ptr<const WifiPsdu> 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> event);
/**
* The trace source fired when a packet begins the transmission process on
@@ -2141,6 +2158,11 @@ private:
Ptr<ErrorModel> m_postReceptionErrorModel; //!< Error model for receive packet events
Time m_timeLastPreambleDetected; //!< Record the time the last preamble was detected
std::vector <EventId> m_endOfMpduEvents; //!< the end of MPDU events (only used for A-MPDUs)
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)
Callback<void> m_capabilitiesChangedCallback; //!< Callback when PHY capabilities changed
};

View File

@@ -1513,6 +1513,10 @@ void
TestAmpduReception::RxSuccess (Ptr<WifiPsdu> psdu, double snr, WifiTxVector txVector, std::vector<bool> 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)