A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
codel-queue-disc-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 ResiliNets, ITTC, University of Kansas
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Truc Anh N Nguyen <trucanh524@gmail.com>
18 * Modified by: Pasquale Imputato <p.imputato@gmail.com>
19 *
20 */
21
22#include "ns3/codel-queue-disc.h"
23#include "ns3/double.h"
24#include "ns3/log.h"
25#include "ns3/packet.h"
26#include "ns3/simulator.h"
27#include "ns3/string.h"
28#include "ns3/test.h"
29#include "ns3/uinteger.h"
30
31using namespace ns3;
32
33// The following code borrowed from Linux codel.h, for unit testing
34#define REC_INV_SQRT_BITS_ns3 (8 * sizeof(uint16_t))
35/* or sizeof_in_bits(rec_inv_sqrt) */
36/* needed shift to get a Q0.32 number from rec_inv_sqrt */
37#define REC_INV_SQRT_SHIFT_ns3 (32 - REC_INV_SQRT_BITS_ns3)
38
39static uint16_t
40_codel_Newton_step(uint16_t rec_inv_sqrt, uint32_t count)
41{
42 uint32_t invsqrt = ((uint32_t)rec_inv_sqrt) << REC_INV_SQRT_SHIFT_ns3;
43 uint32_t invsqrt2 = ((uint64_t)invsqrt * invsqrt) >> 32;
44 uint64_t val = (3LL << 32) - ((uint64_t)count * invsqrt2);
45
46 val >>= 2; /* avoid overflow in following multiply */
47 val = (val * invsqrt) >> (32 - 2 + 1);
48 return static_cast<uint16_t>(val >> REC_INV_SQRT_SHIFT_ns3);
49}
50
51static uint32_t
53{
54 return (uint32_t)(((uint64_t)val * ep_ro) >> 32);
55}
56
57// End Linux borrow
58
59/**
60 * \ingroup traffic-control-test
61 *
62 * \brief Codel Queue Disc Test Item
63 */
65{
66 public:
67 /**
68 * Constructor
69 *
70 * \param p packet
71 * \param addr address
72 * \param ecnCapable ECN capable
73 */
74 CodelQueueDiscTestItem(Ptr<Packet> p, const Address& addr, bool ecnCapable);
75 ~CodelQueueDiscTestItem() override;
76
77 // Delete default constructor, copy constructor and assignment operator to avoid misuse
81
82 void AddHeader() override;
83 bool Mark() override;
84
85 private:
86 bool m_ecnCapablePacket; ///< ECN capable packet?
87};
88
90 : QueueDiscItem(p, addr, 0),
91 m_ecnCapablePacket(ecnCapable)
92{
93}
94
96{
97}
98
99void
101{
102}
103
104bool
106{
107 return m_ecnCapablePacket;
108}
109
110/**
111 * \ingroup traffic-control-test
112 *
113 * \brief Test 1: simple enqueue/dequeue with no drops
114 */
116{
117 public:
118 /**
119 * Constructor
120 *
121 * \param mode the mode
122 */
124 void DoRun() override;
125
126 private:
128};
129
131 : TestCase("Basic enqueue and dequeue operations, and attribute setting")
132{
133 m_mode = mode;
134}
135
136void
138{
139 Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
140
141 uint32_t pktSize = 1000;
142 uint32_t modeSize = 0;
143
144 Address dest;
145
146 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinBytes", UintegerValue(pktSize)),
147 true,
148 "Verify that we can actually set the attribute MinBytes");
149 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Interval", StringValue("50ms")),
150 true,
151 "Verify that we can actually set the attribute Interval");
152 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Target", StringValue("4ms")),
153 true,
154 "Verify that we can actually set the attribute Target");
155
156 if (m_mode == QueueSizeUnit::BYTES)
157 {
158 modeSize = pktSize;
159 }
160 else if (m_mode == QueueSizeUnit::PACKETS)
161 {
162 modeSize = 1;
163 }
165 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 1500))),
166 true,
167 "Verify that we can actually set the attribute MaxSize");
168 queue->Initialize();
169
170 Ptr<Packet> p1;
171 Ptr<Packet> p2;
172 Ptr<Packet> p3;
173 Ptr<Packet> p4;
174 Ptr<Packet> p5;
175 Ptr<Packet> p6;
176 p1 = Create<Packet>(pktSize);
177 p2 = Create<Packet>(pktSize);
178 p3 = Create<Packet>(pktSize);
179 p4 = Create<Packet>(pktSize);
180 p5 = Create<Packet>(pktSize);
181 p6 = Create<Packet>(pktSize);
182
183 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
184 0 * modeSize,
185 "There should be no packets in queue");
186 queue->Enqueue(Create<CodelQueueDiscTestItem>(p1, dest, false));
187 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
188 1 * modeSize,
189 "There should be one packet in queue");
190 queue->Enqueue(Create<CodelQueueDiscTestItem>(p2, dest, false));
191 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
192 2 * modeSize,
193 "There should be two packets in queue");
194 queue->Enqueue(Create<CodelQueueDiscTestItem>(p3, dest, false));
195 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
196 3 * modeSize,
197 "There should be three packets in queue");
198 queue->Enqueue(Create<CodelQueueDiscTestItem>(p4, dest, false));
199 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
200 4 * modeSize,
201 "There should be four packets in queue");
202 queue->Enqueue(Create<CodelQueueDiscTestItem>(p5, dest, false));
203 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
204 5 * modeSize,
205 "There should be five packets in queue");
206 queue->Enqueue(Create<CodelQueueDiscTestItem>(p6, dest, false));
207 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
208 6 * modeSize,
209 "There should be six packets in queue");
210
211 NS_TEST_ASSERT_MSG_EQ(queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::OVERLIMIT_DROP),
212 0,
213 "There should be no packets being dropped due to full queue");
214
216
217 item = queue->Dequeue();
218 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the first packet");
219 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
220 5 * modeSize,
221 "There should be five packets in queue");
222 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p1->GetUid(), "was this the first packet ?");
223
224 item = queue->Dequeue();
225 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the second packet");
226 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
227 4 * modeSize,
228 "There should be four packets in queue");
229 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(),
230 p2->GetUid(),
231 "Was this the second packet ?");
232
233 item = queue->Dequeue();
234 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the third packet");
235 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
236 3 * modeSize,
237 "There should be three packets in queue");
238 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p3->GetUid(), "Was this the third packet ?");
239
240 item = queue->Dequeue();
241 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the forth packet");
242 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
243 2 * modeSize,
244 "There should be two packets in queue");
245 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(),
246 p4->GetUid(),
247 "Was this the fourth packet ?");
248
249 item = queue->Dequeue();
250 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the fifth packet");
251 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
252 1 * modeSize,
253 "There should be one packet in queue");
254 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p5->GetUid(), "Was this the fifth packet ?");
255
256 item = queue->Dequeue();
257 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the last packet");
258 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
259 0 * modeSize,
260 "There should be zero packet in queue");
261 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p6->GetUid(), "Was this the sixth packet ?");
262
263 item = queue->Dequeue();
264 NS_TEST_ASSERT_MSG_EQ(item, nullptr, "There are really no packets in queue");
265
267 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
268 0,
269 "There should be no packet drops according to CoDel algorithm");
270}
271
272/**
273 * \ingroup traffic-control-test
274 *
275 * \brief Test 2: enqueue with drops due to queue overflow
276 */
278{
279 public:
280 /**
281 * Constructor
282 *
283 * \param mode the mode
284 */
286 void DoRun() override;
287
288 private:
289 /**
290 * Enqueue function
291 * \param queue the queue disc
292 * \param size the size
293 * \param nPkt the number of packets
294 */
295 void Enqueue(Ptr<CoDelQueueDisc> queue, uint32_t size, uint32_t nPkt);
297};
298
300 : TestCase("Basic overflow behavior")
301{
302 m_mode = mode;
303}
304
305void
307{
308 Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
309 uint32_t pktSize = 1000;
310 uint32_t modeSize = 0;
311
312 Address dest;
313
314 if (m_mode == QueueSizeUnit::BYTES)
315 {
316 modeSize = pktSize;
317 }
318 else if (m_mode == QueueSizeUnit::PACKETS)
319 {
320 modeSize = 1;
321 }
322
323 Ptr<Packet> p1;
324 Ptr<Packet> p2;
325 Ptr<Packet> p3;
326 p1 = Create<Packet>(pktSize);
327 p2 = Create<Packet>(pktSize);
328 p3 = Create<Packet>(pktSize);
329
331 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
332 true,
333 "Verify that we can actually set the attribute MaxSize");
334 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinBytes", UintegerValue(pktSize)),
335 true,
336 "Verify that we can actually set the attribute MinBytes");
337
338 queue->Initialize();
339
340 Enqueue(queue, pktSize, 500);
341 queue->Enqueue(Create<CodelQueueDiscTestItem>(p1, dest, false));
342 queue->Enqueue(Create<CodelQueueDiscTestItem>(p2, dest, false));
343 queue->Enqueue(Create<CodelQueueDiscTestItem>(p3, dest, false));
344
345 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
346 500 * modeSize,
347 "There should be 500 packets in queue");
348 NS_TEST_ASSERT_MSG_EQ(queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::OVERLIMIT_DROP),
349 3,
350 "There should be three packets being dropped due to full queue");
351}
352
353void
355{
356 Address dest;
357 for (uint32_t i = 0; i < nPkt; i++)
358 {
359 queue->Enqueue(Create<CodelQueueDiscTestItem>(Create<Packet>(size), dest, false));
360 }
361}
362
363/**
364 * \ingroup traffic-control-test
365 *
366 * \brief Test 3: NewtonStep unit test - test against explicit port of Linux implementation
367 */
369{
370 public:
372 void DoRun() override;
373};
374
376 : TestCase("NewtonStep arithmetic unit test")
377{
378}
379
380void
382{
383 Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
384
385 // Spot check a few points in the expected operational range of
386 // CoDelQueueDisc's m_count and m_recInvSqrt variables
387 uint16_t result;
388 for (uint16_t recInvSqrt = 0xff; recInvSqrt > 0; recInvSqrt /= 2)
389 {
390 for (uint32_t count = 1; count < 0xff; count *= 2)
391 {
392 result = queue->NewtonStep(recInvSqrt, count);
393 // Test that ns-3 value is exactly the same as the Linux value
394 NS_TEST_ASSERT_MSG_EQ(_codel_Newton_step(recInvSqrt, count),
395 result,
396 "ns-3 NewtonStep() fails to match Linux equivalent");
397 }
398 }
399}
400
401/**
402 * \ingroup traffic-control-test
403 *
404 * \brief Test 4: ControlLaw unit test - test against explicit port of Linux implementation
405 */
407{
408 public:
410 void DoRun() override;
411 /**
412 * Codel control law function
413 * \param t
414 * \param interval
415 * \param recInvSqrt
416 * \returns the codel control law
417 */
418 uint32_t _codel_control_law(uint32_t t, uint32_t interval, uint32_t recInvSqrt);
419};
420
422 : TestCase("ControlLaw arithmetic unit test")
423{
424}
425
426// The following code borrowed from Linux codel.h,
427// except the addition of queue parameter
430{
431 return t + _reciprocal_scale(interval, recInvSqrt << REC_INV_SQRT_SHIFT_ns3);
432}
433
434// End Linux borrow
435
436void
438{
439 Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
440
441 // Check a few points within the operational range of ControlLaw
442 uint32_t interval = queue->Time2CoDel(MilliSeconds(100));
443
444 uint32_t codelTimeVal;
445 for (Time timeVal = Seconds(0); timeVal <= Seconds(20); timeVal += MilliSeconds(100))
446 {
447 for (uint16_t recInvSqrt = 0xff; recInvSqrt > 0; recInvSqrt /= 2)
448 {
449 codelTimeVal = queue->Time2CoDel(timeVal);
450 uint32_t ns3Result = queue->ControlLaw(codelTimeVal, interval, recInvSqrt);
451 uint32_t linuxResult = _codel_control_law(codelTimeVal, interval, recInvSqrt);
452 NS_TEST_ASSERT_MSG_EQ(ns3Result,
453 linuxResult,
454 "Linux result for ControlLaw should equal ns-3 result");
455 }
456 }
457}
458
459/**
460 * \ingroup traffic-control-test
461 *
462 * \brief Test 5: enqueue/dequeue with drops according to CoDel algorithm
463 */
465{
466 public:
467 /**
468 * Constructor
469 *
470 * \param mode the mode
471 */
473 void DoRun() override;
474
475 private:
476 /**
477 * Enqueue function
478 * \param queue the queue disc
479 * \param size the size
480 * \param nPkt the number of packets
481 */
482 void Enqueue(Ptr<CoDelQueueDisc> queue, uint32_t size, uint32_t nPkt);
483 /** Dequeue function
484 * \param queue the queue disc
485 * \param modeSize the mode size
486 */
487 void Dequeue(Ptr<CoDelQueueDisc> queue, uint32_t modeSize);
488 /**
489 * Drop next tracer function
490 * \param oldVal the old value
491 * \param newVal the new value
492 */
493 void DropNextTracer(uint32_t oldVal, uint32_t newVal);
495 uint32_t m_dropNextCount; ///< count the number of times m_dropNext is recalculated
496};
497
499 : TestCase("Basic drop operations")
500{
501 m_mode = mode;
502 m_dropNextCount = 0;
503}
504
505void
507{
509}
510
511void
513{
514 Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
515 uint32_t pktSize = 1000;
516 uint32_t modeSize = 0;
517
518 if (m_mode == QueueSizeUnit::BYTES)
519 {
520 modeSize = pktSize;
521 }
522 else if (m_mode == QueueSizeUnit::PACKETS)
523 {
524 modeSize = 1;
525 }
526
528 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
529 true,
530 "Verify that we can actually set the attribute MaxSize");
531
532 queue->Initialize();
533
534 Enqueue(queue, pktSize, 20);
535 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
536 20 * modeSize,
537 "There should be 20 packets in queue.");
538
539 // Although the first dequeue occurs with a sojourn time above target
540 // the dequeue should be successful in this interval
541 Time waitUntilFirstDequeue = 2 * queue->GetTarget();
542 Simulator::Schedule(waitUntilFirstDequeue,
544 this,
545 queue,
546 modeSize);
547
548 // This dequeue should cause a drop
549 Time waitUntilSecondDequeue = waitUntilFirstDequeue + 2 * queue->GetInterval();
550 Simulator::Schedule(waitUntilSecondDequeue,
552 this,
553 queue,
554 modeSize);
555
556 // Although we are in dropping state, it's not time for next drop
557 // the dequeue should not cause a drop
558 Simulator::Schedule(waitUntilSecondDequeue,
560 this,
561 queue,
562 modeSize);
563
564 // In dropping time and it's time for next drop
565 // the dequeue should cause additional packet drops
566 Simulator::Schedule(waitUntilSecondDequeue * 2,
568 this,
569 queue,
570 modeSize);
571
574}
575
576void
578{
579 Address dest;
580 for (uint32_t i = 0; i < nPkt; i++)
581 {
582 queue->Enqueue(Create<CodelQueueDiscTestItem>(Create<Packet>(size), dest, false));
583 }
584}
585
586void
588{
589 uint32_t initialDropCount =
590 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
591 uint32_t initialQSize = queue->GetCurrentSize().GetValue();
592 uint32_t initialDropNext = queue->GetDropNext();
593 Time currentTime = Simulator::Now();
594 uint32_t currentDropCount = 0;
595
596 if (initialDropCount > 0 && currentTime.GetMicroSeconds() >= initialDropNext)
597 {
598 queue->TraceConnectWithoutContext(
599 "DropNext",
601 }
602
603 if (initialQSize != 0)
604 {
605 Ptr<QueueDiscItem> item = queue->Dequeue();
606 if (initialDropCount == 0 && currentTime > queue->GetTarget())
607 {
608 if (currentTime < queue->GetInterval())
609 {
610 currentDropCount =
611 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
612 NS_TEST_EXPECT_MSG_EQ(currentDropCount,
613 0,
614 "We are not in dropping state."
615 "Sojourn time has just gone above target from below."
616 "Hence, there should be no packet drops");
617 NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
618 initialQSize - modeSize,
619 "There should be 1 packet dequeued.");
620 }
621 else if (currentTime >= queue->GetInterval())
622 {
623 currentDropCount =
624 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
625 NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
626 initialQSize - 2 * modeSize,
627 "Sojourn time has been above target for at least interval."
628 "We enter the dropping state, perform initial packet drop, "
629 "and dequeue the next."
630 "So there should be 2 more packets dequeued.");
631 NS_TEST_EXPECT_MSG_EQ(currentDropCount, 1, "There should be 1 packet drop");
632 }
633 }
634 else if (initialDropCount > 0)
635 { // In dropping state
636 if (currentTime.GetMicroSeconds() < initialDropNext)
637 {
638 currentDropCount =
639 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
640 NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
641 initialQSize - modeSize,
642 "We are in dropping state."
643 "Sojourn is still above target."
644 "However, it's not time for next drop."
645 "So there should be only 1 more packet dequeued");
646
648 currentDropCount,
649 1,
650 "There should still be only 1 packet drop from the last dequeue");
651 }
652 else if (currentTime.GetMicroSeconds() >= initialDropNext)
653 {
654 currentDropCount =
655 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
656 NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
657 initialQSize - (m_dropNextCount + 1) * modeSize,
658 "We are in dropping state."
659 "It's time for next drop."
660 "The number of packets dequeued equals to the number of "
661 "times m_dropNext is updated plus initial dequeue");
662 NS_TEST_EXPECT_MSG_EQ(currentDropCount,
663 1 + m_dropNextCount,
664 "The number of drops equals to the number of times "
665 "m_dropNext is updated plus 1 from last dequeue");
666 }
667 }
668 }
669}
670
671/**
672 * \ingroup traffic-control-test
673 *
674 * \brief Test 6: enqueue/dequeue with marks according to CoDel algorithm
675 */
677{
678 public:
679 /**
680 * Constructor
681 *
682 * \param mode the mode
683 */
685 void DoRun() override;
686
687 private:
688 /**
689 * Enqueue function
690 * \param queue the queue disc
691 * \param size the size
692 * \param nPkt the number of packets
693 * \param ecnCapable ECN capable traffic
694 */
695 void Enqueue(Ptr<CoDelQueueDisc> queue, uint32_t size, uint32_t nPkt, bool ecnCapable);
696 /** Dequeue function
697 * \param queue the queue disc
698 * \param modeSize the mode size
699 * \param testCase the test case number
700 */
701 void Dequeue(Ptr<CoDelQueueDisc> queue, uint32_t modeSize, uint32_t testCase);
702 /**
703 * Drop next tracer function
704 * \param oldVal the old value
705 * \param newVal the new value
706 */
707 void DropNextTracer(uint32_t oldVal, uint32_t newVal);
709 uint32_t m_dropNextCount; ///< count the number of times m_dropNext is recalculated
710 uint32_t nPacketsBeforeFirstDrop; ///< Number of packets in the queue before first drop
711 uint32_t nPacketsBeforeFirstMark; ///< Number of packets in the queue before first mark
712};
713
715 : TestCase("Basic mark operations")
716{
717 m_mode = mode;
718 m_dropNextCount = 0;
719}
720
721void
723{
725}
726
727void
729{
730 // Test is divided into 4 sub test cases:
731 // 1) Packets are not ECN capable.
732 // 2) Packets are ECN capable but marking due to exceeding CE threshold disabled
733 // 3) Some packets are ECN capable, with CE threshold set to 2ms.
734 // 4) Packets are ECN capable and CE threshold set to 2ms
735
736 // Test case 1
737 Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
738 uint32_t pktSize = 1000;
739 uint32_t modeSize = 0;
742
743 if (m_mode == QueueSizeUnit::BYTES)
744 {
745 modeSize = pktSize;
746 }
747 else if (m_mode == QueueSizeUnit::PACKETS)
748 {
749 modeSize = 1;
750 }
751
753 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
754 true,
755 "Verify that we can actually set the attribute MaxSize");
756 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
757 true,
758 "Verify that we can actually set the attribute UseEcn");
759
760 queue->Initialize();
761
762 // Not-ECT traffic to induce packet drop
763 Enqueue(queue, pktSize, 20, false);
764 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
765 20 * modeSize,
766 "There should be 20 packets in queue.");
767
768 // Although the first dequeue occurs with a sojourn time above target
769 // there should not be any dropped packets in this interval
770 Time waitUntilFirstDequeue = 2 * queue->GetTarget();
771 Simulator::Schedule(waitUntilFirstDequeue,
773 this,
774 queue,
775 modeSize,
776 1);
777
778 // This dequeue should cause a packet to be dropped
779 Time waitUntilSecondDequeue = waitUntilFirstDequeue + 2 * queue->GetInterval();
780 Simulator::Schedule(waitUntilSecondDequeue,
782 this,
783 queue,
784 modeSize,
785 1);
786
789
790 // Test case 2, queue with ECN capable traffic for marking of packets instead of dropping
791 queue = CreateObject<CoDelQueueDisc>();
793 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
794 true,
795 "Verify that we can actually set the attribute MaxSize");
796 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
797 true,
798 "Verify that we can actually set the attribute UseEcn");
799
800 queue->Initialize();
801
802 // ECN capable traffic to induce packets to be marked
803 Enqueue(queue, pktSize, 20, true);
804 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
805 20 * modeSize,
806 "There should be 20 packets in queue.");
807
808 // Although the first dequeue occurs with a sojourn time above target
809 // there should not be any target exceeded marked packets in this interval
810 Simulator::Schedule(waitUntilFirstDequeue,
812 this,
813 queue,
814 modeSize,
815 2);
816
817 // This dequeue should cause a packet to be marked
818 Simulator::Schedule(waitUntilSecondDequeue,
820 this,
821 queue,
822 modeSize,
823 2);
824
825 // Although we are in dropping state, it's not time for next packet to be target exceeded marked
826 // the dequeue should not cause a packet to be target exceeded marked
827 Simulator::Schedule(waitUntilSecondDequeue,
829 this,
830 queue,
831 modeSize,
832 2);
833
834 // In dropping time and it's time for next packet to be target exceeded marked
835 // the dequeue should cause additional packet to be target exceeded marked
836 Simulator::Schedule(waitUntilSecondDequeue * 2,
838 this,
839 queue,
840 modeSize,
841 2);
842
845
846 // Test case 3, some packets are ECN capable, with CE threshold set to 2ms
847 queue = CreateObject<CoDelQueueDisc>();
849 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
850 true,
851 "Verify that we can actually set the attribute MaxSize");
852 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
853 true,
854 "Verify that we can actually set the attribute UseEcn");
855 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("CeThreshold", TimeValue(MilliSeconds(2))),
856 true,
857 "Verify that we can actually set the attribute CeThreshold");
858
859 queue->Initialize();
860
861 // First 3 packets in the queue are ecnCapable
862 Enqueue(queue, pktSize, 3, true);
863 // Rest of the packet are not ecnCapable
864 Enqueue(queue, pktSize, 17, false);
865 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
866 20 * modeSize,
867 "There should be 20 packets in queue.");
868
869 // Although the first dequeue occurs with a sojourn time above target
870 // there should not be any target exceeded marked packets in this interval
871 Simulator::Schedule(waitUntilFirstDequeue,
873 this,
874 queue,
875 modeSize,
876 3);
877
878 // This dequeue should cause a packet to be marked
879 Simulator::Schedule(waitUntilSecondDequeue,
881 this,
882 queue,
883 modeSize,
884 3);
885
886 // Although we are in dropping state, it's not time for next packet to be target exceeded marked
887 // the dequeue should not cause a packet to be target exceeded marked
888 Simulator::Schedule(waitUntilSecondDequeue,
890 this,
891 queue,
892 modeSize,
893 3);
894
895 // In dropping time and it's time for next packet to be dropped as packets are not ECN capable
896 // the dequeue should cause packet to be dropped
897 Simulator::Schedule(waitUntilSecondDequeue * 2,
899 this,
900 queue,
901 modeSize,
902 3);
903
906
907 // Test case 4, queue with ECN capable traffic and CeThreshold set for marking of packets
908 // instead of dropping
909 queue = CreateObject<CoDelQueueDisc>();
911 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
912 true,
913 "Verify that we can actually set the attribute MaxSize");
914 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
915 true,
916 "Verify that we can actually set the attribute UseEcn");
917 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("CeThreshold", TimeValue(MilliSeconds(2))),
918 true,
919 "Verify that we can actually set the attribute CeThreshold");
920
921 queue->Initialize();
922
923 // ECN capable traffic to induce packets to be marked
924 Enqueue(queue, pktSize, 20, true);
925 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
926 20 * modeSize,
927 "There should be 20 packets in queue.");
928
929 // The first dequeue occurs with a sojourn time below CE threshold
930 // there should not any be CE threshold exceeded marked packets
933 this,
934 queue,
935 modeSize,
936 4);
937
938 // Sojourn time above CE threshold so this dequeue should cause a packet to be CE thershold
939 // exceeded marked
942 this,
943 queue,
944 modeSize,
945 4);
946
947 // the dequeue should cause a packet to be CE threshold exceeded marked
948 Simulator::Schedule(waitUntilFirstDequeue,
950 this,
951 queue,
952 modeSize,
953 4);
954
955 // In dropping time and it's time for next packet to be dropped but because of using ECN, packet
956 // should be marked
957 Simulator::Schedule(waitUntilSecondDequeue,
959 this,
960 queue,
961 modeSize,
962 4);
963
966}
967
968void
970 uint32_t size,
971 uint32_t nPkt,
972 bool ecnCapable)
973{
974 Address dest;
975 for (uint32_t i = 0; i < nPkt; i++)
976 {
977 queue->Enqueue(Create<CodelQueueDiscTestItem>(Create<Packet>(size), dest, ecnCapable));
978 }
979}
980
981void
983{
984 uint32_t initialTargetMarkCount =
985 queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
986 uint32_t initialCeThreshMarkCount =
987 queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
988 uint32_t initialQSize = queue->GetCurrentSize().GetValue();
989 uint32_t initialDropNext = queue->GetDropNext();
990 Time currentTime = Simulator::Now();
991 uint32_t currentDropCount = 0;
992 uint32_t currentTargetMarkCount = 0;
993 uint32_t currentCeThreshMarkCount = 0;
994
995 if (initialTargetMarkCount > 0 && currentTime.GetMicroSeconds() >= initialDropNext &&
996 testCase == 3)
997 {
998 queue->TraceConnectWithoutContext(
999 "DropNext",
1001 }
1002
1003 if (initialQSize != 0)
1004 {
1005 Ptr<QueueDiscItem> item = queue->Dequeue();
1006 if (testCase == 1)
1007 {
1008 currentDropCount =
1009 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1010 if (currentDropCount == 1)
1011 {
1012 nPacketsBeforeFirstDrop = initialQSize;
1013 }
1014 }
1015 else if (testCase == 2)
1016 {
1017 if (initialTargetMarkCount == 0 && currentTime > queue->GetTarget())
1018 {
1019 if (currentTime < queue->GetInterval())
1020 {
1021 currentDropCount =
1022 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1023 currentTargetMarkCount =
1024 queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1025 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1027 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1028 initialQSize - modeSize,
1029 "There should be 1 packet dequeued.");
1030 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1031 0,
1032 "There should not be any packet drops");
1034 currentTargetMarkCount,
1035 0,
1036 "We are not in dropping state."
1037 "Sojourn time has just gone above target from below."
1038 "Hence, there should be no target exceeded marked packets");
1040 currentCeThreshMarkCount,
1041 0,
1042 "Marking due to CE threshold is disabled"
1043 "Hence, there should not be any CE threshold exceeded marked packet");
1044 }
1045 else if (currentTime >= queue->GetInterval())
1046 {
1047 currentDropCount =
1048 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1049 currentTargetMarkCount =
1050 queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1051 nPacketsBeforeFirstMark = initialQSize;
1052 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1055 queue->GetCurrentSize().GetValue(),
1056 initialQSize - modeSize,
1057 "Sojourn time has been above target for at least interval."
1058 "We enter the dropping state and perform initial packet marking"
1059 "So there should be only 1 more packet dequeued.");
1060 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1061 0,
1062 "There should not be any packet drops");
1063 NS_TEST_ASSERT_MSG_EQ(currentTargetMarkCount,
1064 1,
1065 "There should be 1 target exceeded marked packet");
1067 currentCeThreshMarkCount,
1068 0,
1069 "There should not be any CE threshold exceeded marked packet");
1070 }
1071 }
1072 else if (initialTargetMarkCount > 0)
1073 { // In dropping state
1074 if (currentTime.GetMicroSeconds() < initialDropNext)
1075 {
1076 currentDropCount =
1077 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1078 currentTargetMarkCount =
1079 queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1080 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1082 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1083 initialQSize - modeSize,
1084 "We are in dropping state."
1085 "Sojourn is still above target."
1086 "However, it's not time for next target exceeded mark."
1087 "So there should be only 1 more packet dequeued");
1088 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1089 0,
1090 "There should not be any packet drops");
1091 NS_TEST_ASSERT_MSG_EQ(currentTargetMarkCount,
1092 1,
1093 "There should still be only 1 target exceeded marked "
1094 "packet from the last dequeue");
1096 currentCeThreshMarkCount,
1097 0,
1098 "There should not be any CE threshold exceeded marked packet");
1099 }
1100 else if (currentTime.GetMicroSeconds() >= initialDropNext)
1101 {
1102 currentDropCount =
1103 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1104 currentTargetMarkCount =
1105 queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1106 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1108 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1109 initialQSize - modeSize,
1110 "We are in dropping state."
1111 "It's time for packet to be marked"
1112 "So there should be only 1 more packet dequeued");
1113 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1114 0,
1115 "There should not be any packet drops");
1116 NS_TEST_ASSERT_MSG_EQ(currentTargetMarkCount,
1117 2,
1118 "There should 2 target exceeded marked packet");
1122 "Number of packets in the queue before drop should be equal"
1123 "to number of packets in the queue before first mark as the behavior "
1124 "until packet N should be the same.");
1126 currentCeThreshMarkCount,
1127 0,
1128 "There should not be any CE threshold exceeded marked packet");
1129 }
1130 }
1131 }
1132 else if (testCase == 3)
1133 {
1134 if (initialTargetMarkCount == 0 && currentTime > queue->GetTarget())
1135 {
1136 if (currentTime < queue->GetInterval())
1137 {
1138 currentDropCount =
1139 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1140 currentTargetMarkCount =
1141 queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1142 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1144 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1145 initialQSize - modeSize,
1146 "There should be 1 packet dequeued.");
1147 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1148 0,
1149 "There should not be any packet drops");
1151 currentTargetMarkCount,
1152 0,
1153 "We are not in dropping state."
1154 "Sojourn time has just gone above target from below."
1155 "Hence, there should be no target exceeded marked packets");
1157 currentCeThreshMarkCount,
1158 1,
1159 "Sojourn time has gone above CE threshold."
1160 "Hence, there should be 1 CE threshold exceeded marked packet");
1161 }
1162 else if (currentTime >= queue->GetInterval())
1163 {
1164 currentDropCount =
1165 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1166 currentTargetMarkCount =
1167 queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1168 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1171 queue->GetCurrentSize().GetValue(),
1172 initialQSize - modeSize,
1173 "Sojourn time has been above target for at least interval."
1174 "We enter the dropping state and perform initial packet marking"
1175 "So there should be only 1 more packet dequeued.");
1176 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1177 0,
1178 "There should not be any packet drops");
1179 NS_TEST_ASSERT_MSG_EQ(currentTargetMarkCount,
1180 1,
1181 "There should be 1 target exceeded marked packet");
1182 NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1183 1,
1184 "There should be 1 CE threshold exceeded marked packets");
1185 }
1186 }
1187 else if (initialTargetMarkCount > 0)
1188 { // In dropping state
1189 if (currentTime.GetMicroSeconds() < initialDropNext)
1190 {
1191 currentDropCount =
1192 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1193 currentTargetMarkCount =
1194 queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1195 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1197 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1198 initialQSize - modeSize,
1199 "We are in dropping state."
1200 "Sojourn is still above target."
1201 "However, it's not time for next target exceeded mark."
1202 "So there should be only 1 more packet dequeued");
1203 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1204 0,
1205 "There should not be any packet drops");
1206 NS_TEST_ASSERT_MSG_EQ(currentTargetMarkCount,
1207 1,
1208 "There should still be only 1 target exceeded marked "
1209 "packet from the last dequeue");
1210 NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1211 2,
1212 "There should be 2 CE threshold exceeded marked packets");
1213 }
1214 else if (currentTime.GetMicroSeconds() >= initialDropNext)
1215 {
1216 currentDropCount =
1217 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1218 currentTargetMarkCount =
1219 queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1220 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1223 queue->GetCurrentSize().GetValue(),
1224 initialQSize - (m_dropNextCount + 1) * modeSize,
1225 "We are in dropping state."
1226 "It's time for packet to be dropped as packets are not ecnCapable"
1227 "The number of packets dequeued equals to the number of times m_dropNext "
1228 "is updated plus initial dequeue");
1230 currentDropCount,
1232 "The number of drops equals to the number of times m_dropNext is updated");
1234 currentTargetMarkCount,
1235 1,
1236 "There should still be only 1 target exceeded marked packet");
1237 NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1238 2,
1239 "There should still be 2 CE threshold exceeded marked "
1240 "packet as packets are not ecnCapable");
1241 }
1242 }
1243 }
1244 else if (testCase == 4)
1245 {
1246 if (currentTime < queue->GetTarget())
1247 {
1248 if (initialCeThreshMarkCount == 0 && currentTime < MilliSeconds(2))
1249 {
1250 currentDropCount =
1251 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1252 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1254 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1255 initialQSize - modeSize,
1256 "There should be 1 packet dequeued.");
1257 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1258 0,
1259 "There should not be any packet drops");
1261 currentCeThreshMarkCount,
1262 0,
1263 "Sojourn time has not gone above CE threshold."
1264 "Hence, there should not be any CE threshold exceeded marked packet");
1265 }
1266 else
1267 {
1268 currentDropCount =
1269 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1270 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1272 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1273 initialQSize - modeSize,
1274 "There should be only 1 more packet dequeued.");
1275 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1276 0,
1277 "There should not be any packet drops");
1278 NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1279 1,
1280 "Sojourn time has gone above CE threshold."
1281 "There should be 1 CE threshold exceeded marked packet");
1282 }
1283 }
1284 else if (initialCeThreshMarkCount > 0 && currentTime < queue->GetInterval())
1285 {
1286 if (initialCeThreshMarkCount < 2)
1287 {
1288 currentDropCount =
1289 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1290 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1292 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1293 initialQSize - modeSize,
1294 "There should be only 1 more packet dequeued.");
1295 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1296 0,
1297 "There should not be any packet drops");
1298 NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1299 2,
1300 "There should be 2 CE threshold exceeded marked packets");
1301 }
1302 else
1303 { // In dropping state
1304 currentDropCount =
1305 queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1306 currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1308 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1309 initialQSize - modeSize,
1310 "There should be only 1 more packet dequeued.");
1311 NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1312 0,
1313 "There should not be any packet drops");
1314 NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1315 3,
1316 "There should be 3 CE threshold exceeded marked packet");
1317 }
1318 }
1319 }
1320 }
1321}
1322
1323/**
1324 * \ingroup traffic-control-test
1325 *
1326 * \brief CoDel Queue Disc Test Suite
1327 */
1329{
1330 public:
1332 : TestSuite("codel-queue-disc", Type::UNIT)
1333 {
1334 // Test 1: simple enqueue/dequeue with no drops
1335 AddTestCase(new CoDelQueueDiscBasicEnqueueDequeue(QueueSizeUnit::PACKETS),
1336 TestCase::Duration::QUICK);
1337 AddTestCase(new CoDelQueueDiscBasicEnqueueDequeue(QueueSizeUnit::BYTES),
1338 TestCase::Duration::QUICK);
1339 // Test 2: enqueue with drops due to queue overflow
1340 AddTestCase(new CoDelQueueDiscBasicOverflow(QueueSizeUnit::PACKETS),
1341 TestCase::Duration::QUICK);
1342 AddTestCase(new CoDelQueueDiscBasicOverflow(QueueSizeUnit::BYTES),
1343 TestCase::Duration::QUICK);
1344 // Test 3: test NewtonStep() against explicit port of Linux implementation
1345 AddTestCase(new CoDelQueueDiscNewtonStepTest(), TestCase::Duration::QUICK);
1346 // Test 4: test ControlLaw() against explicit port of Linux implementation
1347 AddTestCase(new CoDelQueueDiscControlLawTest(), TestCase::Duration::QUICK);
1348 // Test 5: enqueue/dequeue with drops according to CoDel algorithm
1349 AddTestCase(new CoDelQueueDiscBasicDrop(QueueSizeUnit::PACKETS), TestCase::Duration::QUICK);
1350 AddTestCase(new CoDelQueueDiscBasicDrop(QueueSizeUnit::BYTES), TestCase::Duration::QUICK);
1351 // Test 6: enqueue/dequeue with marks according to CoDel algorithm
1352 AddTestCase(new CoDelQueueDiscBasicMark(QueueSizeUnit::PACKETS), TestCase::Duration::QUICK);
1353 AddTestCase(new CoDelQueueDiscBasicMark(QueueSizeUnit::BYTES), TestCase::Duration::QUICK);
1354 }
1355} g_coDelQueueTestSuite; ///< the test suite
Test 5: enqueue/dequeue with drops according to CoDel algorithm.
uint32_t m_dropNextCount
count the number of times m_dropNext is recalculated
CoDelQueueDiscBasicDrop(QueueSizeUnit mode)
Constructor.
void Dequeue(Ptr< CoDelQueueDisc > queue, uint32_t modeSize)
Dequeue function.
void Enqueue(Ptr< CoDelQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
void DoRun() override
Implementation to actually run this TestCase.
void DropNextTracer(uint32_t oldVal, uint32_t newVal)
Drop next tracer function.
Test 1: simple enqueue/dequeue with no drops.
CoDelQueueDiscBasicEnqueueDequeue(QueueSizeUnit mode)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
Test 6: enqueue/dequeue with marks according to CoDel algorithm.
uint32_t nPacketsBeforeFirstMark
Number of packets in the queue before first mark.
void Enqueue(Ptr< CoDelQueueDisc > queue, uint32_t size, uint32_t nPkt, bool ecnCapable)
Enqueue function.
uint32_t m_dropNextCount
count the number of times m_dropNext is recalculated
void DropNextTracer(uint32_t oldVal, uint32_t newVal)
Drop next tracer function.
uint32_t nPacketsBeforeFirstDrop
Number of packets in the queue before first drop.
void Dequeue(Ptr< CoDelQueueDisc > queue, uint32_t modeSize, uint32_t testCase)
Dequeue function.
void DoRun() override
Implementation to actually run this TestCase.
CoDelQueueDiscBasicMark(QueueSizeUnit mode)
Constructor.
Test 2: enqueue with drops due to queue overflow.
CoDelQueueDiscBasicOverflow(QueueSizeUnit mode)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
void Enqueue(Ptr< CoDelQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
Test 4: ControlLaw unit test - test against explicit port of Linux implementation.
void DoRun() override
Implementation to actually run this TestCase.
uint32_t _codel_control_law(uint32_t t, uint32_t interval, uint32_t recInvSqrt)
Codel control law function.
Test 3: NewtonStep unit test - test against explicit port of Linux implementation.
void DoRun() override
Implementation to actually run this TestCase.
CoDel Queue Disc Test Suite.
Codel Queue Disc Test Item.
void AddHeader() override
Add the header to the packet.
bool Mark() override
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification.
bool m_ecnCapablePacket
ECN capable packet?
CodelQueueDiscTestItem & operator=(const CodelQueueDiscTestItem &)=delete
CodelQueueDiscTestItem(const CodelQueueDiscTestItem &)=delete
CodelQueueDiscTestItem()=delete
a polymophic address class
Definition: address.h:101
AttributeValue implementation for Boolean.
Definition: boolean.h:37
static constexpr const char * OVERLIMIT_DROP
Overlimit dropped packet.
static constexpr const char * TARGET_EXCEEDED_DROP
Sojourn time above target.
static constexpr const char * CE_THRESHOLD_EXCEEDED_MARK
Sojourn time above CE threshold.
static constexpr const char * TARGET_EXCEEDED_MARK
Sojourn time above target.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:133
Class for representing queue sizes.
Definition: queue-size.h:96
AttributeValue implementation for QueueSize.
Definition: queue-size.h:221
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static void Run()
Run the simulation.
Definition: simulator.cc:178
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
static constexpr auto UNIT
Definition: test.h:1286
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:413
AttributeValue implementation for Time.
Definition: nstime.h:1406
Hold an unsigned integer type.
Definition: uinteger.h:45
#define REC_INV_SQRT_SHIFT_ns3
static uint16_t _codel_Newton_step(uint16_t rec_inv_sqrt, uint32_t count)
static uint32_t _reciprocal_scale(uint32_t val, uint32_t ep_ro)
QueueSizeUnit
Enumeration of the operating modes of queues.
Definition: queue-size.h:44
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:145
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:252
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition: test.h:565
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1331
CoDelQueueDiscTestSuite g_coDelQueueTestSuite
the test suite
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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:706
uint32_t pktSize
packet size used for the simulation (in bytes)