network: The Queue class holds a list of items

This commit is contained in:
Stefano Avallone
2017-03-08 18:01:59 +01:00
parent 3bb15af825
commit 1d0a27a285
5 changed files with 203 additions and 113 deletions

View File

@@ -101,6 +101,10 @@ us a note on ns-developers mailing list.</p>
</li>
<li>Abstract base class <b>WifiChannel</b> has been removed. As a result, a Channel type instead of a WifiChannel type
is now exported by WifiNetDevice.</li>
<li> The <b>GetPacketSize</b> method of <b>QueueItem</b> has been renamed <b>GetSize</b>
</li>
<li> The <b>DequeueAll</b> method of <b>Queue</b> has been renamed <b>Flush</b>
</li>
</ul>
<h2>Changes to build system:</h2>
<ul>
@@ -126,6 +130,22 @@ is now exported by WifiNetDevice.</li>
</li>
<li> The default value of the <b>TxGain</b> and <b>RxGain</b> attributes in WifiPhy was changed from 1 dB to 0 dB.
</li>
<li><b>Queue</b> has been redesigned as a template class object, where the type parameter
specifies the type of items to be stored in the queue. As a consequence:
<ul>
<li>Being a subclass of Queue, <b>DropTailQueue</b> is a template class as well.
<li>Network devices such as SimpleNetDevice, PointToPointNetDevice and CsmaNetDevice
use a queue of type Queue&lt;Packet&gt; to store the packets to transmit. The SetQueue
method of their helpers, however, can still be invoked as, e.g.,
SetQueue ("ns3::DropTailQueue") instead of, e.g., SetQueue
("ns3::DropTailQueue&lt;Packet&gt;").</li>
<li>The attributes <b>Mode</b>, <b>MaxPackets</b> and <b>MaxBytes</b> are now
defined by the QueueBase class (which Queue is derived from).</li>
</ul>
</li>
<li>Queue discs that can operate both in packet mode and byte mode (Red, CoDel, Pie) define their own
enum QueueDiscMode instead of using QueueBase::QueueMode.
</li>
</ul>
<hr>

View File

@@ -24,6 +24,7 @@ New user-visible features
- (wifi) 802.11ax High Efficiency (HE) physical layer modes are now supported.
- (tcp) The SACK option and the RFC 6675 loss recovery algorithm are now supported.
- (lte) LTE carrier aggregation feature according to 3GPP Release 10 is now supported.
- (network) CsmaNetDevice, SimpleNetDevice and WifiNetDevice support flow control.
Bugs fixed
----------

View File

@@ -11,56 +11,73 @@ This section documents the queue object, which is typically used by NetDevices
and QueueDiscs to store packets.
Packets stored in a queue can be managed according to different policies.
Currently, the following policies are available:
* DropTail
Currently, only the DropTail policy is available.
Model Description
*****************
The source code for the new module lives in the directory ``src/network/utils``.
ns-3 provides the classic droptail queue model and the ability to
trace certain queue operations such as enqueuing, dequeuing, and dropping.
These may be added to certain NetDevice objects that take a Ptr<Queue>
pointer.
ns3::Queue has been redesigned as a template class object to allow us to
instantiate queues storing different types of items. The unique template
type parameter specifies the type of items stored in the queue.
The only requirement on the item type is that it must provide a GetSize ()
method which returns the size of the packet included in the item.
Currently, queue items can be objects of the following classes:
Note that not all device models use these queue models.
In particular, WiFi, WiMax, and LTE use specialized device queues.
The queue models described here are more often used with simpler ns-3
device models such as PointToPoint and Csma.
* Packet
* QueueItem and subclasses (e.g., QueueDiscItem)
* WifiMacQueueItem
All the queuing disciplines, instead, make use of the queue model defined here.
The internal queues of the queue discs are of type Queue<QueueDiscItem>
(an alias of which being InternalQueue). A number of network devices
(SimpleNetDevice, PointToPointNetDevice, CsmaNetDevice) use a Queue<Packet>
to store packets to be transmitted. WifiNetDevices use instead queues of
type WifiMacQueue, which is a subclass of Queue storing objects of
type WifiMacQueueItem. Other devices, such as WiMax and LTE, use specialized
queues.
Design
======
An abstract base class, class Queue, is typically used and subclassed
for specific scheduling and drop policies. A class QueueItem is introduced
to model the items stored in a queue. The base class QueueItem only contains
a pointer to a packet. Subclasses may be defined to store additional information.
Common operations provided by the base class Queue include:
The Queue class derives from the QueueBase class, which is a non-template
class providing all the methods that are independent of the type of the items
stored in the queue. The Queue class provides instead all the operations that
depend on the item type, such as enqueue, dequeue, peek and remove. The Queue
class also provides the ability to trace certain queue operations such as
enqueuing, dequeuing, and dropping.
* ``bool Enqueue (Ptr<QueueItem> item)``: Enqueue a packet
* ``Ptr<QueueItem> Dequeue (void)``: Dequeue a packet
* ``uint32_t GetNPackets (void)``: Get the queue depth, in packets
* ``uint32_t GetNBytes (void)``: Get the queue depth, in packets
Queue is an abstract base class and is subclassed for specific scheduling and
drop policies. Subclasses need to define the following public methods:
as well as tracking some statistics on queue operations.
* ``bool Enqueue (Ptr<Item> item)``: Enqueue a packet
* ``Ptr<Item> Dequeue (void)``: Dequeue a packet
* ``Ptr<Item> Remove (void)``: Remove a packet
* ``Ptr<const Item> Peek (void)``: Peek a packet
There are three trace sources that may be hooked:
The Enqueue method does not allow to store a packet if the queue capacity is exceeded.
Subclasses may also define specialized public methods. For instance, the
WifiMacQueue class provides a method to dequeue a packet based on its tid
and MAC address.
There are five trace sources that may be hooked:
* ``Enqueue``
* ``Dequeue``
* ``Drop``
* ``DropBeforeEnqueue``
* ``DropAfterDequeue``
Also, three attributes are defined in the Queue base class:
Also, the QueueBase class defines three attributes:
* ``Mode``: whether the capacity of the queue is measured in packets or bytes
* ``MaxPackets``: the maximum number of packets accepted by the queue in packet mode
* ``MaxBytes``: the maximum number of bytes accepted by the queue in byte mode
The Enqueue method does not allow to store a packet if the queue capacity is exceeded.
and two trace sources:
* ``PacketsInQueue``
* ``BytesInQueue``
DropTail
########
@@ -98,6 +115,9 @@ the queue type and attributes from the helper, such as this example:
p2p.SetChannelAttribute ("Delay", StringValue (linkDelay));
NetDeviceContainer devn2n3 = p2p.Install (n2n3);
Please note that the SetQueue method of the PointToPointHelper class allows
to specify "ns3::DropTailQueue" instead of "ns3::DropTailQueue<Packet>". The
same holds for CsmaHelper, SimpleNetDeviceHelper and TrafficControlHelper.
Output
======

View File

@@ -19,7 +19,6 @@
#ifndef DROPTAIL_H
#define DROPTAIL_H
#include <queue>
#include "ns3/queue.h"
namespace ns3 {
@@ -47,13 +46,18 @@ public:
virtual ~DropTailQueue ();
private:
virtual bool DoEnqueue (Ptr<Item> item);
virtual Ptr<Item> DoDequeue (void);
virtual Ptr<Item> DoRemove (void);
virtual Ptr<const Item> DoPeek (void) const;
virtual bool Enqueue (Ptr<Item> item);
virtual Ptr<Item> Dequeue (void);
virtual Ptr<Item> Remove (void);
virtual Ptr<const Item> Peek (void) const;
std::queue<Ptr<Item> > m_packets; //!< the items in the queue
private:
using Queue<Item>::Head;
using Queue<Item>::Tail;
using Queue<Item>::DoEnqueue;
using Queue<Item>::DoDequeue;
using Queue<Item>::DoRemove;
using Queue<Item>::DoPeek;
};
@@ -75,8 +79,7 @@ DropTailQueue<Item>::GetTypeId (void)
template <typename Item>
DropTailQueue<Item>::DropTailQueue () :
Queue<Item> (),
m_packets ()
Queue<Item> ()
{
QUEUE_LOG (LOG_LOGIC, "DropTailQueue(" << this << ")");
}
@@ -89,25 +92,20 @@ DropTailQueue<Item>::~DropTailQueue ()
template <typename Item>
bool
DropTailQueue<Item>::DoEnqueue (Ptr<Item> item)
DropTailQueue<Item>::Enqueue (Ptr<Item> item)
{
QUEUE_LOG (LOG_LOGIC, "DropTailQueue:DoEnqueue(" << this << ", " << item << ")");
NS_ASSERT (m_packets.size () == this->GetNPackets ());
QUEUE_LOG (LOG_LOGIC, "DropTailQueue:Enqueue(" << this << ", " << item << ")");
m_packets.push (item);
return true;
return DoEnqueue (Tail (), item);
}
template <typename Item>
Ptr<Item>
DropTailQueue<Item>::DoDequeue (void)
DropTailQueue<Item>::Dequeue (void)
{
QUEUE_LOG (LOG_LOGIC, "DropTailQueue:DoDequeue(" << this << ")");
NS_ASSERT (m_packets.size () == this->GetNPackets ());
QUEUE_LOG (LOG_LOGIC, "DropTailQueue:Dequeue(" << this << ")");
Ptr<Item> item = m_packets.front ();
m_packets.pop ();
Ptr<Item> item = DoDequeue (Head ());
QUEUE_LOG (LOG_LOGIC, "Popped " << item);
@@ -116,13 +114,11 @@ DropTailQueue<Item>::DoDequeue (void)
template <typename Item>
Ptr<Item>
DropTailQueue<Item>::DoRemove (void)
DropTailQueue<Item>::Remove (void)
{
QUEUE_LOG (LOG_LOGIC, "DropTailQueue:DoRemove(" << this << ")");
NS_ASSERT (m_packets.size () == this->GetNPackets ());
QUEUE_LOG (LOG_LOGIC, "DropTailQueue:Remove(" << this << ")");
Ptr<Item> item = m_packets.front ();
m_packets.pop ();
Ptr<Item> item = DoRemove (Head ());
QUEUE_LOG (LOG_LOGIC, "Removed " << item);
@@ -131,12 +127,11 @@ DropTailQueue<Item>::DoRemove (void)
template <typename Item>
Ptr<const Item>
DropTailQueue<Item>::DoPeek (void) const
DropTailQueue<Item>::Peek (void) const
{
QUEUE_LOG (LOG_LOGIC, "DropTailQueue:DoPeek(" << this << ")");
NS_ASSERT (m_packets.size () == this->GetNPackets ());
QUEUE_LOG (LOG_LOGIC, "DropTailQueue:Peek(" << this << ")");
return m_packets.front ();
return DoPeek (Head ());
}
} // namespace ns3

View File

@@ -31,6 +31,7 @@
#include "ns3/log.h"
#include <string>
#include <sstream>
#include <list>
namespace ns3 {
@@ -295,29 +296,32 @@ public:
virtual ~Queue ();
/**
* Place a queue item into the rear of the Queue
* Place an item into the Queue (each subclass defines the position)
* \param item item to enqueue
* \return True if the operation was successful; false otherwise
*/
bool Enqueue (Ptr<Item> item);
virtual bool Enqueue (Ptr<Item> item) = 0;
/**
* Remove an item from the front of the Queue, counting it as dequeued
* Remove an item from the Queue (each subclass defines the position),
* counting it as dequeued
* \return 0 if the operation was not successful; the item otherwise.
*/
Ptr<Item> Dequeue (void);
virtual Ptr<Item> Dequeue (void) = 0;
/**
* Remove an item from the front of the Queue, counting it as dropped
* Remove an item from the Queue (each subclass defines the position),
* counting it as dropped
* \return 0 if the operation was not successful; the item otherwise.
*/
Ptr<Item> Remove (void);
virtual Ptr<Item> Remove (void) = 0;
/**
* Get a copy of the item at the front of the queue without removing it
* Get a copy of an item in the queue (each subclass defines the position)
* without removing it
* \return 0 if the operation was not successful; the item otherwise.
*/
Ptr<const Item> Peek (void) const;
virtual Ptr<const Item> Peek (void) const = 0;
/**
* Flush the queue.
@@ -325,6 +329,70 @@ public:
void Flush (void);
protected:
typedef typename std::list<Ptr<Item> >::const_iterator ConstIterator;
/**
* \brief Get a const iterator which refers to the first item in the queue.
*
* Subclasses can browse the items in the queue by using an iterator
*
* \code
* for (auto i = Head (); i != Tail (); ++i)
* {
* (*i)->method (); // some method of the Item class
* }
* \endcode
*
* \returns a const iterator which refers to the first item in the queue.
*/
ConstIterator Head (void) const;
/**
* \brief Get a const iterator which indicates past-the-last item in the queue.
*
* Subclasses can browse the items in the queue by using an iterator
*
* \code
* for (auto i = Head (); i != Tail (); ++i)
* {
* (*i)->method (); // some method of the Item class
* }
* \endcode
*
* \returns a const iterator which indicates past-the-last item in the queue.
*/
ConstIterator Tail (void) const;
/**
* Push an item in the queue
* \param pos the position where the item is inserted
* \param item the item to enqueue
* \return true if success, false if the packet has been dropped.
*/
bool DoEnqueue (ConstIterator pos, Ptr<Item> item);
/**
* Pull the item to dequeue from the queue
* \param pos the position of the item to dequeue
* \return the item.
*/
Ptr<Item> DoDequeue (ConstIterator pos);
/**
* Pull the item to drop from the queue
* \param pos the position of the item to remove
* \return the item.
*/
Ptr<Item> DoRemove (ConstIterator pos);
/**
* Peek the front item in the queue
* \param pos the position of the item to peek
* \return the item.
*/
Ptr<const Item> DoPeek (ConstIterator pos) const;
/**
* \brief Drop a packet before enqueue
* \param item item that was dropped
@@ -346,32 +414,8 @@ protected:
void DropAfterDequeue (Ptr<Item> item);
private:
/**
* Push an item in the queue
* \param item the item to enqueue
* \return true if success, false if the packet has been dropped.
*/
virtual bool DoEnqueue (Ptr<Item> item) = 0;
std::list<Ptr<Item> > m_packets; //!< the items in the queue
/**
* Pull the item to dequeue from the queue
* \return the item.
*/
virtual Ptr<Item> DoDequeue (void) = 0;
/**
* Pull the item to drop from the queue
* \return the item.
*/
virtual Ptr<Item> DoRemove (void) = 0;
/**
* Peek the front item in the queue
* \return the item.
*/
virtual Ptr<const Item> DoPeek (void) const = 0;
private:
/// Traced callback: fired when a packet is enqueued
TracedCallback<Ptr<const Item> > m_traceEnqueue;
/// Traced callback: fired when a packet is dequeued
@@ -436,9 +480,9 @@ Queue<Item>::~Queue ()
template <typename Item>
bool
Queue<Item>::Enqueue (Ptr<Item> item)
Queue<Item>::DoEnqueue (ConstIterator pos, Ptr<Item> item)
{
QUEUE_LOG (LOG_LOGIC, "Queue:Enqueue(" << this << ", " << item << ")");
QUEUE_LOG (LOG_LOGIC, "Queue:DoEnqueue(" << this << ", " << item << ")");
if (m_mode == QUEUE_MODE_PACKETS && (m_nPackets.Get () >= m_maxPackets))
{
@@ -454,30 +498,26 @@ Queue<Item>::Enqueue (Ptr<Item> item)
return false;
}
//
// If DoEnqueue fails, Queue::DropBeforeEnqueue is called by the subclass
//
bool retval = DoEnqueue (item);
if (retval)
{
uint32_t size = item->GetSize ();
m_nBytes += size;
m_nTotalReceivedBytes += size;
m_packets.insert (pos, item);
m_nPackets++;
m_nTotalReceivedPackets++;
uint32_t size = item->GetSize ();
m_nBytes += size;
m_nTotalReceivedBytes += size;
QUEUE_LOG (LOG_LOGIC, "m_traceEnqueue (p)");
m_traceEnqueue (item);
}
return retval;
m_nPackets++;
m_nTotalReceivedPackets++;
QUEUE_LOG (LOG_LOGIC, "m_traceEnqueue (p)");
m_traceEnqueue (item);
return true;
}
template <typename Item>
Ptr<Item>
Queue<Item>::Dequeue (void)
Queue<Item>::DoDequeue (ConstIterator pos)
{
QUEUE_LOG (LOG_LOGIC, "Queue:Dequeue(" << this << ")");
QUEUE_LOG (LOG_LOGIC, "Queue:DoDequeue(" << this << ")");
if (m_nPackets.Get () == 0)
{
@@ -485,7 +525,8 @@ Queue<Item>::Dequeue (void)
return 0;
}
Ptr<Item> item = DoDequeue ();
Ptr<Item> item = *pos;
m_packets.erase (pos);
if (item != 0)
{
@@ -503,9 +544,9 @@ Queue<Item>::Dequeue (void)
template <typename Item>
Ptr<Item>
Queue<Item>::Remove (void)
Queue<Item>::DoRemove (ConstIterator pos)
{
QUEUE_LOG (LOG_LOGIC, "Queue:Remove(" << this << ")");
QUEUE_LOG (LOG_LOGIC, "Queue:DoRemove(" << this << ")");
if (m_nPackets.Get () == 0)
{
@@ -513,7 +554,8 @@ Queue<Item>::Remove (void)
return 0;
}
Ptr<Item> item = DoRemove ();
Ptr<Item> item = *pos;
m_packets.erase (pos);
if (item != 0)
{
@@ -541,9 +583,9 @@ Queue<Item>::Flush (void)
template <typename Item>
Ptr<const Item>
Queue<Item>::Peek (void) const
Queue<Item>::DoPeek (ConstIterator pos) const
{
QUEUE_LOG (LOG_LOGIC, "Queue:Peek(" << this << ")");
QUEUE_LOG (LOG_LOGIC, "Queue:DoPeek(" << this << ")");
if (m_nPackets.Get () == 0)
{
@@ -551,7 +593,19 @@ Queue<Item>::Peek (void) const
return 0;
}
return DoPeek ();
return *pos;
}
template <typename Item>
typename Queue<Item>::ConstIterator Queue<Item>::Head (void) const
{
return m_packets.cbegin ();
}
template <typename Item>
typename Queue<Item>::ConstIterator Queue<Item>::Tail (void) const
{
return m_packets.cend ();
}
template <typename Item>