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/
This commit is contained in:
Pasquale Imputato
2016-03-08 10:45:36 -08:00
parent 2e7c7dbb00
commit c6e5ecc191
6 changed files with 204 additions and 127 deletions

View File

@@ -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<Queue> ()
.SetGroupName("Network")
.SetGroupName ("Network")
.AddConstructor<DropTailQueue> ()
.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<uint32_t> ())
.AddAttribute ("MaxBytes",
"The maximum number of bytes accepted by this DropTailQueue.",
UintegerValue (100 * 65535),
MakeUintegerAccessor (&DropTailQueue::m_maxBytes),
MakeUintegerChecker<uint32_t> ())
;
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<QueueItem> item)
{
NS_LOG_FUNCTION (this << item);
Ptr<Packet> 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<QueueItem>
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<QueueItem> 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<const QueueItem>
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<QueueItem> 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

View File

@@ -20,19 +20,17 @@
#define DROPTAIL_H
#include <queue>
#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<QueueItem> item);
virtual Ptr<QueueItem> DoDequeue (void);
virtual Ptr<const QueueItem> DoPeek (void) const;
std::queue<Ptr<QueueItem> > 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

View File

@@ -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<Object> ()
.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<uint32_t> ())
.AddAttribute ("MaxBytes",
"The maximum number of bytes accepted by this queue.",
UintegerValue (100 * 65535),
MakeUintegerAccessor (&Queue::SetMaxBytes,
&Queue::GetMaxBytes),
MakeUintegerChecker<uint32_t> ())
.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<QueueItem> item)
{
NS_LOG_FUNCTION (this << item);
Ptr<Packet> 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<QueueItem> item = DoDequeue ();
if (item != 0)
{
Ptr<Packet> 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<const QueueItem>
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<Packet> p)
{

View File

@@ -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<Packet> p);
private:
/**
* Push an item in the queue
* \param item the item to enqueue
@@ -171,14 +219,6 @@ private:
*/
virtual Ptr<const QueueItem> 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<Packet> p);
/// Traced callback: fired when a packet is enqueued
TracedCallback<Ptr<const Packet> > m_traceEnqueue;
/// Traced callback: fired when a packet is dequeued
@@ -186,12 +226,16 @@ protected:
/// Traced callback: fired when a packet is dropped
TracedCallback<Ptr<const Packet> > m_traceDrop;
uint32_t m_nBytes; //!< Number of bytes in the queue
TracedValue<uint32_t> 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<uint32_t> 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

View File

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

View File

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