A Discrete-Event Network Simulator
API
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 
31 using 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 
39 static 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 
51 static uint32_t
52 _reciprocal_scale(uint32_t val, uint32_t ep_ro)
53 {
54  return (uint32_t)(((uint64_t)val * ep_ro) >> 32);
55 }
56 
57 // End Linux borrow
58 
65 {
66  public:
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:
87 };
88 
90  : QueueDiscItem(p, addr, 0),
91  m_ecnCapablePacket(ecnCapable)
92 {
93 }
94 
96 {
97 }
98 
99 void
101 {
102 }
103 
104 bool
106 {
107  if (m_ecnCapablePacket)
108  {
109  return true;
110  }
111  return false;
112 }
113 
120 {
121  public:
128  void DoRun() override;
129 
130  private:
132 };
133 
135  : TestCase("Basic enqueue and dequeue operations, and attribute setting")
136 {
137  m_mode = mode;
138 }
139 
140 void
142 {
143  Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
144 
145  uint32_t pktSize = 1000;
146  uint32_t modeSize = 0;
147 
148  Address dest;
149 
150  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinBytes", UintegerValue(pktSize)),
151  true,
152  "Verify that we can actually set the attribute MinBytes");
153  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Interval", StringValue("50ms")),
154  true,
155  "Verify that we can actually set the attribute Interval");
156  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Target", StringValue("4ms")),
157  true,
158  "Verify that we can actually set the attribute Target");
159 
161  {
162  modeSize = pktSize;
163  }
164  else if (m_mode == QueueSizeUnit::PACKETS)
165  {
166  modeSize = 1;
167  }
169  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 1500))),
170  true,
171  "Verify that we can actually set the attribute MaxSize");
172  queue->Initialize();
173 
174  Ptr<Packet> p1;
175  Ptr<Packet> p2;
176  Ptr<Packet> p3;
177  Ptr<Packet> p4;
178  Ptr<Packet> p5;
179  Ptr<Packet> p6;
180  p1 = Create<Packet>(pktSize);
181  p2 = Create<Packet>(pktSize);
182  p3 = Create<Packet>(pktSize);
183  p4 = Create<Packet>(pktSize);
184  p5 = Create<Packet>(pktSize);
185  p6 = Create<Packet>(pktSize);
186 
187  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
188  0 * modeSize,
189  "There should be no packets in queue");
190  queue->Enqueue(Create<CodelQueueDiscTestItem>(p1, dest, false));
191  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
192  1 * modeSize,
193  "There should be one packet in queue");
194  queue->Enqueue(Create<CodelQueueDiscTestItem>(p2, dest, false));
195  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
196  2 * modeSize,
197  "There should be two packets in queue");
198  queue->Enqueue(Create<CodelQueueDiscTestItem>(p3, dest, false));
199  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
200  3 * modeSize,
201  "There should be three packets in queue");
202  queue->Enqueue(Create<CodelQueueDiscTestItem>(p4, dest, false));
203  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
204  4 * modeSize,
205  "There should be four packets in queue");
206  queue->Enqueue(Create<CodelQueueDiscTestItem>(p5, dest, false));
207  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
208  5 * modeSize,
209  "There should be five packets in queue");
210  queue->Enqueue(Create<CodelQueueDiscTestItem>(p6, dest, false));
211  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
212  6 * modeSize,
213  "There should be six packets in queue");
214 
215  NS_TEST_ASSERT_MSG_EQ(queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::OVERLIMIT_DROP),
216  0,
217  "There should be no packets being dropped due to full queue");
218 
219  Ptr<QueueDiscItem> item;
220 
221  item = queue->Dequeue();
222  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the first packet");
223  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
224  5 * modeSize,
225  "There should be five packets in queue");
226  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p1->GetUid(), "was this the first packet ?");
227 
228  item = queue->Dequeue();
229  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the second packet");
230  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
231  4 * modeSize,
232  "There should be four packets in queue");
233  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(),
234  p2->GetUid(),
235  "Was this the second packet ?");
236 
237  item = queue->Dequeue();
238  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the third packet");
239  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
240  3 * modeSize,
241  "There should be three packets in queue");
242  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p3->GetUid(), "Was this the third packet ?");
243 
244  item = queue->Dequeue();
245  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the forth packet");
246  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
247  2 * modeSize,
248  "There should be two packets in queue");
249  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(),
250  p4->GetUid(),
251  "Was this the fourth packet ?");
252 
253  item = queue->Dequeue();
254  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the fifth packet");
255  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
256  1 * modeSize,
257  "There should be one packet in queue");
258  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p5->GetUid(), "Was this the fifth packet ?");
259 
260  item = queue->Dequeue();
261  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the last packet");
262  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
263  0 * modeSize,
264  "There should be zero packet in queue");
265  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p6->GetUid(), "Was this the sixth packet ?");
266 
267  item = queue->Dequeue();
268  NS_TEST_ASSERT_MSG_EQ(item, nullptr, "There are really no packets in queue");
269 
271  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
272  0,
273  "There should be no packet drops according to CoDel algorithm");
274 }
275 
282 {
283  public:
290  void DoRun() override;
291 
292  private:
299  void Enqueue(Ptr<CoDelQueueDisc> queue, uint32_t size, uint32_t nPkt);
301 };
302 
304  : TestCase("Basic overflow behavior")
305 {
306  m_mode = mode;
307 }
308 
309 void
311 {
312  Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
313  uint32_t pktSize = 1000;
314  uint32_t modeSize = 0;
315 
316  Address dest;
317 
319  {
320  modeSize = pktSize;
321  }
322  else if (m_mode == QueueSizeUnit::PACKETS)
323  {
324  modeSize = 1;
325  }
326 
327  Ptr<Packet> p1;
328  Ptr<Packet> p2;
329  Ptr<Packet> p3;
330  p1 = Create<Packet>(pktSize);
331  p2 = Create<Packet>(pktSize);
332  p3 = Create<Packet>(pktSize);
333 
335  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
336  true,
337  "Verify that we can actually set the attribute MaxSize");
338  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinBytes", UintegerValue(pktSize)),
339  true,
340  "Verify that we can actually set the attribute MinBytes");
341 
342  queue->Initialize();
343 
344  Enqueue(queue, pktSize, 500);
345  queue->Enqueue(Create<CodelQueueDiscTestItem>(p1, dest, false));
346  queue->Enqueue(Create<CodelQueueDiscTestItem>(p2, dest, false));
347  queue->Enqueue(Create<CodelQueueDiscTestItem>(p3, dest, false));
348 
349  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
350  500 * modeSize,
351  "There should be 500 packets in queue");
352  NS_TEST_ASSERT_MSG_EQ(queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::OVERLIMIT_DROP),
353  3,
354  "There should be three packets being dropped due to full queue");
355 }
356 
357 void
358 CoDelQueueDiscBasicOverflow::Enqueue(Ptr<CoDelQueueDisc> queue, uint32_t size, uint32_t nPkt)
359 {
360  Address dest;
361  for (uint32_t i = 0; i < nPkt; i++)
362  {
363  queue->Enqueue(Create<CodelQueueDiscTestItem>(Create<Packet>(size), dest, false));
364  }
365 }
366 
373 {
374  public:
376  void DoRun() override;
377 };
378 
380  : TestCase("NewtonStep arithmetic unit test")
381 {
382 }
383 
384 void
386 {
387  Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
388 
389  // Spot check a few points in the expected operational range of
390  // CoDelQueueDisc's m_count and m_recInvSqrt variables
391  uint16_t result;
392  for (uint16_t recInvSqrt = 0xff; recInvSqrt > 0; recInvSqrt /= 2)
393  {
394  for (uint32_t count = 1; count < 0xff; count *= 2)
395  {
396  result = queue->NewtonStep(recInvSqrt, count);
397  // Test that ns-3 value is exactly the same as the Linux value
398  NS_TEST_ASSERT_MSG_EQ(_codel_Newton_step(recInvSqrt, count),
399  result,
400  "ns-3 NewtonStep() fails to match Linux equivalent");
401  }
402  }
403 }
404 
411 {
412  public:
414  void DoRun() override;
422  uint32_t _codel_control_law(uint32_t t, uint32_t interval, uint32_t recInvSqrt);
423 };
424 
426  : TestCase("ControlLaw arithmetic unit test")
427 {
428 }
429 
430 // The following code borrowed from Linux codel.h,
431 // except the addition of queue parameter
432 uint32_t
433 CoDelQueueDiscControlLawTest::_codel_control_law(uint32_t t, uint32_t interval, uint32_t recInvSqrt)
434 {
435  return t + _reciprocal_scale(interval, recInvSqrt << REC_INV_SQRT_SHIFT_ns3);
436 }
437 
438 // End Linux borrow
439 
440 void
442 {
443  Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
444 
445  // Check a few points within the operational range of ControlLaw
446  uint32_t interval = queue->Time2CoDel(MilliSeconds(100));
447 
448  uint32_t codelTimeVal;
449  for (Time timeVal = Seconds(0); timeVal <= Seconds(20); timeVal += MilliSeconds(100))
450  {
451  for (uint16_t recInvSqrt = 0xff; recInvSqrt > 0; recInvSqrt /= 2)
452  {
453  codelTimeVal = queue->Time2CoDel(timeVal);
454  uint32_t ns3Result = queue->ControlLaw(codelTimeVal, interval, recInvSqrt);
455  uint32_t linuxResult = _codel_control_law(codelTimeVal, interval, recInvSqrt);
456  NS_TEST_ASSERT_MSG_EQ(ns3Result,
457  linuxResult,
458  "Linux result for ControlLaw should equal ns-3 result");
459  }
460  }
461 }
462 
469 {
470  public:
477  void DoRun() override;
478 
479  private:
486  void Enqueue(Ptr<CoDelQueueDisc> queue, uint32_t size, uint32_t nPkt);
491  void Dequeue(Ptr<CoDelQueueDisc> queue, uint32_t modeSize);
497  void DropNextTracer(uint32_t oldVal, uint32_t newVal);
499  uint32_t m_dropNextCount;
500 };
501 
503  : TestCase("Basic drop operations")
504 {
505  m_mode = mode;
506  m_dropNextCount = 0;
507 }
508 
509 void
510 CoDelQueueDiscBasicDrop::DropNextTracer(uint32_t /* oldVal */, uint32_t /* newVal */)
511 {
512  m_dropNextCount++;
513 }
514 
515 void
517 {
518  Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
519  uint32_t pktSize = 1000;
520  uint32_t modeSize = 0;
521 
523  {
524  modeSize = pktSize;
525  }
526  else if (m_mode == QueueSizeUnit::PACKETS)
527  {
528  modeSize = 1;
529  }
530 
532  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
533  true,
534  "Verify that we can actually set the attribute MaxSize");
535 
536  queue->Initialize();
537 
538  Enqueue(queue, pktSize, 20);
539  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
540  20 * modeSize,
541  "There should be 20 packets in queue.");
542 
543  // Although the first dequeue occurs with a sojourn time above target
544  // the dequeue should be successful in this interval
545  Time waitUntilFirstDequeue = 2 * queue->GetTarget();
546  Simulator::Schedule(waitUntilFirstDequeue,
548  this,
549  queue,
550  modeSize);
551 
552  // This dequeue should cause a drop
553  Time waitUntilSecondDequeue = waitUntilFirstDequeue + 2 * queue->GetInterval();
554  Simulator::Schedule(waitUntilSecondDequeue,
556  this,
557  queue,
558  modeSize);
559 
560  // Although we are in dropping state, it's not time for next drop
561  // the dequeue should not cause a drop
562  Simulator::Schedule(waitUntilSecondDequeue,
564  this,
565  queue,
566  modeSize);
567 
568  // In dropping time and it's time for next drop
569  // the dequeue should cause additional packet drops
570  Simulator::Schedule(waitUntilSecondDequeue * 2,
572  this,
573  queue,
574  modeSize);
575 
576  Simulator::Run();
577  Simulator::Destroy();
578 }
579 
580 void
581 CoDelQueueDiscBasicDrop::Enqueue(Ptr<CoDelQueueDisc> queue, uint32_t size, uint32_t nPkt)
582 {
583  Address dest;
584  for (uint32_t i = 0; i < nPkt; i++)
585  {
586  queue->Enqueue(Create<CodelQueueDiscTestItem>(Create<Packet>(size), dest, false));
587  }
588 }
589 
590 void
592 {
593  uint32_t initialDropCount =
594  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
595  uint32_t initialQSize = queue->GetCurrentSize().GetValue();
596  uint32_t initialDropNext = queue->GetDropNext();
597  Time currentTime = Simulator::Now();
598  uint32_t currentDropCount = 0;
599 
600  if (initialDropCount > 0 && currentTime.GetMicroSeconds() >= initialDropNext)
601  {
602  queue->TraceConnectWithoutContext(
603  "DropNext",
605  }
606 
607  if (initialQSize != 0)
608  {
609  Ptr<QueueDiscItem> item = queue->Dequeue();
610  if (initialDropCount == 0 && currentTime > queue->GetTarget())
611  {
612  if (currentTime < queue->GetInterval())
613  {
614  currentDropCount =
615  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
616  NS_TEST_EXPECT_MSG_EQ(currentDropCount,
617  0,
618  "We are not in dropping state."
619  "Sojourn time has just gone above target from below."
620  "Hence, there should be no packet drops");
621  NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
622  initialQSize - modeSize,
623  "There should be 1 packet dequeued.");
624  }
625  else if (currentTime >= queue->GetInterval())
626  {
627  currentDropCount =
628  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
629  NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
630  initialQSize - 2 * modeSize,
631  "Sojourn time has been above target for at least interval."
632  "We enter the dropping state, perform initial packet drop, "
633  "and dequeue the next."
634  "So there should be 2 more packets dequeued.");
635  NS_TEST_EXPECT_MSG_EQ(currentDropCount, 1, "There should be 1 packet drop");
636  }
637  }
638  else if (initialDropCount > 0)
639  { // In dropping state
640  if (currentTime.GetMicroSeconds() < initialDropNext)
641  {
642  currentDropCount =
643  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
644  NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
645  initialQSize - modeSize,
646  "We are in dropping state."
647  "Sojourn is still above target."
648  "However, it's not time for next drop."
649  "So there should be only 1 more packet dequeued");
650 
652  currentDropCount,
653  1,
654  "There should still be only 1 packet drop from the last dequeue");
655  }
656  else if (currentTime.GetMicroSeconds() >= initialDropNext)
657  {
658  currentDropCount =
659  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
660  NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
661  initialQSize - (m_dropNextCount + 1) * modeSize,
662  "We are in dropping state."
663  "It's time for next drop."
664  "The number of packets dequeued equals to the number of "
665  "times m_dropNext is updated plus initial dequeue");
666  NS_TEST_EXPECT_MSG_EQ(currentDropCount,
667  1 + m_dropNextCount,
668  "The number of drops equals to the number of times "
669  "m_dropNext is updated plus 1 from last dequeue");
670  }
671  }
672  }
673 }
674 
681 {
682  public:
689  void DoRun() override;
690 
691  private:
699  void Enqueue(Ptr<CoDelQueueDisc> queue, uint32_t size, uint32_t nPkt, bool ecnCapable);
705  void Dequeue(Ptr<CoDelQueueDisc> queue, uint32_t modeSize, uint32_t testCase);
711  void DropNextTracer(uint32_t oldVal, uint32_t newVal);
713  uint32_t m_dropNextCount;
716 };
717 
719  : TestCase("Basic mark operations")
720 {
721  m_mode = mode;
722  m_dropNextCount = 0;
723 }
724 
725 void
726 CoDelQueueDiscBasicMark::DropNextTracer(uint32_t /* oldVal */, uint32_t /* newVal */)
727 {
728  m_dropNextCount++;
729 }
730 
731 void
733 {
734  // Test is divided into 4 sub test cases:
735  // 1) Packets are not ECN capable.
736  // 2) Packets are ECN capable but marking due to exceeding CE threshold disabled
737  // 3) Some packets are ECN capable, with CE threshold set to 2ms.
738  // 4) Packets are ECN capable and CE threshold set to 2ms
739 
740  // Test case 1
741  Ptr<CoDelQueueDisc> queue = CreateObject<CoDelQueueDisc>();
742  uint32_t pktSize = 1000;
743  uint32_t modeSize = 0;
746 
748  {
749  modeSize = pktSize;
750  }
751  else if (m_mode == QueueSizeUnit::PACKETS)
752  {
753  modeSize = 1;
754  }
755 
757  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
758  true,
759  "Verify that we can actually set the attribute MaxSize");
760  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
761  true,
762  "Verify that we can actually set the attribute UseEcn");
763 
764  queue->Initialize();
765 
766  // Not-ECT traffic to induce packet drop
767  Enqueue(queue, pktSize, 20, false);
768  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
769  20 * modeSize,
770  "There should be 20 packets in queue.");
771 
772  // Although the first dequeue occurs with a sojourn time above target
773  // there should not be any dropped packets in this interval
774  Time waitUntilFirstDequeue = 2 * queue->GetTarget();
775  Simulator::Schedule(waitUntilFirstDequeue,
777  this,
778  queue,
779  modeSize,
780  1);
781 
782  // This dequeue should cause a packet to be dropped
783  Time waitUntilSecondDequeue = waitUntilFirstDequeue + 2 * queue->GetInterval();
784  Simulator::Schedule(waitUntilSecondDequeue,
786  this,
787  queue,
788  modeSize,
789  1);
790 
791  Simulator::Run();
792  Simulator::Destroy();
793 
794  // Test case 2, queue with ECN capable traffic for marking of packets instead of dropping
795  queue = CreateObject<CoDelQueueDisc>();
797  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
798  true,
799  "Verify that we can actually set the attribute MaxSize");
800  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
801  true,
802  "Verify that we can actually set the attribute UseEcn");
803 
804  queue->Initialize();
805 
806  // ECN capable traffic to induce packets to be marked
807  Enqueue(queue, pktSize, 20, true);
808  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
809  20 * modeSize,
810  "There should be 20 packets in queue.");
811 
812  // Although the first dequeue occurs with a sojourn time above target
813  // there should not be any target exceeded marked packets in this interval
814  Simulator::Schedule(waitUntilFirstDequeue,
816  this,
817  queue,
818  modeSize,
819  2);
820 
821  // This dequeue should cause a packet to be marked
822  Simulator::Schedule(waitUntilSecondDequeue,
824  this,
825  queue,
826  modeSize,
827  2);
828 
829  // Although we are in dropping state, it's not time for next packet to be target exceeded marked
830  // the dequeue should not cause a packet to be target exceeded marked
831  Simulator::Schedule(waitUntilSecondDequeue,
833  this,
834  queue,
835  modeSize,
836  2);
837 
838  // In dropping time and it's time for next packet to be target exceeded marked
839  // the dequeue should cause additional packet to be target exceeded marked
840  Simulator::Schedule(waitUntilSecondDequeue * 2,
842  this,
843  queue,
844  modeSize,
845  2);
846 
847  Simulator::Run();
848  Simulator::Destroy();
849 
850  // Test case 3, some packets are ECN capable, with CE threshold set to 2ms
851  queue = CreateObject<CoDelQueueDisc>();
853  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
854  true,
855  "Verify that we can actually set the attribute MaxSize");
856  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
857  true,
858  "Verify that we can actually set the attribute UseEcn");
859  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("CeThreshold", TimeValue(MilliSeconds(2))),
860  true,
861  "Verify that we can actually set the attribute CeThreshold");
862 
863  queue->Initialize();
864 
865  // First 3 packets in the queue are ecnCapable
866  Enqueue(queue, pktSize, 3, true);
867  // Rest of the packet are not ecnCapable
868  Enqueue(queue, pktSize, 17, false);
869  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
870  20 * modeSize,
871  "There should be 20 packets in queue.");
872 
873  // Although the first dequeue occurs with a sojourn time above target
874  // there should not be any target exceeded marked packets in this interval
875  Simulator::Schedule(waitUntilFirstDequeue,
877  this,
878  queue,
879  modeSize,
880  3);
881 
882  // This dequeue should cause a packet to be marked
883  Simulator::Schedule(waitUntilSecondDequeue,
885  this,
886  queue,
887  modeSize,
888  3);
889 
890  // Although we are in dropping state, it's not time for next packet to be target exceeded marked
891  // the dequeue should not cause a packet to be target exceeded marked
892  Simulator::Schedule(waitUntilSecondDequeue,
894  this,
895  queue,
896  modeSize,
897  3);
898 
899  // In dropping time and it's time for next packet to be dropped as packets are not ECN capable
900  // the dequeue should cause packet to be dropped
901  Simulator::Schedule(waitUntilSecondDequeue * 2,
903  this,
904  queue,
905  modeSize,
906  3);
907 
908  Simulator::Run();
909  Simulator::Destroy();
910 
911  // Test case 4, queue with ECN capable traffic and CeThreshold set for marking of packets
912  // instead of dropping
913  queue = CreateObject<CoDelQueueDisc>();
915  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
916  true,
917  "Verify that we can actually set the attribute MaxSize");
918  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
919  true,
920  "Verify that we can actually set the attribute UseEcn");
921  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("CeThreshold", TimeValue(MilliSeconds(2))),
922  true,
923  "Verify that we can actually set the attribute CeThreshold");
924 
925  queue->Initialize();
926 
927  // ECN capable traffic to induce packets to be marked
928  Enqueue(queue, pktSize, 20, true);
929  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
930  20 * modeSize,
931  "There should be 20 packets in queue.");
932 
933  // The first dequeue occurs with a sojourn time below CE threshold
934  // there should not any be CE threshold exceeded marked packets
935  Simulator::Schedule(MilliSeconds(1),
937  this,
938  queue,
939  modeSize,
940  4);
941 
942  // Sojourn time above CE threshold so this dequeue should cause a packet to be CE thershold
943  // exceeded marked
944  Simulator::Schedule(MilliSeconds(3),
946  this,
947  queue,
948  modeSize,
949  4);
950 
951  // the dequeue should cause a packet to be CE threshold exceeded marked
952  Simulator::Schedule(waitUntilFirstDequeue,
954  this,
955  queue,
956  modeSize,
957  4);
958 
959  // In dropping time and it's time for next packet to be dropped but because of using ECN, packet
960  // should be marked
961  Simulator::Schedule(waitUntilSecondDequeue,
963  this,
964  queue,
965  modeSize,
966  4);
967 
968  Simulator::Run();
969  Simulator::Destroy();
970 }
971 
972 void
974  uint32_t size,
975  uint32_t nPkt,
976  bool ecnCapable)
977 {
978  Address dest;
979  for (uint32_t i = 0; i < nPkt; i++)
980  {
981  queue->Enqueue(Create<CodelQueueDiscTestItem>(Create<Packet>(size), dest, ecnCapable));
982  }
983 }
984 
985 void
986 CoDelQueueDiscBasicMark::Dequeue(Ptr<CoDelQueueDisc> queue, uint32_t modeSize, uint32_t testCase)
987 {
988  uint32_t initialTargetMarkCount =
989  queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
990  uint32_t initialCeThreshMarkCount =
991  queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
992  uint32_t initialQSize = queue->GetCurrentSize().GetValue();
993  uint32_t initialDropNext = queue->GetDropNext();
994  Time currentTime = Simulator::Now();
995  uint32_t currentDropCount = 0;
996  uint32_t currentTargetMarkCount = 0;
997  uint32_t currentCeThreshMarkCount = 0;
998 
999  if (initialTargetMarkCount > 0 && currentTime.GetMicroSeconds() >= initialDropNext &&
1000  testCase == 3)
1001  {
1002  queue->TraceConnectWithoutContext(
1003  "DropNext",
1005  }
1006 
1007  if (initialQSize != 0)
1008  {
1009  Ptr<QueueDiscItem> item = queue->Dequeue();
1010  if (testCase == 1)
1011  {
1012  currentDropCount =
1013  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1014  if (currentDropCount == 1)
1015  {
1016  nPacketsBeforeFirstDrop = initialQSize;
1017  }
1018  }
1019  else if (testCase == 2)
1020  {
1021  if (initialTargetMarkCount == 0 && currentTime > queue->GetTarget())
1022  {
1023  if (currentTime < queue->GetInterval())
1024  {
1025  currentDropCount =
1026  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1027  currentTargetMarkCount =
1028  queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1029  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1030  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1031  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1032  initialQSize - modeSize,
1033  "There should be 1 packet dequeued.");
1034  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1035  0,
1036  "There should not be any packet drops");
1038  currentTargetMarkCount,
1039  0,
1040  "We are not in dropping state."
1041  "Sojourn time has just gone above target from below."
1042  "Hence, there should be no target exceeded marked packets");
1044  currentCeThreshMarkCount,
1045  0,
1046  "Marking due to CE threshold is disabled"
1047  "Hence, there should not be any CE threshold exceeded marked packet");
1048  }
1049  else if (currentTime >= queue->GetInterval())
1050  {
1051  currentDropCount =
1052  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1053  currentTargetMarkCount =
1054  queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1055  nPacketsBeforeFirstMark = initialQSize;
1056  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1057  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1059  queue->GetCurrentSize().GetValue(),
1060  initialQSize - modeSize,
1061  "Sojourn time has been above target for at least interval."
1062  "We enter the dropping state and perform initial packet marking"
1063  "So there should be only 1 more packet dequeued.");
1064  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1065  0,
1066  "There should not be any packet drops");
1067  NS_TEST_ASSERT_MSG_EQ(currentTargetMarkCount,
1068  1,
1069  "There should be 1 target exceeded marked packet");
1071  currentCeThreshMarkCount,
1072  0,
1073  "There should not be any CE threshold exceeded marked packet");
1074  }
1075  }
1076  else if (initialTargetMarkCount > 0)
1077  { // In dropping state
1078  if (currentTime.GetMicroSeconds() < initialDropNext)
1079  {
1080  currentDropCount =
1081  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1082  currentTargetMarkCount =
1083  queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1084  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1085  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1086  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1087  initialQSize - modeSize,
1088  "We are in dropping state."
1089  "Sojourn is still above target."
1090  "However, it's not time for next target exceeded mark."
1091  "So there should be only 1 more packet dequeued");
1092  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1093  0,
1094  "There should not be any packet drops");
1095  NS_TEST_ASSERT_MSG_EQ(currentTargetMarkCount,
1096  1,
1097  "There should still be only 1 target exceeded marked "
1098  "packet from the last dequeue");
1100  currentCeThreshMarkCount,
1101  0,
1102  "There should not be any CE threshold exceeded marked packet");
1103  }
1104  else if (currentTime.GetMicroSeconds() >= initialDropNext)
1105  {
1106  currentDropCount =
1107  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1108  currentTargetMarkCount =
1109  queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1110  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1111  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1112  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1113  initialQSize - modeSize,
1114  "We are in dropping state."
1115  "It's time for packet to be marked"
1116  "So there should be only 1 more packet dequeued");
1117  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1118  0,
1119  "There should not be any packet drops");
1120  NS_TEST_ASSERT_MSG_EQ(currentTargetMarkCount,
1121  2,
1122  "There should 2 target exceeded marked packet");
1126  "Number of packets in the queue before drop should be equal"
1127  "to number of packets in the queue before first mark as the behavior "
1128  "until packet N should be the same.");
1130  currentCeThreshMarkCount,
1131  0,
1132  "There should not be any CE threshold exceeded marked packet");
1133  }
1134  }
1135  }
1136  else if (testCase == 3)
1137  {
1138  if (initialTargetMarkCount == 0 && currentTime > queue->GetTarget())
1139  {
1140  if (currentTime < queue->GetInterval())
1141  {
1142  currentDropCount =
1143  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1144  currentTargetMarkCount =
1145  queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1146  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1147  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1148  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1149  initialQSize - modeSize,
1150  "There should be 1 packet dequeued.");
1151  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1152  0,
1153  "There should not be any packet drops");
1155  currentTargetMarkCount,
1156  0,
1157  "We are not in dropping state."
1158  "Sojourn time has just gone above target from below."
1159  "Hence, there should be no target exceeded marked packets");
1161  currentCeThreshMarkCount,
1162  1,
1163  "Sojourn time has gone above CE threshold."
1164  "Hence, there should be 1 CE threshold exceeded marked packet");
1165  }
1166  else if (currentTime >= queue->GetInterval())
1167  {
1168  currentDropCount =
1169  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1170  currentTargetMarkCount =
1171  queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1172  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1173  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1175  queue->GetCurrentSize().GetValue(),
1176  initialQSize - modeSize,
1177  "Sojourn time has been above target for at least interval."
1178  "We enter the dropping state and perform initial packet marking"
1179  "So there should be only 1 more packet dequeued.");
1180  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1181  0,
1182  "There should not be any packet drops");
1183  NS_TEST_ASSERT_MSG_EQ(currentTargetMarkCount,
1184  1,
1185  "There should be 1 target exceeded marked packet");
1186  NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1187  1,
1188  "There should be 1 CE threshold exceeded marked packets");
1189  }
1190  }
1191  else if (initialTargetMarkCount > 0)
1192  { // In dropping state
1193  if (currentTime.GetMicroSeconds() < initialDropNext)
1194  {
1195  currentDropCount =
1196  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1197  currentTargetMarkCount =
1198  queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1199  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1200  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1201  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1202  initialQSize - modeSize,
1203  "We are in dropping state."
1204  "Sojourn is still above target."
1205  "However, it's not time for next target exceeded mark."
1206  "So there should be only 1 more packet dequeued");
1207  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1208  0,
1209  "There should not be any packet drops");
1210  NS_TEST_ASSERT_MSG_EQ(currentTargetMarkCount,
1211  1,
1212  "There should still be only 1 target exceeded marked "
1213  "packet from the last dequeue");
1214  NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1215  2,
1216  "There should be 2 CE threshold exceeded marked packets");
1217  }
1218  else if (currentTime.GetMicroSeconds() >= initialDropNext)
1219  {
1220  currentDropCount =
1221  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1222  currentTargetMarkCount =
1223  queue->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK);
1224  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1225  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1227  queue->GetCurrentSize().GetValue(),
1228  initialQSize - (m_dropNextCount + 1) * modeSize,
1229  "We are in dropping state."
1230  "It's time for packet to be dropped as packets are not ecnCapable"
1231  "The number of packets dequeued equals to the number of times m_dropNext "
1232  "is updated plus initial dequeue");
1234  currentDropCount,
1236  "The number of drops equals to the number of times m_dropNext is updated");
1238  currentTargetMarkCount,
1239  1,
1240  "There should still be only 1 target exceeded marked packet");
1241  NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1242  2,
1243  "There should still be 2 CE threshold exceeded marked "
1244  "packet as packets are not ecnCapable");
1245  }
1246  }
1247  }
1248  else if (testCase == 4)
1249  {
1250  if (currentTime < queue->GetTarget())
1251  {
1252  if (initialCeThreshMarkCount == 0 && currentTime < MilliSeconds(2))
1253  {
1254  currentDropCount =
1255  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1256  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1257  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1258  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1259  initialQSize - modeSize,
1260  "There should be 1 packet dequeued.");
1261  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1262  0,
1263  "There should not be any packet drops");
1265  currentCeThreshMarkCount,
1266  0,
1267  "Sojourn time has not gone above CE threshold."
1268  "Hence, there should not be any CE threshold exceeded marked packet");
1269  }
1270  else
1271  {
1272  currentDropCount =
1273  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1274  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1275  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1276  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1277  initialQSize - modeSize,
1278  "There should be only 1 more packet dequeued.");
1279  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1280  0,
1281  "There should not be any packet drops");
1282  NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1283  1,
1284  "Sojourn time has gone above CE threshold."
1285  "There should be 1 CE threshold exceeded marked packet");
1286  }
1287  }
1288  else if (initialCeThreshMarkCount > 0 && currentTime < queue->GetInterval())
1289  {
1290  if (initialCeThreshMarkCount < 2)
1291  {
1292  currentDropCount =
1293  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1294  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1295  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1296  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1297  initialQSize - modeSize,
1298  "There should be only 1 more packet dequeued.");
1299  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1300  0,
1301  "There should not be any packet drops");
1302  NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1303  2,
1304  "There should be 2 CE threshold exceeded marked packets");
1305  }
1306  else
1307  { // In dropping state
1308  currentDropCount =
1309  queue->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP);
1310  currentCeThreshMarkCount = queue->GetStats().GetNMarkedPackets(
1311  CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK);
1312  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
1313  initialQSize - modeSize,
1314  "There should be only 1 more packet dequeued.");
1315  NS_TEST_ASSERT_MSG_EQ(currentDropCount,
1316  0,
1317  "There should not be any packet drops");
1318  NS_TEST_ASSERT_MSG_EQ(currentCeThreshMarkCount,
1319  3,
1320  "There should be 3 CE threshold exceeded marked packet");
1321  }
1322  }
1323  }
1324  }
1325 }
1326 
1332 static class CoDelQueueDiscTestSuite : public TestSuite
1333 {
1334  public:
1336  : TestSuite("codel-queue-disc", UNIT)
1337  {
1338  // Test 1: simple enqueue/dequeue with no drops
1341  // Test 2: enqueue with drops due to queue overflow
1344  // Test 3: test NewtonStep() against explicit port of Linux implementation
1345  AddTestCase(new CoDelQueueDiscNewtonStepTest(), TestCase::QUICK);
1346  // Test 4: test ControlLaw() against explicit port of Linux implementation
1347  AddTestCase(new CoDelQueueDiscControlLawTest(), TestCase::QUICK);
1348  // Test 5: enqueue/dequeue with drops according to CoDel algorithm
1351  // Test 6: enqueue/dequeue with marks according to CoDel algorithm
1354  }
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.
CodelQueueDiscTestItem & operator=(const CodelQueueDiscTestItem &)=delete
bool m_ecnCapablePacket
ECN capable packet?
CodelQueueDiscTestItem(const CodelQueueDiscTestItem &)=delete
CodelQueueDiscTestItem()=delete
a polymophic address class
Definition: address.h:100
AttributeValue implementation for Boolean.
Definition: boolean.h:37
uint64_t GetUid() const
Returns the packet's Uid.
Definition: packet.cc:412
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.
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
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:412
AttributeValue implementation for Time.
Definition: nstime.h:1423
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
@ BYTES
Use number of bytes for queue size.
Definition: queue-size.h:46
@ PACKETS
Use number of packets for queue size.
Definition: queue-size.h:45
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
#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:144
#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:251
#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:564
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
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:707
uint32_t pktSize
packet size used for the simulation (in bytes)