A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
queue-disc.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007, 2014 University of Washington
3 * 2015 Universita' degli Studi di Napoli Federico II
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 */
7
8#include "queue-disc.h"
9
10#include "ns3/abort.h"
11#include "ns3/log.h"
12#include "ns3/net-device-queue-interface.h"
13#include "ns3/object-vector.h"
14#include "ns3/packet.h"
15#include "ns3/pointer.h"
16#include "ns3/queue.h"
17#include "ns3/simulator.h"
18#include "ns3/socket.h"
19#include "ns3/uinteger.h"
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("QueueDisc");
25
26NS_OBJECT_ENSURE_REGISTERED(QueueDiscClass);
27
28TypeId
30{
31 static TypeId tid = TypeId("ns3::QueueDiscClass")
33 .SetGroupName("TrafficControl")
34 .AddConstructor<QueueDiscClass>()
35 .AddAttribute("QueueDisc",
36 "The queue disc attached to the class",
40 return tid;
41}
42
47
52
53void
60
63{
64 NS_LOG_FUNCTION(this);
65 return m_queueDisc;
66}
67
68void
70{
71 NS_LOG_FUNCTION(this);
73 "Cannot set the queue disc on a class already having an attached queue disc");
74 m_queueDisc = qd;
75}
76
78 : nTotalReceivedPackets(0),
79 nTotalReceivedBytes(0),
80 nTotalSentPackets(0),
81 nTotalSentBytes(0),
82 nTotalEnqueuedPackets(0),
83 nTotalEnqueuedBytes(0),
84 nTotalDequeuedPackets(0),
85 nTotalDequeuedBytes(0),
86 nTotalDroppedPackets(0),
87 nTotalDroppedPacketsBeforeEnqueue(0),
88 nTotalDroppedPacketsAfterDequeue(0),
89 nTotalDroppedBytes(0),
90 nTotalDroppedBytesBeforeEnqueue(0),
91 nTotalDroppedBytesAfterDequeue(0),
92 nTotalRequeuedPackets(0),
93 nTotalRequeuedBytes(0),
94 nTotalMarkedPackets(0),
95 nTotalMarkedBytes(0)
96{
97}
98
101{
102 uint32_t count = 0;
103 auto it = nDroppedPacketsBeforeEnqueue.find(reason);
104
105 if (it != nDroppedPacketsBeforeEnqueue.end())
106 {
107 count += it->second;
108 }
109
110 it = nDroppedPacketsAfterDequeue.find(reason);
111
112 if (it != nDroppedPacketsAfterDequeue.end())
113 {
114 count += it->second;
115 }
116
117 return count;
118}
119
120uint64_t
121QueueDisc::Stats::GetNDroppedBytes(std::string reason) const
122{
123 uint64_t count = 0;
124 auto it = nDroppedBytesBeforeEnqueue.find(reason);
125
126 if (it != nDroppedBytesBeforeEnqueue.end())
127 {
128 count += it->second;
129 }
130
131 it = nDroppedBytesAfterDequeue.find(reason);
132
133 if (it != nDroppedBytesAfterDequeue.end())
134 {
135 count += it->second;
136 }
137
138 return count;
139}
140
142QueueDisc::Stats::GetNMarkedPackets(std::string reason) const
143{
144 auto it = nMarkedPackets.find(reason);
145
146 if (it != nMarkedPackets.end())
147 {
148 return it->second;
149 }
150
151 return 0;
152}
153
154uint64_t
155QueueDisc::Stats::GetNMarkedBytes(std::string reason) const
156{
157 auto it = nMarkedBytes.find(reason);
158
159 if (it != nMarkedBytes.end())
160 {
161 return it->second;
162 }
163
164 return 0;
165}
166
167void
168QueueDisc::Stats::Print(std::ostream& os) const
169{
170 os << std::endl
171 << "Packets/Bytes received: " << nTotalReceivedPackets << " / " << nTotalReceivedBytes
172 << std::endl
173 << "Packets/Bytes enqueued: " << nTotalEnqueuedPackets << " / " << nTotalEnqueuedBytes
174 << std::endl
175 << "Packets/Bytes dequeued: " << nTotalDequeuedPackets << " / " << nTotalDequeuedBytes
176 << std::endl
177 << "Packets/Bytes requeued: " << nTotalRequeuedPackets << " / " << nTotalRequeuedBytes
178 << std::endl
179 << "Packets/Bytes dropped: " << nTotalDroppedPackets << " / " << nTotalDroppedBytes
180 << std::endl
181 << "Packets/Bytes dropped before enqueue: " << nTotalDroppedPacketsBeforeEnqueue << " / "
182 << nTotalDroppedBytesBeforeEnqueue;
183
184 auto itp = nDroppedPacketsBeforeEnqueue.begin();
185 auto itb = nDroppedBytesBeforeEnqueue.begin();
186
187 while (itp != nDroppedPacketsBeforeEnqueue.end() && itb != nDroppedBytesBeforeEnqueue.end())
188 {
189 NS_ASSERT(itp->first == itb->first);
190 os << std::endl << " " << itp->first << ": " << itp->second << " / " << itb->second;
191 itp++;
192 itb++;
193 }
194
195 os << std::endl
196 << "Packets/Bytes dropped after dequeue: " << nTotalDroppedPacketsAfterDequeue << " / "
197 << nTotalDroppedBytesAfterDequeue;
198
199 itp = nDroppedPacketsAfterDequeue.begin();
200 itb = nDroppedBytesAfterDequeue.begin();
201
202 while (itp != nDroppedPacketsAfterDequeue.end() && itb != nDroppedBytesAfterDequeue.end())
203 {
204 NS_ASSERT(itp->first == itb->first);
205 os << std::endl << " " << itp->first << ": " << itp->second << " / " << itb->second;
206 itp++;
207 itb++;
208 }
209
210 os << std::endl
211 << "Packets/Bytes sent: " << nTotalSentPackets << " / " << nTotalSentBytes << std::endl
212 << "Packets/Bytes marked: " << nTotalMarkedPackets << " / " << nTotalMarkedBytes;
213
214 itp = nMarkedPackets.begin();
215 itb = nMarkedBytes.begin();
216
217 while (itp != nMarkedPackets.end() && itb != nMarkedBytes.end())
218 {
219 NS_ASSERT(itp->first == itb->first);
220 os << std::endl << " " << itp->first << ": " << itp->second << " / " << itb->second;
221 itp++;
222 itb++;
223 }
224
225 os << std::endl;
226}
227
228std::ostream&
229operator<<(std::ostream& os, const QueueDisc::Stats& stats)
230{
231 stats.Print(os);
232 return os;
233}
234
236
237TypeId
239{
240 static TypeId tid =
241 TypeId("ns3::QueueDisc")
242 .SetParent<Object>()
243 .SetGroupName("TrafficControl")
244 .AddAttribute("Quota",
245 "The maximum number of packets dequeued in a qdisc run",
249 .AddAttribute("InternalQueueList",
250 "The list of internal queues.",
254 .AddAttribute("PacketFilterList",
255 "The list of packet filters.",
259 .AddAttribute("QueueDiscClassList",
260 "The list of queue disc classes.",
264 .AddTraceSource("Enqueue",
265 "Enqueue a packet in the queue disc",
267 "ns3::QueueDiscItem::TracedCallback")
268 .AddTraceSource("Dequeue",
269 "Dequeue a packet from the queue disc",
271 "ns3::QueueDiscItem::TracedCallback")
272 .AddTraceSource("Requeue",
273 "Requeue a packet in the queue disc",
275 "ns3::QueueDiscItem::TracedCallback")
276 .AddTraceSource("Drop",
277 "Drop a packet stored in the queue disc",
279 "ns3::QueueDiscItem::TracedCallback")
280 .AddTraceSource("DropBeforeEnqueue",
281 "Drop a packet before enqueue",
283 "ns3::QueueDiscItem::TracedCallback")
284 .AddTraceSource("DropAfterDequeue",
285 "Drop a packet after dequeue",
287 "ns3::QueueDiscItem::TracedCallback")
288 .AddTraceSource("Mark",
289 "Mark a packet stored in the queue disc",
291 "ns3::QueueDiscItem::TracedCallback")
292 .AddTraceSource("PacketsInQueue",
293 "Number of packets currently stored in the queue disc",
295 "ns3::TracedValueCallback::Uint32")
296 .AddTraceSource("BytesInQueue",
297 "Number of bytes currently stored in the queue disc",
299 "ns3::TracedValueCallback::Uint32")
300 .AddTraceSource("SojournTime",
301 "Sojourn time of the last packet dequeued from the queue disc",
303 "ns3::Time::TracedCallback");
304 return tid;
305}
306
308 : m_nPackets(0),
309 m_nBytes(0),
310 m_maxSize(QueueSize("1p")), // to avoid that setting the mode at construction time is ignored
311 m_running(false),
312 m_peeked(false),
313 m_sizePolicy(policy),
315{
316 NS_LOG_FUNCTION(this << (uint16_t)policy);
317
318 // These lambdas call the DropBeforeEnqueue or DropAfterDequeue methods of this
319 // QueueDisc object. Given that a callback to the operator() of these lambdas
320 // is connected to the DropBeforeEnqueue and DropAfterDequeue traces of the
321 // internal queues, the INTERNAL_QUEUE_DROP constant is passed as the reason
322 // why the packet is dropped.
325 };
328 };
329
330 // These lambdas call the DropBeforeEnqueue or DropAfterDequeue methods of this
331 // QueueDisc object. Given that a callback to the operator() of these lambdas
332 // is connected to the DropBeforeEnqueue and DropAfterDequeue traces of the
333 // child queue discs, the concatenation of the CHILD_QUEUE_DISC_DROP constant
334 // and the second argument provided by such traces is passed as the reason why
335 // the packet is dropped.
336 m_childQueueDiscDbeFunctor = [this](Ptr<const QueueDiscItem> item, const char* r) {
337 return DropBeforeEnqueue(
338 item,
339 m_childQueueDiscDropMsg.assign(CHILD_QUEUE_DISC_DROP).append(r).data());
340 };
341 m_childQueueDiscDadFunctor = [this](Ptr<const QueueDiscItem> item, const char* r) {
342 return DropAfterDequeue(
343 item,
344 m_childQueueDiscDropMsg.assign(CHILD_QUEUE_DISC_DROP).append(r).data());
345 };
346 m_childQueueDiscMarkFunctor = [this](Ptr<const QueueDiscItem> item, const char* r) {
347 return Mark(const_cast<QueueDiscItem*>(PeekPointer(item)),
348 m_childQueueDiscMarkMsg.assign(CHILD_QUEUE_DISC_MARK).append(r).data());
349 };
350}
351
353 : QueueDisc(policy)
354{
355 m_maxSize = QueueSize(unit, 0);
357}
358
363
364void
366{
367 NS_LOG_FUNCTION(this);
368 m_queues.clear();
369 m_filters.clear();
370 m_classes.clear();
371 m_devQueueIface = nullptr;
372 m_send = nullptr;
373 m_requeued = nullptr;
379}
380
381void
383{
384 NS_LOG_FUNCTION(this);
385
386 // Check the configuration and initialize the parameters of this queue disc
387 bool ok [[maybe_unused]] = CheckConfig();
388 NS_ASSERT_MSG(ok, "The queue disc configuration is not correct");
390
391 // Check the configuration and initialize the parameters of the child queue discs
392 for (auto cl = m_classes.begin(); cl != m_classes.end(); cl++)
393 {
394 (*cl)->GetQueueDisc()->Initialize();
395 }
396
398}
399
400const QueueDisc::Stats&
402{
407
408 // the total number of sent packets is only updated here to avoid to increase it
409 // after a dequeue and then having to decrease it if the packet is dropped after
410 // dequeue or requeued
414 (m_requeued ? m_requeued->GetSize() : 0) -
416
417 return m_stats;
418}
419
422{
423 NS_LOG_FUNCTION(this);
424 return m_nPackets;
425}
426
429{
430 NS_LOG_FUNCTION(this);
431 return m_nBytes;
432}
433
436{
437 NS_LOG_FUNCTION(this);
438
439 switch (m_sizePolicy)
440 {
442 NS_FATAL_ERROR("The size of this queue disc is not limited");
443
445 if (GetNInternalQueues())
446 {
447 return GetInternalQueue(0)->GetMaxSize();
448 }
449
452 {
453 return GetQueueDiscClass(0)->GetQueueDisc()->GetMaxSize();
454 }
455
457 default:
458 return m_maxSize;
459 }
460}
461
462bool
464{
465 NS_LOG_FUNCTION(this << size);
466
467 // do nothing if the limit is null
468 if (!size.GetValue())
469 {
470 return false;
471 }
472
474 {
475 NS_LOG_DEBUG("Changing the mode of this queue disc is prohibited");
476 return false;
477 }
478
479 switch (m_sizePolicy)
480 {
482 NS_FATAL_ERROR("The size of this queue disc is not limited");
483
485 if (GetNInternalQueues())
486 {
487 GetInternalQueue(0)->SetMaxSize(size);
488 }
489
492 {
493 GetQueueDiscClass(0)->GetQueueDisc()->SetMaxSize(size);
494 }
495
497 default:
498 m_maxSize = size;
499 }
500 return true;
501}
502
505{
506 NS_LOG_FUNCTION(this);
507
508 if (GetMaxSize().GetUnit() == QueueSizeUnit::PACKETS)
509 {
511 }
512 if (GetMaxSize().GetUnit() == QueueSizeUnit::BYTES)
513 {
515 }
516 NS_ABORT_MSG("Unknown queue size unit");
517}
518
519void
525
532
533void
535{
536 NS_LOG_FUNCTION(this);
537 m_send = func;
538}
539
542{
543 NS_LOG_FUNCTION(this);
544 return m_send;
545}
546
547void
549{
550 NS_LOG_FUNCTION(this << quota);
551 m_quota = quota;
552}
553
556{
557 NS_LOG_FUNCTION(this);
558 return m_quota;
559}
560
561void
563{
564 NS_LOG_FUNCTION(this);
565
566 // set various callbacks on the internal queue, so that the queue disc is
567 // notified of packets enqueued, dequeued or dropped by the internal queue
568 queue->TraceConnectWithoutContext("Enqueue", MakeCallback(&QueueDisc::PacketEnqueued, this));
569 queue->TraceConnectWithoutContext("Dequeue", MakeCallback(&QueueDisc::PacketDequeued, this));
570 queue->TraceConnectWithoutContext(
571 "DropBeforeEnqueue",
572 MakeCallback(&InternalQueueDropFunctor::operator(), &m_internalQueueDbeFunctor));
573 queue->TraceConnectWithoutContext(
574 "DropAfterDequeue",
575 MakeCallback(&InternalQueueDropFunctor::operator(), &m_internalQueueDadFunctor));
576 m_queues.push_back(queue);
577}
578
580QueueDisc::GetInternalQueue(std::size_t i) const
581{
582 NS_ASSERT(i < m_queues.size());
583 return m_queues[i];
584}
585
586std::size_t
588{
589 return m_queues.size();
590}
591
592void
594{
595 NS_LOG_FUNCTION(this);
596 m_filters.push_back(filter);
597}
598
600QueueDisc::GetPacketFilter(std::size_t i) const
601{
602 NS_ASSERT(i < m_filters.size());
603 return m_filters[i];
604}
605
606std::size_t
608{
609 return m_filters.size();
610}
611
612void
614{
615 NS_LOG_FUNCTION(this);
616 NS_ABORT_MSG_IF(!qdClass->GetQueueDisc(), "Cannot add a class with no attached queue disc");
617 // the child queue disc cannot be one with wake mode equal to WAKE_CHILD because
618 // such queue discs do not implement the enqueue/dequeue methods
619 NS_ABORT_MSG_IF(qdClass->GetQueueDisc()->GetWakeMode() == WAKE_CHILD,
620 "A queue disc with WAKE_CHILD as wake mode can only be a root queue disc");
621
622 // set the parent callbacks on the child queue disc, so that it can notify
623 // the parent queue disc of packets enqueued, dequeued, dropped, or marked
624 qdClass->GetQueueDisc()->TraceConnectWithoutContext(
625 "Enqueue",
627 qdClass->GetQueueDisc()->TraceConnectWithoutContext(
628 "Dequeue",
630 qdClass->GetQueueDisc()->TraceConnectWithoutContext(
631 "DropBeforeEnqueue",
632 MakeCallback(&ChildQueueDiscDropFunctor::operator(), &m_childQueueDiscDbeFunctor));
633 qdClass->GetQueueDisc()->TraceConnectWithoutContext(
634 "DropAfterDequeue",
635 MakeCallback(&ChildQueueDiscDropFunctor::operator(), &m_childQueueDiscDadFunctor));
636 qdClass->GetQueueDisc()->TraceConnectWithoutContext(
637 "Mark",
638 MakeCallback(&ChildQueueDiscMarkFunctor::operator(), &m_childQueueDiscMarkFunctor));
639 m_classes.push_back(qdClass);
640}
641
644{
645 NS_ASSERT(i < m_classes.size());
646 return m_classes[i];
647}
648
649std::size_t
651{
652 return m_classes.size();
653}
654
657{
658 NS_LOG_FUNCTION(this << item);
659
661 for (auto f = m_filters.begin(); f != m_filters.end() && ret == PacketFilter::PF_NO_MATCH; f++)
662 {
663 ret = (*f)->Classify(item);
664 }
665 return ret;
666}
667
670{
671 return WAKE_ROOT;
672}
673
674void
676{
677 m_nPackets++;
678 m_nBytes += item->GetSize();
680 m_stats.nTotalEnqueuedBytes += item->GetSize();
681
682 NS_LOG_LOGIC("m_traceEnqueue (p)");
683 m_traceEnqueue(item);
684}
685
686void
688{
689 // If the queue disc asked the internal queue or the child queue disc to
690 // dequeue a packet because a peek operation was requested, the packet is
691 // still held by the queue disc, hence we do not need to update statistics
692 // and fire the dequeue trace. This function will be explicitly called when
693 // the packet will be actually dequeued.
694 if (!m_peeked)
695 {
696 m_nPackets--;
697 m_nBytes -= item->GetSize();
699 m_stats.nTotalDequeuedBytes += item->GetSize();
700
701 m_sojourn(Simulator::Now() - item->GetTimeStamp());
702
703 NS_LOG_LOGIC("m_traceDequeue (p)");
704 m_traceDequeue(item);
705 }
706}
707
708void
710{
711 NS_LOG_FUNCTION(this << item << reason);
712
714 m_stats.nTotalDroppedBytes += item->GetSize();
716 m_stats.nTotalDroppedBytesBeforeEnqueue += item->GetSize();
717
718 // update the number of packets dropped for the given reason
719 auto itp = m_stats.nDroppedPacketsBeforeEnqueue.find(reason);
720 if (itp != m_stats.nDroppedPacketsBeforeEnqueue.end())
721 {
722 itp->second++;
723 }
724 else
725 {
727 }
728 // update the amount of bytes dropped for the given reason
729 auto itb = m_stats.nDroppedBytesBeforeEnqueue.find(reason);
730 if (itb != m_stats.nDroppedBytesBeforeEnqueue.end())
731 {
732 itb->second += item->GetSize();
733 }
734 else
735 {
736 m_stats.nDroppedBytesBeforeEnqueue[reason] = item->GetSize();
737 }
738
739 NS_LOG_DEBUG("Total packets/bytes dropped before enqueue: "
742 NS_LOG_LOGIC("m_traceDropBeforeEnqueue (p)");
743 m_traceDrop(item);
744 m_traceDropBeforeEnqueue(item, reason);
745}
746
747void
749{
750 NS_LOG_FUNCTION(this << item << reason);
751
753 m_stats.nTotalDroppedBytes += item->GetSize();
755 m_stats.nTotalDroppedBytesAfterDequeue += item->GetSize();
756
757 // update the number of packets dropped for the given reason
758 auto itp = m_stats.nDroppedPacketsAfterDequeue.find(reason);
759 if (itp != m_stats.nDroppedPacketsAfterDequeue.end())
760 {
761 itp->second++;
762 }
763 else
764 {
766 }
767 // update the amount of bytes dropped for the given reason
768 auto itb = m_stats.nDroppedBytesAfterDequeue.find(reason);
769 if (itb != m_stats.nDroppedBytesAfterDequeue.end())
770 {
771 itb->second += item->GetSize();
772 }
773 else
774 {
775 m_stats.nDroppedBytesAfterDequeue[reason] = item->GetSize();
776 }
777
778 // if in the context of a peek request a dequeued packet is dropped, we need
779 // to update the statistics and fire the dequeue trace before firing the drop
780 // after dequeue trace
781 if (m_peeked)
782 {
783 // temporarily set m_peeked to false, otherwise PacketDequeued does nothing
784 m_peeked = false;
785 PacketDequeued(item);
786 m_peeked = true;
787 }
788
789 NS_LOG_DEBUG("Total packets/bytes dropped after dequeue: "
792 NS_LOG_LOGIC("m_traceDropAfterDequeue (p)");
793 m_traceDrop(item);
794 m_traceDropAfterDequeue(item, reason);
795}
796
797bool
798QueueDisc::Mark(Ptr<QueueDiscItem> item, const char* reason)
799{
800 NS_LOG_FUNCTION(this << item << reason);
801
802 bool retval = item->Mark();
803
804 if (!retval)
805 {
806 return false;
807 }
808
810 m_stats.nTotalMarkedBytes += item->GetSize();
811
812 // update the number of packets marked for the given reason
813 auto itp = m_stats.nMarkedPackets.find(reason);
814 if (itp != m_stats.nMarkedPackets.end())
815 {
816 itp->second++;
817 }
818 else
819 {
820 m_stats.nMarkedPackets[reason] = 1;
821 }
822 // update the amount of bytes marked for the given reason
823 auto itb = m_stats.nMarkedBytes.find(reason);
824 if (itb != m_stats.nMarkedBytes.end())
825 {
826 itb->second += item->GetSize();
827 }
828 else
829 {
830 m_stats.nMarkedBytes[reason] = item->GetSize();
831 }
832
833 NS_LOG_DEBUG("Total packets/bytes marked: " << m_stats.nTotalMarkedPackets << " / "
835 m_traceMark(item, reason);
836 return true;
837}
838
839bool
841{
842 NS_LOG_FUNCTION(this << item);
843
845 m_stats.nTotalReceivedBytes += item->GetSize();
846
847 bool retval = DoEnqueue(item);
848
849 if (retval)
850 {
851 item->SetTimeStamp(Simulator::Now());
852 }
853
854 // DoEnqueue may return false because:
855 // 1) the internal queue is full
856 // -> the DropBeforeEnqueue method of this queue disc is automatically called
857 // because QueueDisc::AddInternalQueue sets the trace callback
858 // 2) the child queue disc dropped the packet
859 // -> the DropBeforeEnqueue method of this queue disc is automatically called
860 // because QueueDisc::AddQueueDiscClass sets the trace callback
861 // 3) it dropped the packet
862 // -> DoEnqueue has to explicitly call DropBeforeEnqueue
863 // Thus, we do not have to call DropBeforeEnqueue here.
864
865 // check that the received packet was either enqueued or dropped
870
871 return retval;
872}
873
876{
877 NS_LOG_FUNCTION(this);
878
879 // The QueueDisc::DoPeek method dequeues a packet and keeps it as a requeued
880 // packet. Thus, first check whether a peeked packet exists. Otherwise, call
881 // the private DoDequeue method.
883
884 if (item)
885 {
886 m_requeued = nullptr;
887 if (m_peeked)
888 {
889 // If the packet was requeued because a peek operation was requested
890 // (which is the case here because DequeuePacket calls Dequeue only
891 // when m_requeued is null), we need to explicitly call PacketDequeued
892 // to update statistics about dequeued packets and fire the dequeue trace.
893 m_peeked = false;
894 PacketDequeued(item);
895 }
896 }
897 else
898 {
899 item = DoDequeue();
900 }
901
904
905 return item;
906}
907
910{
911 NS_LOG_FUNCTION(this);
912 return DoPeek();
913}
914
917{
918 NS_LOG_FUNCTION(this);
919
920 if (!m_requeued)
921 {
922 m_peeked = true;
924 // if no packet is returned, reset the m_peeked flag
925 if (!m_requeued)
926 {
927 m_peeked = false;
928 }
929 }
930 return m_requeued;
931}
932
933void
935{
936 NS_LOG_FUNCTION(this);
937
938 if (RunBegin())
939 {
940 uint32_t quota = m_quota;
941 while (Restart())
942 {
943 quota -= 1;
944 if (quota <= 0)
945 {
946 /// \todo netif_schedule (q);
947 break;
948 }
949 }
950 RunEnd();
951 }
952}
953
954bool
956{
957 NS_LOG_FUNCTION(this);
958 if (m_running)
959 {
960 return false;
961 }
962
963 m_running = true;
964 return true;
965}
966
967void
969{
970 NS_LOG_FUNCTION(this);
971 m_running = false;
972}
973
974bool
976{
977 NS_LOG_FUNCTION(this);
979 if (!item)
980 {
981 NS_LOG_LOGIC("No packet to send");
982 return false;
983 }
984
985 return Transmit(item);
986}
987
990{
991 NS_LOG_FUNCTION(this);
992
994
995 // First check if there is a requeued packet
996 if (m_requeued)
997 {
998 // If the queue where the requeued packet is destined to is not stopped, return
999 // the requeued packet; otherwise, return an empty packet.
1000 // If the device does not support flow control, the device queue is never stopped
1001 if (!m_devQueueIface ||
1002 !m_devQueueIface->GetTxQueue(m_requeued->GetTxQueueIndex())->IsStopped())
1003 {
1004 item = m_requeued;
1005 m_requeued = nullptr;
1006 if (m_peeked)
1007 {
1008 // If the packet was requeued because a peek operation was requested
1009 // we need to explicitly call PacketDequeued to update statistics
1010 // about dequeued packets and fire the dequeue trace.
1011 m_peeked = false;
1012 PacketDequeued(item);
1013 }
1014 }
1015 }
1016 else
1017 {
1018 // If the device is multi-queue (actually, Linux checks if the queue disc has
1019 // multiple queues), ask the queue disc to dequeue a packet (a multi-queue aware
1020 // queue disc should try not to dequeue a packet destined to a stopped queue).
1021 // Otherwise, ask the queue disc to dequeue a packet only if the (unique) queue
1022 // is not stopped.
1023 if (!m_devQueueIface || m_devQueueIface->GetNTxQueues() > 1 ||
1024 !m_devQueueIface->GetTxQueue(0)->IsStopped())
1025 {
1026 item = Dequeue();
1027 // If the item is not null, add the header to the packet.
1028 if (item)
1029 {
1030 item->AddHeader();
1031 }
1032 // Here, Linux tries bulk dequeues
1033 }
1034 }
1035 return item;
1036}
1037
1038void
1040{
1041 NS_LOG_FUNCTION(this << item);
1042 m_requeued = item;
1043 /// \todo netif_schedule (q);
1044
1046 m_stats.nTotalRequeuedBytes += item->GetSize();
1047
1048 NS_LOG_LOGIC("m_traceRequeue (p)");
1049 m_traceRequeue(item);
1050}
1051
1052bool
1054{
1055 NS_LOG_FUNCTION(this << item);
1056
1057 // if the device queue is stopped, requeue the packet and return false.
1058 // Note that if the underlying device is tc-unaware, packets are never
1059 // requeued because the queues of tc-unaware devices are never stopped
1060 if (m_devQueueIface && m_devQueueIface->GetTxQueue(item->GetTxQueueIndex())->IsStopped())
1061 {
1062 Requeue(item);
1063 return false;
1064 }
1065
1066 // a single queue device makes no use of the priority tag
1067 // a device that does not install a device queue interface likely makes no use of it as well
1068 if (!m_devQueueIface || m_devQueueIface->GetNTxQueues() == 1)
1069 {
1070 SocketPriorityTag priorityTag;
1071 item->GetPacket()->RemovePacketTag(priorityTag);
1072 }
1073 NS_ASSERT_MSG(m_send, "Send callback not set");
1074 m_send(item);
1075
1076 // the behavior here slightly diverges from Linux. In Linux, it is advised that
1077 // the function called when a packet needs to be transmitted (ndo_start_xmit)
1078 // should always return NETDEV_TX_OK, which means that the packet is consumed by
1079 // the device driver and thus is not requeued. However, the ndo_start_xmit function
1080 // of the device driver is allowed to return NETDEV_TX_BUSY (and hence the packet
1081 // is requeued) when there is no room for the received packet in the device queue,
1082 // despite the queue is not stopped. This case is considered as a corner case or
1083 // an hard error, and should be avoided.
1084 // Here, we do not handle such corner case and always assume that the packet is
1085 // consumed by the netdevice. Thus, we ignore the value returned by Send and a
1086 // packet sent to a netdevice is never requeued. The reason is that the semantics
1087 // of the value returned by NetDevice::Send does not match that of the value
1088 // returned by ndo_start_xmit.
1089
1090 // if the queue disc is empty or the device queue is now stopped, return false so
1091 // that the Run method does not attempt to dequeue other packets and exits
1092 return !(
1093 GetNPackets() == 0 ||
1094 (m_devQueueIface && m_devQueueIface->GetTxQueue(item->GetTxQueueIndex())->IsStopped()));
1095}
1096
1097} // namespace ns3
A base class which provides memory management and object aggregation.
Definition object.h:78
virtual void DoInitialize()
Initialize() implementation.
Definition object.cc:440
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
static const int PF_NO_MATCH
Standard value used by packet filters to indicate that no match was possible.
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
QueueDiscClass is the base class for classes that are included in a queue disc.
Definition queue-disc.h:41
~QueueDiscClass() override
Definition queue-disc.cc:48
Ptr< QueueDisc > GetQueueDisc() const
Get the queue disc attached to this class.
Definition queue-disc.cc:62
static TypeId GetTypeId()
Get the type ID.
Definition queue-disc.cc:29
void DoDispose() override
Dispose of the object.
Definition queue-disc.cc:54
void SetQueueDisc(Ptr< QueueDisc > qd)
Set the queue disc attached to this class.
Definition queue-disc.cc:69
Ptr< QueueDisc > m_queueDisc
Queue disc attached to this class.
Definition queue-disc.h:71
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition queue-disc.h:173
std::vector< Ptr< PacketFilter > > m_filters
Packet filters.
Definition queue-disc.h:680
std::vector< Ptr< QueueDiscClass > > m_classes
Classes.
Definition queue-disc.h:681
static const uint32_t DEFAULT_QUOTA
Default quota (as in /proc/sys/net/core/dev_weight)
Definition queue-disc.h:677
void AddInternalQueue(Ptr< InternalQueue > queue)
Add an internal queue to the tail of the list of queues.
virtual uint32_t GetQuota() const
Get the maximum number of dequeue operations following a packet enqueue.
WakeMode
Used to determine whether the queue disc itself or its children must be activated when a netdevice wa...
Definition queue-disc.h:492
void SetNetDeviceQueueInterface(Ptr< NetDeviceQueueInterface > ndqi)
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
QueueSize m_maxSize
max queue size
Definition queue-disc.h:686
SendCallback GetSendCallback() const
TracedCallback< Ptr< const QueueDiscItem > > m_traceDequeue
Traced callback: fired when a packet is dequeued.
Definition queue-disc.h:703
uint32_t GetNPackets() const
Get the number of packets stored by the queue disc.
virtual bool DoEnqueue(Ptr< QueueDiscItem > item)=0
This function actually enqueues a packet into the queue disc.
Ptr< NetDeviceQueueInterface > m_devQueueIface
NetDevice queue interface.
Definition queue-disc.h:690
bool Transmit(Ptr< QueueDiscItem > item)
Modelled after the Linux function sch_direct_xmit (net/sched/sch_generic.c) Sends a packet to the dev...
static constexpr const char * CHILD_QUEUE_DISC_MARK
Packet marked by a child queue disc.
Definition queue-disc.h:515
uint32_t GetNBytes() const
Get the amount of bytes stored by the queue disc.
static constexpr const char * INTERNAL_QUEUE_DROP
Packet dropped by an internal queue.
Definition queue-disc.h:511
QueueDisc(QueueDiscSizePolicy policy=QueueDiscSizePolicy::SINGLE_INTERNAL_QUEUE)
Constructor.
Ptr< InternalQueue > GetInternalQueue(std::size_t i) const
Get the i-th internal queue.
Ptr< QueueDiscItem > m_requeued
The last packet that failed to be transmitted.
Definition queue-disc.h:693
void Requeue(Ptr< QueueDiscItem > item)
Modelled after the Linux function dev_requeue_skb (net/sched/sch_generic.c) Requeues a packet whose t...
void AddPacketFilter(Ptr< PacketFilter > filter)
Add a packet filter to the tail of the list of filters used to classify packets.
TracedCallback< Ptr< const QueueDiscItem > > m_traceDrop
Traced callback: fired when a packet is dropped.
Definition queue-disc.h:707
QueueSize GetCurrentSize() const
Get the current size of the queue disc in bytes, if operating in bytes mode, or packets,...
uint32_t m_quota
Maximum number of packets dequeued in a qdisc run.
Definition queue-disc.h:689
virtual Ptr< const QueueDiscItem > DoPeek()
Return a copy of the next packet the queue disc will extract.
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...
TracedCallback< Ptr< const QueueDiscItem > > m_traceRequeue
Traced callback: fired when a packet is requeued.
Definition queue-disc.h:705
TracedValue< uint32_t > m_nBytes
Number of bytes in the queue.
Definition queue-disc.h:684
void PacketEnqueued(Ptr< const QueueDiscItem > item)
Perform the actions required when the queue disc is notified of a packet enqueue.
bool m_prohibitChangeMode
True if changing mode is prohibited.
Definition queue-disc.h:698
void DoInitialize() override
Check whether the configuration is correct and initialize parameters.
bool m_peeked
A packet was dequeued because Peek was called.
Definition queue-disc.h:694
std::function< void(Ptr< QueueDiscItem >)> SendCallback
Callback invoked to send a packet to the receiving object when Run is called.
Definition queue-disc.h:352
QueueDiscSizePolicy m_sizePolicy
The queue disc size policy.
Definition queue-disc.h:697
bool m_running
The queue disc is performing multiple dequeue operations.
Definition queue-disc.h:692
virtual bool CheckConfig()=0
Check whether the current configuration is correct.
TracedCallback< Ptr< const QueueDiscItem > > m_traceEnqueue
Traced callback: fired when a packet is enqueued.
Definition queue-disc.h:701
Ptr< NetDeviceQueueInterface > GetNetDeviceQueueInterface() const
void Run()
Modelled after the Linux function __qdisc_run (net/sched/sch_generic.c) Dequeues multiple packets,...
TracedValue< uint32_t > m_nPackets
Number of packets in the queue.
Definition queue-disc.h:683
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.
ChildQueueDiscMarkFunctor m_childQueueDiscMarkFunctor
Function object called when a child queue disc marked a packet.
Definition queue-disc.h:731
void RunEnd()
Modelled after the Linux function qdisc_run_end (include/net/sch_generic.h).
std::size_t GetNQueueDiscClasses() const
Get the number of queue disc classes.
virtual void InitializeParams()=0
Initialize parameters (if any) before the first packet is enqueued.
Stats m_stats
The collected statistics.
Definition queue-disc.h:688
const Stats & GetStats()
Retrieve all the collected statistics.
bool Restart()
Modelled after the Linux function qdisc_restart (net/sched/sch_generic.c) Dequeue a packet (by callin...
QueueSize GetMaxSize() const
Get the maximum size of the queue disc.
Ptr< QueueDiscClass > GetQueueDiscClass(std::size_t i) const
Get the i-th queue disc class.
ChildQueueDiscDropFunctor m_childQueueDiscDbeFunctor
Function object called when a child queue disc dropped a packet before enqueue.
Definition queue-disc.h:727
std::size_t GetNPacketFilters() const
Get the number of packet filters.
std::string m_childQueueDiscMarkMsg
Reason why a packet was marked by a child queue disc.
Definition queue-disc.h:696
virtual void SetQuota(const uint32_t quota)
Set the maximum number of dequeue operations following a packet enqueue.
bool RunBegin()
Modelled after the Linux function qdisc_run_begin (include/net/sch_generic.h).
bool SetMaxSize(QueueSize size)
Set the maximum size of the queue disc.
std::string m_childQueueDiscDropMsg
Reason why a packet was dropped by a child queue disc.
Definition queue-disc.h:695
InternalQueueDropFunctor m_internalQueueDbeFunctor
Function object called when an internal queue dropped a packet before enqueue.
Definition queue-disc.h:723
std::size_t GetNInternalQueues() const
Get the number of internal queues.
static TypeId GetTypeId()
Get the type ID.
void DoDispose() override
Dispose of the object.
SendCallback m_send
Callback used to send a packet to the receiving object.
Definition queue-disc.h:691
virtual WakeMode GetWakeMode() const
When setting up the wake callbacks on the netdevice queues, it is necessary to determine which queue ...
TracedCallback< Ptr< const QueueDiscItem >, const char * > m_traceDropBeforeEnqueue
Traced callback: fired when a packet is dropped before enqueue.
Definition queue-disc.h:709
TracedCallback< Time > m_sojourn
Sojourn time of the latest dequeued packet.
Definition queue-disc.h:685
static constexpr const char * CHILD_QUEUE_DISC_DROP
Packet dropped by a child queue disc.
Definition queue-disc.h:513
TracedCallback< Ptr< const QueueDiscItem >, const char * > m_traceMark
Traced callback: fired when a packet is marked.
Definition queue-disc.h:713
Ptr< QueueDiscItem > DequeuePacket()
Modelled after the Linux function dequeue_skb (net/sched/sch_generic.c)
Ptr< QueueDiscItem > Dequeue()
Extract from the queue disc the packet that has been dequeued by calling Peek, if any,...
std::vector< Ptr< InternalQueue > > m_queues
Internal queues.
Definition queue-disc.h:679
Ptr< const QueueDiscItem > Peek()
Get a copy of the next packet the queue discipline will extract.
ChildQueueDiscDropFunctor m_childQueueDiscDadFunctor
Function object called when a child queue disc dropped a packet after dequeue.
Definition queue-disc.h:729
TracedCallback< Ptr< const QueueDiscItem >, const char * > m_traceDropAfterDequeue
Traced callback: fired when a packet is dropped after dequeue.
Definition queue-disc.h:711
InternalQueueDropFunctor m_internalQueueDadFunctor
Function object called when an internal queue dropped a packet after dequeue.
Definition queue-disc.h:725
bool Mark(Ptr< QueueDiscItem > item, const char *reason)
Marks the given packet and, if successful, updates the counters associated with the given reason.
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.
Ptr< PacketFilter > GetPacketFilter(std::size_t i) const
Get the i-th packet filter.
void PacketDequeued(Ptr< const QueueDiscItem > item)
Perform the actions required when the queue disc is notified of a packet dequeue.
virtual Ptr< QueueDiscItem > DoDequeue()=0
This function actually extracts a packet from the queue disc.
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
void SetSendCallback(SendCallback func)
~QueueDisc() override
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition queue-item.h:122
Class for representing queue sizes.
Definition queue-size.h:85
QueueSizeUnit GetUnit() const
Get the underlying unit.
uint32_t GetValue() const
Get the underlying value.
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
indicates whether the socket has a priority set.
Definition socket.h:1307
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#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:75
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:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
QueueSizeUnit
Enumeration of the operating modes of queues.
Definition queue-size.h:33
@ BYTES
Use number of bytes for queue size.
Definition queue-size.h:35
@ PACKETS
Use number of packets for queue size.
Definition queue-size.h:34
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
QueueDiscSizePolicy
Enumeration of the available policies to handle the queue disc size.
Definition queue-disc.h:96
@ SINGLE_INTERNAL_QUEUE
Used by queue discs with single internal queue.
Definition queue-disc.h:97
@ SINGLE_CHILD_QUEUE_DISC
Used by queue discs with single child queue disc.
Definition queue-disc.h:98
@ MULTIPLE_QUEUES
Used by queue discs with multiple internal queues/child queue discs.
Definition queue-disc.h:99
@ NO_LIMITS
Used by queue discs with unlimited size.
Definition queue-disc.h:100
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:443
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
Ptr< const AttributeChecker > MakeObjectVectorChecker()
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Structure that keeps the queue disc statistics.
Definition queue-disc.h:177
std::map< std::string, uint64_t, std::less<> > nDroppedBytesAfterDequeue
Bytes dropped after dequeue, for each reason.
Definition queue-disc.h:213
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
uint64_t nTotalRequeuedBytes
Total requeued bytes.
Definition queue-disc.h:217
std::map< std::string, uint32_t, std::less<> > nDroppedPacketsBeforeEnqueue
Packets dropped before enqueue, for each reason.
Definition queue-disc.h:199
uint32_t nTotalEnqueuedPackets
Total enqueued packets.
Definition queue-disc.h:187
uint64_t nTotalReceivedBytes
Total received bytes.
Definition queue-disc.h:181
uint32_t nTotalRequeuedPackets
Total requeued packets.
Definition queue-disc.h:215
uint64_t nTotalDroppedBytesBeforeEnqueue
Total bytes dropped before enqueue.
Definition queue-disc.h:207
uint32_t nTotalDequeuedPackets
Total dequeued packets.
Definition queue-disc.h:191
uint32_t nTotalDroppedPackets
Total dropped packets.
Definition queue-disc.h:195
uint64_t GetNDroppedBytes(std::string reason) const
Get the amount of bytes dropped for the given reason.
uint64_t nTotalEnqueuedBytes
Total enqueued bytes.
Definition queue-disc.h:189
uint32_t nTotalSentPackets
Total sent packets – this value is not kept up to date, call GetStats first.
Definition queue-disc.h:183
uint32_t nTotalMarkedBytes
Total marked bytes.
Definition queue-disc.h:223
uint32_t nTotalMarkedPackets
Total marked packets.
Definition queue-disc.h:219
uint64_t GetNMarkedBytes(std::string reason) const
Get the amount of bytes marked for the given reason.
uint64_t nTotalDroppedBytesAfterDequeue
Total bytes dropped after dequeue.
Definition queue-disc.h:211
std::map< std::string, uint64_t, std::less<> > nMarkedBytes
Marked bytes, for each reason.
Definition queue-disc.h:225
std::map< std::string, uint64_t, std::less<> > nDroppedBytesBeforeEnqueue
Bytes dropped before enqueue, for each reason.
Definition queue-disc.h:209
uint32_t nTotalDroppedPacketsBeforeEnqueue
Total packets dropped before enqueue.
Definition queue-disc.h:197
uint64_t nTotalDroppedBytes
Total dropped bytes.
Definition queue-disc.h:205
void Print(std::ostream &os) const
Print the statistics.
uint32_t nTotalReceivedPackets
Total received packets.
Definition queue-disc.h:179
uint32_t GetNMarkedPackets(std::string reason) const
Get the number of packets marked for the given reason.
std::map< std::string, uint32_t, std::less<> > nDroppedPacketsAfterDequeue
Packets dropped after dequeue, for each reason.
Definition queue-disc.h:203
std::map< std::string, uint32_t, std::less<> > nMarkedPackets
Marked packets, for each reason.
Definition queue-disc.h:221
uint64_t nTotalSentBytes
Total sent bytes – this value is not kept up to date, call GetStats first.
Definition queue-disc.h:185
uint32_t nTotalDroppedPacketsAfterDequeue
Total packets dropped after dequeue.
Definition queue-disc.h:201
uint64_t nTotalDequeuedBytes
Total dequeued bytes.
Definition queue-disc.h:193