wifi: Add more methods to WifiMacQueue

- Insert/Dequeue/Remove from specific positions in the queue
- Peek methods are const and return a ConstIterator
- Added a trace for expired MPDUs
This commit is contained in:
Stefano Avallone
2019-04-12 12:18:00 +02:00
parent dc074293d5
commit 99feb162fb
4 changed files with 329 additions and 160 deletions

View File

@@ -120,9 +120,9 @@ MsduAggregator::GetNextAmsdu (Mac48Address recipient, uint8_t tid,
Ptr<QosTxop> qosTxop = m_edca.find (QosUtilsMapTidToAc (tid))->second;
Ptr<WifiMacQueue> queue = qosTxop->GetWifiMacQueue ();
Ptr<const WifiMacQueueItem> peekedItem = queue->PeekByTidAndAddress (tid, recipient);
WifiMacQueue::ConstIterator peekedIt = queue->PeekByTidAndAddress (tid, recipient);
if (!peekedItem)
if (peekedIt == queue->end ())
{
NS_LOG_DEBUG ("No packet with the given TID and address in the queue");
return 0;
@@ -147,19 +147,19 @@ MsduAggregator::GetNextAmsdu (Mac48Address recipient, uint8_t tid,
Ptr<Packet> amsdu = Create<Packet> ();
uint8_t nMsdu = 0;
WifiMacHeader header = peekedItem->GetHeader ();
Time tstamp = peekedItem->GetTimeStamp ();
// We need to keep track of the first MSDU. If it is dequeued but aggregation
// fails, we need to re-insert it in the queue
Ptr<const WifiMacQueueItem> first = peekedItem;
WifiMacHeader header = (*peekedIt)->GetHeader ();
Time tstamp = (*peekedIt)->GetTimeStamp ();
// We need to keep track of the first MSDU. When it is processed, it is not known
// if aggregation will succeed or not.
WifiMacQueue::ConstIterator first = peekedIt;
// TODO Add support for the Max Number Of MSDUs In A-MSDU field in the Extended
// Capabilities element sent by the recipient
while (peekedItem != 0) // && nMsdu < maxNMsdus
while (peekedIt != queue->end ())
{
// check if aggregating the peeked MSDU violates the A-MSDU size limit
uint16_t newAmsduSize = GetSizeIfAggregated (peekedItem->GetPacket ()->GetSize (),
uint16_t newAmsduSize = GetSizeIfAggregated ((*peekedIt)->GetPacket ()->GetSize (),
amsdu->GetSize ());
if (newAmsduSize > maxAmsduSize)
@@ -177,36 +177,43 @@ MsduAggregator::GetNextAmsdu (Mac48Address recipient, uint8_t tid,
break;
}
// We can now safely aggregate the MSDU to the A-MSDU and remove it from the queue
Aggregate (peekedItem->GetPacket (), amsdu,
// We can now safely aggregate the MSDU to the A-MSDU
Aggregate ((*peekedIt)->GetPacket (), amsdu,
qosTxop->MapSrcAddressForAggregation (header),
qosTxop->MapDestAddressForAggregation (header));
queue->Remove (peekedItem->GetPacket ());
nMsdu++;
/* "The expiration of the A-MSDU lifetime timer occurs only when the lifetime
* timer of all of the constituent MSDUs of the A-MSDU have expired" (Section
* 10.12 of 802.11-2016)
*/
// The timestamp of the A-MSDU is the most recent among those of the MSDUs
tstamp = Max (tstamp, peekedItem->GetTimeStamp ());
tstamp = Max (tstamp, (*peekedIt)->GetTimeStamp ());
peekedItem = queue->PeekByTidAndAddress (tid, recipient);
// If it is the first MSDU, move to the next one
if (nMsdu == 0)
{
peekedIt++;
}
// otherwise, remove it from the queue
else
{
peekedIt = queue->Remove (peekedIt);
}
nMsdu++;
peekedIt = queue->PeekByTidAndAddress (tid, recipient, peekedIt);
}
if (nMsdu < 2)
{
NS_LOG_DEBUG ("Aggregation failed (could not aggregate at least two MSDUs)");
// re-insert the first MSDU in the queue if it was removed
if (nMsdu == 1)
{
queue->PushFront (Create<WifiMacQueueItem> (*first));
}
return 0;
}
// Aggregation succeeded, we have to remove the first MSDU
queue->Remove (first);
header.SetQosAmsdu ();
header.SetAddr3 (qosTxop->GetLow ()->GetBssid ());

View File

@@ -190,15 +190,17 @@ 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
for (uint8_t tid = 0; tid < 8; tid++)
{
if (QosUtilsMapTidToAc (tid) == m_ac)
{
item = m_low->GetAggregateQueue ()->PeekByTid (tid);
if (item != 0)
it = m_low->GetAggregateQueue ()->PeekByTid (tid);
if (it != m_low->GetAggregateQueue ()->end ())
{
item = *it;
break;
}
}
@@ -220,10 +222,11 @@ QosTxop::PeekNextFrame (void)
}
// otherwise, check if there is a packet in the EDCA queue
item = m_queue->PeekFirstAvailable (m_qosBlockedDestinations);
it = m_queue->PeekFirstAvailable (m_qosBlockedDestinations);
if (item != 0)
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 ();
@@ -245,10 +248,11 @@ QosTxop::PeekNextFrameByTidAndAddress (uint8_t tid, Mac48Address recipient)
Ptr<const WifiMacQueueItem> item;
// check if there is a packet in the MacLow aggregation queue
item = m_low->GetAggregateQueue ()->PeekByTidAndAddress (tid, recipient);
WifiMacQueue::ConstIterator it = m_low->GetAggregateQueue ()->PeekByTidAndAddress (tid, recipient);
if (item != 0)
if (it != m_low->GetAggregateQueue ()->end ())
{
item = *it;
NS_LOG_DEBUG ("packet peeked from MacLow aggregation queue, " << *item);
return item;
}
@@ -263,10 +267,11 @@ QosTxop::PeekNextFrameByTidAndAddress (uint8_t tid, Mac48Address recipient)
}
// otherwise, check if there is a packet in the EDCA queue
item = m_queue->PeekByTidAndAddress (tid, recipient);
it = m_queue->PeekByTidAndAddress (tid, recipient);
if (item != 0)
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 ();
@@ -367,10 +372,11 @@ 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);
WifiMacQueue::ConstIterator testIt = m_low->GetAggregateQueue ()->PeekByTidAndAddress (tid, recipient);
if (testItem)
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);
@@ -399,9 +405,9 @@ QosTxop::DequeuePeekedFrame (Ptr<const WifiMacQueueItem> peekedItem, WifiTxVecto
if (peekedItem->GetHeader ().IsQosData ())
{
uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
testItem = m_queue->PeekByTidAndAddress (tid, recipient);
WifiMacQueue::ConstIterator testIt = m_queue->PeekByTidAndAddress (tid, recipient);
NS_ASSERT (testItem != 0 && testItem->GetPacket () == peekedItem->GetPacket ());
NS_ASSERT (testIt != m_queue->end () && (*testIt)->GetPacket () == peekedItem->GetPacket ());
// try A-MSDU aggregation
if (m_low->GetMsduAggregator () != 0 && !recipient.IsBroadcast () && aggregate)

View File

@@ -53,12 +53,16 @@ WifiMacQueue::GetTypeId (void)
MakeEnumAccessor (&WifiMacQueue::m_dropPolicy),
MakeEnumChecker (WifiMacQueue::DROP_OLDEST, "DropOldest",
WifiMacQueue::DROP_NEWEST, "DropNewest"))
.AddTraceSource ("Expired", "MPDU dropped because its lifetime expired.",
MakeTraceSourceAccessor (&WifiMacQueue::m_traceExpired),
"ns3::WifiMacQueueItem::TracedCallback")
;
return tid;
}
WifiMacQueue::WifiMacQueue ()
: NS_LOG_TEMPLATE_DEFINE ("WifiMacQueue")
: m_expiredPacketsPresent (false),
NS_LOG_TEMPLATE_DEFINE ("WifiMacQueue")
{
}
@@ -67,6 +71,8 @@ WifiMacQueue::~WifiMacQueue ()
NS_LOG_FUNCTION_NOARGS ();
}
const WifiMacQueue::ConstIterator WifiMacQueue::EMPTY = std::list<Ptr<WifiMacQueueItem>> ().end ();
void
WifiMacQueue::SetMaxQueueSize (QueueSize size)
{
@@ -102,6 +108,7 @@ WifiMacQueue::TtlExceeded (ConstIterator &it)
{
NS_LOG_DEBUG ("Removing packet that stayed in the queue for too long (" <<
Simulator::Now () - (*it)->GetTimeStamp () << ")");
m_traceExpired (*it);
auto curr = it++;
DoRemove (curr);
return true;
@@ -112,59 +119,57 @@ WifiMacQueue::TtlExceeded (ConstIterator &it)
bool
WifiMacQueue::Enqueue (Ptr<WifiMacQueueItem> item)
{
NS_LOG_FUNCTION (this << item);
NS_ASSERT_MSG (GetMaxSize ().GetUnit () == QueueSizeUnit::PACKETS,
"WifiMacQueues must be in packet mode");
NS_LOG_FUNCTION (this << *item);
QueueBase::SetMaxSize (GetMaxQueueSize ()); //Make sure QueueBase has the same maximum queue size
// if the queue is full, remove the first stale packet (if any) encountered
// starting from the head of the queue, in order to make room for the new packet.
if (QueueBase::GetNPackets () == GetMaxSize ().GetValue ())
{
ConstIterator it = begin ();
while (it != end () && !TtlExceeded (it))
{
it++;
}
}
if (QueueBase::GetNPackets () == GetMaxSize ().GetValue () && m_dropPolicy == DROP_OLDEST)
{
NS_LOG_DEBUG ("Remove the oldest item in the queue");
DoRemove (begin ());
}
return DoEnqueue (end (), item);
return Insert (end (), item);
}
bool
WifiMacQueue::PushFront (Ptr<WifiMacQueueItem> item)
{
NS_LOG_FUNCTION (this << item);
NS_LOG_FUNCTION (this << *item);
return Insert (begin (), item);
}
bool
WifiMacQueue::Insert (ConstIterator pos, Ptr<WifiMacQueueItem> item)
{
NS_LOG_FUNCTION (this << *item);
NS_ASSERT_MSG (GetMaxSize ().GetUnit () == QueueSizeUnit::PACKETS,
"WifiMacQueues must be in packet mode");
QueueBase::SetMaxSize (GetMaxQueueSize ()); //Make sure QueueBase has the same maximum queue size
// if the queue is full, remove the first stale packet (if any) encountered
// starting from the head of the queue, in order to make room for the new packet.
if (QueueBase::GetNPackets () == GetMaxSize ().GetValue ())
// insert the item if the queue is not full
if (QueueBase::GetNPackets () < GetMaxSize ().GetValue ())
{
ConstIterator it = begin ();
while (it != end () && !TtlExceeded (it))
{
it++;
}
return DoEnqueue (pos, item);
}
if (QueueBase::GetNPackets () == GetMaxSize ().GetValue () && m_dropPolicy == DROP_OLDEST)
// the queue is full; scan the list in the attempt to remove stale packets
ConstIterator it = begin ();
while (it != end ())
{
if (it == pos && TtlExceeded (it))
{
return DoEnqueue (it, item);
}
if (TtlExceeded (it))
{
return DoEnqueue (pos, item);
}
it++;
}
// the queue is still full, remove the oldest item if the policy is drop oldest
if (m_dropPolicy == DROP_OLDEST)
{
NS_LOG_DEBUG ("Remove the oldest item in the queue");
DoRemove (begin ());
}
return DoEnqueue (begin (), item);
return DoEnqueue (pos, item);
}
Ptr<WifiMacQueueItem>
@@ -186,82 +191,90 @@ Ptr<WifiMacQueueItem>
WifiMacQueue::DequeueByAddress (Mac48Address dest)
{
NS_LOG_FUNCTION (this << dest);
ConstIterator it = PeekByAddress (dest);
for (ConstIterator it = begin (); it != end (); )
if (it == end ())
{
if (!TtlExceeded (it))
{
if ((*it)->GetHeader ().IsData () && (*it)->GetDestinationAddress () == dest)
{
return DoDequeue (it);
}
it++;
}
return 0;
}
NS_LOG_DEBUG ("The queue is empty");
return 0;
return Dequeue (it);
}
Ptr<WifiMacQueueItem>
WifiMacQueue::DequeueByTid (uint8_t tid)
{
NS_LOG_FUNCTION (this << +tid);
for (ConstIterator it = begin (); it != end (); )
{
if (!TtlExceeded (it))
{
if ((*it)->GetHeader ().IsQosData () && (*it)->GetHeader ().GetQosTid () == tid)
{
return DoDequeue (it);
}
ConstIterator it = PeekByTid (tid);
it++;
}
if (it == end ())
{
return 0;
}
NS_LOG_DEBUG ("The queue is empty");
return 0;
return Dequeue (it);
}
Ptr<WifiMacQueueItem>
WifiMacQueue::DequeueByTidAndAddress (uint8_t tid, Mac48Address dest)
{
NS_LOG_FUNCTION (this << dest);
for (ConstIterator it = begin (); it != end (); )
{
if (!TtlExceeded (it))
{
if ((*it)->GetHeader ().IsQosData () && (*it)->GetDestinationAddress () == dest
&& (*it)->GetHeader ().GetQosTid () == tid)
{
return DoDequeue (it);
}
NS_LOG_FUNCTION (this << +tid << dest);
ConstIterator it = PeekByTidAndAddress (tid, dest);
it++;
}
if (it == end ())
{
return 0;
}
NS_LOG_DEBUG ("The queue is empty");
return 0;
return Dequeue (it);
}
Ptr<WifiMacQueueItem>
WifiMacQueue::DequeueFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets)
{
NS_LOG_FUNCTION (this);
for (ConstIterator it = begin (); it != end (); )
{
if (!TtlExceeded (it))
{
if (!(*it)->GetHeader ().IsQosData ()
|| !blockedPackets->IsBlocked ((*it)->GetHeader ().GetAddr1 (), (*it)->GetHeader ().GetQosTid ()))
{
return DoDequeue (it);
}
ConstIterator it = PeekFirstAvailable (blockedPackets);
if (it == end ())
{
return 0;
}
return Dequeue (it);
}
Ptr<WifiMacQueueItem>
WifiMacQueue::Dequeue (ConstIterator pos)
{
NS_LOG_FUNCTION (this);
if (!m_expiredPacketsPresent)
{
if (TtlExceeded (pos))
{
NS_LOG_DEBUG ("Packet lifetime expired");
return 0;
}
return DoDequeue (pos);
}
// remove stale items queued before the given position
ConstIterator it = begin ();
while (it != end ())
{
if (it == pos)
{
// reset the flag signaling the presence of expired packets before returning
m_expiredPacketsPresent = false;
if (TtlExceeded (it))
{
return 0;
}
return DoDequeue (it);
}
else if (!TtlExceeded (it))
{
it++;
}
}
NS_LOG_DEBUG ("The queue is empty");
NS_LOG_DEBUG ("Invalid iterator");
return 0;
}
@@ -277,71 +290,122 @@ WifiMacQueue::Peek (void) const
{
return DoPeek (it);
}
// signal the presence of expired packets
m_expiredPacketsPresent = true;
}
NS_LOG_DEBUG ("The queue is empty");
return 0;
}
Ptr<const WifiMacQueueItem>
WifiMacQueue::PeekByTid (uint8_t tid)
WifiMacQueue::ConstIterator
WifiMacQueue::PeekByAddress (Mac48Address dest, ConstIterator pos) const
{
NS_LOG_FUNCTION (this << dest);
ConstIterator it = (pos != EMPTY ? pos : begin ());
while (it != end ())
{
// skip packets that stayed in the queue for too long. They will be
// actually removed from the queue by the next call to a non-const method
if (Simulator::Now () <= (*it)->GetTimeStamp () + m_maxDelay)
{
if (((*it)->GetHeader ().IsData () || (*it)->GetHeader ().IsQosData ())
&& (*it)->GetDestinationAddress () == dest)
{
return it;
}
}
else
{
// signal the presence of expired packets
m_expiredPacketsPresent = true;
}
it++;
}
NS_LOG_DEBUG ("The queue is empty");
return end ();
}
WifiMacQueue::ConstIterator
WifiMacQueue::PeekByTid (uint8_t tid, ConstIterator pos) const
{
NS_LOG_FUNCTION (this << +tid);
for (ConstIterator it = begin (); it != end (); )
ConstIterator it = (pos != EMPTY ? pos : begin ());
while (it != end ())
{
if (!TtlExceeded (it))
// skip packets that stayed in the queue for too long. They will be
// actually removed from the queue by the next call to a non-const method
if (Simulator::Now () <= (*it)->GetTimeStamp () + m_maxDelay)
{
if ((*it)->GetHeader ().IsQosData () && (*it)->GetHeader ().GetQosTid () == tid)
{
return DoPeek (it);
return it;
}
it++;
}
else
{
// signal the presence of expired packets
m_expiredPacketsPresent = true;
}
it++;
}
NS_LOG_DEBUG ("The queue is empty");
return 0;
return end ();
}
Ptr<const WifiMacQueueItem>
WifiMacQueue::PeekByTidAndAddress (uint8_t tid, Mac48Address dest)
WifiMacQueue::ConstIterator
WifiMacQueue::PeekByTidAndAddress (uint8_t tid, Mac48Address dest, ConstIterator pos) const
{
NS_LOG_FUNCTION (this << dest);
for (ConstIterator it = begin (); it != end (); )
NS_LOG_FUNCTION (this << +tid << dest);
ConstIterator it = (pos != EMPTY ? pos : begin ());
while (it != end ())
{
if (!TtlExceeded (it))
// skip packets that stayed in the queue for too long. They will be
// actually removed from the queue by the next call to a non-const method
if (Simulator::Now () <= (*it)->GetTimeStamp () + m_maxDelay)
{
if ((*it)->GetHeader ().IsQosData () && (*it)->GetDestinationAddress () == dest
&& (*it)->GetHeader ().GetQosTid () == tid)
{
return DoPeek (it);
return it;
}
it++;
}
else
{
// signal the presence of expired packets
m_expiredPacketsPresent = true;
}
it++;
}
NS_LOG_DEBUG ("The queue is empty");
return 0;
return end ();
}
Ptr<const WifiMacQueueItem>
WifiMacQueue::PeekFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets)
WifiMacQueue::ConstIterator
WifiMacQueue::PeekFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets, ConstIterator pos) const
{
NS_LOG_FUNCTION (this);
for (ConstIterator it = begin (); it != end (); )
ConstIterator it = (pos != EMPTY ? pos : begin ());
while (it != end ())
{
if (!TtlExceeded (it))
// skip packets that stayed in the queue for too long. They will be
// actually removed from the queue by the next call to a non-const method
if (Simulator::Now () <= (*it)->GetTimeStamp () + m_maxDelay)
{
if (!(*it)->GetHeader ().IsQosData ()
if (!(*it)->GetHeader ().IsQosData () || !blockedPackets
|| !blockedPackets->IsBlocked ((*it)->GetHeader ().GetAddr1 (), (*it)->GetHeader ().GetQosTid ()))
{
return DoPeek (it);
return it;
}
it++;
}
else
{
// signal the presence of expired packets
m_expiredPacketsPresent = true;
}
it++;
}
NS_LOG_DEBUG ("The queue is empty");
return 0;
return end ();
}
Ptr<WifiMacQueueItem>
@@ -381,6 +445,40 @@ WifiMacQueue::Remove (Ptr<const Packet> packet)
return false;
}
WifiMacQueue::ConstIterator
WifiMacQueue::Remove (ConstIterator pos, bool removeExpired)
{
NS_LOG_FUNCTION (this);
if (!removeExpired)
{
ConstIterator curr = pos++;
DoRemove (curr);
return pos;
}
// remove stale items queued before the given position
ConstIterator it = begin ();
while (it != end ())
{
if (it == pos)
{
// reset the flag signaling the presence of expired packets before returning
m_expiredPacketsPresent = false;
ConstIterator curr = pos++;
DoRemove (curr);
return pos;
}
else if (!TtlExceeded (it))
{
it++;
}
}
NS_LOG_DEBUG ("Invalid iterator");
return end ();
}
uint32_t
WifiMacQueue::GetNPacketsByAddress (Mac48Address dest)
{

View File

@@ -72,6 +72,12 @@ public:
DROP_OLDEST
};
/// allow the usage of iterators and const iterators
using Queue<WifiMacQueueItem>::ConstIterator;
using Queue<WifiMacQueueItem>::Iterator;
using Queue<WifiMacQueueItem>::begin;
using Queue<WifiMacQueueItem>::end;
/**
* \brief Set the maximum size of this queue
*
@@ -111,6 +117,14 @@ public:
* \return true if success, false if the packet has been dropped
*/
bool PushFront (Ptr<WifiMacQueueItem> item);
/**
* Enqueue the given Wifi MAC queue item before the given position.
*
* \param pos the position before which the item is to be inserted
* \param item the Wifi MAC queue item to be enqueued
* \return true if success, false if the packet has been dropped
*/
bool Insert (ConstIterator pos, Ptr<WifiMacQueueItem> item);
/**
* Dequeue the packet in the front of the queue.
*
@@ -118,8 +132,8 @@ public:
*/
Ptr<WifiMacQueueItem> Dequeue (void);
/**
* Search and return, if present in the queue, the first packet having the
* address indicated by <i>type</i> equal to <i>addr</i>.
* Search and return, if present in the queue, the first packet (either Data
* frame or QoS Data frame) having the receiver address equal to <i>addr</i>.
* This method removes the packet from the queue.
* It is typically used by ns3::Txop during the CF period.
*
@@ -163,7 +177,16 @@ public:
*
* \return packet
*/
Ptr<WifiMacQueueItem> DequeueFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets);
Ptr<WifiMacQueueItem> DequeueFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets = nullptr);
/**
* Dequeue the item at position <i>pos</i> in the queue. Return a null
* pointer if the given iterator is invalid, the queue is empty or the
* lifetime of the item pointed to by the given iterator is expired.
*
* \param pos the position of the item to be dequeued
* \return the dequeued item, if any
*/
Ptr<WifiMacQueueItem> Dequeue (WifiMacQueue::ConstIterator pos);
/**
* Peek the packet in the front of the queue. The packet is not removed.
*
@@ -171,36 +194,55 @@ public:
*/
Ptr<const WifiMacQueueItem> Peek (void) const;
/**
* Search and return, if present in the queue, the first packet having the
* tid equal to <i>tid</i>. This method does not remove the packet from the queue.
* Search and return, if present in the queue, the first packet (either Data
* frame or QoS Data frame) having the receiver address equal to <i>addr</i>.
* If <i>pos</i> is a valid iterator, the search starts from the packet pointed
* to by the given iterator.
* This method does not remove the packet from the queue.
*
* \param tid the given TID
* \param dest the given destination
* \param pos the iterator pointing to the packet the search starts from
*
* \return packet
* \return an iterator pointing to the peeked packet
*/
Ptr<const WifiMacQueueItem> PeekByTid (uint8_t tid);
ConstIterator PeekByAddress (Mac48Address dest, ConstIterator pos = EMPTY) const;
/**
* Search and return, if present in the queue, the first packet having the
* address indicated by <i>type</i> equal to <i>addr</i>, and tid
* equal to <i>tid</i>. This method does not remove the packet from the queue.
* It is typically used by ns3::QosTxop in order to perform correct MSDU
* aggregation (A-MSDU).
* tid equal to <i>tid</i>. If <i>pos</i> is a valid iterator, the search starts
* from the packet pointed to by the given iterator.
* This method does not remove the packet from the queue.
*
* \param tid the given TID
* \param pos the iterator pointing to the packet the search starts from
*
* \return an iterator pointing to the peeked packet
*/
ConstIterator PeekByTid (uint8_t tid, ConstIterator pos = EMPTY) const;
/**
* Search and return, if present in the queue, the first packet having the
* receiver address equal to <i>dest</i>, and tid equal to <i>tid</i>.
* If <i>pos</i> is a valid iterator, the search starts from the packet pointed
* to by the given iterator. This method does not remove the packet from the queue.
* It is typically used by ns3::QosTxop in order to perform correct MSDU aggregation
* (A-MSDU).
*
* \param tid the given TID
* \param dest the given destination
* \param pos the iterator pointing to the packet the search starts from
*
* \return packet
* \return an iterator pointing to the peeked packet
*/
Ptr<const WifiMacQueueItem> PeekByTidAndAddress (uint8_t tid,
Mac48Address dest);
ConstIterator PeekByTidAndAddress (uint8_t tid, Mac48Address dest, ConstIterator pos = EMPTY) const;
/**
* Return first available packet for transmission. The packet is not removed from queue.
*
* \param blockedPackets
* \param pos the iterator pointing to the packet the search starts from
*
* \return packet
* \return an iterator pointing to the peeked packet
*/
Ptr<const WifiMacQueueItem> PeekFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets);
ConstIterator PeekFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets = nullptr,
ConstIterator pos = EMPTY) const;
/**
* Remove the packet in the front of the queue.
*
@@ -217,6 +259,17 @@ public:
* \return true if the packet was removed, false otherwise
*/
bool Remove (Ptr<const Packet> packet);
/**
* Remove the item at position <i>pos</i> in the queue and return an iterator
* pointing to the item following the removed one. If <i>removeExpired</i> is
* true, all the items in the queue from the head to the given position are
* removed if their lifetime expired.
*
* \param pos the position of the item to be removed
* \param removeExpired true to remove expired items
* \return an iterator pointing to the item following the removed one
*/
ConstIterator Remove (ConstIterator pos, bool removeExpired = false);
/**
* Return the number of packets having destination address specified by
* <i>dest</i>.
@@ -272,6 +325,11 @@ private:
QueueSize m_maxSize; //!< max queue size
Time m_maxDelay; //!< Time to live for packets in the queue
DropPolicy m_dropPolicy; //!< Drop behavior of queue
mutable bool m_expiredPacketsPresent; //!> True if expired packets are in the queue
static const ConstIterator EMPTY; //!< Invalid iterator to signal an empty queue
/// Traced callback: fired when a packet is dropped due to lifetime expiration
TracedCallback<Ptr<const WifiMacQueueItem> > m_traceExpired;
NS_LOG_TEMPLATE_DECLARE; //!< redefinition of the log component
};