wifi: Forward up MPDUs from an A-MPDU under reception as long as they arrive at the PHY
This commit is contained in:
@@ -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"),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user