From bdc94e40b1f4acc2e54919984be06b73a8d097b9 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Wed, 8 Mar 2017 18:02:03 +0100 Subject: [PATCH] wifi: Make WifiMacQueue a subclass of Queue --- .../ns3wifi/wifi-ac-mapping-test-suite.cc | 4 +- src/wifi/model/block-ack-manager.h | 4 +- src/wifi/model/dca-txop.cc | 17 +- src/wifi/model/dca-txop.h | 1 - src/wifi/model/edca-txop-n.cc | 116 ++-- src/wifi/model/mac-low.cc | 85 ++- src/wifi/model/mac-low.h | 4 +- src/wifi/model/wifi-mac-queue.cc | 555 ++++++++++-------- src/wifi/model/wifi-mac-queue.h | 354 ++++++----- src/wifi/test/wifi-aggregation-test.cc | 40 +- 10 files changed, 666 insertions(+), 514 deletions(-) diff --git a/src/test/ns3wifi/wifi-ac-mapping-test-suite.cc b/src/test/ns3wifi/wifi-ac-mapping-test-suite.cc index 18161c963..990c914de 100644 --- a/src/test/ns3wifi/wifi-ac-mapping-test-suite.cc +++ b/src/test/ns3wifi/wifi-ac-mapping-test-suite.cc @@ -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); } } diff --git a/src/wifi/model/block-ack-manager.h b/src/wifi/model/block-ack-manager.h index 69a94503a..fc0983eee 100644 --- a/src/wifi/model/block-ack-manager.h +++ b/src/wifi/model/block-ack-manager.h @@ -33,7 +33,9 @@ namespace ns3 { class MgtAddBaResponseHeader; class MgtAddBaRequestHeader; class MacTxMiddle; -class WifiMacQueue; +class WifiMacQueueItem; +template class WifiQueue; +typedef WifiQueue WifiMacQueue; /** * \ingroup wifi diff --git a/src/wifi/model/dca-txop.cc b/src/wifi/model/dca-txop.cc index 81e023a2a..5a8231efc 100644 --- a/src/wifi/model/dca-txop.cc +++ b/src/wifi/model/dca-txop.cc @@ -206,7 +206,7 @@ DcaTxop::Queue (Ptr 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 (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 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 (m_currentPacket, m_currentHdr)); m_currentPacket = 0; } } diff --git a/src/wifi/model/dca-txop.h b/src/wifi/model/dca-txop.h index f116651e2..05ee4055d 100644 --- a/src/wifi/model/dca-txop.h +++ b/src/wifi/model/dca-txop.h @@ -29,7 +29,6 @@ namespace ns3 { class DcfState; class DcfManager; -class WifiMacQueue; class MacTxMiddle; class RandomStream; class CtrlBAckResponseHeader; diff --git a/src/wifi/model/edca-txop-n.cc b/src/wifi/model/edca-txop-n.cc index 5be647351..c63b40ca0 100644 --- a/src/wifi/model/edca-txop-n.cc +++ b/src/wifi/model/edca-txop-n.cc @@ -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 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 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 currentAggregatedPacket = Create (); m_msduAggregator->Aggregate (m_currentPacket, currentAggregatedPacket, @@ -294,25 +301,26 @@ EdcaTxopN::NotifyAccessGranted (void) MapDestAddressForAggregation (peekedHdr)); bool aggregated = false; bool isAmsdu = false; - Ptr peekedPacket = m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (), - WifiMacHeader::ADDR1, - m_currentHdr.GetAddr1 (), &tstamp); - while (peekedPacket != 0) + Ptr 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 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 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 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 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 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 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 peekedPacket = m_baManager->GetNextPacket (hdr); if (peekedPacket == 0) { - peekedPacket = m_queue->PeekByTidAndAddress (&hdr, - m_currentHdr.GetQosTid (), - WifiMacHeader::ADDR1, - m_currentHdr.GetAddr1 (), - &tstamp); + Ptr 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 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 peekedPacket = m_queue->PeekByTidAndAddress (&hdr, - m_currentHdr.GetQosTid (), - WifiMacHeader::ADDR1, - m_currentHdr.GetAddr1 (), - &tstamp); - if (peekedPacket == 0) + Ptr peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (), + WifiMacHeader::ADDR1, + m_currentHdr.GetAddr1 ()); + if (peekedItem == 0) { return false; } + Ptr peekedPacket = peekedItem->GetPacket (); + hdr = peekedItem->GetHeader (); MacLowTransmissionParameters params = m_currentParams; if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck ()) { @@ -1215,7 +1247,7 @@ EdcaTxopN::PushFront (Ptr 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 (packet, hdr)); StartAccessIfNeeded (); } diff --git a/src/wifi/model/mac-low.cc b/src/wifi/model/mac-low.cc index d8d930f6f..e43ed5951 100644 --- a/src/wifi/model/mac-low.cc +++ b/src/wifi/model/mac-low.cc @@ -674,11 +674,11 @@ MacLow::StartTransmission (Ptr 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 packet, const WifiMacHeader* hdr, WifiTxV else { Ptr newPacket; - Ptr dequeuedPacket; + Ptr 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 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::size_type i = 0; i != m_txPackets[tid].size (); i++) { @@ -2758,7 +2759,7 @@ MacLow::AggregateToAmpdu (Ptr 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 (aggPacket, peekedHdr)); } } else if (hdr.IsBlockAckReq ()) @@ -2774,9 +2775,15 @@ MacLow::AggregateToAmpdu (Ptr packet, const WifiMacHeader hdr) Ptr peekedPacket = edcaIt->second->PeekNextRetransmitPacket (peekedHdr, peekedHdr.GetAddr1 (), tid, &tstamp); if (peekedPacket == 0) { - peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid, - WifiMacHeader::ADDR1, - hdr.GetAddr1 (), &tstamp); + Ptr 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 packet, const WifiMacHeader hdr) aggregated = edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket); if (aggregated) { - m_aggregateQueue[tid]->Enqueue (aggPacket, peekedHdr); + m_aggregateQueue[tid]->Enqueue (Create (aggPacket, peekedHdr)); if (i == 1 && hdr.IsQosData ()) { if (!m_txParams.MustSendRts ()) @@ -2867,9 +2874,14 @@ MacLow::AggregateToAmpdu (Ptr 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 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 packet, const WifiMacHeader hdr) } else { - peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid, - WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp); - if (peekedPacket != 0) + Ptr 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 packet, const WifiMacHeader hdr) } } } + else + { + peekedPacket = 0; + } } } @@ -2916,7 +2935,7 @@ MacLow::AggregateToAmpdu (Ptr packet, const WifiMacHeader hdr) newPacket = packet->Copy (); peekedHdr = hdr; Ptr aggPacket = newPacket->Copy (); - m_aggregateQueue[tid]->Enqueue (aggPacket, peekedHdr); + m_aggregateQueue[tid]->Enqueue (Create (aggPacket, peekedHdr)); newPacket->AddHeader (peekedHdr); AddWifiMacTrailer (newPacket); edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket); @@ -2940,7 +2959,7 @@ MacLow::AggregateToAmpdu (Ptr 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 packet, const WifiMacHeader hdr) currentAggregatedPacket = Create (); edcaIt->second->GetMpduAggregator ()->AggregateSingleMpdu (packet, currentAggregatedPacket); - m_aggregateQueue[tid]->Enqueue (packet, peekedHdr); + m_aggregateQueue[tid]->Enqueue (Create (packet, peekedHdr)); if (edcaIt->second->GetBaAgreementExists (hdr.GetAddr1 (), tid)) { @@ -2987,7 +3006,7 @@ MacLow::AggregateToAmpdu (Ptr 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 packet, WifiMacHeader *hdr, Ti NS_ASSERT (edcaIt != m_edca.end ()); queue = edcaIt->second->GetQueue (); - Ptr peekedPacket = queue->DequeueByTidAndAddress (hdr, hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 ()); + Ptr 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 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 packet, WifiMacHeader *hdr, Ti } else { - queue->PushFront (packet, *hdr); + queue->PushFront (Create (packet, *hdr)); return 0; } } diff --git a/src/wifi/model/mac-low.h b/src/wifi/model/mac-low.h index d76385b9c..8989ec032 100644 --- a/src/wifi/model/mac-low.h +++ b/src/wifi/model/mac-low.h @@ -37,10 +37,12 @@ class AmpduAggregationTest; namespace ns3 { -class WifiMacQueue; class DcaTxop; class EdcaTxopN; class DcfManager; +class WifiMacQueueItem; +template class WifiQueue; +typedef WifiQueue WifiMacQueue; /** * \brief control how a packet is transmitted. diff --git a/src/wifi/model/wifi-mac-queue.cc b/src/wifi/model/wifi-mac-queue.cc index 1a441ce43..0c9637328 100644 --- a/src/wifi/model/wifi-mac-queue.cc +++ b/src/wifi/model/wifi-mac-queue.cc @@ -18,38 +18,84 @@ * * Authors: Mathieu Lacage * Mirko Banchi + * Stefano Avallone */ #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 packet, - const WifiMacHeader &hdr, - Time tstamp) - : packet (packet), - hdr (hdr), - tstamp (tstamp) +WifiMacQueueItem::WifiMacQueueItem (Ptr p, const WifiMacHeader & header) + : m_packet (p), + m_header (header), + m_tstamp (Simulator::Now ()) { } +WifiMacQueueItem::~WifiMacQueueItem () +{ +} + +Ptr +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 () + .SetParent > () .SetGroupName ("Wifi") .AddConstructor () - .AddAttribute ("MaxPacketNumber", "If a packet arrives when there are already this number of packets, it is dropped.", - UintegerValue (400), - MakeUintegerAccessor (&WifiMacQueue::m_maxSize), - MakeUintegerChecker ()) .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 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 -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 -WifiMacQueue::Peek (WifiMacHeader *hdr) -{ - Cleanup (); - if (!m_queue.empty ()) - { - Item i = m_queue.front (); - *hdr = i.hdr; - return i.packet; - } - return 0; -} - -Ptr -WifiMacQueue::DequeueByTidAndAddress (WifiMacHeader *hdr, uint8_t tid, - WifiMacHeader::AddressType type, Mac48Address dest) -{ - Cleanup (); - Ptr 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 -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 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 packet, const WifiMacHeader &hdr) +template<> +bool +WifiMacQueue::Enqueue (Ptr 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 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 +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 +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 +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 +WifiMacQueue::Peek (void) const +{ + NS_LOG_FUNCTION (this); + return DoPeek (Head ()); +} + +template<> +Ptr +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 +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 +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 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 -WifiMacQueue::DequeueFirstAvailable (WifiMacHeader *hdr, Time ×tamp, - const QosBlockedDestinations *blockedPackets) +template<> +bool +WifiMacQueue::HasPackets (void) { - Cleanup (); - Ptr 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 -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 diff --git a/src/wifi/model/wifi-mac-queue.h b/src/wifi/model/wifi-mac-queue.h index 17fc02da0..3fbf8d27e 100644 --- a/src/wifi/model/wifi-mac-queue.h +++ b/src/wifi/model/wifi-mac-queue.h @@ -18,18 +18,95 @@ * * Authors: Mathieu Lacage * Mirko Banchi + * Stefano Avallone */ #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 +{ +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 p, const WifiMacHeader & header); + + virtual ~WifiMacQueueItem (); + + /** + * \brief Get the packet stored in this item + * \return the packet stored in this item. + */ + Ptr 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 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, + * 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". 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 is introduced + * as a subclass of Queue. WifiMacQueue is then declared as a + * specialization of WifiQueue 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 class WifiQueue; + * typedef WifiQueue WifiMacQueue; + * \endcode + * + * in their header file. */ -class WifiMacQueue : public Object +template +class WifiQueue : public Queue { 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 end of the queue. + * Enqueue the given Wifi MAC queue item at the end 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 packet, const WifiMacHeader &hdr); + bool Enqueue (Ptr item); /** - * Enqueue the given packet and its corresponding WifiMacHeader at the front of the queue. + * Enqueue the given Wifi MAC queue item at the front 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 packet, const WifiMacHeader &hdr); + bool PushFront (Ptr item); /** * Dequeue the packet in the front of the queue. * - * \param hdr the WifiMacHeader of the packet + * \return the packet + */ + Ptr Dequeue (void); + /** + * Search and return, if present in the queue, the first packet having the + * address indicated by type equal to addr, and tid + * equal to tid. 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 Dequeue (WifiMacHeader *hdr); + Ptr 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 tid and addr + * 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 addr. This method removes the packet from queue. + * + * \param blockedPackets + * + * \return packet + */ + Ptr 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 Peek (void) const; + /** + * Search and return, if present in the queue, the first packet having the + * address indicated by type equal to addr, and tid + * equal to tid. 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 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 PeekFirstAvailable (const QosBlockedDestinations *blockedPackets); + /** + * Remove the packet in the front of the queue. * * \return the packet */ - Ptr Peek (WifiMacHeader *hdr); - /** - * Searchs and returns, if is present in this queue, first packet having - * address indicated by type equals to addr, and tid - * equals to tid. 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 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 type equals to addr, and tid - * equals to tid. 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 PeekByTidAndAddress (WifiMacHeader *hdr, - uint8_t tid, - WifiMacHeader::AddressType type, - Mac48Address addr, - Time *timestamp); + Ptr Remove (void); /** * If exists, removes packet 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 packet); /** - * Returns number of QoS packets having tid equals to tid and address - * specified by type equals to addr. + * Return the number of QoS packets having tid equal to tid and address + * specified by type equal to addr. * * \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 tid and addr - * 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 addr. 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 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 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 it 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::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 packet, - const WifiMacHeader &hdr, - Time tstamp); - Ptr 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 PacketQueue; - /** - * typedef for packet (struct Item) queue reverse iterator. - */ - typedef std::list::reverse_iterator PacketQueueRI; - /** - * typedef for packet (struct Item) queue iterator. - */ - typedef std::list::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 WifiMacQueue; + } //namespace ns3 #endif /* WIFI_MAC_QUEUE_H */ diff --git a/src/wifi/test/wifi-aggregation-test.cc b/src/wifi/test/wifi-aggregation-test.cc index e3e26a651..a53b6542d 100644 --- a/src/wifi/test/wifi-aggregation-test.cc +++ b/src/wifi/test/wifi-aggregation-test.cc @@ -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 (pkt1, hdr1)); + m_edca->GetQueue ()->Enqueue (Create (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 dequeuedPacket; + Ptr 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 (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 (pkt, hdr)); + m_edca->GetQueue ()->Enqueue (Create (pkt, hdr)); - Ptr peekedPacket = m_edca->GetQueue ()->PeekByTidAndAddress (&peekedHdr, 0, - WifiMacHeader::ADDR1, - hdr.GetAddr1 (), - &tstamp); + Ptr peekedItem = m_edca->GetQueue ()->PeekByTidAndAddress (0, WifiMacHeader::ADDR1, + hdr.GetAddr1 ()); + Ptr 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 (); m_edca->SetMpduAggregator (m_mpduAggregator); - m_edca->GetQueue ()->Enqueue (pkt, hdr); + m_edca->GetQueue ()->Enqueue (Create (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. */