From c6e5ecc1912f3d2a67349175d93ac308be128542 Mon Sep 17 00:00:00 2001 From: Pasquale Imputato Date: Tue, 8 Mar 2016 10:45:36 -0800 Subject: [PATCH] network: The Queue base class holds mode, maxPackets and maxBytes ...so that all the subclasses have such attributes. This allows queue discs to have attributes specifying the mode and size of their queue(s) and to create queues using their own attributes. This commit is heavily inspired by Natale's queue rework patch: https://codereview.appspot.com/270540044/ --- src/network/utils/drop-tail-queue.cc | 86 +----------- src/network/utils/drop-tail-queue.h | 25 +--- src/network/utils/queue.cc | 144 +++++++++++++++++++-- src/network/utils/queue.h | 72 +++++++++-- src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc | 2 +- src/test/ns3tcp/ns3tcp-state-test-suite.cc | 2 +- 6 files changed, 204 insertions(+), 127 deletions(-) diff --git a/src/network/utils/drop-tail-queue.cc b/src/network/utils/drop-tail-queue.cc index ce137a166..5a8785a7c 100644 --- a/src/network/utils/drop-tail-queue.cc +++ b/src/network/utils/drop-tail-queue.cc @@ -17,8 +17,6 @@ */ #include "ns3/log.h" -#include "ns3/enum.h" -#include "ns3/uinteger.h" #include "drop-tail-queue.h" namespace ns3 { @@ -27,38 +25,19 @@ NS_LOG_COMPONENT_DEFINE ("DropTailQueue"); NS_OBJECT_ENSURE_REGISTERED (DropTailQueue); -TypeId DropTailQueue::GetTypeId (void) +TypeId DropTailQueue::GetTypeId (void) { static TypeId tid = TypeId ("ns3::DropTailQueue") .SetParent () - .SetGroupName("Network") + .SetGroupName ("Network") .AddConstructor () - .AddAttribute ("Mode", - "Whether to use bytes (see MaxBytes) or packets (see MaxPackets) as the maximum queue size metric.", - EnumValue (QUEUE_MODE_PACKETS), - MakeEnumAccessor (&DropTailQueue::SetMode, - &DropTailQueue::GetMode), - MakeEnumChecker (QUEUE_MODE_BYTES, "QUEUE_MODE_BYTES", - QUEUE_MODE_PACKETS, "QUEUE_MODE_PACKETS")) - .AddAttribute ("MaxPackets", - "The maximum number of packets accepted by this DropTailQueue.", - UintegerValue (100), - MakeUintegerAccessor (&DropTailQueue::m_maxPackets), - MakeUintegerChecker ()) - .AddAttribute ("MaxBytes", - "The maximum number of bytes accepted by this DropTailQueue.", - UintegerValue (100 * 65535), - MakeUintegerAccessor (&DropTailQueue::m_maxBytes), - MakeUintegerChecker ()) ; - return tid; } DropTailQueue::DropTailQueue () : Queue (), - m_packets (), - m_bytesInQueue (0) + m_packets () { NS_LOG_FUNCTION (this); } @@ -68,46 +47,14 @@ DropTailQueue::~DropTailQueue () NS_LOG_FUNCTION (this); } -void -DropTailQueue::SetMode (DropTailQueue::QueueMode mode) -{ - NS_LOG_FUNCTION (this << mode); - m_mode = mode; -} - -DropTailQueue::QueueMode -DropTailQueue::GetMode (void) const -{ - NS_LOG_FUNCTION (this); - return m_mode; -} - bool DropTailQueue::DoEnqueue (Ptr item) { NS_LOG_FUNCTION (this << item); - Ptr p = item->GetPacket (); + NS_ASSERT (m_packets.size () == GetNPackets ()); - if (m_mode == QUEUE_MODE_PACKETS && (m_packets.size () >= m_maxPackets)) - { - NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt"); - Drop (p); - return false; - } - - if (m_mode == QUEUE_MODE_BYTES && (m_bytesInQueue + item->GetPacketSize () >= m_maxBytes)) - { - NS_LOG_LOGIC ("Queue full (packet would exceed max bytes) -- droppping pkt"); - Drop (p); - return false; - } - - m_bytesInQueue += item->GetPacketSize (); m_packets.push (item); - NS_LOG_LOGIC ("Number packets " << m_packets.size ()); - NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); - return true; } @@ -115,22 +62,13 @@ Ptr DropTailQueue::DoDequeue (void) { NS_LOG_FUNCTION (this); - - if (m_packets.empty ()) - { - NS_LOG_LOGIC ("Queue empty"); - return 0; - } + NS_ASSERT (m_packets.size () == GetNPackets ()); Ptr item = m_packets.front (); m_packets.pop (); - m_bytesInQueue -= item->GetPacketSize (); NS_LOG_LOGIC ("Popped " << item); - NS_LOG_LOGIC ("Number packets " << m_packets.size ()); - NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); - return item; } @@ -138,19 +76,9 @@ Ptr DropTailQueue::DoPeek (void) const { NS_LOG_FUNCTION (this); + NS_ASSERT (m_packets.size () == GetNPackets ()); - if (m_packets.empty ()) - { - NS_LOG_LOGIC ("Queue empty"); - return 0; - } - - Ptr item = m_packets.front (); - - NS_LOG_LOGIC ("Number packets " << m_packets.size ()); - NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue); - - return item; + return m_packets.front (); } } // namespace ns3 diff --git a/src/network/utils/drop-tail-queue.h b/src/network/utils/drop-tail-queue.h index 64457b307..8f796ecda 100644 --- a/src/network/utils/drop-tail-queue.h +++ b/src/network/utils/drop-tail-queue.h @@ -20,19 +20,17 @@ #define DROPTAIL_H #include -#include "ns3/packet.h" #include "ns3/queue.h" namespace ns3 { -class TraceContainer; - /** * \ingroup queue * * \brief A FIFO packet queue that drops tail-end packets on overflow */ -class DropTailQueue : public Queue { +class DropTailQueue : public Queue +{ public: /** * \brief Get the type ID. @@ -48,31 +46,12 @@ public: virtual ~DropTailQueue(); - /** - * Set the operating mode of this device. - * - * \param mode The operating mode of this device. - * - */ - void SetMode (DropTailQueue::QueueMode mode); - - /** - * Get the encapsulation mode of this device. - * - * \returns The encapsulation mode of this device. - */ - DropTailQueue::QueueMode GetMode (void) const; - private: virtual bool DoEnqueue (Ptr item); virtual Ptr DoDequeue (void); virtual Ptr DoPeek (void) const; std::queue > m_packets; //!< the items in the queue - uint32_t m_maxPackets; //!< max packets in the queue - uint32_t m_maxBytes; //!< max bytes in the queue - uint32_t m_bytesInQueue; //!< actual bytes in the queue - QueueMode m_mode; //!< queue mode (packets or bytes limited) }; } // namespace ns3 diff --git a/src/network/utils/queue.cc b/src/network/utils/queue.cc index 44781cab0..477d992a2 100644 --- a/src/network/utils/queue.cc +++ b/src/network/utils/queue.cc @@ -17,6 +17,9 @@ */ #include "ns3/log.h" +#include "ns3/abort.h" +#include "ns3/enum.h" +#include "ns3/uinteger.h" #include "ns3/trace-source-accessor.h" #include "queue.h" @@ -31,16 +34,43 @@ Queue::GetTypeId (void) { static TypeId tid = TypeId ("ns3::Queue") .SetParent () - .SetGroupName("Network") + .SetGroupName ("Network") + .AddAttribute ("Mode", + "Whether to use bytes (see MaxBytes) or packets (see MaxPackets) as the maximum queue size metric.", + EnumValue (QUEUE_MODE_PACKETS), + MakeEnumAccessor (&Queue::SetMode, + &Queue::GetMode), + MakeEnumChecker (QUEUE_MODE_BYTES, "QUEUE_MODE_BYTES", + QUEUE_MODE_PACKETS, "QUEUE_MODE_PACKETS")) + .AddAttribute ("MaxPackets", + "The maximum number of packets accepted by this queue.", + UintegerValue (100), + MakeUintegerAccessor (&Queue::SetMaxPackets, + &Queue::GetMaxPackets), + MakeUintegerChecker ()) + .AddAttribute ("MaxBytes", + "The maximum number of bytes accepted by this queue.", + UintegerValue (100 * 65535), + MakeUintegerAccessor (&Queue::SetMaxBytes, + &Queue::GetMaxBytes), + MakeUintegerChecker ()) .AddTraceSource ("Enqueue", "Enqueue a packet in the queue.", MakeTraceSourceAccessor (&Queue::m_traceEnqueue), "ns3::Packet::TracedCallback") .AddTraceSource ("Dequeue", "Dequeue a packet from the queue.", MakeTraceSourceAccessor (&Queue::m_traceDequeue), "ns3::Packet::TracedCallback") - .AddTraceSource ("Drop", "Drop a packet stored in the queue.", + .AddTraceSource ("Drop", "Drop a packet (for whatever reason).", MakeTraceSourceAccessor (&Queue::m_traceDrop), "ns3::Packet::TracedCallback") + .AddTraceSource ("PacketsInQueue", + "Number of packets currently stored in the queue", + MakeTraceSourceAccessor (&Queue::m_nPackets), + "ns3::TracedValueCallback::Uint32") + .AddTraceSource ("BytesInQueue", + "Number of bytes currently stored in the queue", + MakeTraceSourceAccessor (&Queue::m_nBytes), + "ns3::TracedValueCallback::Uint32") ; return tid; } @@ -51,7 +81,8 @@ Queue::Queue() : m_nPackets (0), m_nTotalReceivedPackets (0), m_nTotalDroppedBytes (0), - m_nTotalDroppedPackets (0) + m_nTotalDroppedPackets (0), + m_mode (QUEUE_MODE_PACKETS) { NS_LOG_FUNCTION (this); } @@ -66,6 +97,21 @@ 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); + 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); + return false; + } // // If DoEnqueue fails, Queue::Drop is called by the subclass @@ -91,19 +137,24 @@ Queue::Dequeue (void) { NS_LOG_FUNCTION (this); + if (m_nPackets.Get () == 0) + { + NS_LOG_LOGIC ("Queue empty"); + return 0; + } + Ptr item = DoDequeue (); if (item != 0) { - Ptr packet = item->GetPacket (); - NS_ASSERT (m_nBytes >= item->GetPacketSize ()); - NS_ASSERT (m_nPackets > 0); + NS_ASSERT (m_nBytes.Get () >= item->GetPacketSize ()); + NS_ASSERT (m_nPackets.Get () > 0); m_nBytes -= item->GetPacketSize (); m_nPackets--; NS_LOG_LOGIC ("m_traceDequeue (packet)"); - m_traceDequeue (packet); + m_traceDequeue (item->GetPacket ()); } return item; } @@ -122,6 +173,13 @@ Ptr Queue::Peek (void) const { NS_LOG_FUNCTION (this); + + if (m_nPackets.Get () == 0) + { + NS_LOG_LOGIC ("Queue empty"); + return 0; + } + return DoPeek (); } @@ -146,8 +204,8 @@ bool Queue::IsEmpty (void) const { NS_LOG_FUNCTION (this); - NS_LOG_LOGIC ("returns " << (m_nPackets == 0)); - return m_nPackets == 0; + NS_LOG_LOGIC ("returns " << (m_nPackets.Get () == 0)); + return m_nPackets.Get () == 0; } uint32_t @@ -192,6 +250,74 @@ Queue::ResetStatistics (void) m_nTotalDroppedPackets = 0; } +void +Queue::SetMode (Queue::QueueMode mode) +{ + NS_LOG_FUNCTION (this << mode); + + if (mode == QUEUE_MODE_BYTES && m_mode == QUEUE_MODE_PACKETS) + { + NS_ABORT_MSG_IF (m_nPackets.Get () != 0, + "Cannot change queue mode in a queue with packets."); + } + else if (mode == QUEUE_MODE_PACKETS && m_mode == QUEUE_MODE_BYTES) + { + NS_ABORT_MSG_IF (m_nBytes.Get () != 0, + "Cannot change queue mode in a queue with packets."); + } + + m_mode = mode; +} + +Queue::QueueMode +Queue::GetMode (void) const +{ + NS_LOG_FUNCTION (this); + return m_mode; +} + +void +Queue::SetMaxPackets (uint32_t maxPackets) +{ + NS_LOG_FUNCTION (this << maxPackets); + + if (m_mode == QUEUE_MODE_PACKETS) + { + NS_ABORT_MSG_IF (maxPackets < m_nPackets.Get (), + "The new queue size cannot be less than the number of currently stored packets."); + } + + m_maxPackets = maxPackets; +} + +uint32_t +Queue::GetMaxPackets (void) const +{ + NS_LOG_FUNCTION (this); + return m_maxPackets; +} + +void +Queue::SetMaxBytes (uint32_t maxBytes) +{ + NS_LOG_FUNCTION (this << maxBytes); + + if (m_mode == QUEUE_MODE_BYTES) + { + NS_ABORT_MSG_IF (maxBytes < m_nBytes.Get (), + "The new queue size cannot be less than the amount of bytes of currently stored packets."); + } + + m_maxBytes = maxBytes; +} + +uint32_t +Queue::GetMaxBytes (void) const +{ + NS_LOG_FUNCTION (this); + return m_maxBytes; +} + void Queue::Drop (Ptr p) { diff --git a/src/network/utils/queue.h b/src/network/utils/queue.h index f933a9d36..59767edb5 100644 --- a/src/network/utils/queue.h +++ b/src/network/utils/queue.h @@ -16,9 +16,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// The queue base class does not have any limit based on the number -// of packets or number of bytes. It is, conceptually, infinite -// by default. Only subclasses define limitations. +// The queue base class has a limit on its size, in terms of number of +// packets or number of bytes depending on the operating mode. // The base class implements tracing and basic statistics calculations. #ifndef QUEUE_H @@ -28,6 +27,7 @@ #include "ns3/object.h" #include "ns3/traced-callback.h" #include "ns3/net-device.h" +#include "ns3/traced-value.h" namespace ns3 { @@ -128,6 +128,44 @@ public: QUEUE_MODE_BYTES, /**< Use number of bytes for maximum queue size */ }; + /** + * Set the operating mode of this device. + * + * \param mode The operating mode of this device. + */ + void SetMode (Queue::QueueMode mode); + + /** + * Get the encapsulation mode of this device. + * + * \returns The encapsulation mode of this device. + */ + Queue::QueueMode GetMode (void) const; + + /** + * \brief Set the maximum amount of packets that can be stored in this queue + * + * \param maxPackets amount of packets + */ + void SetMaxPackets (uint32_t maxPackets); + + /** + * \return the maximum amount of packets that can be stored in this queue + */ + uint32_t GetMaxPackets (void) const; + + /** + * \brief Set the maximum amount of bytes that can be stored in this queue + * + * \param maxBytes amount of bytes + */ + void SetMaxBytes (uint32_t maxBytes); + + /** + * \return the maximum amount of bytes that can be stored in this queue + */ + uint32_t GetMaxBytes (void) const; + #if 0 // average calculation requires keeping around // a buffer with the date of arrival of past received packets @@ -152,8 +190,18 @@ public: double GetDroppedPacketsPerSecondVariance (void); #endif -private: +protected: + /** + * \brief Drop a packet + * \param p packet 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); +private: /** * Push an item in the queue * \param item the item to enqueue @@ -171,14 +219,6 @@ private: */ virtual Ptr DoPeek (void) const = 0; -protected: - /** - * \brief Drop a packet - * \param p packet that was dropped - * This method is called by subclasses to notify parent (this class) of packet drops. - */ - void Drop (Ptr p); - /// Traced callback: fired when a packet is enqueued TracedCallback > m_traceEnqueue; /// Traced callback: fired when a packet is dequeued @@ -186,12 +226,16 @@ protected: /// Traced callback: fired when a packet is dropped TracedCallback > m_traceDrop; - uint32_t m_nBytes; //!< Number of bytes in the queue + TracedValue m_nBytes; //!< Number of bytes in the queue uint32_t m_nTotalReceivedBytes; //!< Total received bytes - uint32_t m_nPackets; //!< Number of packets in the queue + TracedValue m_nPackets; //!< Number of packets in the queue uint32_t m_nTotalReceivedPackets; //!< Total received packets uint32_t m_nTotalDroppedBytes; //!< Total dropped bytes uint32_t m_nTotalDroppedPackets; //!< Total dropped packets + + 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) }; } // namespace ns3 diff --git a/src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc b/src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc index 1f935b6cf..ddc78b399 100644 --- a/src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc +++ b/src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc @@ -433,7 +433,7 @@ Ns3TcpCwndTestCase2::DoRun (void) { NS_LOG_DEBUG ("Starting test case 2"); // Set up some default values for the simulation. - Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (4)); + Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (4)); NodeContainer n0n1; n0n1.Create (2); diff --git a/src/test/ns3tcp/ns3tcp-state-test-suite.cc b/src/test/ns3tcp/ns3tcp-state-test-suite.cc index b0c83ff25..bf16696ff 100644 --- a/src/test/ns3tcp/ns3tcp-state-test-suite.cc +++ b/src/test/ns3tcp/ns3tcp-state-test-suite.cc @@ -278,7 +278,7 @@ Ns3TcpStateTestCase::DoRun (void) Config::SetDefault ("ns3::TcpL4Protocol::SocketType", StringValue (tcpModel)); Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1000)); Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (1)); - Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (20)); + Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (20)); Config::SetDefault ("ns3::TcpSocketBase::Timestamp", BooleanValue (false)); if (m_writeLogging)