A Discrete-Event Network Simulator
API
queue-disc.cc
Go to the documentation of this file.
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 #include "ns3/log.h"
21 #include "ns3/abort.h"
22 #include "ns3/uinteger.h"
23 #include "ns3/pointer.h"
24 #include "ns3/object-vector.h"
25 #include "ns3/packet.h"
26 #include "ns3/socket.h"
27 #include "ns3/unused.h"
28 #include "ns3/simulator.h"
29 #include "queue-disc.h"
30 #include <ns3/drop-tail-queue.h>
31 #include "ns3/net-device-queue-interface.h"
32 
33 namespace ns3 {
34 
35 NS_OBJECT_TEMPLATE_CLASS_DEFINE (Queue,QueueDiscItem);
36 NS_OBJECT_TEMPLATE_CLASS_DEFINE (DropTailQueue,QueueDiscItem);
37 
38 NS_LOG_COMPONENT_DEFINE ("QueueDisc");
39 
40 
41 NS_OBJECT_ENSURE_REGISTERED (QueueDiscClass);
42 
44 {
45  static TypeId tid = TypeId ("ns3::QueueDiscClass")
46  .SetParent<Object> ()
47  .SetGroupName ("TrafficControl")
48  .AddConstructor<QueueDiscClass> ()
49  .AddAttribute ("QueueDisc", "The queue disc attached to the class",
50  PointerValue (),
52  MakePointerChecker<QueueDisc> ())
53  ;
54  return tid;
55 }
56 
58 {
59  NS_LOG_FUNCTION (this);
60 }
61 
63 {
64  NS_LOG_FUNCTION (this);
65 }
66 
67 void
69 {
70  NS_LOG_FUNCTION (this);
71  m_queueDisc = 0;
73 }
74 
77 {
78  NS_LOG_FUNCTION (this);
79  return m_queueDisc;
80 }
81 
82 void
84 {
85  NS_LOG_FUNCTION (this);
86  NS_ABORT_MSG_IF (m_queueDisc, "Cannot set the queue disc on a class already having an attached queue disc");
87  m_queueDisc = qd;
88 }
89 
91  : nTotalReceivedPackets (0),
92  nTotalReceivedBytes (0),
93  nTotalSentPackets (0),
94  nTotalSentBytes (0),
95  nTotalEnqueuedPackets (0),
96  nTotalEnqueuedBytes (0),
97  nTotalDequeuedPackets (0),
98  nTotalDequeuedBytes (0),
99  nTotalDroppedPackets (0),
100  nTotalDroppedPacketsBeforeEnqueue (0),
101  nTotalDroppedPacketsAfterDequeue (0),
102  nTotalDroppedBytes (0),
103  nTotalDroppedBytesBeforeEnqueue (0),
104  nTotalDroppedBytesAfterDequeue (0),
105  nTotalRequeuedPackets (0),
106  nTotalRequeuedBytes (0),
107  nTotalMarkedPackets (0),
108  nTotalMarkedBytes (0)
109 {
110 }
111 
112 uint32_t
113 QueueDisc::Stats::GetNDroppedPackets (std::string reason) const
114 {
115  uint32_t count = 0;
116  auto it = nDroppedPacketsBeforeEnqueue.find (reason);
117 
118  if (it != nDroppedPacketsBeforeEnqueue.end ())
119  {
120  count += it->second;
121  }
122 
123  it = nDroppedPacketsAfterDequeue.find (reason);
124 
125  if (it != nDroppedPacketsAfterDequeue.end ())
126  {
127  count += it->second;
128  }
129 
130  return count;
131 }
132 
133 uint64_t
134 QueueDisc::Stats::GetNDroppedBytes (std::string reason) const
135 {
136  uint64_t count = 0;
137  auto it = nDroppedBytesBeforeEnqueue.find (reason);
138 
139  if (it != nDroppedBytesBeforeEnqueue.end ())
140  {
141  count += it->second;
142  }
143 
144  it = nDroppedBytesAfterDequeue.find (reason);
145 
146  if (it != nDroppedBytesAfterDequeue.end ())
147  {
148  count += it->second;
149  }
150 
151  return count;
152 }
153 
154 uint32_t
155 QueueDisc::Stats::GetNMarkedPackets (std::string reason) const
156 {
157  auto it = nMarkedPackets.find (reason);
158 
159  if (it != nMarkedPackets.end ())
160  {
161  return it->second;
162  }
163 
164  return 0;
165 }
166 
167 uint64_t
168 QueueDisc::Stats::GetNMarkedBytes (std::string reason) const
169 {
170  auto it = nMarkedBytes.find (reason);
171 
172  if (it != nMarkedBytes.end ())
173  {
174  return it->second;
175  }
176 
177  return 0;
178 }
179 
180 void
181 QueueDisc::Stats::Print (std::ostream &os) const
182 {
183  std::map<std::string, uint32_t>::const_iterator itp;
184  std::map<std::string, uint64_t>::const_iterator itb;
185 
186  os << std::endl << "Packets/Bytes received: "
187  << nTotalReceivedPackets << " / "
188  << nTotalReceivedBytes
189  << std::endl << "Packets/Bytes enqueued: "
190  << nTotalEnqueuedPackets << " / "
191  << nTotalEnqueuedBytes
192  << std::endl << "Packets/Bytes dequeued: "
193  << nTotalDequeuedPackets << " / "
194  << nTotalDequeuedBytes
195  << std::endl << "Packets/Bytes requeued: "
196  << nTotalRequeuedPackets << " / "
197  << nTotalRequeuedBytes
198  << std::endl << "Packets/Bytes dropped: "
199  << nTotalDroppedPackets << " / "
200  << nTotalDroppedBytes
201  << std::endl << "Packets/Bytes dropped before enqueue: "
202  << nTotalDroppedPacketsBeforeEnqueue << " / "
203  << nTotalDroppedBytesBeforeEnqueue;
204 
205  itp = nDroppedPacketsBeforeEnqueue.begin ();
206  itb = nDroppedBytesBeforeEnqueue.begin ();
207 
208  while (itp != nDroppedPacketsBeforeEnqueue.end () &&
209  itb != nDroppedBytesBeforeEnqueue.end ())
210  {
211  NS_ASSERT (itp->first.compare (itb->first) == 0);
212  os << std::endl << " " << itp->first << ": "
213  << itp->second << " / " << itb->second;
214  itp++;
215  itb++;
216  }
217 
218  os << std::endl << "Packets/Bytes dropped after dequeue: "
219  << nTotalDroppedPacketsAfterDequeue << " / "
220  << nTotalDroppedBytesAfterDequeue;
221 
222  itp = nDroppedPacketsAfterDequeue.begin ();
223  itb = nDroppedBytesAfterDequeue.begin ();
224 
225  while (itp != nDroppedPacketsAfterDequeue.end () &&
226  itb != nDroppedBytesAfterDequeue.end ())
227  {
228  NS_ASSERT (itp->first.compare (itb->first) == 0);
229  os << std::endl << " " << itp->first << ": "
230  << itp->second << " / " << itb->second;
231  itp++;
232  itb++;
233  }
234 
235  os << std::endl << "Packets/Bytes sent: "
236  << nTotalSentPackets << " / "
237  << nTotalSentBytes
238  << std::endl << "Packets/Bytes marked: "
239  << nTotalMarkedPackets << " / "
240  << nTotalMarkedBytes;
241 
242  itp = nMarkedPackets.begin ();
243  itb = nMarkedBytes.begin ();
244 
245  while (itp != nMarkedPackets.end () &&
246  itb != nMarkedBytes.end ())
247  {
248  NS_ASSERT (itp->first.compare (itb->first) == 0);
249  os << std::endl << " " << itp->first << ": "
250  << itp->second << " / " << itb->second;
251  itp++;
252  itb++;
253  }
254 
255  os << std::endl;
256 }
257 
258 std::ostream & operator << (std::ostream &os, const QueueDisc::Stats &stats)
259 {
260  stats.Print (os);
261  return os;
262 }
263 
265 
267 {
268  static TypeId tid = TypeId ("ns3::QueueDisc")
269  .SetParent<Object> ()
270  .SetGroupName ("TrafficControl")
271  .AddAttribute ("Quota", "The maximum number of packets dequeued in a qdisc run",
275  MakeUintegerChecker<uint32_t> ())
276  .AddAttribute ("InternalQueueList", "The list of internal queues.",
279  MakeObjectVectorChecker<InternalQueue> ())
280  .AddAttribute ("PacketFilterList", "The list of packet filters.",
283  MakeObjectVectorChecker<PacketFilter> ())
284  .AddAttribute ("QueueDiscClassList", "The list of queue disc classes.",
287  MakeObjectVectorChecker<QueueDiscClass> ())
288  .AddTraceSource ("Enqueue", "Enqueue a packet in the queue disc",
290  "ns3::QueueDiscItem::TracedCallback")
291  .AddTraceSource ("Dequeue", "Dequeue a packet from the queue disc",
293  "ns3::QueueDiscItem::TracedCallback")
294  .AddTraceSource ("Requeue", "Requeue a packet in the queue disc",
296  "ns3::QueueDiscItem::TracedCallback")
297  .AddTraceSource ("Drop", "Drop a packet stored in the queue disc",
299  "ns3::QueueDiscItem::TracedCallback")
300  .AddTraceSource ("DropBeforeEnqueue", "Drop a packet before enqueue",
302  "ns3::QueueDiscItem::TracedCallback")
303  .AddTraceSource ("DropAfterDequeue", "Drop a packet after dequeue",
305  "ns3::QueueDiscItem::TracedCallback")
306  .AddTraceSource ("Mark", "Mark a packet stored in the queue disc",
308  "ns3::QueueDiscItem::TracedCallback")
309  .AddTraceSource ("PacketsInQueue",
310  "Number of packets currently stored in the queue disc",
312  "ns3::TracedValueCallback::Uint32")
313  .AddTraceSource ("BytesInQueue",
314  "Number of bytes currently stored in the queue disc",
316  "ns3::TracedValueCallback::Uint32")
317  .AddTraceSource ("SojournTime",
318  "Sojourn time of the last packet dequeued from the queue disc",
320  "ns3::Time::TracedValueCallback")
321  ;
322  return tid;
323 }
324 
326  : m_nPackets (0),
327  m_nBytes (0),
328  m_sojourn (0),
329  m_running (false)
330 {
331  NS_LOG_FUNCTION (this);
332 
333  // These lambdas call the DropBeforeEnqueue or DropAfterDequeue methods of this
334  // QueueDisc object. Given that a callback to the operator() of these lambdas
335  // is connected to the DropBeforeEnqueue and DropAfterDequeue traces of the
336  // internal queues, the INTERNAL_QUEUE_DROP constant is passed as the reason
337  // why the packet is dropped.
339  {
340  return DropBeforeEnqueue (item, INTERNAL_QUEUE_DROP);
341  };
343  {
344  return DropAfterDequeue (item, INTERNAL_QUEUE_DROP);
345  };
346 
347  // These lambdas call the DropBeforeEnqueue or DropAfterDequeue methods of this
348  // QueueDisc object. Given that a callback to the operator() of these lambdas
349  // is connected to the DropBeforeEnqueue and DropAfterDequeue traces of the
350  // child queue discs, the concatenation of the CHILD_QUEUE_DISC_DROP constant
351  // and the second argument provided by such traces is passed as the reason why
352  // the packet is dropped.
353  m_childQueueDiscDbeFunctor = [this] (Ptr<const QueueDiscItem> item, const char* r)
354  {
355  return DropBeforeEnqueue (item,
356  m_childQueueDiscDropMsg.assign (CHILD_QUEUE_DISC_DROP).append (r).data ());
357  };
358  m_childQueueDiscDadFunctor = [this] (Ptr<const QueueDiscItem> item, const char* r)
359  {
360  return DropAfterDequeue (item,
361  m_childQueueDiscDropMsg.assign (CHILD_QUEUE_DISC_DROP).append (r).data ());
362  };
363 }
364 
366 {
367  NS_LOG_FUNCTION (this);
368 }
369 
370 void
372 {
373  NS_LOG_FUNCTION (this);
374  m_queues.clear ();
375  m_filters.clear ();
376  m_classes.clear ();
377  m_device = 0;
378  m_devQueueIface = 0;
379  m_requeued = 0;
381 }
382 
383 void
385 {
386  NS_LOG_FUNCTION (this);
387  // When adding a new interface, the traffic control aggregates
388  // a NetDeviceQueueInterface object to the netdevice
389  if (m_device)
390  {
392  }
393 
394  // Check the configuration and initialize the parameters of this queue disc
395  bool ok = CheckConfig ();
396  NS_ASSERT_MSG (ok, "The queue disc configuration is not correct");
397  NS_UNUSED (ok); // suppress compiler warning
398  InitializeParams ();
399 
400  // Check the configuration and initialize the parameters of the child queue discs
401  for (std::vector<Ptr<QueueDiscClass> >::iterator cl = m_classes.begin ();
402  cl != m_classes.end (); cl++)
403  {
404  (*cl)->GetQueueDisc ()->Initialize ();
405  }
406 
408 }
409 
410 const QueueDisc::Stats&
412 {
417 
418  // the total number of sent packets is only updated here to avoid to increase it
419  // after a dequeue and then having to decrease it if the packet is dropped after
420  // dequeue or requeued
425 
426  return m_stats;
427 }
428 
429 uint32_t
431 {
432  NS_LOG_FUNCTION (this);
433  return m_nPackets;
434 }
435 
436 uint32_t
438 {
439  NS_LOG_FUNCTION (this);
440  return m_nBytes;
441 }
442 
443 void
445 {
446  NS_LOG_FUNCTION (this << device);
447  m_device = device;
448 }
449 
452 {
453  NS_LOG_FUNCTION (this);
454  return m_device;
455 }
456 
457 void
458 QueueDisc::SetQuota (const uint32_t quota)
459 {
460  NS_LOG_FUNCTION (this << quota);
461  m_quota = quota;
462 }
463 
464 uint32_t
466 {
467  NS_LOG_FUNCTION (this);
468  return m_quota;
469 }
470 
471 void
473 {
474  NS_LOG_FUNCTION (this);
475 
476  // set various callbacks on the internal queue, so that the queue disc is
477  // notified of packets enqueued, dequeued or dropped by the internal queue
478  queue->TraceConnectWithoutContext ("Enqueue",
480  queue->TraceConnectWithoutContext ("Dequeue",
482  queue->TraceConnectWithoutContext ("DropBeforeEnqueue",
483  MakeCallback (&InternalQueueDropFunctor::operator(),
485  queue->TraceConnectWithoutContext ("DropAfterDequeue",
486  MakeCallback (&InternalQueueDropFunctor::operator(),
488  m_queues.push_back (queue);
489 }
490 
492 QueueDisc::GetInternalQueue (uint32_t i) const
493 {
494  NS_ASSERT (i < m_queues.size ());
495  return m_queues[i];
496 }
497 
498 uint32_t
500 {
501  return m_queues.size ();
502 }
503 
504 void
506 {
507  NS_LOG_FUNCTION (this);
508  m_filters.push_back (filter);
509 }
510 
512 QueueDisc::GetPacketFilter (uint32_t i) const
513 {
514  NS_ASSERT (i < m_filters.size ());
515  return m_filters[i];
516 }
517 
518 uint32_t
520 {
521  return m_filters.size ();
522 }
523 
524 void
526 {
527  NS_LOG_FUNCTION (this);
528  NS_ABORT_MSG_IF (qdClass->GetQueueDisc () == 0, "Cannot add a class with no attached queue disc");
529  // the child queue disc cannot be one with wake mode equal to WAKE_CHILD because
530  // such queue discs do not implement the enqueue/dequeue methods
531  NS_ABORT_MSG_IF (qdClass->GetQueueDisc ()->GetWakeMode () == WAKE_CHILD,
532  "A queue disc with WAKE_CHILD as wake mode can only be a root queue disc");
533 
534  // set the parent callbacks on the child queue disc, so that it can notify
535  // the parent queue disc of packets enqueued, dequeued or dropped
536  qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("Enqueue",
538  qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("Dequeue",
540  qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("DropBeforeEnqueue",
541  MakeCallback (&ChildQueueDiscDropFunctor::operator(),
543  qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("DropAfterDequeue",
544  MakeCallback (&ChildQueueDiscDropFunctor::operator(),
546  m_classes.push_back (qdClass);
547 }
548 
551 {
552  NS_ASSERT (i < m_classes.size ());
553  return m_classes[i];
554 }
555 
556 uint32_t
558 {
559  return m_classes.size ();
560 }
561 
562 int32_t
564 {
565  NS_LOG_FUNCTION (this << item);
566 
567  int32_t ret = PacketFilter::PF_NO_MATCH;
568  for (std::vector<Ptr<PacketFilter> >::iterator f = m_filters.begin ();
569  f != m_filters.end () && ret == PacketFilter::PF_NO_MATCH; f++)
570  {
571  ret = (*f)->Classify (item);
572  }
573  return ret;
574 }
575 
578 {
579  return WAKE_ROOT;
580 }
581 
582 void
584 {
585  m_nPackets++;
586  m_nBytes += item->GetSize ();
588  m_stats.nTotalEnqueuedBytes += item->GetSize ();
589 
590  NS_LOG_LOGIC ("m_traceEnqueue (p)");
591  m_traceEnqueue (item);
592 }
593 
594 void
596 {
597  m_nPackets--;
598  m_nBytes -= item->GetSize ();
600  m_stats.nTotalDequeuedBytes += item->GetSize ();
601 
602  m_sojourn = Simulator::Now () - item->GetTimeStamp ();
603 
604  NS_LOG_LOGIC ("m_traceDequeue (p)");
605  m_traceDequeue (item);
606 }
607 
608 void
610 {
611  NS_LOG_FUNCTION (this << item << reason);
612 
614  m_stats.nTotalDroppedBytes += item->GetSize ();
616  m_stats.nTotalDroppedBytesBeforeEnqueue += item->GetSize ();
617 
618  // update the number of packets dropped for the given reason
619  std::map<std::string, uint32_t>::iterator itp = m_stats.nDroppedPacketsBeforeEnqueue.find (reason);
620  if (itp != m_stats.nDroppedPacketsBeforeEnqueue.end ())
621  {
622  itp->second++;
623  }
624  else
625  {
627  }
628  // update the amount of bytes dropped for the given reason
629  std::map<std::string, uint64_t>::iterator itb = m_stats.nDroppedBytesBeforeEnqueue.find (reason);
630  if (itb != m_stats.nDroppedBytesBeforeEnqueue.end ())
631  {
632  itb->second += item->GetSize ();
633  }
634  else
635  {
636  m_stats.nDroppedBytesBeforeEnqueue[reason] = item->GetSize ();
637  }
638 
639  NS_LOG_DEBUG ("Total packets/bytes dropped before enqueue: "
642  NS_LOG_LOGIC ("m_traceDropBeforeEnqueue (p)");
643  m_traceDrop (item);
644  m_traceDropBeforeEnqueue (item, reason);
645 }
646 
647 void
649 {
650  NS_LOG_FUNCTION (this << item << reason);
651 
653  m_stats.nTotalDroppedBytes += item->GetSize ();
655  m_stats.nTotalDroppedBytesAfterDequeue += item->GetSize ();
656 
657  // update the number of packets dropped for the given reason
658  std::map<std::string, uint32_t>::iterator itp = m_stats.nDroppedPacketsAfterDequeue.find (reason);
659  if (itp != m_stats.nDroppedPacketsAfterDequeue.end ())
660  {
661  itp->second++;
662  }
663  else
664  {
666  }
667  // update the amount of bytes dropped for the given reason
668  std::map<std::string, uint64_t>::iterator itb = m_stats.nDroppedBytesAfterDequeue.find (reason);
669  if (itb != m_stats.nDroppedBytesAfterDequeue.end ())
670  {
671  itb->second += item->GetSize ();
672  }
673  else
674  {
675  m_stats.nDroppedBytesAfterDequeue[reason] = item->GetSize ();
676  }
677 
678  NS_LOG_DEBUG ("Total packets/bytes dropped after dequeue: "
681  NS_LOG_LOGIC ("m_traceDropAfterDequeue (p)");
682  m_traceDrop (item);
683  m_traceDropAfterDequeue (item, reason);
684 }
685 
686 bool
687 QueueDisc::Mark (Ptr<QueueDiscItem> item, const char* reason)
688 {
689  NS_LOG_FUNCTION (this << item << reason);
690 
691  bool retval = item->Mark ();
692 
693  if (!retval)
694  {
695  return false;
696  }
697 
699  m_stats.nTotalMarkedBytes += item->GetSize ();
700 
701  // update the number of packets marked for the given reason
702  std::map<std::string, uint32_t>::iterator itp = m_stats.nMarkedPackets.find (reason);
703  if (itp != m_stats.nMarkedPackets.end ())
704  {
705  itp->second++;
706  }
707  else
708  {
709  m_stats.nMarkedPackets[reason] = 1;
710  }
711  // update the amount of bytes marked for the given reason
712  std::map<std::string, uint64_t>::iterator itb = m_stats.nMarkedBytes.find (reason);
713  if (itb != m_stats.nMarkedBytes.end ())
714  {
715  itb->second += item->GetSize ();
716  }
717  else
718  {
719  m_stats.nMarkedBytes[reason] = item->GetSize ();
720  }
721 
722  NS_LOG_DEBUG ("Total packets/bytes marked: "
723  << m_stats.nTotalMarkedPackets << " / "
725  m_traceMark (item, reason);
726  return true;
727 }
728 
729 bool
731 {
732  NS_LOG_FUNCTION (this << item);
733 
735  m_stats.nTotalReceivedBytes += item->GetSize ();
736 
737  bool retval = DoEnqueue (item);
738 
739  if (retval)
740  {
741  item->SetTimeStamp (Simulator::Now ());
742  }
743 
744  // DoEnqueue may return false because:
745  // 1) the internal queue is full
746  // -> the DropBeforeEnqueue method of this queue disc is automatically called
747  // because QueueDisc::AddInternalQueue sets the trace callback
748  // 2) the child queue disc dropped the packet
749  // -> the DropBeforeEnqueue method of this queue disc is automatically called
750  // because QueueDisc::AddQueueDiscClass sets the trace callback
751  // 3) it dropped the packet
752  // -> DoEnqueue has to explicitly call DropBeforeEnqueue
753  // Thus, we do not have to call DropBeforeEnqueue here.
754 
755  // check that the received packet was either enqueued or dropped
760 
761  return retval;
762 }
763 
766 {
767  NS_LOG_FUNCTION (this);
768 
769  Ptr<QueueDiscItem> item = DoDequeue ();
770 
773 
774  return item;
775 }
776 
778 QueueDisc::Peek (void) const
779 {
780  NS_LOG_FUNCTION (this);
781  return DoPeek ();
782 }
783 
784 void
786 {
787  NS_LOG_FUNCTION (this);
788 
789  if (RunBegin ())
790  {
791  uint32_t quota = m_quota;
792  while (Restart ())
793  {
794  quota -= 1;
795  if (quota <= 0)
796  {
798  break;
799  }
800  }
801  RunEnd ();
802  }
803 }
804 
805 bool
807 {
808  NS_LOG_FUNCTION (this);
809  if (m_running)
810  {
811  return false;
812  }
813 
814  m_running = true;
815  return true;
816 }
817 
818 void
820 {
821  NS_LOG_FUNCTION (this);
822  m_running = false;
823 }
824 
825 bool
827 {
828  NS_LOG_FUNCTION (this);
830  if (item == 0)
831  {
832  NS_LOG_LOGIC ("No packet to send");
833  return false;
834  }
835 
836  return Transmit (item);
837 }
838 
841 {
842  NS_LOG_FUNCTION (this);
844  Ptr<QueueDiscItem> item;
845 
846  // First check if there is a requeued packet
847  if (m_requeued != 0)
848  {
849  // If the queue where the requeued packet is destined to is not stopped, return
850  // the requeued packet; otherwise, return an empty packet.
851  // If the device does not support flow control, the device queue is never stopped
852  if (!m_devQueueIface->GetTxQueue (m_requeued->GetTxQueueIndex ())->IsStopped ())
853  {
854  item = m_requeued;
855  m_requeued = 0;
856  }
857  }
858  else
859  {
860  // If the device is multi-queue (actually, Linux checks if the queue disc has
861  // multiple queues), ask the queue disc to dequeue a packet (a multi-queue aware
862  // queue disc should try not to dequeue a packet destined to a stopped queue).
863  // Otherwise, ask the queue disc to dequeue a packet only if the (unique) queue
864  // is not stopped.
865  if (m_devQueueIface->GetNTxQueues ()>1 || !m_devQueueIface->GetTxQueue (0)->IsStopped ())
866  {
867  item = Dequeue ();
868  // If the item is not null, add the header to the packet.
869  if (item != 0)
870  {
871  item->AddHeader ();
872  }
873  // Here, Linux tries bulk dequeues
874  }
875  }
876  return item;
877 }
878 
879 void
881 {
882  NS_LOG_FUNCTION (this << item);
883  m_requeued = item;
885 
887  m_stats.nTotalRequeuedBytes += item->GetSize ();
888 
889  NS_LOG_LOGIC ("m_traceRequeue (p)");
890  m_traceRequeue (item);
891 }
892 
893 bool
895 {
896  NS_LOG_FUNCTION (this << item);
898 
899  // if the device queue is stopped, requeue the packet and return false.
900  // Note that if the underlying device is tc-unaware, packets are never
901  // requeued because the queues of tc-unaware devices are never stopped
902  if (m_devQueueIface->GetTxQueue (item->GetTxQueueIndex ())->IsStopped ())
903  {
904  Requeue (item);
905  return false;
906  }
907 
908  // a single queue device makes no use of the priority tag
909  if (m_devQueueIface->GetNTxQueues () == 1)
910  {
911  SocketPriorityTag priorityTag;
912  item->GetPacket ()->RemovePacketTag (priorityTag);
913  }
914  m_device->Send (item->GetPacket (), item->GetAddress (), item->GetProtocol ());
915 
916  // the behavior here slightly diverges from Linux. In Linux, it is advised that
917  // the function called when a packet needs to be transmitted (ndo_start_xmit)
918  // should always return NETDEV_TX_OK, which means that the packet is consumed by
919  // the device driver and thus is not requeued. However, the ndo_start_xmit function
920  // of the device driver is allowed to return NETDEV_TX_BUSY (and hence the packet
921  // is requeued) when there is no room for the received packet in the device queue,
922  // despite the queue is not stopped. This case is considered as a corner case or
923  // an hard error, and should be avoided.
924  // Here, we do not handle such corner case and always assume that the packet is
925  // consumed by the netdevice. Thus, we ignore the value returned by Send and a
926  // packet sent to a netdevice is never requeued. The reason is that the semantics
927  // of the value returned by NetDevice::Send does not match that of the value
928  // returned by ndo_start_xmit.
929 
930  // if the queue disc is empty or the device queue is now stopped, return false so
931  // that the Run method does not attempt to dequeue other packets and exits
932  if (GetNPackets () == 0 || m_devQueueIface->GetTxQueue (item->GetTxQueueIndex ())->IsStopped ())
933  {
934  return false;
935  }
936 
937  return true;
938 }
939 
940 } // namespace ns3
uint32_t nTotalDequeuedPackets
Total dequeued packets.
Definition: queue-disc.h:170
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:155
TracedValue< Time > m_sojourn
Sojourn time of the latest dequeued packet.
Definition: queue-disc.h:582
Stats()
constructor
Definition: queue-disc.cc:90
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:353
uint32_t nTotalMarkedPackets
Total marked packets.
Definition: queue-disc.h:198
uint32_t GetNQueueDiscClasses(void) const
Get the number of queue disc classes.
Definition: queue-disc.cc:557
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
Ptr< QueueDiscItem > m_requeued
The last packet that failed to be transmitted.
Definition: queue-disc.h:589
std::map< std::string, uint32_t > nDroppedPacketsAfterDequeue
Packets dropped after dequeue, for each reason.
Definition: queue-disc.h:182
uint32_t nTotalDroppedPackets
Total dropped packets.
Definition: queue-disc.h:174
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:525
void DropBeforeEnqueue(Ptr< const QueueDiscItem > item, const char *reason)
Perform the actions required when the queue disc is notified of a packet dropped before enqueue...
Definition: queue-disc.cc:609
static const int PF_NO_MATCH
Standard value used by packet filters to indicate that no match was possible.
Definition: packet-filter.h:48
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
Definition: queue-disc.cc:730
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
virtual ~QueueDiscClass()
Definition: queue-disc.cc:62
virtual ~QueueDisc()
Definition: queue-disc.cc:365
uint32_t GetNBytes(void) const
Get the amount of bytes stored by the queue disc.
Definition: queue-disc.cc:437
uint32_t nTotalRequeuedPackets
Total requeued packets.
Definition: queue-disc.h:194
bool Mark(Ptr< QueueDiscItem > item, const char *reason)
Marks the given packet and, if successful, updates the counters associated with the given reason...
Definition: queue-disc.cc:687
Ptr< QueueDisc > m_queueDisc
Queue disc attached to this class.
Definition: queue-disc.h:78
virtual void DoDispose(void)
Dispose of the object.
Definition: queue-disc.cc:68
void SetQueueDisc(Ptr< QueueDisc > qd)
Set the queue disc attached to this class.
Definition: queue-disc.cc:83
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:81
ChildQueueDiscDropFunctor m_childQueueDiscDbeFunctor
Function object called when a child queue disc dropped a packet before enqueue.
Definition: queue-disc.h:617
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t nTotalSentPackets
Total sent packets – this value is not kept up to date, call GetStats first.
Definition: queue-disc.h:162
virtual Ptr< QueueDiscItem > DoDequeue(void)=0
This function actually extracts a packet from the queue disc.
TracedCallback< Ptr< const QueueDiscItem >, const char * > m_traceMark
Traced callback: fired when a packet is marked.
Definition: queue-disc.h:605
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
WakeMode
Used to determine whether the queue disc itself or its children must be activated when a netdevice wa...
Definition: queue-disc.h:402
TracedCallback< Ptr< const QueueDiscItem >, const char * > m_traceDropAfterDequeue
Traced callback: fired when a packet is dropped after dequeue.
Definition: queue-disc.h:603
uint32_t nTotalMarkedBytes
Total marked bytes.
Definition: queue-disc.h:202
uint32_t nTotalDroppedPacketsBeforeEnqueue
Total packets dropped before enqueue.
Definition: queue-disc.h:176
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Ptr< InternalQueue > GetInternalQueue(uint32_t i) const
Get the i-th internal queue.
Definition: queue-disc.cc:492
uint64_t GetNDroppedBytes(std::string reason) const
Get the amount of bytes dropped for the given reason.
Definition: queue-disc.cc:134
static constexpr const char * CHILD_QUEUE_DISC_DROP
Packet dropped by a child queue disc.
Definition: queue-disc.h:423
uint32_t GetNInternalQueues(void) const
Get the number of internal queues.
Definition: queue-disc.cc:499
void AddInternalQueue(Ptr< InternalQueue > queue)
Add an internal queue to the tail of the list of queues.
Definition: queue-disc.cc:472
uint64_t nTotalEnqueuedBytes
Total enqueued bytes.
Definition: queue-disc.h:168
void PacketEnqueued(Ptr< const QueueDiscItem > item)
Perform the actions required when the queue disc is notified of a packet enqueue. ...
Definition: queue-disc.cc:583
std::string m_childQueueDiscDropMsg
Reason why a packet was dropped by a child queue disc.
Definition: queue-disc.h:590
void DoInitialize(void)
Check whether the configuration is correct and initialize parameters.
Definition: queue-disc.cc:384
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: pointer.h:220
Ptr< NetDeviceQueueInterface > m_devQueueIface
NetDevice queue interface.
Definition: queue-disc.h:587
InternalQueueDropFunctor m_internalQueueDbeFunctor
Function object called when an internal queue dropped a packet before enqueue.
Definition: queue-disc.h:613
Hold an unsigned integer type.
Definition: uinteger.h:44
TracedCallback< Ptr< const QueueDiscItem > > m_traceDequeue
Traced callback: fired when a packet is dequeued.
Definition: queue-disc.h:595
indicates whether the socket has a priority set.
Definition: socket.h:1303
uint64_t nTotalSentBytes
Total sent bytes – this value is not kept up to date, call GetStats first.
Definition: queue-disc.h:164
void Run(void)
Modelled after the Linux function __qdisc_run (net/sched/sch_generic.c) Dequeues multiple packets...
Definition: queue-disc.cc:785
Ptr< PacketFilter > GetPacketFilter(uint32_t i) const
Get the i-th packet filter.
Definition: queue-disc.cc:512
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
virtual bool DoEnqueue(Ptr< QueueDiscItem > item)=0
This function actually enqueues a packet into the queue disc.
const Stats & GetStats(void)
Retrieve all the collected statistics.
Definition: queue-disc.cc:411
std::map< std::string, uint64_t > nDroppedBytesAfterDequeue
Bytes dropped after dequeue, for each reason.
Definition: queue-disc.h:192
bool Transmit(Ptr< QueueDiscItem > item)
Modelled after the Linux function sch_direct_xmit (net/sched/sch_generic.c) Sends a packet to the dev...
Definition: queue-disc.cc:894
Ptr< QueueDisc > GetQueueDisc(void) const
Get the queue disc attached to this class.
Definition: queue-disc.cc:76
uint64_t nTotalDroppedBytesBeforeEnqueue
Total bytes dropped before enqueue.
Definition: queue-disc.h:186
int32_t Classify(Ptr< QueueDiscItem > item)
Classify a packet by calling the packet filters, one at a time, until either a filter able to classif...
Definition: queue-disc.cc:563
Network device transmission queue interface.
virtual void DoDispose(void)
Dispose of the object.
Definition: queue-disc.cc:371
uint32_t GetNPacketFilters(void) const
Get the number of packet filters.
Definition: queue-disc.cc:519
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
Definition: queue-disc.cc:113
std::map< std::string, uint32_t > nMarkedPackets
Marked packets, for each reason.
Definition: queue-disc.h:200
virtual WakeMode GetWakeMode(void) const
When setting up the wake callbacks on the netdevice queues, it is necessary to determine which queue ...
Definition: queue-disc.cc:577
InternalQueueDropFunctor m_internalQueueDadFunctor
Function object called when an internal queue dropped a packet after dequeue.
Definition: queue-disc.h:615
QueueDiscClass is the base class for classes that are included in a queue disc.
Definition: queue-disc.h:48
static const uint32_t DEFAULT_QUOTA
Default quota (as in /proc/sys/net/core/dev_weight)
Definition: queue-disc.h:574
Ptr< QueueDiscItem > Dequeue(void)
Request the queue discipline to extract a packet.
Definition: queue-disc.cc:765
uint64_t nTotalRequeuedBytes
Total requeued bytes.
Definition: queue-disc.h:196
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:42
double f(double x, void *params)
Definition: 80211b.c:72
uint32_t nTotalDroppedPacketsAfterDequeue
Total packets dropped after dequeue.
Definition: queue-disc.h:180
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Hold objects of type Ptr.
Definition: pointer.h:36
uint32_t nTotalReceivedPackets
Total received packets.
Definition: queue-disc.h:158
TracedCallback< Ptr< const QueueDiscItem >, const char * > m_traceDropBeforeEnqueue
Traced callback: fired when a packet is dropped before enqueue.
Definition: queue-disc.h:601
uint32_t m_quota
Maximum number of packets dequeued in a qdisc run.
Definition: queue-disc.h:585
uint64_t GetNMarkedBytes(std::string reason) const
Get the amount of bytes marked for the given reason.
Definition: queue-disc.cc:168
void Print(std::ostream &os) const
Print the statistics.
Definition: queue-disc.cc:181
std::vector< Ptr< InternalQueue > > m_queues
Internal queues.
Definition: queue-disc.h:576
bool RunBegin(void)
Modelled after the Linux function qdisc_run_begin (include/net/sch_generic.h).
Definition: queue-disc.cc:806
TracedCallback< Ptr< const QueueDiscItem > > m_traceEnqueue
Traced callback: fired when a packet is enqueued.
Definition: queue-disc.h:593
bool m_running
The queue disc is performing multiple dequeue operations.
Definition: queue-disc.h:588
uint64_t nTotalReceivedBytes
Total received bytes.
Definition: queue-disc.h:160
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:249
virtual uint32_t GetQuota(void) const
Get the maximum number of dequeue operations following a packet enqueue.
Definition: queue-disc.cc:465
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
virtual bool CheckConfig(void)=0
Check whether the current configuration is correct.
TracedValue< uint32_t > m_nBytes
Number of bytes in the queue.
Definition: queue-disc.h:581
void Requeue(Ptr< QueueDiscItem > item)
Modelled after the Linux function dev_requeue_skb (net/sched/sch_generic.c) Requeues a packet whose t...
Definition: queue-disc.cc:880
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:90
TracedValue< uint32_t > m_nPackets
Number of packets in the queue.
Definition: queue-disc.h:580
void PacketDequeued(Ptr< const QueueDiscItem > item)
Perform the actions required when the queue disc is notified of a packet dequeue. ...
Definition: queue-disc.cc:595
std::vector< Ptr< PacketFilter > > m_filters
Packet filters.
Definition: queue-disc.h:577
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
uint64_t nTotalDequeuedBytes
Total dequeued bytes.
Definition: queue-disc.h:172
std::map< std::string, uint64_t > nDroppedBytesBeforeEnqueue
Bytes dropped before enqueue, for each reason.
Definition: queue-disc.h:188
uint64_t nTotalDroppedBytesAfterDequeue
Total bytes dropped after dequeue.
Definition: queue-disc.h:190
Ptr< NetDevice > m_device
The NetDevice on which this queue discipline is installed.
Definition: queue-disc.h:586
virtual void SetQuota(const uint32_t quota)
Set the maximum number of dequeue operations following a packet enqueue.
Definition: queue-disc.cc:458
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:269
ChildQueueDiscDropFunctor m_childQueueDiscDadFunctor
Function object called when a child queue disc dropped a packet after dequeue.
Definition: queue-disc.h:619
uint32_t nTotalEnqueuedPackets
Total enqueued packets.
Definition: queue-disc.h:166
void AddPacketFilter(Ptr< PacketFilter > filter)
Add a packet filter to the tail of the list of filters used to classify packets.
Definition: queue-disc.cc:505
void DropAfterDequeue(Ptr< const QueueDiscItem > item, const char *reason)
Perform the actions required when the queue disc is notified of a packet dropped after dequeue...
Definition: queue-disc.cc:648
Stats m_stats
The collected statistics.
Definition: queue-disc.h:584
uint64_t nTotalDroppedBytes
Total dropped bytes.
Definition: queue-disc.h:184
std::map< std::string, uint64_t > nMarkedBytes
Marked bytes, for each reason.
Definition: queue-disc.h:204
TracedCallback< Ptr< const QueueDiscItem > > m_traceDrop
Traced callback: fired when a packet is dropped.
Definition: queue-disc.h:599
virtual void InitializeParams(void)=0
Initialize parameters (if any) before the first packet is enqueued.
#define NS_OBJECT_TEMPLATE_CLASS_DEFINE(type, param)
Explicitly instantiate a template class and register the resulting instance with the TypeId system...
Definition: object-base.h:67
static TypeId GetTypeId(void)
Get the type ID.
Definition: queue-disc.cc:266
uint32_t GetNMarkedPackets(std::string reason) const
Get the number of packets marked for the given reason.
Definition: queue-disc.cc:155
A base class which provides memory management and object aggregation.
Definition: object.h:87
Container for a set of ns3::Object pointers.
virtual Ptr< const QueueDiscItem > DoPeek(void) const =0
This function returns a copy of the next packet the queue disc will extract.
bool Restart(void)
Modelled after the Linux function qdisc_restart (net/sched/sch_generic.c) Dequeue a packet (by callin...
Definition: queue-disc.cc:826
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:914
Ptr< QueueDiscItem > DequeuePacket(void)
Modelled after the Linux function dequeue_skb (net/sched/sch_generic.c)
Definition: queue-disc.cc:840
Ptr< NetDevice > GetNetDevice(void) const
Get the NetDevice on which this queue discipline is installed.
Definition: queue-disc.cc:451
static TypeId GetTypeId(void)
Get the type ID.
Definition: queue-disc.cc:43
TracedCallback< Ptr< const QueueDiscItem > > m_traceRequeue
Traced callback: fired when a packet is requeued.
Definition: queue-disc.h:597
Ptr< const QueueDiscItem > Peek(void) const
Get a copy of the next packet the queue discipline will extract, without actually extracting the pack...
Definition: queue-disc.cc:778
void SetNetDevice(Ptr< NetDevice > device)
Set the NetDevice on which this queue discipline is installed.
Definition: queue-disc.cc:444
Ptr< QueueDiscClass > GetQueueDiscClass(uint32_t i) const
Get the i-th queue disc class.
Definition: queue-disc.cc:550
static constexpr const char * INTERNAL_QUEUE_DROP
Packet dropped by an internal queue.
Definition: queue-disc.h:422
void RunEnd(void)
Modelled after the Linux function qdisc_run_end (include/net/sch_generic.h).
Definition: queue-disc.cc:819
std::vector< Ptr< QueueDiscClass > > m_classes
Classes.
Definition: queue-disc.h:578
uint32_t GetNPackets(void) const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:430
std::map< std::string, uint32_t > nDroppedPacketsBeforeEnqueue
Packets dropped before enqueue, for each reason.
Definition: queue-disc.h:178