wifi: QosTxop does not return packets outside of the current transmit window
Also, make use of the new variants of the WifiMacQueue methods and remove unused BlockAckManager methods
This commit is contained in:
@@ -222,6 +222,12 @@ BlockAckManager::UpdateAgreement (const MgtAddBaResponseHeader *respHdr, Mac48Ad
|
||||
m_unblockPackets (recipient, tid);
|
||||
}
|
||||
|
||||
Ptr<WifiMacQueue>
|
||||
BlockAckManager::GetRetransmitQueue (void)
|
||||
{
|
||||
return m_retryPackets;
|
||||
}
|
||||
|
||||
void
|
||||
BlockAckManager::StorePacket (Ptr<WifiMacQueueItem> mpdu)
|
||||
{
|
||||
@@ -252,178 +258,6 @@ BlockAckManager::StorePacket (Ptr<WifiMacQueueItem> mpdu)
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<WifiMacQueueItem>
|
||||
BlockAckManager::GetNextPacket (bool removePacket)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << removePacket);
|
||||
Ptr<WifiMacQueueItem> item;
|
||||
uint8_t tid;
|
||||
Mac48Address recipient;
|
||||
CleanupBuffers ();
|
||||
if (!m_retryPackets->IsEmpty ())
|
||||
{
|
||||
NS_LOG_DEBUG ("Retry buffer size is " << m_retryPackets->GetNPackets ());
|
||||
WifiMacQueue::ConstIterator it = m_retryPackets->begin ();
|
||||
while (it != m_retryPackets->end ())
|
||||
{
|
||||
if ((*it)->GetHeader ().IsQosData ())
|
||||
{
|
||||
tid = (*it)->GetHeader ().GetQosTid ();
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Packet in blockAck manager retry queue is not Qos Data");
|
||||
}
|
||||
recipient = (*it)->GetHeader ().GetAddr1 ();
|
||||
AgreementsI agreement = m_agreements.find (std::make_pair (recipient, tid));
|
||||
NS_ASSERT (agreement != m_agreements.end ());
|
||||
if (removePacket)
|
||||
{
|
||||
if (QosUtilsIsOldPacket (agreement->second.first.GetStartingSequence (), (*it)->GetHeader ().GetSequenceNumber ()))
|
||||
{
|
||||
//Standard says the originator should not send a packet with seqnum < winstart
|
||||
NS_LOG_DEBUG ("The Retry packet have sequence number < WinStartO --> Discard "
|
||||
<< (*it)->GetHeader ().GetSequenceNumber () << " "
|
||||
<< agreement->second.first.GetStartingSequence ());
|
||||
agreement->second.second.remove ((*it));
|
||||
it = m_retryPackets->Remove (it);
|
||||
continue;
|
||||
}
|
||||
else if (((((*it)->GetHeader ().GetSequenceNumber () - agreement->second.first.GetStartingSequence ()) + 4096) % 4096) > (agreement->second.first.GetBufferSize () - 1))
|
||||
{
|
||||
agreement->second.first.SetStartingSequence ((*it)->GetHeader ().GetSequenceNumber ());
|
||||
}
|
||||
}
|
||||
item = *it;
|
||||
item->GetHeader ().SetRetry ();
|
||||
if (item->GetHeader ().IsQosData ())
|
||||
{
|
||||
tid = item->GetHeader ().GetQosTid ();
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Packet in blockAck manager retry queue is not Qos Data");
|
||||
}
|
||||
recipient = item->GetHeader ().GetAddr1 ();
|
||||
if (!agreement->second.first.IsHtSupported ()
|
||||
&& (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED)
|
||||
|| SwitchToBlockAckIfNeeded (recipient, tid, item->GetHeader ().GetSequenceNumber ())))
|
||||
{
|
||||
item->GetHeader ().SetQosAckPolicy (WifiMacHeader::BLOCK_ACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* From section 9.10.3 in IEEE802.11e standard:
|
||||
* In order to improve efficiency, originators using the Block Ack facility
|
||||
* may send MPDU frames with the Ack Policy subfield in QoS control frames
|
||||
* set to Normal Ack if only a few MPDUs are available for transmission.[...]
|
||||
* When there are sufficient number of MPDUs, the originator may switch back to
|
||||
* the use of Block Ack.
|
||||
*/
|
||||
item->GetHeader ().SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
|
||||
if (removePacket)
|
||||
{
|
||||
AgreementsI i = m_agreements.find (std::make_pair (recipient, tid));
|
||||
i->second.second.remove (*it);
|
||||
}
|
||||
}
|
||||
if (removePacket)
|
||||
{
|
||||
NS_LOG_INFO ("Retry packet seq = " << item->GetHeader ().GetSequenceNumber ());
|
||||
it = m_retryPackets->Remove (it);
|
||||
NS_LOG_DEBUG ("Removed one packet, retry buffer size = " << m_retryPackets->GetNPackets ());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
Ptr<const WifiMacQueueItem>
|
||||
BlockAckManager::PeekNextPacketByTidAndAddress (uint8_t tid, Mac48Address recipient)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Ptr<const WifiMacQueueItem> item = 0;
|
||||
CleanupBuffers ();
|
||||
AgreementsI agreement = m_agreements.find (std::make_pair (recipient, tid));
|
||||
NS_ASSERT (agreement != m_agreements.end ());
|
||||
WifiMacQueue::ConstIterator it = m_retryPackets->begin ();
|
||||
for (; it != m_retryPackets->end (); it++)
|
||||
{
|
||||
if (!(*it)->GetHeader ().IsQosData ())
|
||||
{
|
||||
NS_FATAL_ERROR ("Packet in blockAck manager retry queue is not Qos Data");
|
||||
}
|
||||
if ((*it)->GetHeader ().GetAddr1 () == recipient && (*it)->GetHeader ().GetQosTid () == tid)
|
||||
{
|
||||
if (QosUtilsIsOldPacket (agreement->second.first.GetStartingSequence (), (*it)->GetHeader ().GetSequenceNumber ()))
|
||||
{
|
||||
//standard says the originator should not send a packet with seqnum < winstart
|
||||
NS_LOG_DEBUG ("The Retry packet have sequence number < WinStartO --> Discard "
|
||||
<< (*it)->GetHeader ().GetSequenceNumber () << " "
|
||||
<< agreement->second.first.GetStartingSequence ());
|
||||
agreement->second.second.remove ((*it));
|
||||
it = m_retryPackets->Remove (it);
|
||||
it--;
|
||||
continue;
|
||||
}
|
||||
else if (((((*it)->GetHeader ().GetSequenceNumber () - agreement->second.first.GetStartingSequence ()) + 4096) % 4096) > (agreement->second.first.GetBufferSize () - 1))
|
||||
{
|
||||
agreement->second.first.SetStartingSequence ((*it)->GetHeader ().GetSequenceNumber ());
|
||||
}
|
||||
WifiMacHeader hdr = (*it)->GetHeader ();
|
||||
hdr.SetRetry ();
|
||||
item = Create<const WifiMacQueueItem> ((*it)->GetPacket (), hdr, (*it)->GetTimeStamp ());
|
||||
NS_LOG_INFO ("Retry packet seq = " << hdr.GetSequenceNumber ());
|
||||
if (!agreement->second.first.IsHtSupported ()
|
||||
&& (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED)
|
||||
|| SwitchToBlockAckIfNeeded (recipient, tid, hdr.GetSequenceNumber ())))
|
||||
{
|
||||
hdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* From section 9.10.3 in IEEE802.11e standard:
|
||||
* In order to improve efficiency, originators using the Block Ack facility
|
||||
* may send MPDU frames with the Ack Policy subfield in QoS control frames
|
||||
* set to Normal Ack if only a few MPDUs are available for transmission.[...]
|
||||
* When there are sufficient number of MPDUs, the originator may switch back to
|
||||
* the use of Block Ack.
|
||||
*/
|
||||
hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
|
||||
}
|
||||
NS_LOG_DEBUG ("Peeked one packet from retry buffer size = " << m_retryPackets->GetNPackets () );
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
bool
|
||||
BlockAckManager::RemovePacket (uint8_t tid, Mac48Address recipient, uint16_t seqnumber)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << seqnumber);
|
||||
WifiMacQueue::ConstIterator it = m_retryPackets->begin ();
|
||||
for (; it != m_retryPackets->end (); it++)
|
||||
{
|
||||
if (!(*it)->GetHeader ().IsQosData ())
|
||||
{
|
||||
NS_FATAL_ERROR ("Packet in blockAck manager retry queue is not Qos Data");
|
||||
}
|
||||
if ((*it)->GetHeader ().GetAddr1 () == recipient && (*it)->GetHeader ().GetQosTid () == tid
|
||||
&& (*it)->GetHeader ().GetSequenceNumber () == seqnumber)
|
||||
{
|
||||
WifiMacHeader hdr = (*it)->GetHeader ();
|
||||
AgreementsI i = m_agreements.find (std::make_pair (recipient, tid));
|
||||
i->second.second.remove ((*it));
|
||||
m_retryPackets->Remove (it);
|
||||
NS_LOG_DEBUG ("Removed Packet from retry queue = " << hdr.GetSequenceNumber () << " " << +tid << " " << recipient << " Buffer Size = " << m_retryPackets->GetNPackets ());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
BlockAckManager::HasBar (Bar &bar, bool remove)
|
||||
{
|
||||
|
||||
@@ -153,15 +153,6 @@ public:
|
||||
* if the packet, in a block ack frame, is indicated by recipient as not received.
|
||||
*/
|
||||
void StorePacket (Ptr<WifiMacQueueItem> mpdu);
|
||||
/**
|
||||
* \param removePacket flag to indicate whether the packet should be removed from the queue.
|
||||
*
|
||||
* \return the packet
|
||||
*
|
||||
* This methods returns a packet (if exists) indicated as not received in
|
||||
* corresponding block ack bitmap.
|
||||
*/
|
||||
Ptr<WifiMacQueueItem> GetNextPacket (bool removePacket);
|
||||
/**
|
||||
* Returns true if the BAR is scheduled. Returns false otherwise.
|
||||
*
|
||||
@@ -290,6 +281,12 @@ public:
|
||||
* and buffered packets) is greater of <i>nPackets</i>, they are transmitted using block ack mechanism.
|
||||
*/
|
||||
void SetBlockAckThreshold (uint8_t nPackets);
|
||||
/**
|
||||
* \return the retransmit queue.
|
||||
*
|
||||
* Return the retransmit queue.
|
||||
*/
|
||||
Ptr<WifiMacQueue> GetRetransmitQueue (void);
|
||||
|
||||
/**
|
||||
* \param queue The WifiMacQueue object.
|
||||
@@ -355,27 +352,8 @@ public:
|
||||
*/
|
||||
bool AlreadyExists (uint16_t currentSeq, Mac48Address recipient, uint8_t tid) const;
|
||||
/**
|
||||
* Remove a packet after you peek in the queue and get it
|
||||
* \param tid the Traffic ID
|
||||
* \param recipient the destination address
|
||||
* \param seqnumber sequence number
|
||||
* \returns true if a packet was removed
|
||||
*/
|
||||
bool RemovePacket (uint8_t tid, Mac48Address recipient, uint16_t seqnumber);
|
||||
/**
|
||||
* Peek in retransmit queue and get the next packet having address indicated
|
||||
* by <i>type</i> equals to <i>addr</i>, and tid equals to <i>tid</i>.
|
||||
* This method doesn't remove the packet from this queue.
|
||||
*
|
||||
* \param hdr wifi mac header
|
||||
* \param tid Traffic ID
|
||||
* \param timestamp timestamp
|
||||
*
|
||||
* \returns Ptr<const WifiMacQueueItem>
|
||||
*/
|
||||
Ptr<const WifiMacQueueItem> PeekNextPacketByTidAndAddress (uint8_t tid, Mac48Address recipient);
|
||||
/**
|
||||
* This function returns true if the lifetime of the packets a BAR refers to didn't expire yet else it returns false.
|
||||
* This function returns true if the lifetime of the packets a BAR refers to didn't
|
||||
* expire yet otherwise it returns false.
|
||||
* If it return false then the BAR will be discarded (i.e. will not be re-transmitted)
|
||||
*
|
||||
* \param tid Traffic ID
|
||||
|
||||
@@ -173,17 +173,36 @@ QosTxop::PeekNextSequenceNumberFor (const WifiMacHeader *hdr)
|
||||
return m_txMiddle->PeekNextSequenceNumberFor (hdr);
|
||||
}
|
||||
|
||||
Ptr<const WifiMacQueueItem>
|
||||
QosTxop::PeekNextRetransmitPacket (uint8_t tid, Mac48Address recipient)
|
||||
bool
|
||||
QosTxop::IsQosOldPacket (Ptr<const WifiMacQueueItem> mpdu)
|
||||
{
|
||||
return m_baManager->PeekNextPacketByTidAndAddress (tid, recipient);
|
||||
NS_LOG_FUNCTION (this << *mpdu);
|
||||
|
||||
if (!mpdu->GetHeader ().IsQosData ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
|
||||
uint8_t tid = mpdu->GetHeader ().GetQosTid ();
|
||||
|
||||
if (!GetBaAgreementEstablished (recipient, tid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (QosUtilsIsOldPacket (GetBaStartingSequence (recipient, tid),
|
||||
mpdu->GetHeader ().GetSequenceNumber ()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Ptr<const WifiMacQueueItem>
|
||||
QosTxop::PeekNextFrame (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Ptr<const WifiMacQueueItem> item;
|
||||
WifiMacQueue::ConstIterator it;
|
||||
|
||||
// check if there is a packet in the MacLow aggregation queue
|
||||
@@ -192,92 +211,131 @@ QosTxop::PeekNextFrame (void)
|
||||
if (QosUtilsMapTidToAc (tid) == m_ac)
|
||||
{
|
||||
it = m_low->GetAggregateQueue ()->PeekByTid (tid);
|
||||
// remove old packets
|
||||
while (it != m_low->GetAggregateQueue ()->end () && IsQosOldPacket (*it))
|
||||
{
|
||||
NS_LOG_DEBUG ("removing an old packet from MacLow aggregation queue: " << **it);
|
||||
it = m_low->GetAggregateQueue ()->Remove (it);
|
||||
it = m_low->GetAggregateQueue ()->PeekByTid (tid, it);
|
||||
}
|
||||
if (it != m_low->GetAggregateQueue ()->end ())
|
||||
{
|
||||
item = *it;
|
||||
break;
|
||||
NS_LOG_DEBUG ("packet peeked from MacLow aggregation queue: " << **it);
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
it = m_baManager->GetRetransmitQueue ()->PeekFirstAvailable ();
|
||||
// remove old packets
|
||||
while (it != m_baManager->GetRetransmitQueue ()->end () && IsQosOldPacket (*it))
|
||||
{
|
||||
NS_LOG_DEBUG ("packet peeked from BlockAckManager retransmit queue: " << *item);
|
||||
return item;
|
||||
NS_LOG_DEBUG ("removing an old packet from BlockAckManager retransmit queue: " << **it);
|
||||
it = m_baManager->GetRetransmitQueue ()->Remove (it);
|
||||
it = m_baManager->GetRetransmitQueue ()->PeekFirstAvailable (nullptr, it);
|
||||
}
|
||||
if (it != m_baManager->GetRetransmitQueue ()->end ())
|
||||
{
|
||||
NS_LOG_DEBUG ("packet peeked from BlockAckManager retransmit queue: " << **it);
|
||||
return *it;
|
||||
}
|
||||
|
||||
// otherwise, check if there is a packet in the EDCA queue
|
||||
it = m_queue->PeekFirstAvailable (m_qosBlockedDestinations);
|
||||
|
||||
if (it != m_queue->end ())
|
||||
{
|
||||
item = *it;
|
||||
// set the sequence number by just peeking the next value
|
||||
uint16_t sequence = m_txMiddle->PeekNextSequenceNumberFor (&item->GetHeader ());
|
||||
WifiMacHeader hdr = item->GetHeader ();
|
||||
// peek the next sequence number and check if it is within the transmit window
|
||||
// in case of QoS data frame
|
||||
uint16_t sequence = m_txMiddle->PeekNextSequenceNumberFor (&(*it)->GetHeader ());
|
||||
if ((*it)->GetHeader ().IsQosData ())
|
||||
{
|
||||
Mac48Address recipient = (*it)->GetHeader ().GetAddr1 ();
|
||||
uint8_t tid = (*it)->GetHeader ().GetQosTid ();
|
||||
|
||||
if (GetBaAgreementEstablished (recipient, tid)
|
||||
&& !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
|
||||
{
|
||||
NS_LOG_DEBUG ("packet beyond the end of the current transmit window");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
WifiMacHeader hdr = (*it)->GetHeader ();
|
||||
hdr.SetSequenceNumber (sequence);
|
||||
hdr.SetFragmentNumber (0);
|
||||
hdr.SetNoMoreFragments ();
|
||||
hdr.SetNoRetry ();
|
||||
item = Create<const WifiMacQueueItem> (item->GetPacket (), hdr, item->GetTimeStamp ());
|
||||
Ptr<const WifiMacQueueItem> item = Create<const WifiMacQueueItem> ((*it)->GetPacket (), hdr, (*it)->GetTimeStamp ());
|
||||
NS_LOG_DEBUG ("packet peeked from EDCA queue: " << *item);
|
||||
return item;
|
||||
}
|
||||
|
||||
return item;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Ptr<const WifiMacQueueItem>
|
||||
QosTxop::PeekNextFrameByTidAndAddress (uint8_t tid, Mac48Address recipient)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +tid << recipient);
|
||||
Ptr<const WifiMacQueueItem> item;
|
||||
WifiMacQueue::ConstIterator it;
|
||||
|
||||
// check if there is a packet in the MacLow aggregation queue
|
||||
WifiMacQueue::ConstIterator it = m_low->GetAggregateQueue ()->PeekByTidAndAddress (tid, recipient);
|
||||
|
||||
it = m_low->GetAggregateQueue ()->PeekByTidAndAddress (tid, recipient);
|
||||
// remove old packets
|
||||
while (it != m_low->GetAggregateQueue ()->end () && IsQosOldPacket (*it))
|
||||
{
|
||||
NS_LOG_DEBUG ("removing an old packet from MacLow aggregation queue: " << **it);
|
||||
it = m_low->GetAggregateQueue ()->Remove (it);
|
||||
it = m_low->GetAggregateQueue ()->PeekByTidAndAddress (tid, recipient, it);
|
||||
}
|
||||
if (it != m_low->GetAggregateQueue ()->end ())
|
||||
{
|
||||
item = *it;
|
||||
NS_LOG_DEBUG ("packet peeked from MacLow aggregation queue, " << *item);
|
||||
return item;
|
||||
NS_LOG_DEBUG ("packet peeked from MacLow aggregation queue: " << **it);
|
||||
return *it;
|
||||
}
|
||||
|
||||
// otherwise, check if there is a packet in the BlockAckManager retransmit queue
|
||||
item = m_baManager->PeekNextPacketByTidAndAddress (tid, recipient);
|
||||
|
||||
if (item != 0)
|
||||
it = m_baManager->GetRetransmitQueue ()->PeekByTidAndAddress (tid, recipient);
|
||||
// remove old packets
|
||||
while (it != m_baManager->GetRetransmitQueue ()->end () && IsQosOldPacket (*it))
|
||||
{
|
||||
NS_LOG_DEBUG ("packet peeked from BlockAckManager retransmit queue: " << *item);
|
||||
return item;
|
||||
NS_LOG_DEBUG ("removing an old packet from BlockAckManager retransmit queue: " << **it);
|
||||
it = m_baManager->GetRetransmitQueue ()->Remove (it);
|
||||
it = m_baManager->GetRetransmitQueue ()->PeekByTidAndAddress (tid, recipient, it);
|
||||
}
|
||||
if (it != m_baManager->GetRetransmitQueue ()->end ())
|
||||
{
|
||||
NS_LOG_DEBUG ("packet peeked from BlockAckManager retransmit queue: " << **it);
|
||||
return *it;
|
||||
}
|
||||
|
||||
// otherwise, check if there is a packet in the EDCA queue
|
||||
it = m_queue->PeekByTidAndAddress (tid, recipient);
|
||||
|
||||
if (it != m_queue->end ())
|
||||
{
|
||||
item = *it;
|
||||
// set the sequence number by just peeking the next value
|
||||
uint16_t sequence = m_txMiddle->PeekNextSequenceNumberFor (&item->GetHeader ());
|
||||
WifiMacHeader hdr = item->GetHeader ();
|
||||
// peek the next sequence number and check if it is within the transmit window
|
||||
// in case of QoS data frame
|
||||
uint16_t sequence = m_txMiddle->PeekNextSequenceNumberFor (&(*it)->GetHeader ());
|
||||
if ((*it)->GetHeader ().IsQosData ()
|
||||
&& GetBaAgreementEstablished (recipient, tid)
|
||||
&& !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
|
||||
{
|
||||
NS_LOG_DEBUG ("packet beyond the end of the current transmit window");
|
||||
return 0;
|
||||
}
|
||||
|
||||
WifiMacHeader hdr = (*it)->GetHeader ();
|
||||
hdr.SetSequenceNumber (sequence);
|
||||
hdr.SetFragmentNumber (0);
|
||||
hdr.SetNoMoreFragments ();
|
||||
hdr.SetNoRetry ();
|
||||
item = Create<const WifiMacQueueItem> (item->GetPacket (), hdr, item->GetTimeStamp ());
|
||||
Ptr<const WifiMacQueueItem> item = Create<const WifiMacQueueItem> ((*it)->GetPacket (), hdr, (*it)->GetTimeStamp ());
|
||||
NS_LOG_DEBUG ("packet peeked from EDCA queue: " << *item);
|
||||
return item;
|
||||
}
|
||||
|
||||
return item;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -356,6 +414,7 @@ QosTxop::DequeuePeekedFrame (Ptr<const WifiMacQueueItem> peekedItem, WifiTxVecto
|
||||
Mac48Address recipient = peekedItem->GetHeader ().GetAddr1 ();
|
||||
Ptr<WifiMacQueueItem> item;
|
||||
Ptr<const WifiMacQueueItem> testItem;
|
||||
WifiMacQueue::ConstIterator testIt;
|
||||
|
||||
// the packet can only have been peeked from the Block Ack manager retransmit
|
||||
// queue or the MacLow aggregation queue if:
|
||||
@@ -366,26 +425,32 @@ QosTxop::DequeuePeekedFrame (Ptr<const WifiMacQueueItem> peekedItem, WifiTxVecto
|
||||
&& GetBaAgreementEstablished (recipient, peekedItem->GetHeader ().GetQosTid ()))
|
||||
{
|
||||
uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
|
||||
WifiMacQueue::ConstIterator testIt = m_low->GetAggregateQueue ()->PeekByTidAndAddress (tid, recipient);
|
||||
testIt = m_low->GetAggregateQueue ()->PeekByTidAndAddress (tid, recipient);
|
||||
|
||||
if (testIt != m_low->GetAggregateQueue ()->end ())
|
||||
{
|
||||
testItem = *testIt;
|
||||
// if not null, the test packet must equal the peeked packet
|
||||
NS_ASSERT (testItem->GetPacket () == peekedItem->GetPacket ());
|
||||
item = m_low->GetAggregateQueue ()->DequeueByTidAndAddress (tid, recipient);
|
||||
// we should not be asked to dequeue an old packet
|
||||
NS_ASSERT (!QosUtilsIsOldPacket (GetBaStartingSequence (recipient, tid),
|
||||
testItem->GetHeader ().GetSequenceNumber ()));
|
||||
item = m_low->GetAggregateQueue ()->Dequeue (testIt);
|
||||
NS_LOG_DEBUG ("dequeued from aggregation queue: " << *item);
|
||||
return item;
|
||||
}
|
||||
|
||||
testItem = m_baManager->PeekNextPacketByTidAndAddress (tid, recipient);
|
||||
testIt = m_baManager->GetRetransmitQueue ()->PeekByTidAndAddress (tid, recipient);
|
||||
|
||||
if (testItem)
|
||||
if (testIt != m_baManager->GetRetransmitQueue ()->end ())
|
||||
{
|
||||
testItem = *testIt;
|
||||
// if not null, the test packet must equal the peeked packet
|
||||
NS_ASSERT (testItem->GetPacket () == peekedItem->GetPacket ());
|
||||
item = Create<WifiMacQueueItem> (*peekedItem);
|
||||
m_baManager->RemovePacket (tid, recipient, testItem->GetHeader ().GetSequenceNumber ());
|
||||
// we should not be asked to dequeue an old packet
|
||||
NS_ASSERT (!QosUtilsIsOldPacket (GetBaStartingSequence (recipient, tid),
|
||||
testItem->GetHeader ().GetSequenceNumber ()));
|
||||
item = m_baManager->GetRetransmitQueue ()->Dequeue (testIt);
|
||||
NS_LOG_DEBUG ("dequeued from BA manager queue: " << *item);
|
||||
return item;
|
||||
}
|
||||
@@ -394,15 +459,26 @@ 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
|
||||
// the packet has been peeked from the EDCA queue.
|
||||
uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&peekedItem->GetHeader ());
|
||||
|
||||
// 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 ())
|
||||
{
|
||||
uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
|
||||
WifiMacQueue::ConstIterator testIt = m_queue->PeekByTidAndAddress (tid, recipient);
|
||||
testIt = m_queue->PeekByTidAndAddress (tid, recipient);
|
||||
|
||||
NS_ASSERT (testIt != m_queue->end () && (*testIt)->GetPacket () == peekedItem->GetPacket ());
|
||||
|
||||
// check if the peeked packet is within the transmit window
|
||||
if (GetBaAgreementEstablished (recipient, tid)
|
||||
&& !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
|
||||
{
|
||||
NS_LOG_DEBUG ("packet beyond the end of the current transmit window");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// try A-MSDU aggregation
|
||||
if (m_low->GetMsduAggregator () != 0 && !recipient.IsBroadcast () && aggregate)
|
||||
{
|
||||
@@ -415,7 +491,7 @@ QosTxop::DequeuePeekedFrame (Ptr<const WifiMacQueueItem> peekedItem, WifiTxVecto
|
||||
}
|
||||
else // aggregation was not attempted or failed
|
||||
{
|
||||
item = m_queue->DequeueByTidAndAddress (tid, recipient);
|
||||
item = m_queue->Dequeue (testIt);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -428,7 +504,6 @@ QosTxop::DequeuePeekedFrame (Ptr<const WifiMacQueueItem> peekedItem, WifiTxVecto
|
||||
|
||||
// Assign a sequence number to the MSDU or A-MSDU dequeued from the EDCA queue
|
||||
NS_ASSERT (item != 0);
|
||||
uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&item->GetHeader ());
|
||||
item->GetHeader ().SetSequenceNumber (sequence);
|
||||
item->GetHeader ().SetFragmentNumber (0);
|
||||
item->GetHeader ().SetNoMoreFragments ();
|
||||
|
||||
@@ -379,14 +379,6 @@ public:
|
||||
* \return the next sequence number.
|
||||
*/
|
||||
uint16_t PeekNextSequenceNumberFor (const WifiMacHeader *hdr);
|
||||
/**
|
||||
* Peek in retransmit queue and get the next packet without removing it from the queue.
|
||||
*
|
||||
* \param tid traffic ID.
|
||||
* \param recipient the receiver station address.
|
||||
* \returns the packet.
|
||||
*/
|
||||
Ptr<const WifiMacQueueItem> PeekNextRetransmitPacket (uint8_t tid, Mac48Address recipient);
|
||||
/**
|
||||
* Peek the next frame to transmit from the Block Ack manager retransmit
|
||||
* queue first and, if not found, from the EDCA queue.
|
||||
@@ -541,6 +533,15 @@ private:
|
||||
* \param bar the block ack request.
|
||||
*/
|
||||
void SendBlockAckRequest (const Bar &bar);
|
||||
/**
|
||||
* Check if the given MPDU is to be considered old according to the current
|
||||
* starting sequence number of the transmit window, provided that a block ack
|
||||
* agreement has been established with the recipient for the given TID.
|
||||
*
|
||||
* \param mpdu the given MPDU
|
||||
* \return true if the MPDU is to be considered old, false otherwise
|
||||
*/
|
||||
bool IsQosOldPacket (Ptr<const WifiMacQueueItem> mpdu);
|
||||
/**
|
||||
* For now is typically invoked to complete transmission of a packets sent with ack policy
|
||||
* Block Ack: the packet is buffered and dcf is reset.
|
||||
|
||||
Reference in New Issue
Block a user