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:
Stefano Avallone
2019-03-02 22:27:55 +01:00
parent 94cc4b70dd
commit df5ceef9a9
5 changed files with 164 additions and 306 deletions

View File

@@ -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
{

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);

View File

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