wifi: Make WifiMacQueue a subclass of Queue

This commit is contained in:
Stefano Avallone
2017-03-08 18:02:03 +01:00
parent 1d0a27a285
commit bdc94e40b1
10 changed files with 666 additions and 514 deletions

View File

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

View File

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

View File

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

View File

@@ -29,7 +29,6 @@ namespace ns3 {
class DcfState;
class DcfManager;
class WifiMacQueue;
class MacTxMiddle;
class RandomStream;
class CtrlBAckResponseHeader;

View File

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

View File

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

View File

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

View File

@@ -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 &timestamp,
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 &timestamp,
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

View File

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

View File

@@ -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.
*/