wifi: Improve logic when RTS/CTS exchange fails
See issue #27 Also, regenerate data files used by devices-mesh-dot11s-regression
This commit is contained in:
@@ -131,10 +131,7 @@ MacLow::MacLow ()
|
||||
m_cfAckInfo ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
m_aggregateQueue[i] = CreateObject<WifiMacQueue> ();
|
||||
}
|
||||
m_aggregateQueue = CreateObject<WifiMacQueue> ();
|
||||
}
|
||||
|
||||
MacLow::~MacLow ()
|
||||
@@ -193,10 +190,7 @@ MacLow::DoDispose (void)
|
||||
delete m_phyMacLowListener;
|
||||
m_phyMacLowListener = 0;
|
||||
}
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
m_aggregateQueue[i] = 0;
|
||||
}
|
||||
m_aggregateQueue = 0;
|
||||
m_ampdu = false;
|
||||
}
|
||||
|
||||
@@ -543,90 +537,40 @@ MacLow::StartTransmission (Ptr<const Packet> packet,
|
||||
m_txParams.DisableRts ();
|
||||
}
|
||||
|
||||
/* The packet received by this function can be any of the following:
|
||||
* (a) a management frame dequeued from the Txop
|
||||
* (b) a non-QoS data frame dequeued from the Txop
|
||||
* (c) a QoS data or DELBA Request frame dequeued from a QosTxop
|
||||
* (d) a BlockAckReq or ADDBA Request frame
|
||||
*/
|
||||
if (!hdr->IsQosData () || hdr->GetAddr1 ().IsBroadcast ())
|
||||
{
|
||||
//This is mainly encountered when a higher priority control or management frame is
|
||||
//sent between A-MPDU transmissions. It avoids to unexpectedly flush the aggregate
|
||||
//queue when previous RTS request has failed.
|
||||
// We don't try to aggregate management frames or non-QoS data frames
|
||||
m_ampdu = false;
|
||||
}
|
||||
else if (hdr->IsQosData () && !m_aggregateQueue[GetTid (packet, *hdr)]->IsEmpty ())
|
||||
{
|
||||
//m_aggregateQueue > 0 occurs when a RTS/CTS exchange failed before an A-MPDU transmission.
|
||||
//In that case, we transmit the same A-MPDU as previously.
|
||||
uint32_t sentMpdus = m_aggregateQueue[GetTid (packet, *hdr)]->GetNPackets ();
|
||||
m_ampdu = true;
|
||||
if (sentMpdus > 1)
|
||||
{
|
||||
AcIndex ac = QosUtilsMapTidToAc (GetTid (packet, *hdr));
|
||||
std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
|
||||
if (edcaIt->second->GetBaBufferSize (hdr->GetAddr1 (), hdr->GetQosTid ()) > 64)
|
||||
{
|
||||
m_txParams.EnableExtendedCompressedBlockAck ();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_txParams.EnableCompressedBlockAck ();
|
||||
}
|
||||
}
|
||||
else if (hdr->IsQosData ())
|
||||
{
|
||||
//VHT/HE single MPDUs are followed by normal ACKs
|
||||
m_txParams.EnableAck ();
|
||||
}
|
||||
std::vector<Ptr<WifiMacQueueItem>> mpduList;
|
||||
for (uint32_t i = 0; i < sentMpdus; i++)
|
||||
{
|
||||
Ptr<WifiMacQueueItem> newPacket;
|
||||
newPacket = Create<WifiMacQueueItem> (m_txPackets[GetTid (packet, *hdr)].at (i)->GetPacket (),
|
||||
m_txPackets[GetTid (packet, *hdr)].at (i)->GetHeader ());
|
||||
mpduList.push_back (newPacket);
|
||||
}
|
||||
m_currentPacket = Create<WifiPsdu> (mpduList);
|
||||
m_currentTxVector = GetDataTxVector (*m_currentPacket->begin ());
|
||||
}
|
||||
else if (m_mpduAggregator != 0)
|
||||
{
|
||||
//Perform MPDU aggregation if possible
|
||||
/* We get here if the received packet is any of the following:
|
||||
* (a) a QoS data frame
|
||||
* (b) a BlockAckRequest
|
||||
*/
|
||||
uint8_t tid = GetTid (packet, *hdr);
|
||||
Ptr<QosTxop> qosTxop = m_edca.find (QosUtilsMapTidToAc (tid))->second;
|
||||
std::vector<Ptr<WifiMacQueueItem>> mpduList;
|
||||
|
||||
mpduList = m_mpduAggregator->GetNextAmpdu (Create<const WifiMacQueueItem> (packet, *hdr),
|
||||
m_currentTxVector);
|
||||
//Perform MPDU aggregation if possible
|
||||
mpduList = m_mpduAggregator->GetNextAmpdu (*m_currentPacket->begin (), m_currentTxVector);
|
||||
|
||||
if (mpduList.size () > 1)
|
||||
{
|
||||
m_ampdu = true;
|
||||
|
||||
for (auto& mpdu : mpduList)
|
||||
{
|
||||
// Store the MPDU in the aggregate queue
|
||||
NS_LOG_DEBUG ("Adding packet with sequence number " << mpdu->GetHeader ().GetSequenceNumber ()
|
||||
<< " to A-MPDU, packet size = " << mpdu->GetSize ()
|
||||
<< ", A-MPDU size = " << m_currentPacket->GetSize ());
|
||||
m_aggregateQueue[tid]->Enqueue (mpdu);
|
||||
|
||||
// Complete the processing of the MPDU
|
||||
if (mpdu->GetHeader ().IsQosData ())
|
||||
{
|
||||
if (!m_txParams.MustSendRts ())
|
||||
{
|
||||
qosTxop->CompleteMpduTx (mpdu);
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertInTxQueue (mpdu, tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_currentPacket = Create<WifiPsdu> (mpduList);
|
||||
|
||||
// assume implicit block ack for now
|
||||
qosTxop->CompleteAmpduTransfer (hdr->GetAddr1 (), tid);
|
||||
|
||||
if (qosTxop->GetBaBufferSize (hdr->GetAddr1 (), hdr->GetQosTid ()) > 64)
|
||||
if (qosTxop->GetBaBufferSize (hdr->GetAddr1 (), tid) > 64)
|
||||
{
|
||||
m_txParams.EnableExtendedCompressedBlockAck ();
|
||||
}
|
||||
@@ -643,22 +587,10 @@ MacLow::StartTransmission (Ptr<const Packet> packet,
|
||||
{
|
||||
// VHT/HE single MPDU
|
||||
m_ampdu = true;
|
||||
Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (packet, *hdr);
|
||||
Ptr<WifiMacQueueItem> mpdu = *m_currentPacket->begin ();
|
||||
mpdu->GetHeader ().SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
|
||||
m_currentPacket = Create<WifiPsdu> (mpdu, true);
|
||||
|
||||
// Store the MPDU in the aggregate queue
|
||||
NS_LOG_DEBUG ("Adding packet with sequence number " << mpdu->GetHeader ().GetSequenceNumber ()
|
||||
<< " to S-MPDU, packet size = " << mpdu->GetSize ()
|
||||
<< ", S-MPDU size = " << m_currentPacket->GetSize ());
|
||||
m_aggregateQueue[tid]->Enqueue (mpdu);
|
||||
|
||||
// Complete the processing of the MPDU
|
||||
if (m_txParams.MustSendRts ())
|
||||
{
|
||||
InsertInTxQueue (mpdu, tid);
|
||||
}
|
||||
|
||||
if (qosTxop->GetBaAgreementEstablished (hdr->GetAddr1 (), tid))
|
||||
{
|
||||
qosTxop->CompleteAmpduTransfer (hdr->GetAddr1 (), tid);
|
||||
@@ -908,10 +840,6 @@ MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, bool
|
||||
}
|
||||
}
|
||||
m_ampdu = false;
|
||||
if (m_currentPacket->GetHeader (0).IsQosData ())
|
||||
{
|
||||
FlushAggregateQueue (m_currentPacket->GetHeader (0).GetQosTid ());
|
||||
}
|
||||
}
|
||||
else if (hdr.IsBlockAck () && hdr.GetAddr1 () == m_self
|
||||
&& (m_txParams.MustWaitBasicBlockAck () || m_txParams.MustWaitCompressedBlockAck () || m_txParams.MustWaitExtendedCompressedBlockAck ())
|
||||
@@ -920,7 +848,6 @@ MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, bool
|
||||
NS_LOG_DEBUG ("got block ack from " << hdr.GetAddr2 ());
|
||||
SnrTag tag;
|
||||
packet->RemovePacketTag (tag);
|
||||
FlushAggregateQueue (GetTid (packet, hdr));
|
||||
CtrlBAckResponseHeader blockAck;
|
||||
packet->RemoveHeader (blockAck);
|
||||
m_blockAckTimeoutEvent.Cancel ();
|
||||
@@ -1177,6 +1104,12 @@ rxPacket:
|
||||
return;
|
||||
}
|
||||
|
||||
Ptr<WifiMacQueue>
|
||||
MacLow::GetAggregateQueue (void) const
|
||||
{
|
||||
return m_aggregateQueue;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MacLow::GetCfEndSize (void) const
|
||||
{
|
||||
@@ -1676,6 +1609,18 @@ MacLow::ForwardDown (Ptr<const WifiPsdu> psdu, WifiTxVector txVector)
|
||||
{
|
||||
NS_LOG_DEBUG ("Sending A-MPDU");
|
||||
}
|
||||
|
||||
if (psdu->GetNMpdus () > 1)
|
||||
{
|
||||
for (auto& mpdu : *PeekPointer (psdu))
|
||||
{
|
||||
if (mpdu->GetHeader ().IsQosData ())
|
||||
{
|
||||
auto edcaIt = m_edca.find (QosUtilsMapTidToAc (mpdu->GetHeader ().GetQosTid ()));
|
||||
edcaIt->second->CompleteMpduTx (mpdu);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_phy->SendPacket (psdu->GetPacket (), txVector);
|
||||
}
|
||||
@@ -1707,6 +1652,20 @@ MacLow::CtsTimeout (void)
|
||||
/// we should restart a new cts timeout now until the expected
|
||||
/// end of rx if there was a rx start before now.
|
||||
m_stationManager->ReportRtsFailed (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0));
|
||||
// if the current packet is being sent under block ack agreement, store the MPDUs
|
||||
// in the aggregation queue. If not, the retransmission is handled by the QosTxop
|
||||
if (m_currentPacket->GetNMpdus () > 1 ||
|
||||
(m_currentPacket->GetHeader (0).IsQosData ()
|
||||
&& DynamicCast<QosTxop> (m_currentTxop)->GetBaAgreementEstablished (m_currentPacket->GetAddr1 (),
|
||||
m_currentPacket->GetHeader (0).GetQosTid ())))
|
||||
{
|
||||
for (auto& mpdu : *PeekPointer (m_currentPacket))
|
||||
{
|
||||
NS_LOG_DEBUG ("Storing packet with sequence number " << mpdu->GetHeader ().GetSequenceNumber ()
|
||||
<< " in the aggregation queue");
|
||||
m_aggregateQueue->Enqueue (mpdu);
|
||||
}
|
||||
}
|
||||
Ptr<Txop> txop = m_currentTxop;
|
||||
m_currentTxop = 0;
|
||||
m_ampdu = false;
|
||||
@@ -1724,10 +1683,6 @@ MacLow::NormalAckTimeout (void)
|
||||
Ptr<Txop> txop = m_currentTxop;
|
||||
m_currentTxop = 0;
|
||||
m_ampdu = false;
|
||||
if (m_currentPacket->GetHeader (0).IsQosData ())
|
||||
{
|
||||
FlushAggregateQueue (GetTid (m_currentPacket->GetPayload (0), m_currentPacket->GetHeader (0)));
|
||||
}
|
||||
txop->MissedAck ();
|
||||
}
|
||||
|
||||
@@ -1739,9 +1694,7 @@ MacLow::BlockAckTimeout (void)
|
||||
Ptr<Txop> txop = m_currentTxop;
|
||||
m_currentTxop = 0;
|
||||
m_ampdu = false;
|
||||
uint8_t tid = GetTid (m_currentPacket->GetPayload (0), m_currentPacket->GetHeader (0));
|
||||
txop->MissedBlockAck (m_currentPacket->GetNMpdus ());
|
||||
FlushAggregateQueue (tid);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2113,20 +2066,6 @@ MacLow::SendDataAfterCts (Time duration)
|
||||
*/
|
||||
NS_ASSERT (m_currentPacket != 0);
|
||||
|
||||
if (m_currentPacket->GetHeader (0).IsQosData ())
|
||||
{
|
||||
uint8_t tid = GetTid (m_currentPacket->GetPayload (0), m_currentPacket->GetHeader (0));
|
||||
if (!m_aggregateQueue[tid]->IsEmpty ())
|
||||
{
|
||||
for (std::vector<Ptr<WifiMacQueueItem>>::size_type i = 0; i != m_txPackets[tid].size (); i++)
|
||||
{
|
||||
AcIndex ac = QosUtilsMapTidToAc (tid);
|
||||
std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
|
||||
edcaIt->second->CompleteMpduTx (m_txPackets[tid].at (i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StartDataTxTimers (m_currentTxVector);
|
||||
Time newDuration = Seconds (0);
|
||||
if (m_txParams.MustWaitBasicBlockAck ())
|
||||
@@ -2761,25 +2700,6 @@ MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacLow::FlushAggregateQueue (uint8_t tid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +tid);
|
||||
if (!m_aggregateQueue[tid]->IsEmpty ())
|
||||
{
|
||||
NS_LOG_DEBUG ("Flush aggregate queue");
|
||||
m_aggregateQueue[tid]->Flush ();
|
||||
}
|
||||
m_txPackets[tid].clear ();
|
||||
}
|
||||
|
||||
void
|
||||
MacLow::InsertInTxQueue (Ptr<const WifiMacQueueItem> mpdu, uint8_t tid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_txPackets[tid].push_back (mpdu);
|
||||
}
|
||||
|
||||
Time
|
||||
MacLow::GetRemainingCfpDuration (void) const
|
||||
{
|
||||
|
||||
@@ -420,13 +420,6 @@ public:
|
||||
*/
|
||||
void DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector,
|
||||
std::vector<bool> statusPerMpdu);
|
||||
/**
|
||||
*
|
||||
* This function is called to flush the aggregate queue, which is used for A-MPDU
|
||||
* \param tid the Traffic ID
|
||||
*
|
||||
*/
|
||||
void FlushAggregateQueue (uint8_t tid);
|
||||
|
||||
/**
|
||||
* Return a TXVECTOR for the DATA frame given the destination.
|
||||
@@ -479,6 +472,14 @@ public:
|
||||
*/
|
||||
void SetMpduAggregator (const Ptr<MpduAggregator> aggr);
|
||||
|
||||
/**
|
||||
* Get the aggregate queue, which stores the MPDUs that were part of an A-MPDU
|
||||
* that could not be transmitted because the RTS/CTS exchange failed
|
||||
*
|
||||
* \return the aggregate queue
|
||||
*/
|
||||
Ptr<WifiMacQueue> GetAggregateQueue (void) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Cancel all scheduled events. Called before beginning a transmission
|
||||
@@ -854,14 +855,6 @@ private:
|
||||
* \param phy the WifiPhy this MacLow is connected to
|
||||
*/
|
||||
void RemovePhyMacLowListener (Ptr<WifiPhy> phy);
|
||||
/**
|
||||
* Insert in a temporary queue.
|
||||
* It is only used with a RTS/CTS exchange for an A-MPDU transmission.
|
||||
*
|
||||
* \param mpdu MPDU to be inserted in the A-MPDU tx queue
|
||||
* \param tid the Traffic ID of the MPDU to be inserted in the A-MPDU tx queue
|
||||
*/
|
||||
void InsertInTxQueue (Ptr<const WifiMacQueueItem> mpdu, uint8_t tid);
|
||||
|
||||
Ptr<WifiPhy> m_phy; //!< Pointer to WifiPhy (actually send/receives frames)
|
||||
Ptr<WifiMac> m_mac; //!< Pointer to WifiMac (to fetch configuration)
|
||||
@@ -952,8 +945,7 @@ private:
|
||||
QueueEdcas m_edca; //!< EDCA queues
|
||||
|
||||
bool m_ctsToSelfSupported; //!< Flag whether CTS-to-self is supported
|
||||
Ptr<WifiMacQueue> m_aggregateQueue[8]; //!< Queues per TID used for MPDU aggregation
|
||||
std::vector<Ptr<const WifiMacQueueItem>> m_txPackets[8]; //!< Contain temporary items to be sent with the next A-MPDU transmission for a given TID, once RTS/CTS exchange has succeeded.
|
||||
Ptr<WifiMacQueue> m_aggregateQueue; //!< Queue storing MPDUs after RTS/CTS exchange failure
|
||||
WifiTxVector m_currentTxVector; //!< TXVECTOR used for the current packet transmission
|
||||
|
||||
CfAckInfo m_cfAckInfo; //!< Info about piggyback ACKs used in PCF
|
||||
|
||||
@@ -317,6 +317,7 @@ std::vector<Ptr<WifiMacQueueItem>>
|
||||
MpduAggregator::GetNextAmpdu (Ptr<const WifiMacQueueItem> mpdu, WifiTxVector txVector,
|
||||
Time ppduDurationLimit) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *mpdu << ppduDurationLimit);
|
||||
std::vector<Ptr<WifiMacQueueItem>> mpduList;
|
||||
Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
|
||||
|
||||
@@ -339,167 +340,58 @@ MpduAggregator::GetNextAmpdu (Ptr<const WifiMacQueueItem> mpdu, WifiTxVector txV
|
||||
if (edcaIt->second->GetBaAgreementEstablished (recipient, tid))
|
||||
{
|
||||
/* here is performed mpdu aggregation */
|
||||
uint16_t startingSequenceNumber = 0;
|
||||
uint16_t currentSequenceNumber = 0;
|
||||
uint8_t qosPolicy = 0;
|
||||
bool retry = false;
|
||||
Ptr<const WifiMacQueueItem> nextMpdu = mpdu;
|
||||
uint16_t nMpdus = 0; // number of aggregated MPDUs
|
||||
uint16_t startingSequenceNumber = mpdu->GetHeader ().GetSequenceNumber ();
|
||||
Ptr<WifiMacQueueItem> nextMpdu;
|
||||
uint16_t maxMpdus = edcaIt->second->GetBaBufferSize (recipient, tid);
|
||||
uint32_t currentAmpduSize = 0;
|
||||
Ptr<WifiMacQueue> queue = edcaIt->second->GetWifiMacQueue ();
|
||||
Ptr<WifiPhy> phy = edcaIt->second->GetLow ()->GetPhy ();
|
||||
|
||||
// Get the maximum PPDU Duration based on the preamble type. It must be a
|
||||
// non null value because aggregation is available for HT, VHT and HE, which
|
||||
// also provide a limit on the maximum PPDU duration
|
||||
Time maxPpduDuration = GetPpduMaxTime (txVector.GetPreambleType ());
|
||||
NS_ASSERT (maxPpduDuration.IsStrictlyPositive ());
|
||||
|
||||
// the limit on the PPDU duration is the minimum between the maximum PPDU
|
||||
// duration (depending on the PPDU format) and the additional limit provided
|
||||
// by the caller (if non-zero)
|
||||
if (ppduDurationLimit.IsStrictlyPositive ())
|
||||
// check if the received MPDU meets the size and duration constraints
|
||||
if (edcaIt->second->IsWithinSizeAndTimeLimits (mpdu, txVector, 0, ppduDurationLimit))
|
||||
{
|
||||
maxPpduDuration = std::min (maxPpduDuration, ppduDurationLimit);
|
||||
// mpdu can be aggregated
|
||||
nextMpdu = Copy (mpdu);
|
||||
}
|
||||
|
||||
while (nextMpdu != 0)
|
||||
{
|
||||
/* nextMpdu may be any of the following:
|
||||
* (a) an A-MSDU (with all the constituent MSDUs dequeued from
|
||||
* the EDCA queue)
|
||||
* (b) an MSDU dequeued (1st iteration) or peeked (other iterations)
|
||||
* from the EDCA queue
|
||||
* (c) a retransmitted MSDU or A-MSDU dequeued (1st iteration) or
|
||||
* peeked (other iterations) from the BA Manager queue
|
||||
* (d) a control or management frame (only 1st iteration, for now)
|
||||
*/
|
||||
/* if we are here, nextMpdu can be aggregated to the A-MPDU.
|
||||
* nextMpdu may be any of the following:
|
||||
* (a) an A-MSDU (with all the constituent MSDUs dequeued from
|
||||
* the EDCA queue)
|
||||
* (b) an MSDU dequeued from the EDCA queue
|
||||
* (c) a retransmitted MSDU or A-MSDU dequeued from the BA Manager queue
|
||||
* (d) an MPDU that was aggregated in an A-MPDU which was not
|
||||
* transmitted (e.g., because the RTS/CTS exchange failed)
|
||||
*/
|
||||
|
||||
// Check if aggregating nextMpdu violates the constraints on the
|
||||
// maximum A-MPDU size or on the maximum PPDU duration. This is
|
||||
// guaranteed by MsduAggregator::Aggregate in the case of (a)
|
||||
currentAmpduSize = GetSizeIfAggregated (nextMpdu->GetSize (), currentAmpduSize);
|
||||
|
||||
uint32_t ampduSize = GetSizeIfAggregated (nextMpdu->GetSize (), currentAmpduSize);
|
||||
NS_LOG_DEBUG ("Adding packet with sequence number " << nextMpdu->GetHeader ().GetSequenceNumber ()
|
||||
<< " to A-MPDU, packet size = " << nextMpdu->GetSize ()
|
||||
<< ", A-MPDU size = " << currentAmpduSize);
|
||||
|
||||
if (ampduSize > maxAmpduSize ||
|
||||
phy->CalculateTxDuration (ampduSize, txVector, phy->GetFrequency ()) > maxPpduDuration)
|
||||
{
|
||||
NS_LOG_DEBUG ("No other MPDU can be aggregated: " << (ampduSize == 0 ? "size" : "time")
|
||||
<< " limit exceeded");
|
||||
break;
|
||||
}
|
||||
// Always use the Normal Ack policy (Implicit Block Ack), for now
|
||||
nextMpdu->GetHeader ().SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
|
||||
|
||||
// nextMpdu can be aggregated
|
||||
nMpdus++;
|
||||
currentAmpduSize = ampduSize;
|
||||
|
||||
// Update the header of nextMpdu in case it is not a retransmitted packet
|
||||
WifiMacHeader nextHeader = nextMpdu->GetHeader ();
|
||||
|
||||
if (nMpdus == 1) // first MPDU
|
||||
{
|
||||
if (!mpdu->GetHeader ().IsBlockAckReq ())
|
||||
{
|
||||
if (!mpdu->GetHeader ().IsBlockAck ())
|
||||
{
|
||||
startingSequenceNumber = mpdu->GetHeader ().GetSequenceNumber ();
|
||||
nextHeader.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("BlockAck is not handled");
|
||||
}
|
||||
|
||||
currentSequenceNumber = mpdu->GetHeader ().GetSequenceNumber ();
|
||||
}
|
||||
else
|
||||
{
|
||||
qosPolicy = 3; //if the last subframe is block ack req then set ack policy of all frames to blockack
|
||||
CtrlBAckRequestHeader blockAckReq;
|
||||
mpdu->GetPacket ()->PeekHeader (blockAckReq);
|
||||
startingSequenceNumber = blockAckReq.GetStartingSequence ();
|
||||
}
|
||||
/// \todo We should also handle Ack and BlockAck
|
||||
}
|
||||
else if (retry == false)
|
||||
{
|
||||
currentSequenceNumber = edcaIt->second->GetNextSequenceNumberFor (&nextHeader);
|
||||
nextHeader.SetSequenceNumber (currentSequenceNumber);
|
||||
nextHeader.SetFragmentNumber (0);
|
||||
nextHeader.SetNoMoreFragments ();
|
||||
nextHeader.SetNoRetry ();
|
||||
}
|
||||
|
||||
if (qosPolicy == 0)
|
||||
{
|
||||
nextHeader.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextHeader.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK);
|
||||
}
|
||||
|
||||
mpduList.push_back (Create<WifiMacQueueItem> (nextMpdu->GetPacket (), nextHeader,
|
||||
nextMpdu->GetTimeStamp ()));
|
||||
|
||||
// Except for the first iteration, complete the processing of the
|
||||
// current MPDU, which includes removal from the respective queue
|
||||
// (needed for cases (b) and (c) because the packet was just peeked)
|
||||
if (nMpdus >= 2 && nextHeader.IsQosData ())
|
||||
{
|
||||
if (retry)
|
||||
{
|
||||
edcaIt->second->RemoveRetransmitPacket (tid, recipient,
|
||||
nextHeader.GetSequenceNumber ());
|
||||
}
|
||||
else if (nextHeader.IsQosData () && !nextHeader.IsQosAmsdu ())
|
||||
{
|
||||
queue->Remove (nextMpdu->GetPacket ());
|
||||
}
|
||||
}
|
||||
mpduList.push_back (nextMpdu);
|
||||
|
||||
// If allowed by the BA agreement, get the next MPDU
|
||||
nextMpdu = 0;
|
||||
|
||||
if ((nMpdus == 1 || retry) // check retransmit in the 1st iteration or if retry is true
|
||||
&& (nextMpdu = edcaIt->second->PeekNextRetransmitPacket (tid, recipient)) != 0)
|
||||
Ptr<const WifiMacQueueItem> peekedMpdu;
|
||||
peekedMpdu = edcaIt->second->PeekNextFrameByTidAndAddress (tid, recipient);
|
||||
if (peekedMpdu != 0)
|
||||
{
|
||||
retry = true;
|
||||
currentSequenceNumber = nextMpdu->GetHeader ().GetSequenceNumber ();
|
||||
uint16_t currentSequenceNumber = peekedMpdu->GetHeader ().GetSequenceNumber ();
|
||||
|
||||
if (!IsInWindow (currentSequenceNumber, startingSequenceNumber, maxMpdus))
|
||||
if (IsInWindow (currentSequenceNumber, startingSequenceNumber, maxMpdus))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
retry = false;
|
||||
nextMpdu = queue->PeekByTidAndAddress (tid, recipient);
|
||||
|
||||
if (nextMpdu)
|
||||
{
|
||||
currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&nextMpdu->GetHeader ());
|
||||
|
||||
if (!IsInWindow (currentSequenceNumber, startingSequenceNumber, maxMpdus))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Attempt A-MSDU aggregation
|
||||
Ptr<const WifiMacQueueItem> amsdu;
|
||||
if (edcaIt->second->GetLow ()->GetMsduAggregator () != 0)
|
||||
{
|
||||
amsdu = edcaIt->second->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (recipient, tid,
|
||||
txVector,
|
||||
currentAmpduSize,
|
||||
maxPpduDuration);
|
||||
if (amsdu)
|
||||
{
|
||||
nextMpdu = amsdu;
|
||||
}
|
||||
}
|
||||
// dequeue the frame if constraints on size and duration limit are met.
|
||||
// Note that the dequeued MPDU differs from the peeked MPDU if A-MSDU
|
||||
// aggregation is performed during the dequeue
|
||||
NS_LOG_DEBUG ("Trying to aggregate another MPDU");
|
||||
nextMpdu = edcaIt->second->DequeuePeekedFrame (peekedMpdu, txVector, true,
|
||||
currentAmpduSize, ppduDurationLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -509,7 +401,6 @@ MpduAggregator::GetNextAmpdu (Ptr<const WifiMacQueueItem> mpdu, WifiTxVector txV
|
||||
mpduList.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
return mpduList;
|
||||
}
|
||||
|
||||
|
||||
@@ -190,7 +190,26 @@ QosTxop::PeekNextFrame (void)
|
||||
NS_LOG_FUNCTION (this);
|
||||
Ptr<const WifiMacQueueItem> item;
|
||||
|
||||
// check if there is a packet in the BlockAckManager retransmit queue
|
||||
// check if there is a packet in the MacLow aggregation queue
|
||||
for (uint8_t tid = 0; tid < 8; tid++)
|
||||
{
|
||||
if (QosUtilsMapTidToAc (tid) == m_ac)
|
||||
{
|
||||
item = m_low->GetAggregateQueue ()->PeekByTid (tid);
|
||||
if (item != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item != 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("packet peeked from MacLow aggregation queue, " << *item);
|
||||
return item;
|
||||
}
|
||||
|
||||
// otherwise, check if there is a packet in the BlockAckManager retransmit queue
|
||||
item = m_baManager->GetNextPacket (false);
|
||||
|
||||
if (item != 0)
|
||||
@@ -224,7 +243,16 @@ QosTxop::PeekNextFrameByTidAndAddress (uint8_t tid, Mac48Address recipient)
|
||||
NS_LOG_FUNCTION (this << +tid << recipient);
|
||||
Ptr<const WifiMacQueueItem> item;
|
||||
|
||||
// check if there is a packet in the BlockAckManager retransmit queue
|
||||
// check if there is a packet in the MacLow aggregation queue
|
||||
item = m_low->GetAggregateQueue ()->PeekByTidAndAddress (tid, recipient);
|
||||
|
||||
if (item != 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("packet peeked from MacLow aggregation queue, " << *item);
|
||||
return item;
|
||||
}
|
||||
|
||||
// otherwise, check if there is a packet in the BlockAckManager retransmit queue
|
||||
item = m_baManager->PeekNextPacketByTidAndAddress (tid, recipient);
|
||||
|
||||
if (item != 0)
|
||||
@@ -330,7 +358,7 @@ QosTxop::DequeuePeekedFrame (Ptr<const WifiMacQueueItem> peekedItem, WifiTxVecto
|
||||
Ptr<const WifiMacQueueItem> testItem;
|
||||
|
||||
// the packet can only have been peeked from the Block Ack manager retransmit
|
||||
// queue if:
|
||||
// queue or the MacLow aggregation queue if:
|
||||
// - the peeked packet is a QoS Data frame AND
|
||||
// - the peeked packet is not a broadcast frame AND
|
||||
// - an agreement has been established
|
||||
@@ -338,6 +366,17 @@ QosTxop::DequeuePeekedFrame (Ptr<const WifiMacQueueItem> peekedItem, WifiTxVecto
|
||||
&& GetBaAgreementEstablished (recipient, peekedItem->GetHeader ().GetQosTid ()))
|
||||
{
|
||||
uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
|
||||
testItem = m_low->GetAggregateQueue ()->PeekByTidAndAddress (tid, recipient);
|
||||
|
||||
if (testItem)
|
||||
{
|
||||
// if not null, the test packet must equal the peeked packet
|
||||
NS_ASSERT (testItem->GetPacket () == peekedItem->GetPacket ());
|
||||
item = m_low->GetAggregateQueue ()->DequeueByTidAndAddress (tid, recipient);
|
||||
NS_LOG_DEBUG ("dequeued from aggregation queue: " << *item);
|
||||
return item;
|
||||
}
|
||||
|
||||
testItem = m_baManager->PeekNextPacketByTidAndAddress (tid, recipient);
|
||||
|
||||
if (testItem)
|
||||
@@ -351,6 +390,9 @@ QosTxop::DequeuePeekedFrame (Ptr<const WifiMacQueueItem> peekedItem, WifiTxVecto
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE if frames other than QoS Data frame can be aggregated into A-MPDUs and hence
|
||||
// potentially stored in the MacLow aggregation queue, then handle them here
|
||||
|
||||
// the packet has been peeked from the EDCA queue. If it is a QoS Data frame and
|
||||
// it is not a broadcast frame, attempt A-MSDU aggregation if aggregate is true
|
||||
if (peekedItem->GetHeader ().IsQosData ())
|
||||
@@ -403,6 +445,13 @@ QosTxop::NotifyAccessGranted (void)
|
||||
m_accessRequested = false;
|
||||
m_isAccessRequestedForRts = false;
|
||||
m_startTxop = Simulator::Now ();
|
||||
// discard the current packet if it is a QoS Data frame with expired lifetime
|
||||
if (m_currentPacket != 0 && m_currentHdr.IsQosData ()
|
||||
&& (m_currentPacketTimestamp + m_queue->GetMaxDelay () < Simulator::Now ()))
|
||||
{
|
||||
NS_LOG_DEBUG ("the lifetime of current packet expired");
|
||||
m_currentPacket = 0;
|
||||
}
|
||||
if (m_currentPacket == 0)
|
||||
{
|
||||
if (m_baManager->HasBar (m_currentBar))
|
||||
@@ -613,7 +662,6 @@ QosTxop::MissedCts (void)
|
||||
if (GetAmpduExist (m_currentHdr.GetAddr1 ()) || m_currentHdr.IsQosData ())
|
||||
{
|
||||
uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
|
||||
m_low->FlushAggregateQueue (tid);
|
||||
|
||||
if (GetBaAgreementEstablished (m_currentHdr.GetAddr1 (), tid))
|
||||
{
|
||||
@@ -653,6 +701,13 @@ QosTxop::MissedCts (void)
|
||||
{
|
||||
UpdateFailedCw ();
|
||||
m_cwTrace = GetCw ();
|
||||
// if a BA agreement is established, packets have been stored in MacLow
|
||||
// aggregation queue for retransmission
|
||||
if (m_currentHdr.IsQosData () && GetBaAgreementEstablished (m_currentHdr.GetAddr1 (),
|
||||
m_currentHdr.GetQosTid ()))
|
||||
{
|
||||
m_currentPacket = 0;
|
||||
}
|
||||
}
|
||||
m_backoff = m_rng->GetInteger (0, GetCw ());
|
||||
m_backoffTrace (m_backoff);
|
||||
|
||||
@@ -147,9 +147,9 @@ AmpduAggregationTest::DoRun (void)
|
||||
(*m_mac->GetBEQueue ()->GetLow ()->m_currentPacket->begin ());
|
||||
|
||||
auto mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu
|
||||
(Create<const WifiMacQueueItem> (pkt, hdr), m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector);
|
||||
(Create<WifiMacQueueItem> (pkt, hdr), m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector);
|
||||
NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "a single packet should not result in an A-MPDU");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->GetNPackets (), 0, "aggregation queue is not flushed");
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -173,15 +173,15 @@ AmpduAggregationTest::DoRun (void)
|
||||
m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt1, hdr1));
|
||||
m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt2, hdr2));
|
||||
|
||||
mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create<const WifiMacQueueItem> (pkt, hdr),
|
||||
mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create<WifiMacQueueItem> (pkt, hdr),
|
||||
m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector);
|
||||
m_mac->GetBEQueue ()->GetLow ()->m_currentPacket = Create<WifiPsdu> (mpduList);
|
||||
for (auto& mpdu : mpduList)
|
||||
{
|
||||
m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue[0]->Enqueue (Create<WifiMacQueueItem> (*mpdu));
|
||||
m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->Enqueue (Create<WifiMacQueueItem> (*mpdu));
|
||||
}
|
||||
|
||||
uint32_t aggregationQueueSize = m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue[0]->GetNPackets ();
|
||||
uint32_t aggregationQueueSize = m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->GetNPackets ();
|
||||
NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), false, "MPDU aggregation failed");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_currentPacket->GetSize (), 4606, "A-MPDU size is not correct");
|
||||
NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 3, "aggregation queue should not be empty");
|
||||
@@ -192,7 +192,7 @@ AmpduAggregationTest::DoRun (void)
|
||||
uint32_t i = 0;
|
||||
for (; aggregationQueueSize > 0; aggregationQueueSize--, i++)
|
||||
{
|
||||
dequeuedItem = m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue[0]->Dequeue ();
|
||||
dequeuedItem = m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->Dequeue ();
|
||||
dequeuedHdr = dequeuedItem->GetHeader ();
|
||||
NS_TEST_EXPECT_MSG_EQ (dequeuedHdr.GetSequenceNumber (), i, "wrong sequence number");
|
||||
}
|
||||
@@ -227,17 +227,17 @@ AmpduAggregationTest::DoRun (void)
|
||||
|
||||
m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt3, hdr3));
|
||||
|
||||
mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create<const WifiMacQueueItem> (pkt1, hdr1),
|
||||
mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create<WifiMacQueueItem> (pkt1, hdr1),
|
||||
m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector);
|
||||
NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "a single packet for this destination should not result in an A-MPDU");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->GetNPackets (), 0, "aggregation queue is not flushed");
|
||||
|
||||
m_mac->GetBEQueue ()->m_currentHdr = hdr2;
|
||||
m_mac->GetBEQueue ()->m_currentPacket = pkt2->Copy ();
|
||||
mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu
|
||||
(Create<const WifiMacQueueItem> (pkt2, hdr2), m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector);
|
||||
(Create<WifiMacQueueItem> (pkt2, hdr2), m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector);
|
||||
NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "no MPDU aggregation should be performed if there is no agreement");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->GetNPackets (), 0, "aggregation queue is not flushed");
|
||||
|
||||
m_manager->SetMaxSsrc (0); //set to 0 in order to fake that the maximum number of retries has been reached
|
||||
m_mac->GetBEQueue ()->MissedAck ();
|
||||
@@ -541,15 +541,15 @@ HeAggregationTest::DoRunSubTest (uint16_t bufferSize)
|
||||
m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
|
||||
}
|
||||
|
||||
auto mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create<const WifiMacQueueItem> (pkt, hdr),
|
||||
auto mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create<WifiMacQueueItem> (pkt, hdr),
|
||||
m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector);
|
||||
for (auto& mpdu : mpduList)
|
||||
{
|
||||
m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue[0]->Enqueue (Create<WifiMacQueueItem> (*mpdu));
|
||||
m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->Enqueue (Create<WifiMacQueueItem> (*mpdu));
|
||||
}
|
||||
|
||||
NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), false, "MPDU aggregation failed");
|
||||
uint32_t aggregationQueueSize = m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue[0]->GetNPackets ();
|
||||
uint32_t aggregationQueueSize = m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->GetNPackets ();
|
||||
NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, bufferSize, "aggregation queue should countain " << bufferSize << " MPDUs");
|
||||
uint16_t expectedRemainingPacketsInQueue = 300 - bufferSize + 1;
|
||||
NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetWifiMacQueue ()->GetNPackets (), expectedRemainingPacketsInQueue, "queue should contain 300 - "<< bufferSize - 1 << " = "<< expectedRemainingPacketsInQueue << " packets");
|
||||
|
||||
Reference in New Issue
Block a user