network: The Queue class holds a list of items
This commit is contained in:
20
CHANGES.html
20
CHANGES.html
@@ -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<Packet> 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<Packet>").</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>
|
||||
|
||||
@@ -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
|
||||
----------
|
||||
|
||||
@@ -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
|
||||
======
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user