/* -*- 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 #include "packet-filter.h" namespace ns3 { class QueueDisc; template 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 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 qd); protected: /** * \brief Dispose of the object */ virtual void DoDispose (void); private: Ptr 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 device); /** * \brief Get the NetDevice on which this queue discipline is installed * \return the NetDevice on which this queue discipline is installed. */ Ptr 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 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 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 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 InternalQueue; /** * \brief Add an internal queue to the tail of the list of queues. * \param queue the queue to be added */ void AddInternalQueue (Ptr queue); /** * \brief Get the i-th internal queue * \param i the index of the queue * \return the i-th internal queue. */ Ptr 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 filter); /** * \brief Get the i-th packet filter * \param i the index of the packet filter * \return the i-th packet filter. */ Ptr 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 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 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 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 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 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 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 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 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 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 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 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 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 item); static const uint32_t DEFAULT_QUOTA = 64; //!< Default quota (as in /proc/sys/net/core/dev_weight) std::vector > m_queues; //!< Internal queues std::vector > m_filters; //!< Packet filters std::vector > m_classes; //!< Classes TracedValue m_nPackets; //!< Number of packets in the queue TracedValue 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 m_device; //!< The NetDevice on which this queue discipline is installed Ptr m_devQueueIface; //!< NetDevice queue interface bool m_running; //!< The queue disc is performing multiple dequeue operations Ptr m_requeued; //!< The last packet that failed to be transmitted /// Traced callback: fired when a packet is enqueued TracedCallback > m_traceEnqueue; /// Traced callback: fired when a packet is dequeued TracedCallback > m_traceDequeue; /// Traced callback: fired when a packet is requeued TracedCallback > m_traceRequeue; /// Traced callback: fired when a packet is dropped TracedCallback > m_traceDrop; /// Traced callback: fired when a packet is dropped before enqueue TracedCallback > m_traceDropBeforeEnqueue; /// Traced callback: fired when a packet is dropped after dequeue TracedCallback > 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 */