wifi: Make WifiMacQueue a subclass of Queue
This commit is contained in:
@@ -174,11 +174,11 @@ WifiAcMappingTest::DoRun (void)
|
||||
{
|
||||
if (i == m_expectedQueue)
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ (queues[i]->GetSize (), 1, "There is no packet in the expected queue " << i);
|
||||
NS_TEST_ASSERT_MSG_EQ (queues[i]->GetNPackets (), 1, "There is no packet in the expected queue " << i);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ (queues[i]->GetSize (), 0, "Unexpectedly, there is a packet in queue " << i);
|
||||
NS_TEST_ASSERT_MSG_EQ (queues[i]->GetNPackets (), 0, "Unexpectedly, there is a packet in queue " << i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,9 @@ namespace ns3 {
|
||||
class MgtAddBaResponseHeader;
|
||||
class MgtAddBaRequestHeader;
|
||||
class MacTxMiddle;
|
||||
class WifiMacQueue;
|
||||
class WifiMacQueueItem;
|
||||
template <typename Item> class WifiQueue;
|
||||
typedef WifiQueue<WifiMacQueueItem> WifiMacQueue;
|
||||
|
||||
/**
|
||||
* \ingroup wifi
|
||||
|
||||
@@ -206,7 +206,7 @@ DcaTxop::Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << &hdr);
|
||||
m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr, packet);
|
||||
m_queue->Enqueue (packet, hdr);
|
||||
m_queue->Enqueue (Create<WifiMacQueueItem> (packet, hdr));
|
||||
StartAccessIfNeeded ();
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ DcaTxop::RestartAccessIfNeeded (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if ((m_currentPacket != 0
|
||||
|| !m_queue->IsEmpty ())
|
||||
|| m_queue->HasPackets ())
|
||||
&& !m_dcf->IsAccessRequested ())
|
||||
{
|
||||
m_manager->RequestAccess (m_dcf);
|
||||
@@ -235,7 +235,7 @@ DcaTxop::StartAccessIfNeeded (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (m_currentPacket == 0
|
||||
&& !m_queue->IsEmpty ()
|
||||
&& m_queue->HasPackets ()
|
||||
&& !m_dcf->IsAccessRequested ())
|
||||
{
|
||||
m_manager->RequestAccess (m_dcf);
|
||||
@@ -343,7 +343,7 @@ bool
|
||||
DcaTxop::NeedsAccess (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return !m_queue->IsEmpty () || m_currentPacket != 0;
|
||||
return m_queue->HasPackets () || m_currentPacket != 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -352,12 +352,15 @@ DcaTxop::NotifyAccessGranted (void)
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (m_currentPacket == 0)
|
||||
{
|
||||
if (m_queue->IsEmpty ())
|
||||
if (!m_queue->HasPackets ())
|
||||
{
|
||||
NS_LOG_DEBUG ("queue empty");
|
||||
return;
|
||||
}
|
||||
m_currentPacket = m_queue->Dequeue (&m_currentHdr);
|
||||
Ptr<WifiMacQueueItem> item = m_queue->Dequeue ();
|
||||
NS_ASSERT (item != 0);
|
||||
m_currentPacket = item->GetPacket ();
|
||||
m_currentHdr = item->GetHeader ();
|
||||
NS_ASSERT (m_currentPacket != 0);
|
||||
uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
|
||||
m_currentHdr.SetSequenceNumber (sequence);
|
||||
@@ -436,7 +439,7 @@ DcaTxop::NotifySleep (void)
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (m_currentPacket != 0)
|
||||
{
|
||||
m_queue->PushFront (m_currentPacket, m_currentHdr);
|
||||
m_queue->PushFront (Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr));
|
||||
m_currentPacket = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace ns3 {
|
||||
|
||||
class DcfState;
|
||||
class DcfManager;
|
||||
class WifiMacQueue;
|
||||
class MacTxMiddle;
|
||||
class RandomStream;
|
||||
class CtrlBAckResponseHeader;
|
||||
|
||||
@@ -153,7 +153,7 @@ bool
|
||||
EdcaTxopN::NeedsAccess (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return !m_queue->IsEmpty () || m_currentPacket != 0 || m_baManager->HasPackets ();
|
||||
return m_queue->HasPackets () || m_currentPacket != 0 || m_baManager->HasPackets ();
|
||||
}
|
||||
|
||||
uint16_t EdcaTxopN::GetNextSequenceNumberFor (WifiMacHeader *hdr)
|
||||
@@ -186,7 +186,7 @@ EdcaTxopN::NotifyAccessGranted (void)
|
||||
m_startTxop = Simulator::Now ();
|
||||
if (m_currentPacket == 0)
|
||||
{
|
||||
if (m_queue->IsEmpty () && !m_baManager->HasPackets ())
|
||||
if (!m_queue->HasPackets () && !m_baManager->HasPackets ())
|
||||
{
|
||||
NS_LOG_DEBUG ("queue is empty");
|
||||
return;
|
||||
@@ -200,11 +200,14 @@ EdcaTxopN::NotifyAccessGranted (void)
|
||||
m_currentPacket = m_baManager->GetNextPacket (m_currentHdr);
|
||||
if (m_currentPacket == 0)
|
||||
{
|
||||
if (m_queue->PeekFirstAvailable (&m_currentHdr, m_currentPacketTimestamp, m_qosBlockedDestinations) == 0)
|
||||
Ptr<const WifiMacQueueItem> item = m_queue->PeekFirstAvailable (m_qosBlockedDestinations);
|
||||
if (item == 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("no available packets in the queue");
|
||||
return;
|
||||
}
|
||||
m_currentHdr = item->GetHeader ();
|
||||
m_currentPacketTimestamp = item->GetTimeStamp ();
|
||||
if (m_currentHdr.IsQosData () && !m_currentHdr.GetAddr1 ().IsBroadcast ()
|
||||
&& m_stationManager->GetQosSupported (m_currentHdr.GetAddr1 ())
|
||||
&& !m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
|
||||
@@ -212,7 +215,10 @@ EdcaTxopN::NotifyAccessGranted (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_currentPacket = m_queue->DequeueFirstAvailable (&m_currentHdr, m_currentPacketTimestamp, m_qosBlockedDestinations);
|
||||
item = m_queue->DequeueFirstAvailable (m_qosBlockedDestinations);
|
||||
m_currentPacket = item->GetPacket ();
|
||||
m_currentHdr = item->GetHeader ();
|
||||
m_currentPacketTimestamp = item->GetTimeStamp ();
|
||||
NS_ASSERT (m_currentPacket != 0);
|
||||
|
||||
uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
|
||||
@@ -280,13 +286,14 @@ EdcaTxopN::NotifyAccessGranted (void)
|
||||
{
|
||||
m_currentIsFragmented = false;
|
||||
WifiMacHeader peekedHdr;
|
||||
Time tstamp;
|
||||
Ptr<const WifiMacQueueItem> item;
|
||||
if (m_currentHdr.IsQosData ()
|
||||
&& m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1, m_currentHdr.GetAddr1 (), &tstamp)
|
||||
&& (item = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1, m_currentHdr.GetAddr1 ()))
|
||||
&& !m_currentHdr.GetAddr1 ().IsBroadcast ()
|
||||
&& m_msduAggregator != 0 && !m_currentHdr.IsRetry ())
|
||||
{
|
||||
peekedHdr = item->GetHeader ();
|
||||
/* here is performed aggregation */
|
||||
Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
|
||||
m_msduAggregator->Aggregate (m_currentPacket, currentAggregatedPacket,
|
||||
@@ -294,25 +301,26 @@ EdcaTxopN::NotifyAccessGranted (void)
|
||||
MapDestAddressForAggregation (peekedHdr));
|
||||
bool aggregated = false;
|
||||
bool isAmsdu = false;
|
||||
Ptr<const Packet> peekedPacket = m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1,
|
||||
m_currentHdr.GetAddr1 (), &tstamp);
|
||||
while (peekedPacket != 0)
|
||||
Ptr<const WifiMacQueueItem> peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1,
|
||||
m_currentHdr.GetAddr1 ());
|
||||
while (peekedItem != 0)
|
||||
{
|
||||
aggregated = m_msduAggregator->Aggregate (peekedPacket, currentAggregatedPacket,
|
||||
peekedHdr = peekedItem->GetHeader ();
|
||||
aggregated = m_msduAggregator->Aggregate (peekedItem->GetPacket (), currentAggregatedPacket,
|
||||
MapSrcAddressForAggregation (peekedHdr),
|
||||
MapDestAddressForAggregation (peekedHdr));
|
||||
if (aggregated)
|
||||
{
|
||||
isAmsdu = true;
|
||||
m_queue->Remove (peekedPacket);
|
||||
m_queue->Remove (peekedItem->GetPacket ());
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
peekedPacket = m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1, m_currentHdr.GetAddr1 (), &tstamp);
|
||||
peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1, m_currentHdr.GetAddr1 ());
|
||||
}
|
||||
if (isAmsdu)
|
||||
{
|
||||
@@ -349,7 +357,12 @@ void EdcaTxopN::NotifyInternalCollision (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
packet = m_queue->Peek (&header);
|
||||
Ptr<const WifiMacQueueItem> item = m_queue->Peek ();
|
||||
if (item)
|
||||
{
|
||||
packet = item->GetPacket ();
|
||||
header = item->GetHeader ();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -403,7 +416,12 @@ void EdcaTxopN::NotifyInternalCollision (void)
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Dequeueing and discarding head of queue");
|
||||
packet = m_queue->Peek (&header);
|
||||
Ptr<const WifiMacQueueItem> item = m_queue->Peek ();
|
||||
if (item)
|
||||
{
|
||||
packet = item->GetPacket ();
|
||||
header = item->GetHeader ();
|
||||
}
|
||||
}
|
||||
m_dcf->ResetCw ();
|
||||
}
|
||||
@@ -711,7 +729,7 @@ EdcaTxopN::RestartAccessIfNeeded (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if ((m_currentPacket != 0
|
||||
|| !m_queue->IsEmpty () || m_baManager->HasPackets ())
|
||||
|| m_queue->HasPackets () || m_baManager->HasPackets ())
|
||||
&& !m_dcf->IsAccessRequested ())
|
||||
{
|
||||
Ptr<const Packet> packet;
|
||||
@@ -725,9 +743,15 @@ EdcaTxopN::RestartAccessIfNeeded (void)
|
||||
{
|
||||
packet = m_baManager->PeekNextPacket (hdr);
|
||||
}
|
||||
else if (m_queue->PeekFirstAvailable (&hdr, m_currentPacketTimestamp, m_qosBlockedDestinations) != 0)
|
||||
else
|
||||
{
|
||||
packet = m_queue->PeekFirstAvailable (&hdr, m_currentPacketTimestamp, m_qosBlockedDestinations);
|
||||
Ptr<const WifiMacQueueItem> item = m_queue->PeekFirstAvailable (m_qosBlockedDestinations);
|
||||
if (item)
|
||||
{
|
||||
packet = item->GetPacket ();
|
||||
hdr = item->GetHeader ();
|
||||
m_currentPacketTimestamp = item->GetTimeStamp ();
|
||||
}
|
||||
}
|
||||
if (packet != 0)
|
||||
{
|
||||
@@ -746,7 +770,7 @@ EdcaTxopN::StartAccessIfNeeded (void)
|
||||
{
|
||||
//NS_LOG_FUNCTION (this);
|
||||
if (m_currentPacket == 0
|
||||
&& (!m_queue->IsEmpty () || m_baManager->HasPackets ())
|
||||
&& (m_queue->HasPackets () || m_baManager->HasPackets ())
|
||||
&& !m_dcf->IsAccessRequested ())
|
||||
{
|
||||
Ptr<const Packet> packet;
|
||||
@@ -760,9 +784,15 @@ EdcaTxopN::StartAccessIfNeeded (void)
|
||||
{
|
||||
packet = m_baManager->PeekNextPacket (hdr);
|
||||
}
|
||||
else if (m_queue->PeekFirstAvailable (&hdr, m_currentPacketTimestamp, m_qosBlockedDestinations) != 0)
|
||||
else
|
||||
{
|
||||
packet = m_queue->PeekFirstAvailable (&hdr, m_currentPacketTimestamp, m_qosBlockedDestinations);
|
||||
Ptr<const WifiMacQueueItem> item = m_queue->PeekFirstAvailable (m_qosBlockedDestinations);
|
||||
if (item)
|
||||
{
|
||||
packet = item->GetPacket ();
|
||||
hdr = item->GetHeader ();
|
||||
m_currentPacketTimestamp = item->GetTimeStamp ();
|
||||
}
|
||||
}
|
||||
if (packet != 0)
|
||||
{
|
||||
@@ -810,15 +840,17 @@ EdcaTxopN::StartNextPacket (void)
|
||||
Time txopLimit = GetTxopLimit ();
|
||||
NS_ASSERT (txopLimit == NanoSeconds (0) || Simulator::Now () - m_startTxop <= txopLimit);
|
||||
WifiMacHeader hdr = m_currentHdr;
|
||||
Time tstamp;
|
||||
Ptr<const Packet> peekedPacket = m_baManager->GetNextPacket (hdr);
|
||||
if (peekedPacket == 0)
|
||||
{
|
||||
peekedPacket = m_queue->PeekByTidAndAddress (&hdr,
|
||||
m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1,
|
||||
m_currentHdr.GetAddr1 (),
|
||||
&tstamp);
|
||||
Ptr<const WifiMacQueueItem> peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1,
|
||||
m_currentHdr.GetAddr1 ());
|
||||
if (peekedItem)
|
||||
{
|
||||
peekedPacket = peekedItem->GetPacket ();
|
||||
hdr = peekedItem->GetHeader ();
|
||||
}
|
||||
}
|
||||
if ((m_currentHdr.IsQosBlockAck () && peekedPacket == 0) || m_baManager->HasBar (m_currentBar))
|
||||
{
|
||||
@@ -847,11 +879,12 @@ EdcaTxopN::StartNextPacket (void)
|
||||
if (txopLimit >= GetLow ()->CalculateOverallTxTime (peekedPacket, &hdr, m_currentParams))
|
||||
{
|
||||
NS_LOG_DEBUG ("start next packet");
|
||||
m_currentPacket = m_queue->DequeueByTidAndAddress (&hdr,
|
||||
m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1,
|
||||
m_currentHdr.GetAddr1 ());
|
||||
m_currentHdr = hdr;
|
||||
Ptr<WifiMacQueueItem> item = m_queue->DequeueByTidAndAddress (m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1,
|
||||
m_currentHdr.GetAddr1 ());
|
||||
NS_ASSERT (item != 0);
|
||||
m_currentPacket = item->GetPacket ();
|
||||
m_currentHdr = item->GetHeader ();
|
||||
NS_ASSERT (m_currentPacket != 0);
|
||||
uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
|
||||
m_currentHdr.SetSequenceNumber (sequence);
|
||||
@@ -891,22 +924,21 @@ EdcaTxopN::HasTxop (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
WifiMacHeader hdr;
|
||||
Time tstamp;
|
||||
if (!m_currentHdr.IsQosData () || GetTxopLimit () == NanoSeconds (0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Ptr<const Packet> peekedPacket = m_queue->PeekByTidAndAddress (&hdr,
|
||||
m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1,
|
||||
m_currentHdr.GetAddr1 (),
|
||||
&tstamp);
|
||||
if (peekedPacket == 0)
|
||||
Ptr<const WifiMacQueueItem> peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
|
||||
WifiMacHeader::ADDR1,
|
||||
m_currentHdr.GetAddr1 ());
|
||||
if (peekedItem == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Ptr<const Packet> peekedPacket = peekedItem->GetPacket ();
|
||||
hdr = peekedItem->GetHeader ();
|
||||
MacLowTransmissionParameters params = m_currentParams;
|
||||
if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck ())
|
||||
{
|
||||
@@ -1215,7 +1247,7 @@ EdcaTxopN::PushFront (Ptr<const Packet> packet, const WifiMacHeader &hdr)
|
||||
NS_LOG_FUNCTION (this << packet << &hdr);
|
||||
WifiMacTrailer fcs;
|
||||
m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr, packet);
|
||||
m_queue->PushFront (packet, hdr);
|
||||
m_queue->PushFront (Create<WifiMacQueueItem> (packet, hdr));
|
||||
StartAccessIfNeeded ();
|
||||
}
|
||||
|
||||
|
||||
@@ -674,11 +674,11 @@ MacLow::StartTransmission (Ptr<const Packet> packet,
|
||||
//queue when previous RTS request has failed.
|
||||
m_ampdu = false;
|
||||
}
|
||||
else if (m_currentHdr.IsQosData () && m_aggregateQueue[GetTid (packet, *hdr)]->GetSize () > 0)
|
||||
else if (m_currentHdr.IsQosData () && m_aggregateQueue[GetTid (packet, *hdr)]->GetNPackets () > 0)
|
||||
{
|
||||
//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.
|
||||
uint8_t sentMpdus = m_aggregateQueue[GetTid (packet, *hdr)]->GetSize ();
|
||||
uint8_t sentMpdus = m_aggregateQueue[GetTid (packet, *hdr)]->GetNPackets ();
|
||||
m_ampdu = true;
|
||||
if (sentMpdus > 1)
|
||||
{
|
||||
@@ -1502,10 +1502,10 @@ MacLow::ForwardDown (Ptr<const Packet> packet, const WifiMacHeader* hdr, WifiTxV
|
||||
else
|
||||
{
|
||||
Ptr<Packet> newPacket;
|
||||
Ptr <const Packet> dequeuedPacket;
|
||||
Ptr <WifiMacQueueItem> dequeuedItem;
|
||||
WifiMacHeader newHdr;
|
||||
WifiMacTrailer fcs;
|
||||
uint8_t queueSize = m_aggregateQueue[GetTid (packet, *hdr)]->GetSize ();
|
||||
uint8_t queueSize = m_aggregateQueue[GetTid (packet, *hdr)]->GetNPackets ();
|
||||
bool singleMpdu = false;
|
||||
bool last = false;
|
||||
MpduType mpdutype = NORMAL_MPDU;
|
||||
@@ -1530,8 +1530,9 @@ MacLow::ForwardDown (Ptr<const Packet> packet, const WifiMacHeader* hdr, WifiTxV
|
||||
}
|
||||
for (; queueSize > 0; queueSize--)
|
||||
{
|
||||
dequeuedPacket = m_aggregateQueue[GetTid (packet, *hdr)]->Dequeue (&newHdr);
|
||||
newPacket = dequeuedPacket->Copy ();
|
||||
dequeuedItem = m_aggregateQueue[GetTid (packet, *hdr)]->Dequeue ();
|
||||
newHdr = dequeuedItem->GetHeader ();
|
||||
newPacket = dequeuedItem->GetPacket ()->Copy ();
|
||||
newHdr.SetDuration (hdr->GetDuration ());
|
||||
newPacket->AddHeader (newHdr);
|
||||
AddWifiMacTrailer (newPacket);
|
||||
@@ -1657,7 +1658,7 @@ MacLow::BlockAckTimeout (void)
|
||||
m_currentDca = 0;
|
||||
m_ampdu = false;
|
||||
uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
|
||||
uint8_t nTxMpdus = m_aggregateQueue[tid]->GetSize ();
|
||||
uint8_t nTxMpdus = m_aggregateQueue[tid]->GetNPackets ();
|
||||
FlushAggregateQueue (tid);
|
||||
dca->MissedBlockAck (nTxMpdus);
|
||||
}
|
||||
@@ -2025,7 +2026,7 @@ MacLow::SendDataAfterCts (Mac48Address source, Time duration)
|
||||
if (m_currentHdr.IsQosData ())
|
||||
{
|
||||
uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
|
||||
if (m_aggregateQueue[GetTid (m_currentPacket, m_currentHdr)]->GetSize () != 0)
|
||||
if (m_aggregateQueue[GetTid (m_currentPacket, m_currentHdr)]->GetNPackets () != 0)
|
||||
{
|
||||
for (std::vector<Item>::size_type i = 0; i != m_txPackets[tid].size (); i++)
|
||||
{
|
||||
@@ -2758,7 +2759,7 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
{
|
||||
NS_LOG_DEBUG ("Adding packet with Sequence number " << currentSequenceNumber << " to A-MPDU, packet size = " << newPacket->GetSize () << ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
|
||||
i++;
|
||||
m_aggregateQueue[tid]->Enqueue (aggPacket, peekedHdr);
|
||||
m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
|
||||
}
|
||||
}
|
||||
else if (hdr.IsBlockAckReq ())
|
||||
@@ -2774,9 +2775,15 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
Ptr<const Packet> peekedPacket = edcaIt->second->PeekNextRetransmitPacket (peekedHdr, peekedHdr.GetAddr1 (), tid, &tstamp);
|
||||
if (peekedPacket == 0)
|
||||
{
|
||||
peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
|
||||
WifiMacHeader::ADDR1,
|
||||
hdr.GetAddr1 (), &tstamp);
|
||||
Ptr<const WifiMacQueueItem> item = queue->PeekByTidAndAddress (tid,
|
||||
WifiMacHeader::ADDR1,
|
||||
hdr.GetAddr1 ());
|
||||
if (item)
|
||||
{
|
||||
peekedPacket = item->GetPacket ();
|
||||
peekedHdr = item->GetHeader ();
|
||||
tstamp = item->GetTimeStamp ();
|
||||
}
|
||||
currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
|
||||
|
||||
/* here is performed MSDU aggregation (two-level aggregation) */
|
||||
@@ -2823,7 +2830,7 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
aggregated = edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
|
||||
if (aggregated)
|
||||
{
|
||||
m_aggregateQueue[tid]->Enqueue (aggPacket, peekedHdr);
|
||||
m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
|
||||
if (i == 1 && hdr.IsQosData ())
|
||||
{
|
||||
if (!m_txParams.MustSendRts ())
|
||||
@@ -2867,9 +2874,14 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
{
|
||||
//I reached the first packet that I added to this A-MPDU
|
||||
retry = false;
|
||||
peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid, WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp);
|
||||
if (peekedPacket != 0)
|
||||
Ptr<const WifiMacQueueItem> item = queue->PeekByTidAndAddress (tid,
|
||||
WifiMacHeader::ADDR1,
|
||||
hdr.GetAddr1 ());
|
||||
if (item != 0)
|
||||
{
|
||||
peekedPacket = item->GetPacket ();
|
||||
peekedHdr = item->GetHeader ();
|
||||
tstamp = item->GetTimeStamp ();
|
||||
//find what will the sequence number be so that we don't send more than 64 packets apart
|
||||
currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
|
||||
|
||||
@@ -2890,10 +2902,13 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
}
|
||||
else
|
||||
{
|
||||
peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
|
||||
WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp);
|
||||
if (peekedPacket != 0)
|
||||
Ptr<const WifiMacQueueItem> item = queue->PeekByTidAndAddress (tid,
|
||||
WifiMacHeader::ADDR1, hdr.GetAddr1 ());
|
||||
if (item != 0)
|
||||
{
|
||||
peekedPacket = item->GetPacket ();
|
||||
peekedHdr = item->GetHeader ();
|
||||
tstamp = item->GetTimeStamp ();
|
||||
//find what will the sequence number be so that we don't send more than 64 packets apart
|
||||
currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
|
||||
|
||||
@@ -2906,6 +2921,10 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
peekedPacket = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2916,7 +2935,7 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
newPacket = packet->Copy ();
|
||||
peekedHdr = hdr;
|
||||
Ptr<Packet> aggPacket = newPacket->Copy ();
|
||||
m_aggregateQueue[tid]->Enqueue (aggPacket, peekedHdr);
|
||||
m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
|
||||
newPacket->AddHeader (peekedHdr);
|
||||
AddWifiMacTrailer (newPacket);
|
||||
edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
|
||||
@@ -2940,7 +2959,7 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t queueSize = m_aggregateQueue[tid]->GetSize ();
|
||||
uint8_t queueSize = m_aggregateQueue[tid]->GetNPackets ();
|
||||
NS_ASSERT (queueSize <= 2); //since it is not an A-MPDU then only 2 packets should have been added to the queue no more
|
||||
if (queueSize >= 1)
|
||||
{
|
||||
@@ -2961,7 +2980,7 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
|
||||
currentAggregatedPacket = Create<Packet> ();
|
||||
edcaIt->second->GetMpduAggregator ()->AggregateSingleMpdu (packet, currentAggregatedPacket);
|
||||
m_aggregateQueue[tid]->Enqueue (packet, peekedHdr);
|
||||
m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (packet, peekedHdr));
|
||||
|
||||
if (edcaIt->second->GetBaAgreementExists (hdr.GetAddr1 (), tid))
|
||||
{
|
||||
@@ -2987,7 +3006,7 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
void
|
||||
MacLow::FlushAggregateQueue (uint8_t tid)
|
||||
{
|
||||
if (m_aggregateQueue[tid]->GetSize () > 0)
|
||||
if (m_aggregateQueue[tid]->GetNPackets () > 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Flush aggregate queue");
|
||||
m_aggregateQueue[tid]->Flush ();
|
||||
@@ -3020,18 +3039,26 @@ MacLow::PerformMsduAggregation (Ptr<const Packet> packet, WifiMacHeader *hdr, Ti
|
||||
NS_ASSERT (edcaIt != m_edca.end ());
|
||||
queue = edcaIt->second->GetQueue ();
|
||||
|
||||
Ptr<const Packet> peekedPacket = queue->DequeueByTidAndAddress (hdr, hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 ());
|
||||
Ptr<const WifiMacQueueItem> peekedItem = queue->DequeueByTidAndAddress (hdr->GetQosTid (),
|
||||
WifiMacHeader::ADDR1,
|
||||
hdr->GetAddr1 ());
|
||||
if (peekedItem)
|
||||
{
|
||||
*hdr = peekedItem->GetHeader ();
|
||||
}
|
||||
|
||||
edcaIt->second->GetMsduAggregator ()->Aggregate (packet, currentAmsduPacket,
|
||||
edcaIt->second->MapSrcAddressForAggregation (*hdr),
|
||||
edcaIt->second->MapDestAddressForAggregation (*hdr));
|
||||
|
||||
peekedPacket = queue->PeekByTidAndAddress (hdr, hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 (), tstamp);
|
||||
while (peekedPacket != 0)
|
||||
peekedItem = queue->PeekByTidAndAddress (hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 ());
|
||||
while (peekedItem != 0)
|
||||
{
|
||||
*hdr = peekedItem->GetHeader ();
|
||||
*tstamp = peekedItem->GetTimeStamp ();
|
||||
tempPacket = currentAmsduPacket;
|
||||
|
||||
msduAggregation = edcaIt->second->GetMsduAggregator ()->Aggregate (peekedPacket, tempPacket,
|
||||
msduAggregation = edcaIt->second->GetMsduAggregator ()->Aggregate (peekedItem->GetPacket (), tempPacket,
|
||||
edcaIt->second->MapSrcAddressForAggregation (*hdr),
|
||||
edcaIt->second->MapDestAddressForAggregation (*hdr));
|
||||
|
||||
@@ -3039,13 +3066,13 @@ MacLow::PerformMsduAggregation (Ptr<const Packet> packet, WifiMacHeader *hdr, Ti
|
||||
{
|
||||
isAmsdu = true;
|
||||
currentAmsduPacket = tempPacket;
|
||||
queue->Remove (peekedPacket);
|
||||
queue->Remove (peekedItem->GetPacket ());
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
peekedPacket = queue->PeekByTidAndAddress (hdr, hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 (), tstamp);
|
||||
peekedItem = queue->PeekByTidAndAddress (hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 ());
|
||||
}
|
||||
|
||||
if (isAmsdu)
|
||||
@@ -3057,7 +3084,7 @@ MacLow::PerformMsduAggregation (Ptr<const Packet> packet, WifiMacHeader *hdr, Ti
|
||||
}
|
||||
else
|
||||
{
|
||||
queue->PushFront (packet, *hdr);
|
||||
queue->PushFront (Create<WifiMacQueueItem> (packet, *hdr));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,12 @@ class AmpduAggregationTest;
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class WifiMacQueue;
|
||||
class DcaTxop;
|
||||
class EdcaTxopN;
|
||||
class DcfManager;
|
||||
class WifiMacQueueItem;
|
||||
template <typename Item> class WifiQueue;
|
||||
typedef WifiQueue<WifiMacQueueItem> WifiMacQueue;
|
||||
|
||||
/**
|
||||
* \brief control how a packet is transmitted.
|
||||
|
||||
@@ -18,38 +18,84 @@
|
||||
*
|
||||
* Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
* Mirko Banchi <mk.banchi@gmail.com>
|
||||
* Stefano Avallone <stavallo@unina.it>
|
||||
*/
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/enum.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "wifi-mac-queue.h"
|
||||
#include "qos-blocked-destinations.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (WifiMacQueue);
|
||||
NS_LOG_COMPONENT_DEFINE ("WifiMacQueue");
|
||||
|
||||
WifiMacQueue::Item::Item (Ptr<const Packet> packet,
|
||||
const WifiMacHeader &hdr,
|
||||
Time tstamp)
|
||||
: packet (packet),
|
||||
hdr (hdr),
|
||||
tstamp (tstamp)
|
||||
WifiMacQueueItem::WifiMacQueueItem (Ptr<const Packet> p, const WifiMacHeader & header)
|
||||
: m_packet (p),
|
||||
m_header (header),
|
||||
m_tstamp (Simulator::Now ())
|
||||
{
|
||||
}
|
||||
|
||||
WifiMacQueueItem::~WifiMacQueueItem ()
|
||||
{
|
||||
}
|
||||
|
||||
Ptr<const Packet>
|
||||
WifiMacQueueItem::GetPacket (void) const
|
||||
{
|
||||
return m_packet;
|
||||
}
|
||||
|
||||
const WifiMacHeader&
|
||||
WifiMacQueueItem::GetHeader (void) const
|
||||
{
|
||||
return m_header;
|
||||
}
|
||||
|
||||
Mac48Address
|
||||
WifiMacQueueItem::GetAddress (enum WifiMacHeader::AddressType type) const
|
||||
{
|
||||
if (type == WifiMacHeader::ADDR1)
|
||||
{
|
||||
return m_header.GetAddr1 ();
|
||||
}
|
||||
if (type == WifiMacHeader::ADDR2)
|
||||
{
|
||||
return m_header.GetAddr2 ();
|
||||
}
|
||||
if (type == WifiMacHeader::ADDR3)
|
||||
{
|
||||
return m_header.GetAddr3 ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Time
|
||||
WifiMacQueueItem::GetTimeStamp (void) const
|
||||
{
|
||||
return m_tstamp;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
WifiMacQueueItem::GetSize (void) const
|
||||
{
|
||||
return m_packet->GetSize () + m_header.GetSerializedSize ();
|
||||
}
|
||||
|
||||
|
||||
NS_OBJECT_TEMPLATE_CLASS_DEFINE (Queue,WifiMacQueueItem);
|
||||
|
||||
template<>
|
||||
TypeId
|
||||
WifiMacQueue::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::WifiMacQueue")
|
||||
.SetParent<Object> ()
|
||||
.SetParent<Queue<WifiMacQueueItem> > ()
|
||||
.SetGroupName ("Wifi")
|
||||
.AddConstructor<WifiMacQueue> ()
|
||||
.AddAttribute ("MaxPacketNumber", "If a packet arrives when there are already this number of packets, it is dropped.",
|
||||
UintegerValue (400),
|
||||
MakeUintegerAccessor (&WifiMacQueue::m_maxSize),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
.AddAttribute ("MaxDelay", "If a packet stays longer than this delay in the queue, it is dropped.",
|
||||
TimeValue (MilliSeconds (500.0)),
|
||||
MakeTimeAccessor (&WifiMacQueue::m_maxDelay),
|
||||
@@ -63,296 +109,305 @@ WifiMacQueue::GetTypeId (void)
|
||||
return tid;
|
||||
}
|
||||
|
||||
WifiMacQueue::WifiMacQueue ()
|
||||
: m_size (0)
|
||||
template<>
|
||||
WifiMacQueue::WifiQueue ()
|
||||
{
|
||||
}
|
||||
|
||||
WifiMacQueue::~WifiMacQueue ()
|
||||
template<>
|
||||
WifiMacQueue::~WifiQueue ()
|
||||
{
|
||||
Flush ();
|
||||
}
|
||||
|
||||
void
|
||||
WifiMacQueue::SetMaxSize (uint32_t maxSize)
|
||||
{
|
||||
m_maxSize = maxSize;
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
WifiMacQueue::SetMaxDelay (Time delay)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << delay);
|
||||
|
||||
m_maxDelay = delay;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
WifiMacQueue::GetMaxSize (void) const
|
||||
{
|
||||
return m_maxSize;
|
||||
}
|
||||
|
||||
template<>
|
||||
Time
|
||||
WifiMacQueue::GetMaxDelay (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
return m_maxDelay;
|
||||
}
|
||||
|
||||
void
|
||||
WifiMacQueue::Enqueue (Ptr<const Packet> packet, const WifiMacHeader &hdr)
|
||||
{
|
||||
Cleanup ();
|
||||
if (m_size == m_maxSize)
|
||||
{
|
||||
if (m_dropPolicy == DROP_NEWEST)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (m_dropPolicy == DROP_OLDEST)
|
||||
{
|
||||
m_queue.pop_front ();
|
||||
m_size--;
|
||||
}
|
||||
}
|
||||
Time now = Simulator::Now ();
|
||||
m_queue.push_back (Item (packet, hdr, now));
|
||||
m_size++;
|
||||
}
|
||||
|
||||
void
|
||||
WifiMacQueue::Cleanup (void)
|
||||
{
|
||||
if (m_queue.empty ())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Time now = Simulator::Now ();
|
||||
uint32_t n = 0;
|
||||
for (PacketQueueI i = m_queue.begin (); i != m_queue.end (); )
|
||||
{
|
||||
if (i->tstamp + m_maxDelay > now)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = m_queue.erase (i);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
m_size -= n;
|
||||
}
|
||||
|
||||
Ptr<const Packet>
|
||||
WifiMacQueue::Dequeue (WifiMacHeader *hdr)
|
||||
{
|
||||
Cleanup ();
|
||||
if (!m_queue.empty ())
|
||||
{
|
||||
Item i = m_queue.front ();
|
||||
m_queue.pop_front ();
|
||||
m_size--;
|
||||
*hdr = i.hdr;
|
||||
return i.packet;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Ptr<const Packet>
|
||||
WifiMacQueue::Peek (WifiMacHeader *hdr)
|
||||
{
|
||||
Cleanup ();
|
||||
if (!m_queue.empty ())
|
||||
{
|
||||
Item i = m_queue.front ();
|
||||
*hdr = i.hdr;
|
||||
return i.packet;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Ptr<const Packet>
|
||||
WifiMacQueue::DequeueByTidAndAddress (WifiMacHeader *hdr, uint8_t tid,
|
||||
WifiMacHeader::AddressType type, Mac48Address dest)
|
||||
{
|
||||
Cleanup ();
|
||||
Ptr<const Packet> packet = 0;
|
||||
if (!m_queue.empty ())
|
||||
{
|
||||
PacketQueueI it;
|
||||
for (it = m_queue.begin (); it != m_queue.end (); ++it)
|
||||
{
|
||||
if (it->hdr.IsQosData ())
|
||||
{
|
||||
if (GetAddressForPacket (type, it) == dest
|
||||
&& it->hdr.GetQosTid () == tid)
|
||||
{
|
||||
packet = it->packet;
|
||||
*hdr = it->hdr;
|
||||
m_queue.erase (it);
|
||||
m_size--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
Ptr<const Packet>
|
||||
WifiMacQueue::PeekByTidAndAddress (WifiMacHeader *hdr, uint8_t tid,
|
||||
WifiMacHeader::AddressType type, Mac48Address dest, Time *timestamp)
|
||||
{
|
||||
Cleanup ();
|
||||
if (!m_queue.empty ())
|
||||
{
|
||||
PacketQueueI it;
|
||||
for (it = m_queue.begin (); it != m_queue.end (); ++it)
|
||||
{
|
||||
if (it->hdr.IsQosData ())
|
||||
{
|
||||
if (GetAddressForPacket (type, it) == dest
|
||||
&& it->hdr.GetQosTid () == tid)
|
||||
{
|
||||
*hdr = it->hdr;
|
||||
*timestamp = it->tstamp;
|
||||
return it->packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
WifiMacQueue::IsEmpty (void)
|
||||
WifiMacQueue::TtlExceeded (ConstIterator &it)
|
||||
{
|
||||
Cleanup ();
|
||||
return m_queue.empty ();
|
||||
}
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
uint32_t
|
||||
WifiMacQueue::GetSize (void)
|
||||
{
|
||||
Cleanup ();
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void
|
||||
WifiMacQueue::Flush (void)
|
||||
{
|
||||
m_queue.erase (m_queue.begin (), m_queue.end ());
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
Mac48Address
|
||||
WifiMacQueue::GetAddressForPacket (WifiMacHeader::AddressType type, PacketQueueI it)
|
||||
{
|
||||
if (type == WifiMacHeader::ADDR1)
|
||||
if (Simulator::Now () > (*it)->GetTimeStamp () + m_maxDelay)
|
||||
{
|
||||
return it->hdr.GetAddr1 ();
|
||||
}
|
||||
if (type == WifiMacHeader::ADDR2)
|
||||
{
|
||||
return it->hdr.GetAddr2 ();
|
||||
}
|
||||
if (type == WifiMacHeader::ADDR3)
|
||||
{
|
||||
return it->hdr.GetAddr3 ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
WifiMacQueue::Remove (Ptr<const Packet> packet)
|
||||
{
|
||||
PacketQueueI it = m_queue.begin ();
|
||||
for (; it != m_queue.end (); it++)
|
||||
{
|
||||
if (it->packet == packet)
|
||||
{
|
||||
m_queue.erase (it);
|
||||
m_size--;
|
||||
return true;
|
||||
}
|
||||
NS_LOG_DEBUG ("Removing packet that stayed in the queue for too long (" <<
|
||||
Simulator::Now () - (*it)->GetTimeStamp () << ")");
|
||||
auto curr = it++;
|
||||
DoRemove (curr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WifiMacQueue::PushFront (Ptr<const Packet> packet, const WifiMacHeader &hdr)
|
||||
template<>
|
||||
bool
|
||||
WifiMacQueue::Enqueue (Ptr<WifiMacQueueItem> item)
|
||||
{
|
||||
Cleanup ();
|
||||
if (m_size == m_maxSize)
|
||||
NS_LOG_FUNCTION (this << item);
|
||||
|
||||
NS_ASSERT_MSG (GetMode () == QueueBase::QUEUE_MODE_PACKETS, "WifiMacQueues must be in packet mode");
|
||||
|
||||
// if the queue is full, check if the time-to-live of the oldest packet has
|
||||
// expired. If so, it can be removed so as to make room for the new packet.
|
||||
if (GetNPackets () == GetMaxPackets ())
|
||||
{
|
||||
return;
|
||||
auto it = Head ();
|
||||
TtlExceeded (it);
|
||||
}
|
||||
Time now = Simulator::Now ();
|
||||
m_queue.push_front (Item (packet, hdr, now));
|
||||
m_size++;
|
||||
|
||||
if (GetNPackets () == GetMaxPackets () && m_dropPolicy == DROP_OLDEST)
|
||||
{
|
||||
NS_LOG_DEBUG ("Remove the oldest item in the queue");
|
||||
DoRemove (Head ());
|
||||
}
|
||||
|
||||
return DoEnqueue (Tail (), item);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
WifiMacQueue::PushFront (Ptr<WifiMacQueueItem> item)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << item);
|
||||
|
||||
NS_ASSERT_MSG (GetMode () == QueueBase::QUEUE_MODE_PACKETS, "WifiMacQueues must be in packet mode");
|
||||
|
||||
// if the queue is full, check if the time-to-live of the oldest packet has
|
||||
// expired. If so, it can be removed so as to make room for the new packet.
|
||||
if (GetNPackets () == GetMaxPackets ())
|
||||
{
|
||||
auto it = Head ();
|
||||
TtlExceeded (it);
|
||||
}
|
||||
|
||||
if (GetNPackets () == GetMaxPackets () && m_dropPolicy == DROP_OLDEST)
|
||||
{
|
||||
NS_LOG_DEBUG ("Remove the oldest item in the queue");
|
||||
DoRemove (Head ());
|
||||
}
|
||||
|
||||
return DoEnqueue (Head (), item);
|
||||
}
|
||||
|
||||
template<>
|
||||
Ptr<WifiMacQueueItem>
|
||||
WifiMacQueue::Dequeue (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
for (auto it = Head (); it != Tail (); )
|
||||
{
|
||||
if (!TtlExceeded (it))
|
||||
{
|
||||
return DoDequeue (it);
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("The queue is empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<>
|
||||
Ptr<WifiMacQueueItem>
|
||||
WifiMacQueue::DequeueByTidAndAddress (uint8_t tid,
|
||||
WifiMacHeader::AddressType type, Mac48Address dest)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << dest);
|
||||
|
||||
for (auto it = Head (); it != Tail (); )
|
||||
{
|
||||
if (!TtlExceeded (it))
|
||||
{
|
||||
if ((*it)->GetHeader ().IsQosData () && (*it)->GetAddress (type) == dest &&
|
||||
(*it)->GetHeader ().GetQosTid () == tid)
|
||||
{
|
||||
return DoDequeue (it);
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("The queue is empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<>
|
||||
Ptr<WifiMacQueueItem>
|
||||
WifiMacQueue::DequeueFirstAvailable (const QosBlockedDestinations *blockedPackets)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
for (auto it = Head (); it != Tail (); )
|
||||
{
|
||||
if (!TtlExceeded (it))
|
||||
{
|
||||
if (!(*it)->GetHeader ().IsQosData ()
|
||||
|| !blockedPackets->IsBlocked ((*it)->GetHeader ().GetAddr1 (), (*it)->GetHeader ().GetQosTid ()))
|
||||
{
|
||||
return DoDequeue (it);
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("The queue is empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<>
|
||||
Ptr<const WifiMacQueueItem>
|
||||
WifiMacQueue::Peek (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return DoPeek (Head ());
|
||||
}
|
||||
|
||||
template<>
|
||||
Ptr<const WifiMacQueueItem>
|
||||
WifiMacQueue::PeekByTidAndAddress (uint8_t tid,
|
||||
WifiMacHeader::AddressType type, Mac48Address dest)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << dest);
|
||||
|
||||
for (auto it = Head (); it != Tail (); )
|
||||
{
|
||||
if (!TtlExceeded (it))
|
||||
{
|
||||
if ((*it)->GetHeader ().IsQosData () && (*it)->GetAddress (type) == dest &&
|
||||
(*it)->GetHeader ().GetQosTid () == tid)
|
||||
{
|
||||
return DoPeek (it);
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("The queue is empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<>
|
||||
Ptr<const WifiMacQueueItem>
|
||||
WifiMacQueue::PeekFirstAvailable (const QosBlockedDestinations *blockedPackets)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
for (auto it = Head (); it != Tail (); )
|
||||
{
|
||||
if (!TtlExceeded (it))
|
||||
{
|
||||
if (!(*it)->GetHeader ().IsQosData ()
|
||||
|| !blockedPackets->IsBlocked ((*it)->GetHeader ().GetAddr1 (), (*it)->GetHeader ().GetQosTid ()))
|
||||
{
|
||||
return DoPeek (it);
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("The queue is empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<>
|
||||
Ptr<WifiMacQueueItem>
|
||||
WifiMacQueue::Remove (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
for (auto it = Head (); it != Tail (); )
|
||||
{
|
||||
if (!TtlExceeded (it))
|
||||
{
|
||||
return DoRemove (it);
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("The queue is empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
WifiMacQueue::Remove (Ptr<const Packet> packet)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet);
|
||||
|
||||
for (auto it = Head (); it != Tail (); )
|
||||
{
|
||||
if (!TtlExceeded (it))
|
||||
{
|
||||
if ((*it)->GetPacket () == packet)
|
||||
{
|
||||
DoRemove (it);
|
||||
return true;
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("Packet " << packet << " not found in the queue");
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
uint32_t
|
||||
WifiMacQueue::GetNPacketsByTidAndAddress (uint8_t tid, WifiMacHeader::AddressType type,
|
||||
Mac48Address addr)
|
||||
{
|
||||
Cleanup ();
|
||||
NS_LOG_FUNCTION (this << addr);
|
||||
|
||||
uint32_t nPackets = 0;
|
||||
if (!m_queue.empty ())
|
||||
|
||||
for (auto it = Head (); it != Tail (); )
|
||||
{
|
||||
PacketQueueI it;
|
||||
for (it = m_queue.begin (); it != m_queue.end (); it++)
|
||||
if (!TtlExceeded (it))
|
||||
{
|
||||
if (GetAddressForPacket (type, it) == addr)
|
||||
if ((*it)->GetHeader ().IsQosData () && (*it)->GetAddress (type) == addr &&
|
||||
(*it)->GetHeader ().GetQosTid () == tid)
|
||||
{
|
||||
if (it->hdr.IsQosData () && it->hdr.GetQosTid () == tid)
|
||||
{
|
||||
nPackets++;
|
||||
}
|
||||
nPackets++;
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("returns " << nPackets);
|
||||
return nPackets;
|
||||
}
|
||||
|
||||
Ptr<const Packet>
|
||||
WifiMacQueue::DequeueFirstAvailable (WifiMacHeader *hdr, Time ×tamp,
|
||||
const QosBlockedDestinations *blockedPackets)
|
||||
template<>
|
||||
bool
|
||||
WifiMacQueue::HasPackets (void)
|
||||
{
|
||||
Cleanup ();
|
||||
Ptr<const Packet> packet = 0;
|
||||
for (PacketQueueI it = m_queue.begin (); it != m_queue.end (); it++)
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
for (auto it = Head (); it != Tail (); )
|
||||
{
|
||||
if (!it->hdr.IsQosData ()
|
||||
|| !blockedPackets->IsBlocked (it->hdr.GetAddr1 (), it->hdr.GetQosTid ()))
|
||||
if (!TtlExceeded (it))
|
||||
{
|
||||
*hdr = it->hdr;
|
||||
timestamp = it->tstamp;
|
||||
packet = it->packet;
|
||||
m_queue.erase (it);
|
||||
m_size--;
|
||||
return packet;
|
||||
NS_LOG_DEBUG ("returns true");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
NS_LOG_DEBUG ("returns false");
|
||||
return false;
|
||||
}
|
||||
|
||||
Ptr<const Packet>
|
||||
WifiMacQueue::PeekFirstAvailable (WifiMacHeader *hdr, Time ×tamp,
|
||||
const QosBlockedDestinations *blockedPackets)
|
||||
{
|
||||
Cleanup ();
|
||||
for (PacketQueueI it = m_queue.begin (); it != m_queue.end (); it++)
|
||||
{
|
||||
if (!it->hdr.IsQosData ()
|
||||
|| !blockedPackets->IsBlocked (it->hdr.GetAddr1 (), it->hdr.GetQosTid ()))
|
||||
{
|
||||
*hdr = it->hdr;
|
||||
timestamp = it->tstamp;
|
||||
return it->packet;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
NS_OBJECT_TEMPLATE_CLASS_DEFINE (WifiQueue,WifiMacQueueItem);
|
||||
|
||||
} //namespace ns3
|
||||
|
||||
@@ -18,18 +18,95 @@
|
||||
*
|
||||
* Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
* Mirko Banchi <mk.banchi@gmail.com>
|
||||
* Stefano Avallone <stavallo@unina.it>
|
||||
*/
|
||||
|
||||
#ifndef WIFI_MAC_QUEUE_H
|
||||
#define WIFI_MAC_QUEUE_H
|
||||
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/queue.h"
|
||||
#include "wifi-mac-header.h"
|
||||
|
||||
namespace ns3 {
|
||||
class QosBlockedDestinations;
|
||||
|
||||
/**
|
||||
* \ingroup wifi
|
||||
*
|
||||
* WifiMacQueueItem stores (const) packets along with their Wifi MAC headers
|
||||
* and the time when they were enqueued.
|
||||
*/
|
||||
class WifiMacQueueItem : public SimpleRefCount<WifiMacQueueItem>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Create a Wifi MAC queue item containing a packet and a Wifi MAC header.
|
||||
* \param p the const packet included in the created item.
|
||||
* \param header the Wifi Mac header included in the created item.
|
||||
*/
|
||||
WifiMacQueueItem (Ptr<const Packet> p, const WifiMacHeader & header);
|
||||
|
||||
virtual ~WifiMacQueueItem ();
|
||||
|
||||
/**
|
||||
* \brief Get the packet stored in this item
|
||||
* \return the packet stored in this item.
|
||||
*/
|
||||
Ptr<const Packet> GetPacket (void) const;
|
||||
|
||||
/**
|
||||
* \brief Get the header stored in this item
|
||||
* \return the header stored in this item.
|
||||
*/
|
||||
const WifiMacHeader & GetHeader (void) const;
|
||||
|
||||
/**
|
||||
* \brief Return the requested address present in the header
|
||||
* \param type the type of the address to return
|
||||
* \return the address
|
||||
*/
|
||||
Mac48Address GetAddress (enum WifiMacHeader::AddressType type) const;
|
||||
|
||||
/**
|
||||
* \brief Get the timestamp included in this item
|
||||
* \return the timestamp included in this item.
|
||||
*/
|
||||
Time GetTimeStamp (void) const;
|
||||
|
||||
/**
|
||||
* \brief Return the size of the packet included in this item
|
||||
*
|
||||
* \return the size of the packet included in this item.
|
||||
*/
|
||||
uint32_t GetSize (void) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Default constructor
|
||||
*
|
||||
* Defined and unimplemented to avoid misuse
|
||||
*/
|
||||
WifiMacQueueItem ();
|
||||
/**
|
||||
* \brief Copy constructor
|
||||
*
|
||||
* Defined and unimplemented to avoid misuse
|
||||
*/
|
||||
WifiMacQueueItem (const WifiMacQueueItem &);
|
||||
/**
|
||||
* \brief Assignment operator
|
||||
*
|
||||
* Defined and unimplemented to avoid misuse
|
||||
* \returns
|
||||
*/
|
||||
WifiMacQueueItem &operator = (const WifiMacQueueItem &);
|
||||
|
||||
Ptr<const Packet> m_packet; //!< The packet contained in this queue item
|
||||
WifiMacHeader m_header; //!< Wifi MAC header associated with the packet
|
||||
Time m_tstamp; //!< timestamp when the packet arrived at the queue
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup wifi
|
||||
*
|
||||
@@ -44,8 +121,32 @@ class QosBlockedDestinations;
|
||||
* to verify whether or not it should be dropped. If
|
||||
* dot11EDCATableMSDULifetime has elapsed, it is dropped.
|
||||
* Otherwise, it is returned to the caller.
|
||||
*
|
||||
* WifiMacQueue could have been declared as a subclass of Queue<WifiMacQueueItem>,
|
||||
* but this would have caused python examples using wifi to crash at runtime
|
||||
* with the following error message: "Trying to allocate twice the same uid:
|
||||
* ns3::Queue<WifiMacQueueItem>". Such an error wasn't fully debugged but it
|
||||
* may have been due to static initialization order issues.
|
||||
*
|
||||
* To avoid such an error, the template class WifiQueue<Item> is introduced
|
||||
* as a subclass of Queue<Item>. WifiMacQueue is then declared as a
|
||||
* specialization of WifiQueue<Item> with Item equal to WifiMacQueueItem.
|
||||
* The methods of the WifiQueue class are left unimplemented for Item other
|
||||
* than WifiMacQueueItem.
|
||||
*
|
||||
* Modules that need to forward declare WifiMacQueue have to include the
|
||||
* following:
|
||||
*
|
||||
* \code
|
||||
* class WifiMacQueueItem;
|
||||
* template <typename Item> class WifiQueue;
|
||||
* typedef WifiQueue<WifiMacQueueItem> WifiMacQueue;
|
||||
* \endcode
|
||||
*
|
||||
* in their header file.
|
||||
*/
|
||||
class WifiMacQueue : public Object
|
||||
template <typename Item>
|
||||
class WifiQueue : public Queue<Item>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -53,8 +154,8 @@ public:
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
WifiMacQueue ();
|
||||
~WifiMacQueue ();
|
||||
WifiQueue ();
|
||||
~WifiQueue ();
|
||||
|
||||
/// drop policy
|
||||
enum DropPolicy
|
||||
@@ -63,24 +164,12 @@ public:
|
||||
DROP_OLDEST
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the maximum queue size.
|
||||
*
|
||||
* \param maxSize the maximum queue size
|
||||
*/
|
||||
void SetMaxSize (uint32_t maxSize);
|
||||
/**
|
||||
* Set the maximum delay before the packet is discarded.
|
||||
*
|
||||
* \param delay the maximum delay
|
||||
*/
|
||||
void SetMaxDelay (Time delay);
|
||||
/**
|
||||
* Return the maximum queue size.
|
||||
*
|
||||
* \return the maximum queue size
|
||||
*/
|
||||
uint32_t GetMaxSize (void) const;
|
||||
/**
|
||||
* Return the maximum delay before the packet is discarded.
|
||||
*
|
||||
@@ -89,73 +178,91 @@ public:
|
||||
Time GetMaxDelay (void) const;
|
||||
|
||||
/**
|
||||
* Enqueue the given packet and its corresponding WifiMacHeader at the <i>end</i> of the queue.
|
||||
* Enqueue the given Wifi MAC queue item at the <i>end</i> of the queue.
|
||||
*
|
||||
* \param packet the packet to be enqueued at the end
|
||||
* \param hdr the header of the given packet
|
||||
* \param item the Wifi MAC queue item to be enqueued at the end
|
||||
* \return true if success, false if the packet has been dropped
|
||||
*/
|
||||
void Enqueue (Ptr<const Packet> packet, const WifiMacHeader &hdr);
|
||||
bool Enqueue (Ptr<Item> item);
|
||||
/**
|
||||
* Enqueue the given packet and its corresponding WifiMacHeader at the <i>front</i> of the queue.
|
||||
* Enqueue the given Wifi MAC queue item at the <i>front</i> of the queue.
|
||||
*
|
||||
* \param packet the packet to be enqueued at the front
|
||||
* \param hdr the header of the given packet
|
||||
* \param item the Wifi MAC queue item to be enqueued at the front
|
||||
* \return true if success, false if the packet has been dropped
|
||||
*/
|
||||
void PushFront (Ptr<const Packet> packet, const WifiMacHeader &hdr);
|
||||
bool PushFront (Ptr<Item> item);
|
||||
/**
|
||||
* Dequeue the packet in the front of the queue.
|
||||
*
|
||||
* \param hdr the WifiMacHeader of the packet
|
||||
* \return the packet
|
||||
*/
|
||||
Ptr<Item> 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>, and tid
|
||||
* equal to <i>tid</i>. This method removes the packet from the queue.
|
||||
* It is typically used by ns3::EdcaTxopN in order to perform correct MSDU
|
||||
* aggregation (A-MSDU).
|
||||
*
|
||||
* \param tid the given TID
|
||||
* \param type the given address type
|
||||
* \param addr the given destination
|
||||
*
|
||||
* \return the packet
|
||||
*/
|
||||
Ptr<const Packet> Dequeue (WifiMacHeader *hdr);
|
||||
Ptr<Item> DequeueByTidAndAddress (uint8_t tid,
|
||||
WifiMacHeader::AddressType type,
|
||||
Mac48Address addr);
|
||||
/**
|
||||
* Return first available packet for transmission. A packet could be no available
|
||||
* if it is a QoS packet with a tid and an address1 fields equal to <i>tid</i> and <i>addr</i>
|
||||
* respectively that index a pending agreement in the BlockAckManager object.
|
||||
* So that packet must not be transmitted until reception of an ADDBA response frame from station
|
||||
* addressed by <i>addr</i>. This method removes the packet from queue.
|
||||
*
|
||||
* \param blockedPackets
|
||||
*
|
||||
* \return packet
|
||||
*/
|
||||
Ptr<Item> DequeueFirstAvailable (const QosBlockedDestinations *blockedPackets);
|
||||
/**
|
||||
* Peek the packet in the front of the queue. The packet is not removed.
|
||||
*
|
||||
* \param hdr the WifiMacHeader of the packet
|
||||
* \return the packet
|
||||
*/
|
||||
Ptr<const Item> Peek (void) 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::EdcaTxopN in order to perform correct MSDU
|
||||
* aggregation (A-MSDU).
|
||||
*
|
||||
* \param tid the given TID
|
||||
* \param type the given address type
|
||||
* \param addr the given destination
|
||||
*
|
||||
* \return packet
|
||||
*/
|
||||
Ptr<const Item> PeekByTidAndAddress (uint8_t tid,
|
||||
WifiMacHeader::AddressType type,
|
||||
Mac48Address addr);
|
||||
/**
|
||||
* Return first available packet for transmission. The packet is not removed from queue.
|
||||
*
|
||||
* \param hdr the header of the dequeued packet
|
||||
* \param tStamp
|
||||
* \param blockedPackets
|
||||
*
|
||||
* \return packet
|
||||
*/
|
||||
Ptr<const Item> PeekFirstAvailable (const QosBlockedDestinations *blockedPackets);
|
||||
/**
|
||||
* Remove the packet in the front of the queue.
|
||||
*
|
||||
* \return the packet
|
||||
*/
|
||||
Ptr<const Packet> Peek (WifiMacHeader *hdr);
|
||||
/**
|
||||
* Searchs and returns, if is present in this queue, first packet having
|
||||
* address indicated by <i>type</i> equals to <i>addr</i>, and tid
|
||||
* equals to <i>tid</i>. This method removes the packet from this queue.
|
||||
* Is typically used by ns3::EdcaTxopN in order to perform correct MSDU
|
||||
* aggregation (A-MSDU).
|
||||
*
|
||||
* \param hdr the header of the dequeued packet
|
||||
* \param tid the given TID
|
||||
* \param type the given address type
|
||||
* \param addr the given destination
|
||||
*
|
||||
* \return packet
|
||||
*/
|
||||
Ptr<const Packet> DequeueByTidAndAddress (WifiMacHeader *hdr,
|
||||
uint8_t tid,
|
||||
WifiMacHeader::AddressType type,
|
||||
Mac48Address addr);
|
||||
/**
|
||||
* Searchs and returns, if is present in this queue, first 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.
|
||||
* Is typically used by ns3::EdcaTxopN in order to perform correct MSDU
|
||||
* aggregation (A-MSDU).
|
||||
*
|
||||
* \param hdr the header of the dequeued packet
|
||||
* \param tid the given TID
|
||||
* \param type the given address type
|
||||
* \param addr the given destination
|
||||
* \param timestamp
|
||||
*
|
||||
* \return packet
|
||||
*/
|
||||
Ptr<const Packet> PeekByTidAndAddress (WifiMacHeader *hdr,
|
||||
uint8_t tid,
|
||||
WifiMacHeader::AddressType type,
|
||||
Mac48Address addr,
|
||||
Time *timestamp);
|
||||
Ptr<Item> Remove (void);
|
||||
/**
|
||||
* If exists, removes <i>packet</i> from queue and returns true. Otherwise it
|
||||
* takes no effects and return false. Deletion of the packet is
|
||||
@@ -167,8 +274,8 @@ public:
|
||||
*/
|
||||
bool Remove (Ptr<const Packet> packet);
|
||||
/**
|
||||
* Returns number of QoS packets having tid equals to <i>tid</i> and address
|
||||
* specified by <i>type</i> equals to <i>addr</i>.
|
||||
* Return the number of QoS packets having tid equal to <i>tid</i> and address
|
||||
* specified by <i>type</i> equal to <i>addr</i>.
|
||||
*
|
||||
* \param tid the given TID
|
||||
* \param type the given address type
|
||||
@@ -180,108 +287,31 @@ public:
|
||||
WifiMacHeader::AddressType type,
|
||||
Mac48Address addr);
|
||||
/**
|
||||
* Returns first available packet for transmission. A packet could be no available
|
||||
* if it's a QoS packet with a tid and an address1 fields equal to <i>tid</i> and <i>addr</i>
|
||||
* respectively that index a pending agreement in the BlockAckManager object.
|
||||
* So that packet must not be transmitted until reception of an ADDBA response frame from station
|
||||
* addressed by <i>addr</i>. This method removes the packet from queue.
|
||||
* This method must be used (instead of the IsEmpty method of the base class)
|
||||
* to check whether there are packets with unexpired time to live in the queue
|
||||
*
|
||||
* \param hdr the header of the dequeued packet
|
||||
* \param tStamp
|
||||
* \param blockedPackets
|
||||
*
|
||||
* \return packet
|
||||
* \return true if there are packets with unexpired time to live
|
||||
*/
|
||||
Ptr<const Packet> DequeueFirstAvailable (WifiMacHeader *hdr,
|
||||
Time &tStamp,
|
||||
const QosBlockedDestinations *blockedPackets);
|
||||
/**
|
||||
* Returns first available packet for transmission. The packet isn't removed from queue.
|
||||
*
|
||||
* \param hdr the header of the dequeued packet
|
||||
* \param tStamp
|
||||
* \param blockedPackets
|
||||
*
|
||||
* \return packet
|
||||
*/
|
||||
Ptr<const Packet> PeekFirstAvailable (WifiMacHeader *hdr,
|
||||
Time &tStamp,
|
||||
const QosBlockedDestinations *blockedPackets);
|
||||
/**
|
||||
* Flush the queue.
|
||||
*/
|
||||
void Flush (void);
|
||||
bool HasPackets (void);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Return if the queue is empty.
|
||||
* 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
|
||||
* point to the item that followed the erased one.
|
||||
*
|
||||
* \return true if the queue is empty, false otherwise
|
||||
* \param it an iterator pointing to the item
|
||||
* \return true if the item is removed, false otherwise
|
||||
*/
|
||||
bool IsEmpty (void);
|
||||
/**
|
||||
* Return the current queue size.
|
||||
*
|
||||
* \return the current queue size
|
||||
*/
|
||||
uint32_t GetSize (void);
|
||||
bool TtlExceeded (typename Queue<Item>::ConstIterator &it);
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Clean up the queue by removing packets that exceeded the maximum delay.
|
||||
*/
|
||||
void Cleanup (void);
|
||||
|
||||
/**
|
||||
* A struct that holds information about a packet for putting
|
||||
* in a packet queue.
|
||||
*/
|
||||
struct Item
|
||||
{
|
||||
/**
|
||||
* Create a struct with the given parameters.
|
||||
*
|
||||
* \param packet
|
||||
* \param hdr
|
||||
* \param tstamp
|
||||
*/
|
||||
Item (Ptr<const Packet> packet,
|
||||
const WifiMacHeader &hdr,
|
||||
Time tstamp);
|
||||
Ptr<const Packet> packet; //!< Actual packet
|
||||
WifiMacHeader hdr; //!< Wifi MAC header associated with the packet
|
||||
Time tstamp; //!< timestamp when the packet arrived at the queue
|
||||
};
|
||||
|
||||
/**
|
||||
* typedef for packet (struct Item) queue.
|
||||
*/
|
||||
typedef std::list<Item> PacketQueue;
|
||||
/**
|
||||
* typedef for packet (struct Item) queue reverse iterator.
|
||||
*/
|
||||
typedef std::list<Item>::reverse_iterator PacketQueueRI;
|
||||
/**
|
||||
* typedef for packet (struct Item) queue iterator.
|
||||
*/
|
||||
typedef std::list<Item>::iterator PacketQueueI;
|
||||
/**
|
||||
* Return the appropriate address for the given packet (given by PacketQueue iterator).
|
||||
*
|
||||
* \param type
|
||||
* \param it
|
||||
*
|
||||
* \return the address
|
||||
*/
|
||||
Mac48Address GetAddressForPacket (WifiMacHeader::AddressType type, PacketQueueI it);
|
||||
|
||||
PacketQueue m_queue; //!< Packet (struct Item) queue
|
||||
uint32_t m_size; //!< Current queue size
|
||||
uint32_t m_maxSize; //!< Queue capacity
|
||||
Time m_maxDelay; //!< Time to live for packets in the queue
|
||||
DropPolicy m_dropPolicy; //!< Drop behavior of queue
|
||||
Time m_maxDelay; //!< Time to live for packets in the queue
|
||||
DropPolicy m_dropPolicy; //!< Drop behavior of queue
|
||||
};
|
||||
|
||||
/// Declare WifiMacQueue as a specialization of template class WifiQueue
|
||||
typedef WifiQueue<WifiMacQueueItem> WifiMacQueue;
|
||||
|
||||
} //namespace ns3
|
||||
|
||||
#endif /* WIFI_MAC_QUEUE_H */
|
||||
|
||||
@@ -149,7 +149,7 @@ AmpduAggregationTest::DoRun (void)
|
||||
|
||||
bool isAmpdu = m_low->IsAmpdu (pkt, hdr);
|
||||
NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "a single packet should not result in an A-MPDU");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetSize (), 0, "aggregation queue is not flushed");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -170,22 +170,23 @@ AmpduAggregationTest::DoRun (void)
|
||||
hdr2.SetType (WIFI_MAC_QOSDATA);
|
||||
hdr2.SetQosTid (0);
|
||||
|
||||
m_edca->GetQueue ()->Enqueue (pkt1, hdr1);
|
||||
m_edca->GetQueue ()->Enqueue (pkt2, hdr2);
|
||||
m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt1, hdr1));
|
||||
m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt2, hdr2));
|
||||
|
||||
isAmpdu = m_low->IsAmpdu (pkt, hdr);
|
||||
uint32_t aggregationQueueSize = m_low->m_aggregateQueue[0]->GetSize ();
|
||||
uint32_t aggregationQueueSize = m_low->m_aggregateQueue[0]->GetNPackets ();
|
||||
NS_TEST_EXPECT_MSG_EQ (isAmpdu, true, "MPDU aggregation failed");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_low->m_currentPacket->GetSize (), 4606, "A-MPDU size is not correct");
|
||||
NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 3, "aggregation queue should not be empty");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_edca->GetQueue ()->GetSize (), 0, "queue should be empty");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_edca->GetQueue ()->GetNPackets (), 0, "queue should be empty");
|
||||
|
||||
Ptr <const Packet> dequeuedPacket;
|
||||
Ptr <WifiMacQueueItem> dequeuedItem;
|
||||
WifiMacHeader dequeuedHdr;
|
||||
uint32_t i = 0;
|
||||
for (; aggregationQueueSize > 0; aggregationQueueSize--, i++)
|
||||
{
|
||||
dequeuedPacket = m_low->m_aggregateQueue[0]->Dequeue (&dequeuedHdr);
|
||||
dequeuedItem = m_low->m_aggregateQueue[0]->Dequeue ();
|
||||
dequeuedHdr = dequeuedItem->GetHeader ();
|
||||
NS_TEST_EXPECT_MSG_EQ (dequeuedHdr.GetSequenceNumber (), i, "wrong sequence number");
|
||||
}
|
||||
NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 0, "aggregation queue should be empty");
|
||||
@@ -217,17 +218,17 @@ AmpduAggregationTest::DoRun (void)
|
||||
hdr3.SetType (WIFI_MAC_DATA);
|
||||
hdr3.SetQosTid (0);
|
||||
|
||||
m_edca->GetQueue ()->Enqueue (pkt3, hdr3);
|
||||
m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt3, hdr3));
|
||||
|
||||
isAmpdu = m_low->IsAmpdu (pkt1, hdr1);
|
||||
NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "a single packet for this destination should not result in an A-MPDU");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetSize (), 0, "aggregation queue is not flushed");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
|
||||
|
||||
m_edca->m_currentHdr = hdr2;
|
||||
m_edca->m_currentPacket = pkt2->Copy ();
|
||||
isAmpdu = m_low->IsAmpdu (pkt2, hdr2);
|
||||
NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "no MPDU aggregation should be performed if there is no agreement");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetSize (), 0, "aggregation queue is not flushed");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
|
||||
|
||||
m_manager->SetMaxSlrc (0); //set to 0 in order to fake that the maximum number of retries has been reached
|
||||
m_edca->MissedAck ();
|
||||
@@ -339,13 +340,14 @@ TwoLevelAggregationTest::DoRun (void)
|
||||
* - A-MSDU frame size should be 3030 bytes (= 2 packets + headers + padding);
|
||||
* - one packet should be removed from the queue (the other packet is removed later in MacLow::AggregateToAmpdu) .
|
||||
*/
|
||||
m_edca->GetQueue ()->Enqueue (pkt, hdr);
|
||||
m_edca->GetQueue ()->Enqueue (pkt, hdr);
|
||||
m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
|
||||
m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
|
||||
|
||||
Ptr<const Packet> peekedPacket = m_edca->GetQueue ()->PeekByTidAndAddress (&peekedHdr, 0,
|
||||
WifiMacHeader::ADDR1,
|
||||
hdr.GetAddr1 (),
|
||||
&tstamp);
|
||||
Ptr<const WifiMacQueueItem> peekedItem = m_edca->GetQueue ()->PeekByTidAndAddress (0, WifiMacHeader::ADDR1,
|
||||
hdr.GetAddr1 ());
|
||||
Ptr<const Packet> peekedPacket = peekedItem->GetPacket ();
|
||||
peekedHdr = peekedItem->GetHeader ();
|
||||
tstamp = peekedItem->GetTimeStamp ();
|
||||
m_low->m_currentPacket = peekedPacket->Copy ();
|
||||
m_low->m_currentHdr = peekedHdr;
|
||||
m_low->m_currentTxVector = m_low->GetDataTxVector (m_low->m_currentPacket, &m_low->m_currentHdr);
|
||||
@@ -355,7 +357,7 @@ TwoLevelAggregationTest::DoRun (void)
|
||||
bool result = (packet != 0);
|
||||
NS_TEST_EXPECT_MSG_EQ (result, true, "aggregation failed");
|
||||
NS_TEST_EXPECT_MSG_EQ (packet->GetSize (), 3030, "wrong packet size");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_edca->GetQueue ()->GetSize (), 0, "aggregated packets not removed from the queue");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_edca->GetQueue ()->GetNPackets (), 0, "aggregated packets not removed from the queue");
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -370,7 +372,7 @@ TwoLevelAggregationTest::DoRun (void)
|
||||
m_mpduAggregator = m_factory.Create<MpduAggregator> ();
|
||||
m_edca->SetMpduAggregator (m_mpduAggregator);
|
||||
|
||||
m_edca->GetQueue ()->Enqueue (pkt, hdr);
|
||||
m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
|
||||
packet = m_low->PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, 0);
|
||||
|
||||
result = (packet != 0);
|
||||
@@ -379,7 +381,7 @@ TwoLevelAggregationTest::DoRun (void)
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Aggregation does not occur zhen there is no more packets in the queue.
|
||||
* Aggregation does not occur when there is no more packets in the queue.
|
||||
* It checks whether MSDU aggregation has been rejected because there is no packets ready in the queue (returned packet should be equal to 0).
|
||||
* This test is needed to ensure that there is no issue when the queue is empty.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user