diff --git a/src/network/utils/queue.cc b/src/network/utils/queue.cc index 477d992a2..0788b9b30 100644 --- a/src/network/utils/queue.cc +++ b/src/network/utils/queue.cc @@ -97,19 +97,18 @@ bool Queue::Enqueue (Ptr item) { NS_LOG_FUNCTION (this << item); - Ptr p = item->GetPacket (); if (m_mode == QUEUE_MODE_PACKETS && (m_nPackets.Get () >= m_maxPackets)) { NS_LOG_LOGIC ("Queue full (at max packets) -- dropping pkt"); - Drop (p); + Drop (item); return false; } if (m_mode == QUEUE_MODE_BYTES && (m_nBytes.Get () + item->GetPacketSize () > m_maxBytes)) { NS_LOG_LOGIC ("Queue full (packet would exceed max bytes) -- dropping pkt"); - Drop (p); + Drop (item); return false; } @@ -319,15 +318,33 @@ Queue::GetMaxBytes (void) const } void -Queue::Drop (Ptr p) +Queue::SetDropCallback (DropCallback cb) { - NS_LOG_FUNCTION (this << p); + m_dropCallback = cb; +} + +void +Queue::NotifyDrop (Ptr item) +{ + NS_LOG_FUNCTION (this << item); + + if (!m_dropCallback.IsNull ()) + { + m_dropCallback (item); + } +} + +void +Queue::Drop (Ptr item) +{ + NS_LOG_FUNCTION (this << item); m_nTotalDroppedPackets++; - m_nTotalDroppedBytes += p->GetSize (); + m_nTotalDroppedBytes += item->GetPacketSize (); NS_LOG_LOGIC ("m_traceDrop (p)"); - m_traceDrop (p); + m_traceDrop (item->GetPacket ()); + NotifyDrop (item); } } // namespace ns3 diff --git a/src/network/utils/queue.h b/src/network/utils/queue.h index 59767edb5..b1309490d 100644 --- a/src/network/utils/queue.h +++ b/src/network/utils/queue.h @@ -190,16 +190,28 @@ public: double GetDroppedPacketsPerSecondVariance (void); #endif + /// Callback set by the object (e.g., a queue disc) that wants to be notified of a packet drop + typedef Callback > DropCallback; + + /** + * \brief Set the drop callback + * \param cb the callback to set + * + * Called when a queue is added to a queue disc in order to set a + * callback to the Drop method of the queue disc. + */ + virtual void SetDropCallback (DropCallback cb); + protected: /** * \brief Drop a packet - * \param p packet that was dropped + * \param item item that was dropped * * This method is called by the base class when a packet is dropped because * the queue is full and by the subclasses to notify parent (this class) that * a packet has been dropped for other reasons. */ - void Drop (Ptr p); + void Drop (Ptr item); private: /** @@ -219,6 +231,12 @@ private: */ virtual Ptr DoPeek (void) const = 0; + /** + * \brief Notification of a packet drop + * \param item item that was dropped + */ + void NotifyDrop (Ptr item); + /// Traced callback: fired when a packet is enqueued TracedCallback > m_traceEnqueue; /// Traced callback: fired when a packet is dequeued @@ -236,6 +254,7 @@ private: uint32_t m_maxPackets; //!< max packets in the queue uint32_t m_maxBytes; //!< max bytes in the queue QueueMode m_mode; //!< queue mode (packets or bytes limited) + DropCallback m_dropCallback; //!< drop callback }; } // namespace ns3 diff --git a/src/traffic-control/model/codel-queue-disc.cc b/src/traffic-control/model/codel-queue-disc.cc index ada8988e1..cc2860b72 100644 --- a/src/traffic-control/model/codel-queue-disc.cc +++ b/src/traffic-control/model/codel-queue-disc.cc @@ -296,13 +296,16 @@ CoDelQueueDisc::DoEnqueue (Ptr item) // Tag packet with current time for DoDequeue() to compute sojourn time CoDelTimestampTag tag; p->AddPacketTag (tag); - - GetInternalQueue (0)->Enqueue (item); + + bool retval = GetInternalQueue (0)->Enqueue (item); + + // If Queue::Enqueue fails, QueueDisc::Drop is called by the internal queue + // because QueueDisc::AddInternalQueue sets the drop callback NS_LOG_LOGIC ("Number packets " << GetInternalQueue (0)->GetNPackets ()); NS_LOG_LOGIC ("Number bytes " << GetInternalQueue (0)->GetNBytes ()); - return true; + return retval; } bool diff --git a/src/traffic-control/model/pfifo-fast-queue-disc.cc b/src/traffic-control/model/pfifo-fast-queue-disc.cc index ca2ba04fe..12ea4eb99 100644 --- a/src/traffic-control/model/pfifo-fast-queue-disc.cc +++ b/src/traffic-control/model/pfifo-fast-queue-disc.cc @@ -87,15 +87,14 @@ PfifoFastQueueDisc::DoEnqueue (Ptr item) band = ret; } - if (!GetInternalQueue(band)->Enqueue (item)) - { - NS_LOG_LOGIC ("Enqueue failed -- dropping pkt"); - Drop (item); - return false; - } + bool retval = GetInternalQueue(band)->Enqueue (item); + + // If Queue::Enqueue fails, QueueDisc::Drop is called by the internal queue + // because QueueDisc::AddInternalQueue sets the drop callback + NS_LOG_LOGIC ("Number packets band " << band << ": " << GetInternalQueue(band)->GetNPackets ()); - return true; + return retval; } Ptr diff --git a/src/traffic-control/model/queue-disc.cc b/src/traffic-control/model/queue-disc.cc index 0e02b8f26..18f25ddb3 100644 --- a/src/traffic-control/model/queue-disc.cc +++ b/src/traffic-control/model/queue-disc.cc @@ -313,6 +313,9 @@ void QueueDisc::AddInternalQueue (Ptr queue) { NS_LOG_FUNCTION (this); + // set the drop callback on the internal queue, so that the queue disc is + // notified of packets dropped by the internal queue + queue->SetDropCallback (MakeCallback (&QueueDisc::Drop, this)); m_queues.push_back (queue); } diff --git a/src/traffic-control/model/red-queue-disc.cc b/src/traffic-control/model/red-queue-disc.cc index 030bbe6f6..0269ab664 100644 --- a/src/traffic-control/model/red-queue-disc.cc +++ b/src/traffic-control/model/red-queue-disc.cc @@ -410,12 +410,15 @@ RedQueueDisc::DoEnqueue (Ptr item) return false; } - GetInternalQueue (0)->Enqueue (item); + bool retval = GetInternalQueue (0)->Enqueue (item); + + // If Queue::Enqueue fails, QueueDisc::Drop is called by the internal queue + // because QueueDisc::AddInternalQueue sets the drop callback NS_LOG_LOGIC ("Number packets " << GetInternalQueue (0)->GetNPackets ()); NS_LOG_LOGIC ("Number bytes " << GetInternalQueue (0)->GetNBytes ()); - return true; + return retval; } /*