wifi: Replace iterators with pointers to queued items in public APIs

This commit is contained in:
Stefano Avallone
2021-09-27 07:55:04 +02:00
parent cf2ccdc041
commit 882a746500
19 changed files with 227 additions and 243 deletions

View File

@@ -133,7 +133,7 @@ WaveFrameExchangeManager::StartTransmission (Ptr<Txop> dcf)
}
m_dcf->NotifyChannelAccessed ();
Ptr<WifiMacQueueItem> mpdu = *queue->Peek ()->GetQueueIterator ();
Ptr<WifiMacQueueItem> mpdu = queue->Peek ()->GetItem ();
NS_ASSERT (mpdu != 0);
// assign a sequence number if this is not a fragment nor a retransmission

View File

@@ -293,7 +293,7 @@ BlockAckManager::GetBar (bool remove, uint8_t tid, Mac48Address address)
continue;
}
if (nextBar->skipIfNoDataQueued
&& m_queue->PeekByTidAndAddress (nextBar->tid, recipient) == m_queue->end ())
&& m_queue->PeekByTidAndAddress (nextBar->tid, recipient) == nullptr)
{
// skip this BAR as there is no data queued
nextBar++;
@@ -309,8 +309,6 @@ BlockAckManager::GetBar (bool remove, uint8_t tid, Mac48Address address)
continue;
}
WifiMacQueue::ConstIterator queueIt = (*mpduIt)->GetQueueIterator ();
if ((*mpduIt)->GetTimeStamp () + m_queue->GetMaxDelay () <= now)
{
// MPDU expired
@@ -319,7 +317,7 @@ BlockAckManager::GetBar (bool remove, uint8_t tid, Mac48Address address)
// consequent call to NotifyDiscardedMpdu does nothing (in particular,
// does not schedule a BAR) because we have advanced the transmit window
// and hence this MPDU became an old packet
m_queue->TtlExceeded (queueIt, now);
m_queue->TtlExceeded (*mpduIt, now);
mpduIt = it->second.second.erase (mpduIt);
}
else
@@ -391,7 +389,6 @@ BlockAckManager::HandleInFlightMpdu (PacketQueueI mpduIt, MpduStatus status,
}
WifiMacHeader& hdr = (*mpduIt)->GetHeader ();
WifiMacQueue::ConstIterator queueIt = (*mpduIt)->GetQueueIterator ();
NS_ASSERT (hdr.GetAddr1 () == it->first.first);
NS_ASSERT (hdr.IsQosData () && hdr.GetQosTid () == it->first.second);
@@ -401,15 +398,15 @@ BlockAckManager::HandleInFlightMpdu (PacketQueueI mpduIt, MpduStatus status,
NS_LOG_DEBUG ("Old packet. Remove from the EDCA queue, too");
if (!m_droppedOldMpduCallback.IsNull ())
{
m_droppedOldMpduCallback (*queueIt);
m_droppedOldMpduCallback (*mpduIt);
}
m_queue->Remove (queueIt);
m_queue->Remove (*mpduIt, false);
return it->second.second.erase (mpduIt);
}
auto nextIt = std::next (mpduIt);
if (m_queue->TtlExceeded (queueIt, now))
if (m_queue->TtlExceeded (*mpduIt, now))
{
// WifiMacQueue::TtlExceeded() has removed the MPDU from the EDCA queue
// and fired the Expired trace source, which called NotifyDiscardedMpdu,

View File

@@ -281,7 +281,7 @@ FrameExchangeManager::StartTransmission (Ptr<Txop> dcf)
}
m_dcf->NotifyChannelAccessed ();
Ptr<WifiMacQueueItem> mpdu = *queue->Peek ()->GetQueueIterator ();
Ptr<WifiMacQueueItem> mpdu = queue->Peek ()->GetItem ();
NS_ASSERT (mpdu != 0);
NS_ASSERT (mpdu->GetHeader ().IsData () || mpdu->GetHeader ().IsMgt ());

View File

@@ -1197,15 +1197,13 @@ HeFrameExchangeManager::ReceiveBasicTrigger (const CtrlTriggerHeader& trigger, c
// otherwise, check if a suitable data frame is available
if ((mpdu = edca->PeekNextMpdu (tid, hdr.GetAddr2 ())) != 0)
{
WifiMacQueueItem::ConstIterator queueIt;
Ptr<WifiMacQueueItem> item = edca->GetNextMpdu (mpdu, txParams, ppduDuration, false, queueIt);
Ptr<WifiMacQueueItem> item = edca->GetNextMpdu (mpdu, txParams, ppduDuration, false);
if (item != 0)
{
// try A-MPDU aggregation
std::vector<Ptr<WifiMacQueueItem>> mpduList = m_mpduAggregator->GetNextAmpdu (item, txParams,
ppduDuration,
queueIt);
ppduDuration);
psdu = (mpduList.size () > 1 ? Create<WifiPsdu> (std::move (mpduList))
: Create<WifiPsdu> (item, true));
break;

View File

@@ -728,26 +728,24 @@ RrMultiUserScheduler::ComputeDlMuInfo (void)
NS_ASSERT (receiver == candidate.first->address);
NS_ASSERT (mpdu->IsQueued ());
WifiMacQueueItem::ConstIterator queueIt = mpdu->GetQueueIterator ();
Ptr<WifiMacQueueItem> item = *queueIt;
queueIt++;
Ptr<WifiMacQueueItem> item = mpdu->GetItem ();
if (!mpdu->GetHeader ().IsRetry ())
{
// this MPDU must have been dequeued from the AC queue and we can try
// A-MSDU aggregation
item = m_heFem->GetMsduAggregator ()->GetNextAmsdu (mpdu, dlMuInfo.txParams, m_availableTime, queueIt);
item = m_heFem->GetMsduAggregator ()->GetNextAmsdu (mpdu, dlMuInfo.txParams, m_availableTime);
if (item == nullptr)
{
// A-MSDU aggregation failed or disabled
item = *mpdu->GetQueueIterator ();
item = mpdu->GetItem ();
}
m_apMac->GetQosTxop (QosUtilsMapTidToAc (tid))->AssignSequenceNumber (item);
}
// Now, let's try A-MPDU aggregation if possible
std::vector<Ptr<WifiMacQueueItem>> mpduList = m_heFem->GetMpduAggregator ()->GetNextAmpdu (item, dlMuInfo.txParams, m_availableTime, queueIt);
std::vector<Ptr<WifiMacQueueItem>> mpduList = m_heFem->GetMpduAggregator ()->GetNextAmpdu (item, dlMuInfo.txParams, m_availableTime);
if (mpduList.size () > 1)
{

View File

@@ -447,8 +447,7 @@ HtFrameExchangeManager::SendDataFrame (Ptr<const WifiMacQueueItem> peekedItem,
Ptr<QosTxop> edca = m_mac->GetQosTxop (peekedItem->GetHeader ().GetQosTid ());
WifiTxParameters txParams;
txParams.m_txVector = m_mac->GetWifiRemoteStationManager ()->GetDataTxVector (peekedItem->GetHeader ());
WifiMacQueueItem::ConstIterator queueIt;
Ptr<WifiMacQueueItem> mpdu = edca->GetNextMpdu (peekedItem, txParams, availableTime, initialFrame, queueIt);
Ptr<WifiMacQueueItem> mpdu = edca->GetNextMpdu (peekedItem, txParams, availableTime, initialFrame);
if (mpdu == nullptr)
{
@@ -458,7 +457,7 @@ HtFrameExchangeManager::SendDataFrame (Ptr<const WifiMacQueueItem> peekedItem,
// try A-MPDU aggregation
std::vector<Ptr<WifiMacQueueItem>> mpduList = m_mpduAggregator->GetNextAmpdu (mpdu, txParams,
availableTime, queueIt);
availableTime);
NS_ASSERT (txParams.m_acknowledgment);
if (mpduList.size () > 1)

View File

@@ -192,7 +192,7 @@ MpduAggregator::GetAmpduSubframeHeader (uint16_t mpduSize, bool isSingle)
std::vector<Ptr<WifiMacQueueItem>>
MpduAggregator::GetNextAmpdu (Ptr<WifiMacQueueItem> mpdu, WifiTxParameters& txParams,
Time availableTime, WifiMacQueueItem::ConstIterator queueIt) const
Time availableTime) const
{
NS_LOG_FUNCTION (this << *mpdu << &txParams << availableTime);
@@ -222,10 +222,10 @@ MpduAggregator::GetNextAmpdu (Ptr<WifiMacQueueItem> mpdu, WifiTxParameters& txPa
mpduList.push_back (nextMpdu);
// If allowed by the BA agreement, get the next MPDU
Ptr<const WifiMacQueueItem> peekedMpdu;
peekedMpdu = qosTxop->PeekNextMpdu (tid, recipient, nextMpdu);
nextMpdu = 0;
Ptr<const WifiMacQueueItem> peekedMpdu;
peekedMpdu = qosTxop->PeekNextMpdu (queueIt, tid, recipient);
if (peekedMpdu != 0)
{
// PeekNextMpdu() does not return an MPDU that is beyond the transmit window
@@ -237,7 +237,7 @@ MpduAggregator::GetNextAmpdu (Ptr<WifiMacQueueItem> mpdu, WifiTxParameters& txPa
// and duration limit are met. Note that the returned MPDU differs from
// the peeked MPDU if A-MSDU aggregation is enabled.
NS_LOG_DEBUG ("Trying to aggregate another MPDU");
nextMpdu = qosTxop->GetNextMpdu (peekedMpdu, txParams, availableTime, false, queueIt);
nextMpdu = qosTxop->GetNextMpdu (peekedMpdu, txParams, availableTime, false);
}
}

View File

@@ -118,14 +118,11 @@ public:
* \param mpdu the given MPDU.
* \param txParams the TX parameters used to transmit the frame
* \param availableTime the time available for the frame exchange
* \param queueIt the QueueIteratorPair pointing to the queue item from which the
* search for an MPDU starts, if the QueueIteratorPair is valid
* \return the resulting A-MPDU, if aggregation is possible.
*/
std::vector<Ptr<WifiMacQueueItem>> GetNextAmpdu (Ptr<WifiMacQueueItem> mpdu,
WifiTxParameters& txParams,
Time availableTime,
WifiMacQueueItem::ConstIterator queueIt) const;
Time availableTime) const;
/**
* Set the MAC layer to use.

View File

@@ -84,13 +84,11 @@ MsduAggregator::GetSizeIfAggregated (uint16_t msduSize, uint16_t amsduSize)
Ptr<WifiMacQueueItem>
MsduAggregator::GetNextAmsdu (Ptr<const WifiMacQueueItem> peekedItem, WifiTxParameters& txParams,
Time availableTime, WifiMacQueueItem::ConstIterator& queueIt) const
Time availableTime) const
{
NS_LOG_FUNCTION (this << *peekedItem << &txParams << availableTime);
Ptr<WifiMacQueue> queue = m_mac->GetTxopQueue (peekedItem->GetQueueAc ());
auto it = peekedItem->GetQueueIterator ();
NS_ASSERT ((*it)->GetPacket () == peekedItem->GetPacket ());
uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
Mac48Address recipient = peekedItem->GetHeader ().GetAddr1 ();
@@ -119,27 +117,23 @@ MsduAggregator::GetNextAmsdu (Ptr<const WifiMacQueueItem> peekedItem, WifiTxPara
return nullptr;
}
Ptr<WifiMacQueueItem> amsdu = *it; // amsdu points to the peeked MPDU, but it's non-const
Ptr<WifiMacQueueItem> amsdu = peekedItem->GetItem (); // amsdu points to the peeked MPDU, but it's non-const
uint8_t nMsdu = 1;
peekedItem = queue->PeekByTidAndAddress (tid, recipient, peekedItem);
it++;
while ((it = queue->PeekByTidAndAddress (tid, recipient, it)) != queue->end ()
&& m_htFem->TryAggregateMsdu (*it, txParams, availableTime))
while (peekedItem != nullptr
&& m_htFem->TryAggregateMsdu (peekedItem, txParams, availableTime))
{
// dequeue the MSDU being aggregated and advance the current iterator
// before it is invalidated
Ptr<WifiMacQueueItem> msdu = *it++;
// find the next MPDU before dequeuing the current one
Ptr<const WifiMacQueueItem> msdu = peekedItem;
peekedItem = queue->PeekByTidAndAddress (tid, recipient, peekedItem);
queue->DequeueIfQueued (msdu);
auto pos = std::next (amsdu->GetQueueIterator ());
queue->DequeueIfQueued (amsdu);
amsdu->Aggregate (msdu);
bool ret = queue->Insert (pos, amsdu);
// The size of a WifiMacQueue is measured as number of packets. We dequeued
// two packets, so there is certainly room for inserting one packet
NS_ABORT_IF (!ret);
// perform A-MSDU aggregation
queue->Transform (amsdu, [&msdu](Ptr<WifiMacQueueItem> amsdu)
{
amsdu->Aggregate (msdu);
});
nMsdu++;
}
@@ -151,8 +145,6 @@ MsduAggregator::GetNextAmsdu (Ptr<const WifiMacQueueItem> peekedItem, WifiTxPara
}
// Aggregation succeeded
queueIt = it;
return amsdu;
}

View File

@@ -96,13 +96,10 @@ public:
* \param peekedItem the MSDU which we attempt to aggregate other MSDUs to
* \param txParams the TX parameters for the current frame
* \param availableTime the time available for the frame exchange
* \param[out] queueIt a queue iterator pointing to the queue item following the
* last item used to prepare the returned A-MSDU, if any; otherwise,
* its value is unchanged
* \return the resulting A-MSDU, if aggregation is possible, a null pointer otherwise.
*/
Ptr<WifiMacQueueItem> GetNextAmsdu (Ptr<const WifiMacQueueItem> peekedItem, WifiTxParameters& txParams,
Time availableTime, WifiMacQueueItem::ConstIterator& queueIt) const;
Time availableTime) const;
/**
* Determine the maximum size for an A-MSDU of the given TID that can be sent

View File

@@ -277,8 +277,7 @@ QosFrameExchangeManager::StartFrameExchange (Ptr<QosTxop> edca, Time availableTi
WifiTxParameters txParams;
txParams.m_txVector = m_mac->GetWifiRemoteStationManager ()->GetDataTxVector (mpdu->GetHeader ());
WifiMacQueueItem::ConstIterator queueIt;
Ptr<WifiMacQueueItem> item = edca->GetNextMpdu (mpdu, txParams, availableTime, initialFrame, queueIt);
Ptr<WifiMacQueueItem> item = edca->GetNextMpdu (mpdu, txParams, availableTime, initialFrame);
if (item == nullptr)
{

View File

@@ -308,7 +308,7 @@ QosTxop::HasFramesToTransmit (void)
// TODO Add a WifiMacQueue method that serves this purpose; IsEmpty () can
// then reuse such method.
m_queue->IsEmpty ();
bool queueIsNotEmpty = (m_queue->PeekFirstAvailable (m_qosBlockedDestinations) != m_queue->end ());
bool queueIsNotEmpty = (m_queue->PeekFirstAvailable (m_qosBlockedDestinations) != nullptr);
bool ret = (baManagerHasPackets || queueIsNotEmpty);
NS_LOG_FUNCTION (this << baManagerHasPackets << queueIsNotEmpty);
@@ -354,61 +354,55 @@ QosTxop::IsQosOldPacket (Ptr<const WifiMacQueueItem> mpdu)
}
Ptr<const WifiMacQueueItem>
QosTxop::PeekNextMpdu (uint8_t tid, Mac48Address recipient)
QosTxop::PeekNextMpdu (uint8_t tid, Mac48Address recipient, Ptr<const WifiMacQueueItem> item)
{
return PeekNextMpdu (WifiMacQueue::EMPTY, tid, recipient);
}
Ptr<const WifiMacQueueItem>
QosTxop::PeekNextMpdu (WifiMacQueueItem::ConstIterator queueIt, uint8_t tid, Mac48Address recipient)
{
NS_LOG_FUNCTION (this << +tid << recipient);
NS_LOG_FUNCTION (this << +tid << recipient << item);
// lambda to peek the next frame
auto peek = [this, &tid, &recipient, &queueIt] () -> WifiMacQueue::ConstIterator
auto peek = [this, &tid, &recipient, &item] () -> Ptr<const WifiMacQueueItem>
{
if (tid == 8 && recipient.IsBroadcast ()) // undefined TID and recipient
{
return m_queue->PeekFirstAvailable (m_qosBlockedDestinations, queueIt);
return m_queue->PeekFirstAvailable (m_qosBlockedDestinations, item);
}
if (m_qosBlockedDestinations->IsBlocked (recipient, tid))
{
return m_queue->end ();
return nullptr;
}
return m_queue->PeekByTidAndAddress (tid, recipient, queueIt);
return m_queue->PeekByTidAndAddress (tid, recipient, item);
};
queueIt = peek ();
item = peek ();
// remove old packets (must be retransmissions or in flight, otherwise they did
// not get a sequence number assigned)
while (queueIt != m_queue->end () && !(*queueIt)->IsFragment ())
while (item != nullptr && !item->IsFragment ())
{
if (((*queueIt)->GetHeader ().IsRetry () || (*queueIt)->IsInFlight ())
&& IsQosOldPacket (*queueIt))
if ((item->GetHeader ().IsRetry () || item->IsInFlight ())
&& IsQosOldPacket (item))
{
NS_LOG_DEBUG ("Removing an old packet from EDCA queue: " << **queueIt);
NS_LOG_DEBUG ("Removing an old packet from EDCA queue: " << *item);
if (!m_droppedMpduCallback.IsNull ())
{
m_droppedMpduCallback (WIFI_MAC_DROP_QOS_OLD_PACKET, *queueIt);
m_droppedMpduCallback (WIFI_MAC_DROP_QOS_OLD_PACKET, item);
}
queueIt = m_queue->Remove (queueIt);
queueIt = peek ();
auto oldItem = item;
item = peek ();
m_queue->Remove (oldItem);
}
else if ((*queueIt)->IsInFlight ())
else if (item->IsInFlight ())
{
NS_LOG_DEBUG ("Skipping in flight MPDU: " << **queueIt);
++queueIt;
queueIt = peek ();
NS_LOG_DEBUG ("Skipping in flight MPDU: " << *item);
item = peek ();
}
else
{
break;
}
}
if (queueIt != m_queue->end ())
if (item != nullptr)
{
NS_ASSERT (!(*queueIt)->IsInFlight ());
WifiMacHeader& hdr = (*queueIt)->GetHeader ();
NS_ASSERT (!item->IsInFlight ());
WifiMacHeader& hdr = item->GetItem ()->GetHeader ();
// peek the next sequence number and check if it is within the transmit window
// in case of QoS data frame
@@ -423,25 +417,25 @@ QosTxop::PeekNextMpdu (WifiMacQueueItem::ConstIterator queueIt, uint8_t tid, Mac
&& !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
{
NS_LOG_DEBUG ("Packet beyond the end of the current transmit window");
return 0;
return nullptr;
}
}
// Assign a sequence number if this is not a fragment nor a retransmission
if (!(*queueIt)->IsFragment () && !hdr.IsRetry ())
if (!item->IsFragment () && !hdr.IsRetry ())
{
hdr.SetSequenceNumber (sequence);
}
NS_LOG_DEBUG ("Packet peeked from EDCA queue: " << **queueIt);
return *queueIt;
NS_LOG_DEBUG ("Packet peeked from EDCA queue: " << *item);
return item;
}
return 0;
return nullptr;
}
Ptr<WifiMacQueueItem>
QosTxop::GetNextMpdu (Ptr<const WifiMacQueueItem> peekedItem, WifiTxParameters& txParams,
Time availableTime, bool initialFrame, WifiMacQueueItem::ConstIterator& queueIt)
Time availableTime, bool initialFrame)
{
NS_ASSERT (peekedItem != 0);
NS_ASSERT (m_qosFem != 0);
@@ -461,9 +455,6 @@ QosTxop::GetNextMpdu (Ptr<const WifiMacQueueItem> peekedItem, WifiTxParameters&
}
NS_ASSERT (peekedItem->IsQueued ());
WifiMacQueueItem::ConstIterator peekedIt = peekedItem->GetQueueIterator ();
NS_ASSERT ((*peekedIt)->GetPacket () == peekedItem->GetPacket ());
NS_ASSERT ((*peekedIt)->GetQueueAc () == m_ac);
Ptr<WifiMacQueueItem> mpdu;
// If it is a non-broadcast QoS Data frame and it is not a retransmission nor a fragment,
@@ -486,7 +477,7 @@ QosTxop::GetNextMpdu (Ptr<const WifiMacQueueItem> peekedItem, WifiTxParameters&
&& !peekedItem->IsInFlight ())
{
Ptr<HtFrameExchangeManager> htFem = StaticCast<HtFrameExchangeManager> (m_qosFem);
mpdu = htFem->GetMsduAggregator ()->GetNextAmsdu (peekedItem, txParams, availableTime, peekedIt);
mpdu = htFem->GetMsduAggregator ()->GetNextAmsdu (peekedItem, txParams, availableTime);
}
if (mpdu != 0)
@@ -498,14 +489,12 @@ QosTxop::GetNextMpdu (Ptr<const WifiMacQueueItem> peekedItem, WifiTxParameters&
if (mpdu == 0)
{
mpdu = *peekedIt;
peekedIt++;
mpdu = peekedItem->GetItem ();
}
// Assign a sequence number if this is not a fragment nor a retransmission
AssignSequenceNumber (mpdu);
NS_LOG_DEBUG ("Got MPDU from EDCA queue: " << *mpdu);
queueIt = peekedIt;
return mpdu;
}
@@ -608,10 +597,10 @@ QosTxop::GotAddBaResponse (const MgtAddBaResponseHeader *respHdr, Mac48Address r
// Add BA Response is received. In this case, the starting sequence number
// shall be set equal to the sequence number of such packet.
uint16_t startingSeq = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
WifiMacQueue::ConstIterator peekedIt = m_queue->PeekByTidAndAddress (tid, recipient);
if (peekedIt != m_queue->end () && (*peekedIt)->GetHeader ().IsRetry ())
auto peekedItem = m_queue->PeekByTidAndAddress (tid, recipient);
if (peekedItem != nullptr && peekedItem->GetHeader ().IsRetry ())
{
startingSeq = (*peekedIt)->GetHeader ().GetSequenceNumber ();
startingSeq = peekedItem->GetHeader ().GetSequenceNumber ();
}
m_baManager->UpdateAgreement (respHdr, recipient, startingSeq);
}

View File

@@ -303,38 +303,22 @@ public:
*/
uint16_t PeekNextSequenceNumberFor (const WifiMacHeader *hdr);
/**
* Peek the next frame to transmit to the given receiver and of the given
* TID from the block ack manager retransmit queue first and, if not found, from
* the EDCA queue. If <i>tid</i> is equal to 8 (invalid value) and <i>recipient</i>
* is the broadcast address, the first available frame is returned.
* Note that A-MSDU aggregation is never attempted (this is relevant if the
* frame is peeked from the EDCA queue). If the frame is peeked from the EDCA
* queue, it is assigned a sequence number peeked from MacTxMiddle.
* Peek the next frame to transmit to the given receiver and of the given TID
* from the EDCA queue. If <i>tid</i> is equal to 8 (invalid value) and <i>recipient</i>
* is the broadcast address, the first available frame is returned. If <i>item</i>
* is not a null pointer, the search starts from the packet following <i>item</i>
* in the queue; otherwise, the search starts from the head of the queue.
* Note that A-MSDU aggregation is never attempted. If the frame has never been
* transmitted, it is assigned a sequence number peeked from MacTxMiddle.
*
* \param tid traffic ID.
* \param recipient the receiver station address.
* \param item the item after which the search starts from
* \returns the peeked frame.
*/
Ptr<const WifiMacQueueItem> PeekNextMpdu (uint8_t tid = 8,
Mac48Address recipient = Mac48Address::GetBroadcast ());
/**
* Peek the next frame to transmit to the given receiver and of the given
* TID from the block ack manager retransmit queue first and, if not found, from
* the EDCA queue. If <i>tid</i> is equal to 8 (invalid value) and <i>recipient</i>
* is the broadcast address, the first available frame is returned.
* Note that A-MSDU aggregation is never attempted (this is relevant if the
* frame is peeked from the EDCA queue). If the frame is peeked from the EDCA
* queue, it is assigned a sequence number peeked from MacTxMiddle.
*
* \param queueIt the QueueIteratorPair pointing to the queue item from which the
* search for an MPDU starts, if the QueueIteratorPair is valid
* \param tid traffic ID.
* \param recipient the receiver station address.
* \returns the peeked frame.
*/
Ptr<const WifiMacQueueItem> PeekNextMpdu (WifiMacQueueItem::ConstIterator queueIt,
uint8_t tid = 8,
Mac48Address recipient = Mac48Address::GetBroadcast ());
Mac48Address recipient = Mac48Address::GetBroadcast (),
Ptr<const WifiMacQueueItem> item = nullptr);
/**
* Prepare the frame to transmit starting from the MPDU that has been previously
* peeked by calling PeekNextMpdu. A frame is only returned if it meets the
@@ -351,14 +335,10 @@ public:
(including protection and acknowledgment); a value of
* Time::Min() indicates no time constraint
* \param initialFrame true if the frame is the initial PPDU of a TXOP
* \param[out] queueIt a queue iterator pointing to the queue item following the
* last item used to prepare the returned MPDU, if any; if no MPDU
* is returned, its value is unchanged
* \return the frame to transmit or a null pointer if no frame meets the time constraints
*/
Ptr<WifiMacQueueItem> GetNextMpdu (Ptr<const WifiMacQueueItem> peekedItem, WifiTxParameters& txParams,
Time availableTime, bool initialFrame,
WifiMacQueueItem::ConstIterator& queueIt);
Time availableTime, bool initialFrame);
/**
* Assign a sequence number to the given MPDU, if it is not a fragment

View File

@@ -55,6 +55,13 @@ WifiMacQueueItem::~WifiMacQueueItem ()
{
}
Ptr<WifiMacQueueItem>
WifiMacQueueItem::GetItem (void) const
{
NS_ASSERT (IsQueued ());
return *m_queueIt;
}
Ptr<const Packet>
WifiMacQueueItem::GetPacket (void) const
{

View File

@@ -61,6 +61,15 @@ public:
virtual ~WifiMacQueueItem ();
/**
* Get a pointer to this WifiMacQueueItem object. This method is useful to convert
* a pointer to const WifiMacQueueItem into a pointer to non-const WifiMacQueueItem.
* This method can only be called if this item is stored in a wifi MAC queue.
*
* \return a pointer to this WifiMacQueueItem object
*/
Ptr<WifiMacQueueItem> GetItem (void) const;
/**
* \brief Get the packet stored in this item
* \return the packet stored in this item.

View File

@@ -79,6 +79,28 @@ static std::list<Ptr<WifiMacQueueItem>> g_emptyWifiMacQueue; //!< empty Wi-Fi MA
const WifiMacQueue::ConstIterator WifiMacQueue::EMPTY = g_emptyWifiMacQueue.end ();
bool
WifiMacQueue::TtlExceeded (ConstIterator &it, const Time& now)
{
if (now > (*it)->GetTimeStamp () + m_maxDelay)
{
NS_LOG_DEBUG ("Removing packet that stayed in the queue for too long (" <<
now - (*it)->GetTimeStamp () << ")");
auto curr = it++;
m_traceExpired (DoRemove (curr));
return true;
}
return false;
}
bool
WifiMacQueue::TtlExceeded (Ptr<const WifiMacQueueItem> item, const Time& now)
{
NS_ASSERT (item != nullptr && item->IsQueued ());
auto it = item->m_queueIt;
return TtlExceeded (it, now);
}
void
WifiMacQueue::SetMaxDelay (Time delay)
{
@@ -204,11 +226,13 @@ WifiMacQueue::Peek (void) const
return 0;
}
WifiMacQueue::ConstIterator
WifiMacQueue::PeekByAddress (Mac48Address dest, ConstIterator pos) const
Ptr<const WifiMacQueueItem>
WifiMacQueue::PeekByAddress (Mac48Address dest, Ptr<const WifiMacQueueItem> item) const
{
NS_LOG_FUNCTION (this << dest);
ConstIterator it = (pos != EMPTY ? pos : begin ());
NS_LOG_FUNCTION (this << dest << item);
NS_ASSERT (item == nullptr || item->IsQueued ());
ConstIterator it = (item != nullptr ? std::next (item->m_queueIt) : begin ());
const Time now = Simulator::Now ();
while (it != end ())
{
@@ -219,20 +243,22 @@ WifiMacQueue::PeekByAddress (Mac48Address dest, ConstIterator pos) const
if (((*it)->GetHeader ().IsData () || (*it)->GetHeader ().IsQosData ())
&& (*it)->GetDestinationAddress () == dest)
{
return it;
return *it;
}
}
it++;
}
NS_LOG_DEBUG ("The queue is empty");
return end ();
return nullptr;
}
WifiMacQueue::ConstIterator
WifiMacQueue::PeekByTid (uint8_t tid, ConstIterator pos) const
Ptr<const WifiMacQueueItem>
WifiMacQueue::PeekByTid (uint8_t tid, Ptr<const WifiMacQueueItem> item) const
{
NS_LOG_FUNCTION (this << +tid);
ConstIterator it = (pos != EMPTY ? pos : begin ());
NS_LOG_FUNCTION (this << +tid << item);
NS_ASSERT (item == nullptr || item->IsQueued ());
ConstIterator it = (item != nullptr ? std::next (item->m_queueIt) : begin ());
const Time now = Simulator::Now ();
while (it != end ())
{
@@ -242,20 +268,22 @@ WifiMacQueue::PeekByTid (uint8_t tid, ConstIterator pos) const
{
if ((*it)->GetHeader ().IsQosData () && (*it)->GetHeader ().GetQosTid () == tid)
{
return it;
return *it;
}
}
it++;
}
NS_LOG_DEBUG ("The queue is empty");
return end ();
return nullptr;
}
WifiMacQueue::ConstIterator
WifiMacQueue::PeekByTidAndAddress (uint8_t tid, Mac48Address dest, ConstIterator pos) const
Ptr<const WifiMacQueueItem>
WifiMacQueue::PeekByTidAndAddress (uint8_t tid, Mac48Address dest, Ptr<const WifiMacQueueItem> item) const
{
NS_LOG_FUNCTION (this << +tid << dest);
ConstIterator it = (pos != EMPTY ? pos : begin ());
NS_LOG_FUNCTION (this << +tid << dest << item);
NS_ASSERT (item == nullptr || item->IsQueued ());
ConstIterator it = (item != nullptr ? std::next (item->m_queueIt) : begin ());
const Time now = Simulator::Now ();
while (it != end ())
{
@@ -266,20 +294,23 @@ WifiMacQueue::PeekByTidAndAddress (uint8_t tid, Mac48Address dest, ConstIterator
if ((*it)->GetHeader ().IsQosData () && (*it)->GetDestinationAddress () == dest
&& (*it)->GetHeader ().GetQosTid () == tid)
{
return it;
return *it;
}
}
it++;
}
NS_LOG_DEBUG ("The queue is empty");
return end ();
return nullptr;
}
WifiMacQueue::ConstIterator
WifiMacQueue::PeekFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets, ConstIterator pos) const
Ptr<const WifiMacQueueItem>
WifiMacQueue::PeekFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets,
Ptr<const WifiMacQueueItem> item) const
{
NS_LOG_FUNCTION (this);
ConstIterator it = (pos != EMPTY ? pos : begin ());
NS_LOG_FUNCTION (this << item);
NS_ASSERT (item == nullptr || item->IsQueued ());
ConstIterator it = (item != nullptr ? std::next (item->m_queueIt) : begin ());
const Time now = Simulator::Now ();
while (it != end ())
{
@@ -290,13 +321,13 @@ WifiMacQueue::PeekFirstAvailable (const Ptr<QosBlockedDestinations> blockedPacke
if (!(*it)->GetHeader ().IsQosData () || !blockedPackets
|| !blockedPackets->IsBlocked ((*it)->GetHeader ().GetAddr1 (), (*it)->GetHeader ().GetQosTid ()))
{
return it;
return *it;
}
}
it++;
}
NS_LOG_DEBUG ("The queue is empty");
return end ();
return nullptr;
}
Ptr<WifiMacQueueItem>
@@ -316,16 +347,17 @@ WifiMacQueue::Remove (void)
return 0;
}
WifiMacQueue::ConstIterator
WifiMacQueue::Remove (ConstIterator pos, bool removeExpired)
Ptr<const WifiMacQueueItem>
WifiMacQueue::Remove (Ptr<const WifiMacQueueItem> item, bool removeExpired)
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION (this << item << removeExpired);
NS_ASSERT (item != 0 && item->IsQueued ());
if (!removeExpired)
{
ConstIterator curr = pos++;
DoRemove (curr);
return pos;
ConstIterator next = std::next (item->m_queueIt);
DoRemove (item->m_queueIt);
return (next == end () ? nullptr : *next);
}
const Time now = Simulator::Now ();
@@ -334,11 +366,11 @@ WifiMacQueue::Remove (ConstIterator pos, bool removeExpired)
ConstIterator it = begin ();
while (it != end ())
{
if (it == pos)
if (*it == item)
{
ConstIterator curr = pos++;
DoRemove (curr);
return pos;
ConstIterator next = std::next (item->m_queueIt);
DoRemove (item->m_queueIt);
return (next == end () ? nullptr : *next);
}
else if (!TtlExceeded (it, now))
{
@@ -346,7 +378,7 @@ WifiMacQueue::Remove (ConstIterator pos, bool removeExpired)
}
}
NS_LOG_DEBUG ("Invalid iterator");
return end ();
return nullptr;
}
void

View File

@@ -144,53 +144,61 @@ public:
/**
* 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.
* If <i>item</i> is not a null pointer, the search starts from the packet following
* <i>item</i> in the queue; otherwise, the search starts from the head of the queue.
* This method does not remove the packet from the queue.
*
* \param dest the given destination
* \param pos the iterator pointing to the packet the search starts from
* \param item the item after which the search starts from
*
* \return an iterator pointing to the peeked packet
* \return the peeked packet or nullptr if no packet was found
*/
ConstIterator PeekByAddress (Mac48Address dest, ConstIterator pos = EMPTY) const;
Ptr<const WifiMacQueueItem> PeekByAddress (Mac48Address dest,
Ptr<const WifiMacQueueItem> item = nullptr) const;
/**
* Search and return, if present in the queue, the first packet having the
* 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.
* TID equal to <i>tid</i>. If <i>item</i> is not a null pointer, the search
* starts from the packet following <i>item</i> in the queue; otherwise, the
* search starts from the head of the queue.
* 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
* \param item the item after which the search starts from
*
* \return an iterator pointing to the peeked packet
* \return the peeked packet or nullptr if no packet was found
*/
ConstIterator PeekByTid (uint8_t tid, ConstIterator pos = EMPTY) const;
Ptr<const WifiMacQueueItem> PeekByTid (uint8_t tid,
Ptr<const WifiMacQueueItem> item = nullptr) 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.
* If <i>item</i> is not a null pointer, the search starts from the packet
* following <i>item</i> in the queue; otherwise, the search starts from the
* head of the queue. 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
* \param item the item after which the search starts from
*
* \return an iterator pointing to the peeked packet
* \return the peeked packet or nullptr if no packet was found
*/
ConstIterator PeekByTidAndAddress (uint8_t tid, Mac48Address dest, ConstIterator pos = EMPTY) const;
Ptr<const WifiMacQueueItem> PeekByTidAndAddress (uint8_t tid, Mac48Address dest,
Ptr<const WifiMacQueueItem> item = nullptr) const;
/**
* Return first available packet for transmission. The packet is not removed from queue.
* Return first available packet for transmission. If <i>item</i> is not a null
* pointer, the search starts from the packet following <i>item</i> in the queue;
* otherwise, the search starts from the head of the queue.
* The packet is not removed from queue.
*
* \param blockedPackets the destination address & TID pairs that are waiting for a BlockAck response
* \param pos the iterator pointing to the packet the search starts from
* \param item the item after which the search starts from
*
* \return an iterator pointing to the peeked packet
* \return the peeked packet or nullptr if no packet was found
*/
ConstIterator PeekFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets = nullptr,
ConstIterator pos = EMPTY) const;
Ptr<const WifiMacQueueItem> PeekFirstAvailable (const Ptr<QosBlockedDestinations> blockedPackets = nullptr,
Ptr<const WifiMacQueueItem> item = nullptr) const;
/**
* Remove the packet in the front of the queue.
*
@@ -198,16 +206,16 @@ public:
*/
Ptr<WifiMacQueueItem> Remove (void) override;
/**
* 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
* Remove the given item from the queue and return the item following the
* removed one, if any, or a null pointer otherwise. 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 item the item to be removed
* \param removeExpired true to remove expired items
* \return an iterator pointing to the item following the removed one
* \return the item following the removed one, if any, or a null pointer, otherwise
*/
ConstIterator Remove (ConstIterator pos, bool removeExpired = false);
Ptr<const WifiMacQueueItem> Remove (Ptr<const WifiMacQueueItem> item, bool removeExpired = false);
/**
* Replace the given current item with the given new item. Actually, the current
@@ -312,6 +320,20 @@ public:
*/
uint32_t GetNBytes (void);
/**
* Remove the given item if it has been in the queue for too long. Return true
* if the item is removed, false otherwise.
*
* \param item the item whose lifetime is checked
* \param now a copy of Simulator::Now()
* \return true if the item is removed, false otherwise
*/
bool TtlExceeded (Ptr<const WifiMacQueueItem> item, const Time& now);
static const ConstIterator EMPTY; //!< Invalid iterator to signal an empty queue
private:
/**
* Remove the item pointed to by the iterator <i>it</i> if it has been in the
* queue for too long. If the item is removed, the iterator is updated to
@@ -323,10 +345,6 @@ public:
*/
inline bool TtlExceeded (ConstIterator &it, const Time& now);
static const ConstIterator EMPTY; //!< Invalid iterator to signal an empty queue
private:
/**
* Wrapper for the DoEnqueue method provided by the base class that additionally
* sets the iterator field of the item and updates internal statistics, if
@@ -371,25 +389,6 @@ private:
NS_LOG_TEMPLATE_DECLARE; //!< redefinition of the log component
};
/**
* Implementation of inline functions
*/
bool
WifiMacQueue::TtlExceeded (ConstIterator &it, const Time& now)
{
if (now > (*it)->GetTimeStamp () + m_maxDelay)
{
NS_LOG_DEBUG ("Removing packet that stayed in the queue for too long (" <<
now - (*it)->GetTimeStamp () << ")");
auto curr = it++;
m_traceExpired (DoRemove (curr));
return true;
}
return false;
}
} // namespace ns3

View File

@@ -192,11 +192,9 @@ AmpduAggregationTest::DoRun (void)
Ptr<const WifiMacQueueItem> peeked = m_mac->GetBEQueue ()->PeekNextMpdu ();
WifiTxParameters txParams;
txParams.m_txVector = m_mac->GetWifiRemoteStationManager ()->GetDataTxVector (peeked->GetHeader ());
WifiMacQueueItem::ConstIterator queueIt;
Ptr<WifiMacQueueItem> item = m_mac->GetBEQueue ()->GetNextMpdu (peeked, txParams, Time::Min (),
true, queueIt);
Ptr<WifiMacQueueItem> item = m_mac->GetBEQueue ()->GetNextMpdu (peeked, txParams, Time::Min (), true);
auto mpduList = mpduAggregator->GetNextAmpdu (item, txParams, Time::Min (), queueIt);
auto mpduList = mpduAggregator->GetNextAmpdu (item, txParams, Time::Min ());
NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "a single packet should not result in an A-MPDU");
@@ -225,8 +223,8 @@ AmpduAggregationTest::DoRun (void)
m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt1, hdr1));
m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt2, hdr2));
item = m_mac->GetBEQueue ()->GetNextMpdu (peeked, txParams, Time::Min (), true, queueIt);
mpduList = mpduAggregator->GetNextAmpdu (item, txParams, Time::Min (), queueIt);
item = m_mac->GetBEQueue ()->GetNextMpdu (peeked, txParams, Time::Min (), true);
mpduList = mpduAggregator->GetNextAmpdu (item, txParams, Time::Min ());
NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), false, "MPDU aggregation failed");
@@ -276,10 +274,9 @@ AmpduAggregationTest::DoRun (void)
peeked = m_mac->GetBEQueue ()->PeekNextMpdu ();
txParams.Clear ();
txParams.m_txVector = m_mac->GetWifiRemoteStationManager ()->GetDataTxVector (peeked->GetHeader ());
queueIt = WifiMacQueue::EMPTY; // reset queueIt
item = m_mac->GetBEQueue ()->GetNextMpdu (peeked, txParams, Time::Min (), true, queueIt);
item = m_mac->GetBEQueue ()->GetNextMpdu (peeked, txParams, Time::Min (), true);
mpduList = mpduAggregator->GetNextAmpdu (item, txParams, Time::Min (), queueIt);
mpduList = mpduAggregator->GetNextAmpdu (item, txParams, Time::Min ());
NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "a single packet for this destination should not result in an A-MPDU");
// dequeue the MPDU
@@ -288,10 +285,9 @@ AmpduAggregationTest::DoRun (void)
peeked = m_mac->GetBEQueue ()->PeekNextMpdu ();
txParams.Clear ();
txParams.m_txVector = m_mac->GetWifiRemoteStationManager ()->GetDataTxVector (peeked->GetHeader ());
queueIt = WifiMacQueue::EMPTY; // reset queueIt
item = m_mac->GetBEQueue ()->GetNextMpdu (peeked, txParams, Time::Min (), true, queueIt);
item = m_mac->GetBEQueue ()->GetNextMpdu (peeked, txParams, Time::Min (), true);
mpduList = mpduAggregator->GetNextAmpdu (item, txParams, Time::Min (), queueIt);
mpduList = mpduAggregator->GetNextAmpdu (item, txParams, Time::Min ());
NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "no MPDU aggregation should be performed if there is no agreement");
@@ -424,8 +420,7 @@ TwoLevelAggregationTest::DoRun (void)
WifiTxParameters txParams;
txParams.m_txVector = m_mac->GetWifiRemoteStationManager ()->GetDataTxVector (peeked->GetHeader ());
htFem->TryAddMpdu (peeked, txParams, Time::Min ());
WifiMacQueueItem::ConstIterator queueIt;
Ptr<WifiMacQueueItem> item = msduAggregator->GetNextAmsdu (peeked, txParams, Time::Min (), queueIt);
Ptr<WifiMacQueueItem> item = msduAggregator->GetNextAmsdu (peeked, txParams, Time::Min ());
bool result = (item != 0);
NS_TEST_EXPECT_MSG_EQ (result, true, "aggregation failed");
@@ -447,11 +442,11 @@ TwoLevelAggregationTest::DoRun (void)
txParams.Clear ();
txParams.m_txVector = m_mac->GetWifiRemoteStationManager ()->GetDataTxVector (peeked->GetHeader ());
htFem->TryAddMpdu (peeked, txParams, Time::Min ());
item = msduAggregator->GetNextAmsdu (peeked, txParams, Time::Min (), queueIt);
item = msduAggregator->GetNextAmsdu (peeked, txParams, Time::Min ());
NS_TEST_EXPECT_MSG_EQ ((item == 0), true, "A-MSDU aggregation did not fail");
htFem->DequeueMpdu (*peeked->GetQueueIterator ());
htFem->DequeueMpdu (peeked);
NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetWifiMacQueue ()->GetNPackets (), 0, "queue should be empty");
@@ -502,12 +497,11 @@ TwoLevelAggregationTest::DoRun (void)
// Compute the first MPDU to be aggregated in an A-MPDU. It must contain an A-MSDU
// aggregating two MSDUs
queueIt = WifiMacQueue::EMPTY; // reset queueIt
item = m_mac->GetVIQueue ()->GetNextMpdu (peeked, txParams, txopLimit, true, queueIt);
item = m_mac->GetVIQueue ()->GetNextMpdu (peeked, txParams, txopLimit, true);
NS_TEST_EXPECT_MSG_EQ (std::distance (item->begin (), item->end ()), 2, "There must be 2 MSDUs in the A-MSDU");
auto mpduList = mpduAggregator->GetNextAmpdu (item, txParams, txopLimit, queueIt);
auto mpduList = mpduAggregator->GetNextAmpdu (item, txParams, txopLimit);
// The maximum number of bytes that can be transmitted in a TXOP is (approximately, as we
// do not consider that the preamble is transmitted at a different rate):
@@ -684,11 +678,9 @@ HeAggregationTest::DoRunSubTest (uint16_t bufferSize)
Ptr<const WifiMacQueueItem> peeked = m_mac->GetBEQueue ()->PeekNextMpdu ();
WifiTxParameters txParams;
txParams.m_txVector = m_mac->GetWifiRemoteStationManager ()->GetDataTxVector (peeked->GetHeader ());
WifiMacQueueItem::ConstIterator queueIt;
Ptr<WifiMacQueueItem> item = m_mac->GetBEQueue ()->GetNextMpdu (peeked, txParams, Time::Min (),
true, queueIt);
Ptr<WifiMacQueueItem> item = m_mac->GetBEQueue ()->GetNextMpdu (peeked, txParams, Time::Min (), true);
auto mpduList = mpduAggregator->GetNextAmpdu (item, txParams, Time::Min (), queueIt);
auto mpduList = mpduAggregator->GetNextAmpdu (item, txParams, Time::Min ());
Ptr<WifiPsdu> psdu = Create<WifiPsdu> (mpduList);
htFem->DequeuePsdu (psdu);

View File

@@ -205,10 +205,9 @@ TestMultiUserScheduler::SelectTxFormat (void)
return SU_TX;
}
WifiMacQueueItem::ConstIterator queueIt;
Ptr<WifiMacQueueItem> mpdu = m_apMac->GetQosTxop (AC_BE)->GetNextMpdu (peeked, m_txParams,
m_availableTime,
m_initialFrame, queueIt);
m_initialFrame);
if (mpdu == 0)
{
NS_LOG_DEBUG ("Not enough time to send frames to all the stations");
@@ -216,7 +215,7 @@ TestMultiUserScheduler::SelectTxFormat (void)
}
std::vector<Ptr<WifiMacQueueItem>> mpduList;
mpduList = m_heFem->GetMpduAggregator ()->GetNextAmpdu (mpdu, m_txParams, m_availableTime, queueIt);
mpduList = m_heFem->GetMpduAggregator ()->GetNextAmpdu (mpdu, m_txParams, m_availableTime);
if (mpduList.size () > 1)
{
@@ -486,7 +485,7 @@ OfdmaAckSequenceTest::Transmit (std::string context, WifiConstPsduMap psduMap, W
auto tmp = it++;
if (!(*tmp)->IsInFlight ())
{
queue->Remove (tmp);
queue->Remove (*tmp, false);
m_flushed++;
}
}