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)