1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007, 2014 University of Washington
4  *               2015 Universita' degli Studi di Napoli Federico II
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 
20 #ifndef QUEUE_DISC_H
21 #define QUEUE_DISC_H
22 
23 #include "ns3/object.h"
24 #include "ns3/traced-value.h"
25 #include "ns3/traced-callback.h"
26 #include "ns3/queue-item.h"
27 #include "ns3/queue-size.h"
28 #include <vector>
29 #include <map>
30 #include <functional>
31 #include <string>
32 #include "packet-filter.h"
33 
34 namespace ns3 {
35 
36 class QueueDisc;
37 template <typename Item> class Queue;
38 class NetDeviceQueueInterface;
39 
40 /**
41  * \ingroup traffic-control
42  *
43  * QueueDiscClass is the base class for classes that are included in a queue
44  * disc. It has a single attribute, QueueDisc, used to set the child queue disc
45  * attached to the class. Classful queue discs needing to set parameters for
46  * their classes can subclass QueueDiscClass and add the required parameters
47  * as attributes.
48  */
49 class QueueDiscClass : public Object {
50 public:
51   /**
52    * \brief Get the type ID.
53    * \return the object TypeId
54    */
55   static TypeId GetTypeId (void);
56 
57   QueueDiscClass ();
58   virtual ~QueueDiscClass ();
59 
60   /**
61    * \brief Get the queue disc attached to this class
62    * \return the queue disc attached to this class.
63    */
64   Ptr<QueueDisc> GetQueueDisc (void) const;
65 
66   /**
67    * \brief Set the queue disc attached to this class
68    * \param qd The queue disc to attach to this class
69    */
70   void SetQueueDisc (Ptr<QueueDisc> qd);
71 
72 protected:
73   /**
74    * \brief Dispose of the object
75    */
76   virtual void DoDispose (void);
77 
78 private:
79   Ptr<QueueDisc> m_queueDisc;        //!< Queue disc attached to this class
80 };
81 
82 /**
83  * \ingroup traffic-control
84  * \brief Enumeration of the available policies to handle the queue disc size.
85  *
86  * - SINGLE_INTERNAL_QUEUE is intended to handle the maxSize attribute
87  * of queue discs having a single internal queue. If no internal queue is
88  * yet attached to the queue disc, setting/getting this attribute involves
89  * setting/getting the member variable of the queue disc; otherwise, the
90  * corresponding attribute of the internal queue is set/get.
91  * - SINGLE_CHILD_QUEUE_DISC is intended to handle the maxSize attribute
92  * of queue discs having a single child queue disc. If no child queue disc is
93  * yet attached to the queue disc, setting/getting this attribute involves
94  * setting/getting the member variable of the queue disc; otherwise, the
95  * corresponding attribute of the child queue disc is set/get.
96  * - MULTIPLE_QUEUES is intended to handle the maxSize attribute of queue
97  * discs having multiple internal queues or child queue discs. Setting/getting
98  * this attribute always involves setting/getting the member variable of the
99  * queue disc. Queue discs should warn the user if a packet is dropped by an
100  * internal queue/child queue disc because of lack of space, while the queue
101  * disc limit is not exceeded.
102  */
103 enum QueueDiscSizePolicy
104 {
105   SINGLE_INTERNAL_QUEUE,       /**< Used by queue discs with single internal queue */
106   SINGLE_CHILD_QUEUE_DISC,     /**< Used by queue discs with single child queue disc */
107   MULTIPLE_QUEUES,             /**< Used by queue discs with multiple internal queues/child queue discs */
108   NO_LIMITS                    /**< Used by queue discs with unlimited size */
109 };
110 
111 
112 /**
113  * \ingroup traffic-control
114  *
115  * QueueDisc is an abstract base class providing the interface and implementing
116  * the operations common to all the queueing disciplines. Child classes
117  * need to implement the methods used to enqueue a packet (DoEnqueue),
118  * dequeue a single packet (DoDequeue), get a copy of the next packet
119  * to extract (DoPeek), check whether the current configuration is correct
120  * (CheckConfig).
121  *
122  * As in Linux, a queue disc may contain distinct elements:
123  * - queues, which actually store the packets waiting for transmission
124  * - classes, which allow to reserve a different treatment to different packets
125  * - filters, which determine the queue or class which a packet is destined to
126  *
127  * Notice that a child queue disc must be attached to every class and a packet
128  * filter is only able to classify packets of a single protocol. Also, while in Linux
129  * some queue discs (e.g., fq-codel) use an internal classifier and do not make use of
130  * packet filters, in ns-3 every queue disc including multiple queues or multiple classes
131  * needs an external filter to classify packets (this is to avoid having the traffic-control
132  * module depend on other modules such as internet).
133  *
134  * Queue disc configuration vary from queue disc to queue disc. A typical taxonomy divides
135  * queue discs in classful (i.e., support classes) and classless (i.e., do not support
136  * classes). More recently, after the appearance of multi-queue devices (such as Wifi),
137  * some multi-queue aware queue discs have been introduced. Multi-queue aware queue discs
138  * handle as many queues (or queue discs -- without using classes) as the number of
139  * transmission queues used by the device on which the queue disc is installed.
140  * An attempt is made, also, to enqueue each packet in the "same" queue both within the
141  * queue disc and within the device.
142  *
143  * The traffic control layer interacts with a queue disc in a simple manner: after
144  * requesting to enqueue a packet, the traffic control layer requests the qdisc to
145  * "run", i.e., to dequeue a set of packets, until a predefined number ("quota")
146  * of packets is dequeued or the netdevice stops the queue disc. A netdevice shall
147  * stop the queue disc when its transmission queue does not have room for another
148  * packet. Also, a netdevice shall wake the queue disc when it detects that there
149  * is room for another packet in its transmission queue, but the transmission queue
150  * is stopped. Waking a queue disc is equivalent to make it run.
151  *
152  * Every queue disc collects statistics about the total number of packets/bytes
153  * received from the upper layers (in case of root queue disc) or from the parent
154  * queue disc (in case of child queue disc), enqueued, dequeued, requeued, dropped,
155  * dropped before enqueue, dropped after dequeue, queued in the queue disc and
156  * sent to the netdevice or to the parent queue disc. Note that packets that are
157  * dequeued may be requeued, i.e., retained by the traffic control infrastructure,
158  * if the netdevice is not ready to receive them. Requeued packets are not part
159  * of the queue disc. The following identities hold:
160  * - dropped = dropped before enqueue + dropped after dequeue
161  * - received = dropped before enqueue + enqueued
162  * - queued = enqueued - dequeued
163  * - sent = dequeued - dropped after dequeue (- 1 if there is a requeued packet)
164  *
165  * Separate counters are also kept for each possible reason to drop a packet.
166  * When a packet is dropped by an internal queue, e.g., because the queue is full,
167  * the reason is "Dropped by internal queue". When a packet is dropped by a child
168  * queue disc, the reason is "(Dropped by child queue disc) " followed by the
169  * reason why the child queue disc dropped the packet.
170  *
171  * The QueueDisc base class provides the SojournTime trace source, which provides
172  * the sojourn time of every packet dequeued from a queue disc, including packets
173  * that are dropped or requeued after being dequeued. The sojourn time is taken
174  * when the packet is dequeued from the queue disc, hence it does not account for
175  * the additional time the packet is retained within the traffic control
176  * infrastructure in case it is requeued.
177  *
178  * The design and implementation of this class is heavily inspired by Linux.
179  * For more details, see the traffic-control model page.
180  */
181 class QueueDisc : public Object {
182 public:
183 
184   /// \brief Structure that keeps the queue disc statistics
185   struct Stats
186   {
187     /// Total received packets
188     uint32_t nTotalReceivedPackets;
189     /// Total received bytes
190     uint64_t nTotalReceivedBytes;
191     /// Total sent packets -- this value is not kept up to date, call GetStats first
192     uint32_t nTotalSentPackets;
193     /// Total sent bytes -- this value is not kept up to date, call GetStats first
194     uint64_t nTotalSentBytes;
195     /// Total enqueued packets
196     uint32_t nTotalEnqueuedPackets;
197     /// Total enqueued bytes
198     uint64_t nTotalEnqueuedBytes;
199     /// Total dequeued packets
200     uint32_t nTotalDequeuedPackets;
201     /// Total dequeued bytes
202     uint64_t nTotalDequeuedBytes;
203     /// Total dropped packets
204     uint32_t nTotalDroppedPackets;
205     /// Total packets dropped before enqueue
206     uint32_t nTotalDroppedPacketsBeforeEnqueue;
207     /// Packets dropped before enqueue, for each reason
208     std::map<std::string, uint32_t> nDroppedPacketsBeforeEnqueue;
209     /// Total packets dropped after dequeue
210     uint32_t nTotalDroppedPacketsAfterDequeue;
211     /// Packets dropped after dequeue, for each reason
212     std::map<std::string, uint32_t> nDroppedPacketsAfterDequeue;
213     /// Total dropped bytes
214     uint64_t nTotalDroppedBytes;
215     /// Total bytes dropped before enqueue
216     uint64_t nTotalDroppedBytesBeforeEnqueue;
217     /// Bytes dropped before enqueue, for each reason
218     std::map<std::string, uint64_t> nDroppedBytesBeforeEnqueue;
219     /// Total bytes dropped after dequeue
220     uint64_t nTotalDroppedBytesAfterDequeue;
221     /// Bytes dropped after dequeue, for each reason
222     std::map<std::string, uint64_t> nDroppedBytesAfterDequeue;
223     /// Total requeued packets
224     uint32_t nTotalRequeuedPackets;
225     /// Total requeued bytes
226     uint64_t nTotalRequeuedBytes;
227     /// Total marked packets
228     uint32_t nTotalMarkedPackets;
229     /// Marked packets, for each reason
230     std::map<std::string, uint32_t> nMarkedPackets;
231     /// Total marked bytes
232     uint32_t nTotalMarkedBytes;
233     /// Marked bytes, for each reason
234     std::map<std::string, uint64_t> nMarkedBytes;
235 
236     /// constructor
237     Stats ();
238 
239     /**
240      * \brief Get the number of packets dropped for the given reason
241      * \param reason the reason why packets were dropped
242      * \return the number of packets dropped for the given reason
243      */
244     uint32_t GetNDroppedPackets (std::string reason) const;
245     /**
246      * \brief Get the amount of bytes dropped for the given reason
247      * \param reason the reason why packets were dropped
248      * \return the amount of bytes dropped for the given reason
249      */
250     uint64_t GetNDroppedBytes (std::string reason) const;
251     /**
252      * \brief Get the number of packets marked for the given reason
253      * \param reason the reason why packets were marked
254      * \return the number of packets marked for the given reason
255      */
256     uint32_t GetNMarkedPackets (std::string reason) const;
257     /**
258      * \brief Get the amount of bytes marked for the given reason
259      * \param reason the reason why packets were marked
260      * \return the amount of bytes marked for the given reason
261      */
262     uint64_t GetNMarkedBytes (std::string reason) const;
263     /**
264      * \brief Print the statistics.
265      * \param os output stream in which the data should be printed.
266      */
267     void Print (std::ostream &os) const;
268   };
269 
270   /**
271    * \brief Get the type ID.
272    * \return the object TypeId
273    */
274   static TypeId GetTypeId (void);
275 
276   /**
277    * \brief Constructor
278    * \param policy the policy to handle the queue disc size
279    */
280   QueueDisc (QueueDiscSizePolicy policy = QueueDiscSizePolicy::SINGLE_INTERNAL_QUEUE);
281 
282   /**
283    * \brief Constructor
284    * \param policy the policy to handle the queue disc size
285    * \param unit The fixed operating mode of this queue disc
286    */
287   QueueDisc (QueueDiscSizePolicy policy, QueueSizeUnit unit);
288 
289   virtual ~QueueDisc ();
290 
291   /**
292    * \brief Get the number of packets stored by the queue disc
293    * \return the number of packets stored by the queue disc.
294    *
295    * The requeued packet, if any, is counted.
296    */
297   uint32_t GetNPackets (void) const;
298 
299   /**
300    * \brief Get the amount of bytes stored by the queue disc
301    * \return the amount of bytes stored by the queue disc.
302    *
303    * The requeued packet, if any, is counted.
304    */
305   uint32_t GetNBytes (void) const;
306 
307   /**
308    * \brief Get the maximum size of the queue disc.
309    *
310    * \returns the maximum size of the queue disc.
311    */
312   QueueSize GetMaxSize (void) const;
313 
314   /**
315    * \brief Set the maximum size of the queue disc.
316    *
317    * Trying to set a null size has no effect.
318    *
319    * \param size the maximum size.
320    * \returns true if setting the size succeeded, false otherwise.
321    */
322   bool SetMaxSize (QueueSize size);
323 
324   /**
325    * \brief Get the current size of the queue disc in bytes, if
326    *        operating in bytes mode, or packets, otherwise.
327    *
328    * Do not call this method if the queue disc size is not limited.
329    *
330    * \returns The queue disc size in bytes or packets.
331    */
332   QueueSize GetCurrentSize (void);
333 
334   /**
335    * \brief Retrieve all the collected statistics.
336    * \return the collected statistics.
337    */
338   const Stats& GetStats (void);
339 
340   /**
341    * \param ndqi the NetDeviceQueueInterface aggregated to the receiving object.
342    *
343    * Set the pointer to the NetDeviceQueueInterface object aggregated to the
344    * object receiving the packets dequeued from this queue disc.
345    */
346   void SetNetDeviceQueueInterface (Ptr<NetDeviceQueueInterface> ndqi);
347 
348   /**
349    * \return the NetDeviceQueueInterface aggregated to the receiving object.
350    *
351    * Get the pointer to the NetDeviceQueueInterface object aggregated to the
352    * object receiving the packets dequeued from this queue disc.
353    */
354   Ptr<NetDeviceQueueInterface> GetNetDeviceQueueInterface (void) const;
355 
356   /// Callback invoked to send a packet to the receiving object when Run is called
357   typedef std::function<void (Ptr<QueueDiscItem>)> SendCallback;
358 
359   /**
360    * \param func the callback to send a packet to the receiving object.
361    *
362    * Set the callback used by the Transmit method (called eventually by the Run
363    * method) to send a packet to the receiving object.
364    */
365   void SetSendCallback (SendCallback func);
366 
367   /**
368    * \return the callback to send a packet to the receiving object.
369    *
370    * Get the callback used by the Transmit method (called eventually by the Run
371    * method) to send a packet to the receiving object.
372    */
373   SendCallback GetSendCallback (void) const;
374 
375   /**
376    * \brief Set the maximum number of dequeue operations following a packet enqueue
377    * \param quota the maximum number of dequeue operations following a packet enqueue.
378    */
379   virtual void SetQuota (const uint32_t quota);
380 
381   /**
382    * \brief Get the maximum number of dequeue operations following a packet enqueue
383    * \return the maximum number of dequeue operations following a packet enqueue.
384    */
385   virtual uint32_t GetQuota (void) const;
386 
387   /**
388    * Pass a packet to store to the queue discipline. This function only updates
389    * the statistics and calls the (private) DoEnqueue function, which must be
390    * implemented by derived classes.
391    * \param item item to enqueue
392    * \return True if the operation was successful; false otherwise
393    */
394   bool Enqueue (Ptr<QueueDiscItem> item);
395 
396   /**
397    * Extract from the queue disc the packet that has been dequeued by calling
398    * Peek, if any, or call the private DoDequeue method (which must be
399    * implemented by derived classes) to dequeue a packet, otherwise.
400    *
401    * \return 0 if the operation was not successful; the item otherwise.
402    */
403   Ptr<QueueDiscItem> Dequeue (void);
404 
405   /**
406    * Get a copy of the next packet the queue discipline will extract. This
407    * function only calls the (private) DoPeek function. This base class provides
408    * a default implementation of DoPeek, which dequeues the next packet but
409    * retains it into the queue disc.
410    * \return 0 if the operation was not successful; the item otherwise.
411    */
412   Ptr<const QueueDiscItem> Peek (void);
413 
414   /**
415    * Modelled after the Linux function __qdisc_run (net/sched/sch_generic.c)
416    * Dequeues multiple packets, until a quota is exceeded or sending a packet
417    * to the device failed.
418    */
419   void Run (void);
420 
421   /// Internal queues store QueueDiscItem objects
422   typedef Queue<QueueDiscItem> InternalQueue;
423 
424   /**
425    * \brief Add an internal queue to the tail of the list of queues.
426    * \param queue the queue to be added
427    */
428   void AddInternalQueue (Ptr<InternalQueue> queue);
429 
430   /**
431    * \brief Get the i-th internal queue
432    * \param i the index of the queue
433    * \return the i-th internal queue.
434    */
435   Ptr<InternalQueue> GetInternalQueue (std::size_t i) const;
436 
437   /**
438    * \brief Get the number of internal queues
439    * \return the number of internal queues.
440    */
441   std::size_t GetNInternalQueues (void) const;
442 
443   /**
444    * \brief Add a packet filter to the tail of the list of filters used to classify packets.
445    * \param filter the packet filter to be added
446    */
447   void AddPacketFilter (Ptr<PacketFilter> filter);
448 
449   /**
450    * \brief Get the i-th packet filter
451    * \param i the index of the packet filter
452    * \return the i-th packet filter.
453    */
454   Ptr<PacketFilter> GetPacketFilter (std::size_t i) const;
455 
456   /**
457    * \brief Get the number of packet filters
458    * \return the number of packet filters.
459    */
460   std::size_t GetNPacketFilters (void) const;
461 
462   /**
463    * \brief Add a queue disc class to the tail of the list of classes.
464    * \param qdClass the queue disc class to be added
465    */
466   void AddQueueDiscClass (Ptr<QueueDiscClass> qdClass);
467 
468   /**
469    * \brief Get the i-th queue disc class
470    * \param i the index of the queue disc class
471    * \return the i-th queue disc class.
472    */
473   Ptr<QueueDiscClass> GetQueueDiscClass (std::size_t i) const;
474 
475   /**
476    * \brief Get the number of queue disc classes
477    * \return the number of queue disc classes.
478    */
479   std::size_t GetNQueueDiscClasses (void) const;
480 
481   /**
482    * Classify a packet by calling the packet filters, one at a time, until either
483    * a filter able to classify the packet is found or all the filters have been
484    * processed.
485    * \param item item to classify
486    * \return -1 if no filter able to classify the packet has been found, the value
487    * returned by first filter found to be able to classify the packet otherwise.
488    */
489   int32_t Classify (Ptr<QueueDiscItem> item);
490 
491   /**
492    * \enum WakeMode
493    * \brief Used to determine whether the queue disc itself or its children must
494    *        be activated when a netdevice wakes a transmission queue
495    */
496   enum WakeMode
497     {
498       WAKE_ROOT = 0x00,
499       WAKE_CHILD = 0x01
500     };
501 
502   /**
503    * When setting up the wake callbacks on the netdevice queues, it is necessary to
504    * determine which queue disc (the root queue disc or one of its children) should
505    * be activated when the netdevice wakes one of its transmission queues. The
506    * implementation of this method for the base class returns WAKE_ROOT, i.e., the
507    * root queue disc is activated. Subclasses implementing queue discs adopting
508    * a different strategy (e.g., multi-queue aware queue discs such as mq) have
509    * to redefine this method.
510    *
511    * \return the wake mode adopted by this queue disc.
512    */
513   virtual WakeMode GetWakeMode (void) const;
514 
515   // Reasons for dropping packets
516   static constexpr const char* INTERNAL_QUEUE_DROP = "Dropped by internal queue";    //!< Packet dropped by an internal queue
517   static constexpr const char* CHILD_QUEUE_DISC_DROP = "(Dropped by child queue disc) "; //!< Packet dropped by a child queue disc
518   static constexpr const char* CHILD_QUEUE_DISC_MARK = "(Marked by child queue disc) "; //!< Packet marked by a child queue disc
519 
520 protected:
521   /**
522    * \brief Dispose of the object
523    */
524   virtual void DoDispose (void);
525 
526   /**
527    * \brief Check whether the configuration is correct and initialize parameters
528    *
529    * This method is not virtual to prevent subclasses from redefining it.
530    * Subclasses must instead provide the implementation of the CheckConfig
531    * and InitializeParams methods (which are called by this method).
532    * \sa QueueDisc::InitializeParams
533    * \sa QueueDisc::CheckConfig
534    */
535   void DoInitialize (void);
536 
537   /**
538    *  \brief Perform the actions required when the queue disc is notified of
539    *         a packet dropped before enqueue
540    *  \param item item that was dropped
541    *  \param reason the reason why the item was dropped
542    *  This method must be called by subclasses to record that a packet was
543    *  dropped before enqueue for the specified reason
544    */
545   void DropBeforeEnqueue (Ptr<const QueueDiscItem> item, const char* reason);
546 
547   /**
548    *  \brief Perform the actions required when the queue disc is notified of
549    *         a packet dropped after dequeue
550    *  \param item item that was dropped
551    *  \param reason the reason why the item was dropped
552    *  This method must be called by subclasses to record that a packet was
553    *  dropped after dequeue for the specified reason
554    */
555   void DropAfterDequeue (Ptr<const QueueDiscItem> item, const char* reason);
556 
557   /**
558    *  \brief Marks the given packet and, if successful, updates the counters
559    *         associated with the given reason
560    *  \param item item that has to be marked
561    *  \param reason the reason why the item has to be marked
562    *  \return true if the item was successfully marked, false otherwise
563    */
564   bool Mark (Ptr<QueueDiscItem> item, const char* reason);
565 
566 private:
567   /**
568    * \brief Copy constructor
569    * \param o object to copy
570    *
571    * Defined and unimplemented to avoid misuse
572    */
573   QueueDisc (const QueueDisc &o);
574 
575   /**
576    * \brief Assignment operator
577    * \param o object to copy
578    * \returns the copied object
579    *
580    * Defined and unimplemented to avoid misuse
581    */
582   QueueDisc &operator = (const QueueDisc &o);
583 
584   /**
585    * This function actually enqueues a packet into the queue disc.
586    * \param item item to enqueue
587    * \return True if the operation was successful; false otherwise
588    */
589   virtual bool DoEnqueue (Ptr<QueueDiscItem> item) = 0;
590 
591   /**
592    * This function actually extracts a packet from the queue disc.
593    * \return 0 if the operation was not successful; the item otherwise.
594    */
595   virtual Ptr<QueueDiscItem> DoDequeue (void) = 0;
596 
597   /**
598    * \brief Return a copy of the next packet the queue disc will extract.
599    *
600    * The implementation of this method is based on the qdisc_peek_dequeued
601    * function of the Linux kernel, which dequeues a packet and retains it in the
602    * queue disc as a requeued packet. The packet is not traced as requeued, nor
603    * is the total count of requeued packets increased. The packet is still
604    * considered to be part of the queue disc and the dequeue trace is fired
605    * when Dequeue is called and the packet is actually extracted from the
606    * queue disc.
607    *
608    * This approach is especially recommended for queue discs for which it is not
609    * obvious what is the next packet that will be dequeued (e.g., queue discs
610    * having multiple internal queues or child queue discs or queue discs that
611    * drop packets after dequeue). Subclasses can however provide their own
612    * implementation of this method that overrides the default one.
613    *
614    * \return 0 if the operation was not successful; the packet otherwise.
615    */
616   virtual Ptr<const QueueDiscItem> DoPeek (void);
617 
618   /**
619    * Check whether the current configuration is correct. Default objects (such
620    * as internal queues) might be created by this method to ensure the
621    * configuration is correct.  This method is automatically called at
622    * simulation initialization time, and it is called before
623    * the InitializeParams () method.  It is appropriate to promote parameter
624    * initialization to this method if it aids in checking for correct
625    * configuration.
626    * \sa QueueDisc::InitializeParams
627    * \return true if the configuration is correct, false otherwise
628    */
629   virtual bool CheckConfig (void) = 0;
630 
631   /**
632    * Initialize parameters (if any) before the first packet is enqueued.
633    * This method is automatically called at simulation initialization time,
634    * after the CheckConfig() method has been called.
635    * \sa QueueDisc::CheckConfig
636    */
637   virtual void InitializeParams (void) = 0;
638 
639   /**
640    * Modelled after the Linux function qdisc_run_begin (include/net/sch_generic.h).
641    * \return false if the qdisc is already running; otherwise, set the qdisc as running and return true.
642    */
643   bool RunBegin (void);
644 
645   /**
646    * Modelled after the Linux function qdisc_run_end (include/net/sch_generic.h).
647    * Set the qdisc as not running.
648    */
649   void RunEnd (void);
650 
651   /**
652    * Modelled after the Linux function qdisc_restart (net/sched/sch_generic.c)
653    * Dequeue a packet (by calling DequeuePacket) and send it to the device (by calling Transmit).
654    * \return true if a packet is successfully sent to the device.
655    */
656   bool Restart (void);
657 
658   /**
659    * Modelled after the Linux function dequeue_skb (net/sched/sch_generic.c)
660    * \return the requeued packet, if any, or the packet dequeued by the queue disc, otherwise.
661    */
662   Ptr<QueueDiscItem> DequeuePacket (void);
663 
664   /**
665    * Modelled after the Linux function dev_requeue_skb (net/sched/sch_generic.c)
666    * Requeues a packet whose transmission failed.
667    * \param item the packet to requeue
668    */
669   void Requeue (Ptr<QueueDiscItem> item);
670 
671   /**
672    * Modelled after the Linux function sch_direct_xmit (net/sched/sch_generic.c)
673    * Sends a packet to the device if the device queue is not stopped, and requeues
674    * it otherwise.
675    * \param item the packet to transmit
676    * \return true if the device queue is not stopped and the queue disc is not empty
677    */
678   bool Transmit (Ptr<QueueDiscItem> item);
679 
680   /**
681    *  \brief Perform the actions required when the queue disc is notified of
682    *         a packet enqueue
683    *  \param item item that was enqueued
684    */
685   void PacketEnqueued (Ptr<const QueueDiscItem> item);
686 
687   /**
688    *  \brief Perform the actions required when the queue disc is notified of
689    *         a packet dequeue
690    *  \param item item that was dequeued
691    */
692   void PacketDequeued (Ptr<const QueueDiscItem> item);
693 
694   static const uint32_t DEFAULT_QUOTA = 64; //!< Default quota (as in /proc/sys/net/core/dev_weight)
695 
696   std::vector<Ptr<InternalQueue> > m_queues;    //!< Internal queues
697   std::vector<Ptr<PacketFilter> > m_filters;    //!< Packet filters
698   std::vector<Ptr<QueueDiscClass> > m_classes;  //!< Classes
699 
700   TracedValue<uint32_t> m_nPackets; //!< Number of packets in the queue
701   TracedValue<uint32_t> m_nBytes;   //!< Number of bytes in the queue
702   TracedCallback<Time> m_sojourn;   //!< Sojourn time of the latest dequeued packet
703   QueueSize m_maxSize;              //!< max queue size
704 
705   Stats m_stats;                    //!< The collected statistics
706   uint32_t m_quota;                 //!< Maximum number of packets dequeued in a qdisc run
707   Ptr<NetDeviceQueueInterface> m_devQueueIface;   //!< NetDevice queue interface
708   SendCallback m_send;              //!< Callback used to send a packet to the receiving object
709   bool m_running;                   //!< The queue disc is performing multiple dequeue operations
710   Ptr<QueueDiscItem> m_requeued;    //!< The last packet that failed to be transmitted
711   bool m_peeked;                    //!< A packet was dequeued because Peek was called
712   std::string m_childQueueDiscDropMsg;  //!< Reason why a packet was dropped by a child queue disc
713   std::string m_childQueueDiscMarkMsg;  //!< Reason why a packet was marked by a child queue disc
714   QueueDiscSizePolicy m_sizePolicy;     //!< The queue disc size policy
715   bool m_prohibitChangeMode;            //!< True if changing mode is prohibited
716 
717   /// Traced callback: fired when a packet is enqueued
718   TracedCallback<Ptr<const QueueDiscItem> > m_traceEnqueue;
719   /// Traced callback: fired when a packet is dequeued
720   TracedCallback<Ptr<const QueueDiscItem> > m_traceDequeue;
721   /// Traced callback: fired when a packet is requeued
722   TracedCallback<Ptr<const QueueDiscItem> > m_traceRequeue;
723   /// Traced callback: fired when a packet is dropped
724   TracedCallback<Ptr<const QueueDiscItem> > m_traceDrop;
725   /// Traced callback: fired when a packet is dropped before enqueue
726   TracedCallback<Ptr<const QueueDiscItem>, const char* > m_traceDropBeforeEnqueue;
727   /// Traced callback: fired when a packet is dropped after dequeue
728   TracedCallback<Ptr<const QueueDiscItem>, const char* > m_traceDropAfterDequeue;
729   /// Traced callback: fired when a packet is marked
730   TracedCallback<Ptr<const QueueDiscItem>, const char* > m_traceMark;
731 
732   /// Type for the function objects notifying that a packet has been dropped by an internal queue
733   typedef std::function<void (Ptr<const QueueDiscItem>)> InternalQueueDropFunctor;
734   /// Type for the function objects notifying that a packet has been dropped by a child queue disc
735   typedef std::function<void (Ptr<const QueueDiscItem>, const char*)> ChildQueueDiscDropFunctor;
736   /// Type for the function objects notifying that a packet has been marked by a child queue disc
737   typedef std::function<void (Ptr<const QueueDiscItem>, const char*)> ChildQueueDiscMarkFunctor;
738 
739   /// Function object called when an internal queue dropped a packet before enqueue
740   InternalQueueDropFunctor m_internalQueueDbeFunctor;
741   /// Function object called when an internal queue dropped a packet after dequeue
742   InternalQueueDropFunctor m_internalQueueDadFunctor;
743   /// Function object called when a child queue disc dropped a packet before enqueue
744   ChildQueueDiscDropFunctor m_childQueueDiscDbeFunctor;
745   /// Function object called when a child queue disc dropped a packet after dequeue
746   ChildQueueDiscDropFunctor m_childQueueDiscDadFunctor;
747   /// Function object called when a child queue disc marked a packet
748   ChildQueueDiscMarkFunctor m_childQueueDiscMarkFunctor;
749 };
750 
751 /**
752  * \brief Stream insertion operator.
753  *
754  * \param os the stream
755  * \param stats the queue disc statistics
756  * \returns a reference to the stream
757  */
758 std::ostream& operator<< (std::ostream& os, const QueueDisc::Stats &stats);
759 
760 } // namespace ns3
761 
762 #endif /* QueueDisc */
763