545 lines
19 KiB
C++
545 lines
19 KiB
C++
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
|
/*
|
|
* Copyright (c) 2007, 2014 University of Washington
|
|
* 2015 Universita' degli Studi di Napoli Federico II
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation;
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifndef QUEUE_DISC_H
|
|
#define QUEUE_DISC_H
|
|
|
|
#include "ns3/object.h"
|
|
#include "ns3/traced-value.h"
|
|
#include "ns3/net-device.h"
|
|
#include "ns3/queue-item.h"
|
|
#include <vector>
|
|
#include "packet-filter.h"
|
|
|
|
namespace ns3 {
|
|
|
|
class QueueDisc;
|
|
template <typename Item> class Queue;
|
|
class NetDeviceQueueInterface;
|
|
|
|
/**
|
|
* \ingroup traffic-control
|
|
*
|
|
* QueueDiscClass is the base class for classes that are included in a queue
|
|
* disc. It has a single attribute, QueueDisc, used to set the child queue disc
|
|
* attached to the class. Classful queue discs needing to set parameters for
|
|
* their classes can subclass QueueDiscClass and add the required parameters
|
|
* as attributes.
|
|
*/
|
|
class QueueDiscClass : public Object {
|
|
public:
|
|
/**
|
|
* \brief Get the type ID.
|
|
* \return the object TypeId
|
|
*/
|
|
static TypeId GetTypeId (void);
|
|
|
|
QueueDiscClass ();
|
|
virtual ~QueueDiscClass ();
|
|
|
|
/**
|
|
* \brief Get the queue disc attached to this class
|
|
* \return the queue disc attached to this class.
|
|
*/
|
|
Ptr<QueueDisc> GetQueueDisc (void) const;
|
|
|
|
/**
|
|
* \brief Set the queue disc attached to this class
|
|
* \param qd The queue disc to attach to this class
|
|
*/
|
|
void SetQueueDisc (Ptr<QueueDisc> qd);
|
|
|
|
protected:
|
|
/**
|
|
* \brief Dispose of the object
|
|
*/
|
|
virtual void DoDispose (void);
|
|
|
|
private:
|
|
Ptr<QueueDisc> m_queueDisc; //!< Queue disc attached to this class
|
|
};
|
|
|
|
|
|
/**
|
|
* \ingroup traffic-control
|
|
*
|
|
* QueueDisc is an abstract base class providing the interface and implementing
|
|
* the operations common to all the queueing disciplines. Child classes
|
|
* need to implement the methods used to enqueue a packet (DoEnqueue),
|
|
* dequeue a single packet (DoDequeue), get a copy of the next packet
|
|
* to extract (DoPeek), check whether the current configuration is correct
|
|
* (CheckConfig).
|
|
*
|
|
* As in Linux, a queue disc may contain distinct elements:
|
|
* - queues, which actually store the packets waiting for transmission
|
|
* - classes, which allow to reserve a different treatment to different packets
|
|
* - filters, which determine the queue or class which a packet is destined to
|
|
*
|
|
* Notice that a child queue disc must be attached to every class and a packet
|
|
* filter is only able to classify packets of a single protocol. Also, while in Linux
|
|
* some queue discs (e.g., fq-codel) use an internal classifier and do not make use of
|
|
* packet filters, in ns-3 every queue disc including multiple queues or multiple classes
|
|
* needs an external filter to classify packets (this is to avoid having the traffic-control
|
|
* module depend on other modules such as internet).
|
|
*
|
|
* Queue disc configuration vary from queue disc to queue disc. A typical taxonomy divides
|
|
* queue discs in classful (i.e., support classes) and classless (i.e., do not support
|
|
* classes). More recently, after the appearance of multi-queue devices (such as Wifi),
|
|
* some multi-queue aware queue discs have been introduced. Multi-queue aware queue discs
|
|
* handle as many queues (or queue discs -- without using classes) as the number of
|
|
* transmission queues used by the device on which the queue disc is installed.
|
|
* An attempt is made, also, to enqueue each packet in the "same" queue both within the
|
|
* queue disc and within the device.
|
|
*
|
|
* The traffic control layer interacts with a queue disc in a simple manner: after
|
|
* requesting to enqueue a packet, the traffic control layer requests the qdisc to
|
|
* "run", i.e., to dequeue a set of packets, until a predefined number ("quota")
|
|
* of packets is dequeued or the netdevice stops the queue disc. A netdevice shall
|
|
* stop the queue disc when its transmission queue does not have room for another
|
|
* packet. Also, a netdevice shall wake the queue disc when it detects that there
|
|
* is room for another packet in its transmission queue, but the transmission queue
|
|
* is stopped. Waking a queue disc is equivalent to make it run.
|
|
*
|
|
* Every queue disc collects statistics about the total number of packets/bytes
|
|
* received from the upper layers (in case of root queue disc) or from the parent
|
|
* queue disc (in case of child queue disc), enqueued, dequeued, requeued, dropped,
|
|
* dropped before enqueue, dropped after dequeue, queued in the queue disc and
|
|
* sent to the netdevice or to the parent queue disc. Note that packets that are
|
|
* dequeued may be requeued, i.e., retained by the traffic control infrastructure,
|
|
* if the netdevice is not ready to receive them. Requeued packets are not part
|
|
* of the queue disc. The following identities hold:
|
|
* - dropped = dropped before enqueue + dropped after dequeue
|
|
* - received = dropped before enqueue + enqueued
|
|
* - queued = enqueued - dequeued
|
|
* - sent = dequeued - dropped after dequeue (- 1 if there is a requeued packet)
|
|
*
|
|
* The design and implementation of this class is heavily inspired by Linux.
|
|
* For more details, see the traffic-control model page.
|
|
*/
|
|
class QueueDisc : public Object {
|
|
public:
|
|
|
|
/// \brief Structure that keeps the queue disc statistics
|
|
struct Stats
|
|
{
|
|
/// Total received packets
|
|
uint32_t nTotalReceivedPackets;
|
|
/// Total received bytes
|
|
uint64_t nTotalReceivedBytes;
|
|
/// Total sent packets -- this value is not kept up to date, call GetStats first
|
|
uint32_t nTotalSentPackets;
|
|
/// Total sent bytes -- this value is not kept up to date, call GetStats first
|
|
uint64_t nTotalSentBytes;
|
|
/// Total enqueued packets
|
|
uint32_t nTotalEnqueuedPackets;
|
|
/// Total enqueued bytes
|
|
uint64_t nTotalEnqueuedBytes;
|
|
/// Total dequeued packets
|
|
uint32_t nTotalDequeuedPackets;
|
|
/// Total dequeued bytes
|
|
uint64_t nTotalDequeuedBytes;
|
|
/// Total dropped packets
|
|
uint32_t nTotalDroppedPackets;
|
|
/// Total packets dropped before enqueue
|
|
uint32_t nTotalDroppedPacketsBeforeEnqueue;
|
|
/// Total packets dropped after dequeue
|
|
uint32_t nTotalDroppedPacketsAfterDequeue;
|
|
/// Total dropped bytes
|
|
uint64_t nTotalDroppedBytes;
|
|
/// Total bytes dropped before enqueue
|
|
uint64_t nTotalDroppedBytesBeforeEnqueue;
|
|
/// Total bytes dropped after dequeue
|
|
uint64_t nTotalDroppedBytesAfterDequeue;
|
|
/// Total requeued packets
|
|
uint32_t nTotalRequeuedPackets;
|
|
/// Total requeued bytes
|
|
uint64_t nTotalRequeuedBytes;
|
|
|
|
/// constructor
|
|
Stats ();
|
|
|
|
/**
|
|
* \brief Print the statistics.
|
|
* \param os output stream in which the data should be printed.
|
|
*/
|
|
void Print (std::ostream &os) const;
|
|
};
|
|
|
|
/**
|
|
* \brief Get the type ID.
|
|
* \return the object TypeId
|
|
*/
|
|
static TypeId GetTypeId (void);
|
|
|
|
QueueDisc ();
|
|
virtual ~QueueDisc ();
|
|
|
|
/**
|
|
* \brief Get the number of packets stored by the queue disc
|
|
* \return the number of packets stored by the queue disc.
|
|
*
|
|
* The requeued packet, if any, is counted.
|
|
*/
|
|
uint32_t GetNPackets (void) const;
|
|
|
|
/**
|
|
* \brief Get the amount of bytes stored by the queue disc
|
|
* \return the amount of bytes stored by the queue disc.
|
|
*
|
|
* The requeued packet, if any, is counted.
|
|
*/
|
|
uint32_t GetNBytes (void) const;
|
|
|
|
/**
|
|
* \brief Retrieve all the collected statistics.
|
|
* \return the collected statistics.
|
|
*/
|
|
const Stats& GetStats (void);
|
|
|
|
/**
|
|
* \brief Set the NetDevice on which this queue discipline is installed.
|
|
* \param device the NetDevice on which this queue discipline is installed.
|
|
*/
|
|
void SetNetDevice (Ptr<NetDevice> device);
|
|
|
|
/**
|
|
* \brief Get the NetDevice on which this queue discipline is installed
|
|
* \return the NetDevice on which this queue discipline is installed.
|
|
*/
|
|
Ptr<NetDevice> GetNetDevice (void) const;
|
|
|
|
/**
|
|
* \brief Set the maximum number of dequeue operations following a packet enqueue
|
|
* \param quota the maximum number of dequeue operations following a packet enqueue.
|
|
*/
|
|
virtual void SetQuota (const uint32_t quota);
|
|
|
|
/**
|
|
* \brief Get the maximum number of dequeue operations following a packet enqueue
|
|
* \return the maximum number of dequeue operations following a packet enqueue.
|
|
*/
|
|
virtual uint32_t GetQuota (void) const;
|
|
|
|
/**
|
|
* Pass a packet to store to the queue discipline. This function only updates
|
|
* the statistics and calls the (private) DoEnqueue function, which must be
|
|
* implemented by derived classes.
|
|
* \param item item to enqueue
|
|
* \return True if the operation was successful; false otherwise
|
|
*/
|
|
bool Enqueue (Ptr<QueueDiscItem> item);
|
|
|
|
/**
|
|
* Request the queue discipline to extract a packet. This function only updates
|
|
* the statistics and calls the (private) DoDequeue function, which must be
|
|
* implemented by derived classes.
|
|
* \return 0 if the operation was not successful; the item otherwise.
|
|
*/
|
|
Ptr<QueueDiscItem> Dequeue (void);
|
|
|
|
/**
|
|
* Get a copy of the next packet the queue discipline will extract, without
|
|
* actually extracting the packet. This function only calls the (private)
|
|
* DoPeek function, which must be implemented by derived classes.
|
|
* \return 0 if the operation was not successful; the item otherwise.
|
|
*/
|
|
Ptr<const QueueDiscItem> Peek (void) const;
|
|
|
|
/**
|
|
* Modelled after the Linux function __qdisc_run (net/sched/sch_generic.c)
|
|
* Dequeues multiple packets, until a quota is exceeded or sending a packet
|
|
* to the device failed.
|
|
*/
|
|
void Run (void);
|
|
|
|
/// Internal queues store QueueDiscItem objects
|
|
typedef Queue<QueueDiscItem> InternalQueue;
|
|
|
|
/**
|
|
* \brief Add an internal queue to the tail of the list of queues.
|
|
* \param queue the queue to be added
|
|
*/
|
|
void AddInternalQueue (Ptr<InternalQueue> queue);
|
|
|
|
/**
|
|
* \brief Get the i-th internal queue
|
|
* \param i the index of the queue
|
|
* \return the i-th internal queue.
|
|
*/
|
|
Ptr<InternalQueue> GetInternalQueue (uint32_t i) const;
|
|
|
|
/**
|
|
* \brief Get the number of internal queues
|
|
* \return the number of internal queues.
|
|
*/
|
|
uint32_t GetNInternalQueues (void) const;
|
|
|
|
/**
|
|
* \brief Add a packet filter to the tail of the list of filters used to classify packets.
|
|
* \param filter the packet filter to be added
|
|
*/
|
|
void AddPacketFilter (Ptr<PacketFilter> filter);
|
|
|
|
/**
|
|
* \brief Get the i-th packet filter
|
|
* \param i the index of the packet filter
|
|
* \return the i-th packet filter.
|
|
*/
|
|
Ptr<PacketFilter> GetPacketFilter (uint32_t i) const;
|
|
|
|
/**
|
|
* \brief Get the number of packet filters
|
|
* \return the number of packet filters.
|
|
*/
|
|
uint32_t GetNPacketFilters (void) const;
|
|
|
|
/**
|
|
* \brief Add a queue disc class to the tail of the list of classes.
|
|
* \param qdClass the queue disc class to be added
|
|
*/
|
|
void AddQueueDiscClass (Ptr<QueueDiscClass> qdClass);
|
|
|
|
/**
|
|
* \brief Get the i-th queue disc class
|
|
* \param i the index of the queue disc class
|
|
* \return the i-th queue disc class.
|
|
*/
|
|
Ptr<QueueDiscClass> GetQueueDiscClass (uint32_t i) const;
|
|
|
|
/**
|
|
* \brief Get the number of queue disc classes
|
|
* \return the number of queue disc classes.
|
|
*/
|
|
uint32_t GetNQueueDiscClasses (void) const;
|
|
|
|
/**
|
|
* Classify a packet by calling the packet filters, one at a time, until either
|
|
* a filter able to classify the packet is found or all the filters have been
|
|
* processed.
|
|
* \param item item to classify
|
|
* \return -1 if no filter able to classify the packet has been found, the value
|
|
* returned by first filter found to be able to classify the packet otherwise.
|
|
*/
|
|
int32_t Classify (Ptr<QueueDiscItem> item);
|
|
|
|
/**
|
|
* \enum WakeMode
|
|
* \brief Used to determine whether the queue disc itself or its children must
|
|
* be activated when a netdevice wakes a transmission queue
|
|
*/
|
|
enum WakeMode
|
|
{
|
|
WAKE_ROOT = 0x00,
|
|
WAKE_CHILD = 0x01
|
|
};
|
|
|
|
/**
|
|
* When setting up the wake callbacks on the netdevice queues, it is necessary to
|
|
* determine which queue disc (the root queue disc or one of its children) should
|
|
* be activated when the netdevice wakes one of its transmission queues. The
|
|
* implementation of this method for the base class returns WAKE_ROOT, i.e., the
|
|
* root queue disc is activated. Subclasses implementing queue discs adopting
|
|
* a different strategy (e.g., multi-queue aware queue discs such as mq) have
|
|
* to redefine this method.
|
|
*
|
|
* \return the wake mode adopted by this queue disc.
|
|
*/
|
|
virtual WakeMode GetWakeMode (void) const;
|
|
|
|
protected:
|
|
/**
|
|
* \brief Dispose of the object
|
|
*/
|
|
virtual void DoDispose (void);
|
|
|
|
/**
|
|
* \brief Check whether the configuration is correct and initialize parameters
|
|
*
|
|
* This method is not virtual to prevent subclasses from redefining it.
|
|
* Subclasses must instead provide the implementation of the CheckConfig
|
|
* and InitializeParams methods (which are called by this method).
|
|
*/
|
|
void DoInitialize (void);
|
|
|
|
/**
|
|
* \brief Perform the actions required when the queue disc is notified of
|
|
* a packet dropped before enqueue
|
|
* \param item item that was dropped
|
|
* This method must be called by subclasses to notify parent (this class) of a packet
|
|
* dropped before enqueue
|
|
*/
|
|
void DropBeforeEnqueue (Ptr<const QueueDiscItem> item);
|
|
|
|
/**
|
|
* \brief Perform the actions required when the queue disc is notified of
|
|
* a packet dropped after dequeue
|
|
* \param item item that was dropped
|
|
* This method must be called by subclasses to notify parent (this class) of a packet
|
|
* dropped after dequeue
|
|
*/
|
|
void DropAfterDequeue (Ptr<const QueueDiscItem> item);
|
|
|
|
private:
|
|
/**
|
|
* \brief Copy constructor
|
|
* \param o object to copy
|
|
*
|
|
* Defined and unimplemented to avoid misuse
|
|
*/
|
|
QueueDisc (const QueueDisc &o);
|
|
|
|
/**
|
|
* \brief Assignment operator
|
|
* \param o object to copy
|
|
* \returns the copied object
|
|
*
|
|
* Defined and unimplemented to avoid misuse
|
|
*/
|
|
QueueDisc &operator = (const QueueDisc &o);
|
|
|
|
/**
|
|
* This function actually enqueues a packet into the queue disc.
|
|
* \param item item to enqueue
|
|
* \return True if the operation was successful; false otherwise
|
|
*/
|
|
virtual bool DoEnqueue (Ptr<QueueDiscItem> item) = 0;
|
|
|
|
/**
|
|
* This function actually extracts a packet from the queue disc.
|
|
* \return 0 if the operation was not successful; the item otherwise.
|
|
*/
|
|
virtual Ptr<QueueDiscItem> DoDequeue (void) = 0;
|
|
|
|
/**
|
|
* This function returns a copy of the next packet the queue disc will extract.
|
|
* \return 0 if the operation was not successful; the packet otherwise.
|
|
*/
|
|
virtual Ptr<const QueueDiscItem> DoPeek (void) const = 0;
|
|
|
|
/**
|
|
* Check whether the current configuration is correct. Default objects (such
|
|
* as internal queues) might be created by this method to ensure the
|
|
* configuration is correct.
|
|
* \return true if the configuration is correct, false otherwise
|
|
*/
|
|
virtual bool CheckConfig (void) = 0;
|
|
|
|
/**
|
|
* Initialize parameters (if any) before the first packet is enqueued.
|
|
*/
|
|
virtual void InitializeParams (void) = 0;
|
|
|
|
/**
|
|
* Modelled after the Linux function qdisc_run_begin (include/net/sch_generic.h).
|
|
* \return false if the qdisc is already running; otherwise, set the qdisc as running and return true.
|
|
*/
|
|
bool RunBegin (void);
|
|
|
|
/**
|
|
* Modelled after the Linux function qdisc_run_end (include/net/sch_generic.h).
|
|
* Set the qdisc as not running.
|
|
*/
|
|
void RunEnd (void);
|
|
|
|
/**
|
|
* Modelled after the Linux function qdisc_restart (net/sched/sch_generic.c)
|
|
* Dequeue a packet (by calling DequeuePacket) and send it to the device (by calling Transmit).
|
|
* \return true if a packet is successfully sent to the device.
|
|
*/
|
|
bool Restart (void);
|
|
|
|
/**
|
|
* Modelled after the Linux function dequeue_skb (net/sched/sch_generic.c)
|
|
* \return the requeued packet, if any, or the packet dequeued by the queue disc, otherwise.
|
|
*/
|
|
Ptr<QueueDiscItem> DequeuePacket (void);
|
|
|
|
/**
|
|
* Modelled after the Linux function dev_requeue_skb (net/sched/sch_generic.c)
|
|
* Requeues a packet whose transmission failed.
|
|
* \param item the packet to requeue
|
|
*/
|
|
void Requeue (Ptr<QueueDiscItem> item);
|
|
|
|
/**
|
|
* Modelled after the Linux function sch_direct_xmit (net/sched/sch_generic.c)
|
|
* Sends a packet to the device if the device queue is not stopped, and requeues
|
|
* it otherwise.
|
|
* \param item the packet to transmit
|
|
* \return true if the device queue is not stopped and the queue disc is not empty
|
|
*/
|
|
bool Transmit (Ptr<QueueDiscItem> item);
|
|
|
|
/**
|
|
* \brief Perform the actions required when the queue disc is notified of
|
|
* a packet enqueue
|
|
* \param item item that was enqueued
|
|
*/
|
|
void PacketEnqueued (Ptr<const QueueDiscItem> item);
|
|
|
|
/**
|
|
* \brief Perform the actions required when the queue disc is notified of
|
|
* a packet dequeue
|
|
* \param item item that was dequeued
|
|
*/
|
|
void PacketDequeued (Ptr<const QueueDiscItem> item);
|
|
|
|
static const uint32_t DEFAULT_QUOTA = 64; //!< Default quota (as in /proc/sys/net/core/dev_weight)
|
|
|
|
std::vector<Ptr<InternalQueue> > m_queues; //!< Internal queues
|
|
std::vector<Ptr<PacketFilter> > m_filters; //!< Packet filters
|
|
std::vector<Ptr<QueueDiscClass> > m_classes; //!< Classes
|
|
|
|
TracedValue<uint32_t> m_nPackets; //!< Number of packets in the queue
|
|
TracedValue<uint32_t> m_nBytes; //!< Number of bytes in the queue
|
|
|
|
Stats m_stats; //!< The collected statistics
|
|
uint32_t m_quota; //!< Maximum number of packets dequeued in a qdisc run
|
|
Ptr<NetDevice> m_device; //!< The NetDevice on which this queue discipline is installed
|
|
Ptr<NetDeviceQueueInterface> m_devQueueIface; //!< NetDevice queue interface
|
|
bool m_running; //!< The queue disc is performing multiple dequeue operations
|
|
Ptr<QueueDiscItem> m_requeued; //!< The last packet that failed to be transmitted
|
|
|
|
/// Traced callback: fired when a packet is enqueued
|
|
TracedCallback<Ptr<const QueueDiscItem> > m_traceEnqueue;
|
|
/// Traced callback: fired when a packet is dequeued
|
|
TracedCallback<Ptr<const QueueDiscItem> > m_traceDequeue;
|
|
/// Traced callback: fired when a packet is requeued
|
|
TracedCallback<Ptr<const QueueDiscItem> > m_traceRequeue;
|
|
/// Traced callback: fired when a packet is dropped
|
|
TracedCallback<Ptr<const QueueDiscItem> > m_traceDrop;
|
|
/// Traced callback: fired when a packet is dropped before enqueue
|
|
TracedCallback<Ptr<const QueueDiscItem> > m_traceDropBeforeEnqueue;
|
|
/// Traced callback: fired when a packet is dropped after dequeue
|
|
TracedCallback<Ptr<const QueueDiscItem> > m_traceDropAfterDequeue;
|
|
};
|
|
|
|
/**
|
|
* \brief Stream insertion operator.
|
|
*
|
|
* \param os the stream
|
|
* \param stats the queue disc statistics
|
|
* \returns a reference to the stream
|
|
*/
|
|
std::ostream& operator<< (std::ostream& os, const QueueDisc::Stats &stats);
|
|
|
|
} // namespace ns3
|
|
|
|
#endif /* QueueDisc */
|