A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
cobalt-queue-disc-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 NITK Surathkal
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 * Ported to ns-3 by: Vignesh Kannan <vignesh2496@gmail.com>
18 * Harsh Lara <harshapplefan@gmail.com>
19 * Jendaipou Palmei <jendaipoupalmei@gmail.com>
20 * Shefali Gupta <shefaligups11@gmail.com>
21 * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
22 */
23
24#include "ns3/cobalt-queue-disc.h"
25#include "ns3/double.h"
26#include "ns3/log.h"
27#include "ns3/packet.h"
28#include "ns3/simulator.h"
29#include "ns3/string.h"
30#include "ns3/test.h"
31#include "ns3/uinteger.h"
32
33using namespace ns3;
34
41{
42 public:
50 CobaltQueueDiscTestItem(Ptr<Packet> p, const Address& addr, bool ecnCapable);
51 ~CobaltQueueDiscTestItem() override;
52
53 // Delete default constructor, copy constructor and assignment operator to avoid misuse
57
58 void AddHeader() override;
59 bool Mark() override;
60
61 private:
63};
64
66 const Address& addr,
67 bool ecnCapable)
68 : QueueDiscItem(p, addr, 0),
69 m_ecnCapablePacket(ecnCapable)
70{
71}
72
74{
75}
76
77void
79{
80}
81
82bool
84{
86 {
87 return true;
88 }
89 return false;
90}
91
98{
99 public:
106 void DoRun() override;
107
116 private:
118};
119
121 : TestCase("Basic enqueue and dequeue operations, and attribute setting" + std::to_string(mode))
122{
123 m_mode = mode;
124}
125
126void
128{
129 Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc>();
130
131 uint32_t pktSize = 1000;
132 uint32_t modeSize = 0;
133
134 Address dest;
135
136 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Interval", StringValue("50ms")),
137 true,
138 "Verify that we can actually set the attribute Interval");
139 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Target", StringValue("4ms")),
140 true,
141 "Verify that we can actually set the attribute Target");
142 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("BlueThreshold", TimeValue(Time::Max())),
143 true,
144 "Disable Blue enhancement");
145
146 if (m_mode == QueueSizeUnit::BYTES)
147 {
148 modeSize = pktSize;
149 }
150 else if (m_mode == QueueSizeUnit::PACKETS)
151 {
152 modeSize = 1;
153 }
155 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 1500))),
156 true,
157 "Verify that we can actually set the attribute MaxSize");
158 queue->Initialize();
159
160 Ptr<Packet> p1;
161 Ptr<Packet> p2;
162 Ptr<Packet> p3;
163 Ptr<Packet> p4;
164 Ptr<Packet> p5;
165 Ptr<Packet> p6;
166 p1 = Create<Packet>(pktSize);
167 p2 = Create<Packet>(pktSize);
168 p3 = Create<Packet>(pktSize);
169 p4 = Create<Packet>(pktSize);
170 p5 = Create<Packet>(pktSize);
171 p6 = Create<Packet>(pktSize);
172
173 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
174 0 * modeSize,
175 "There should be no packets in queue");
176 queue->Enqueue(Create<CobaltQueueDiscTestItem>(p1, dest, false));
177 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
178 1 * modeSize,
179 "There should be one packet in queue");
180 queue->Enqueue(Create<CobaltQueueDiscTestItem>(p2, dest, false));
181 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
182 2 * modeSize,
183 "There should be two packets in queue");
184 queue->Enqueue(Create<CobaltQueueDiscTestItem>(p3, dest, false));
185 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
186 3 * modeSize,
187 "There should be three packets in queue");
188 queue->Enqueue(Create<CobaltQueueDiscTestItem>(p4, dest, false));
189 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
190 4 * modeSize,
191 "There should be four packets in queue");
192 queue->Enqueue(Create<CobaltQueueDiscTestItem>(p5, dest, false));
193 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
194 5 * modeSize,
195 "There should be five packets in queue");
196 queue->Enqueue(Create<CobaltQueueDiscTestItem>(p6, dest, false));
197 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
198 6 * modeSize,
199 "There should be six packets in queue");
200
201 NS_TEST_ASSERT_MSG_EQ(queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::OVERLIMIT_DROP),
202 0,
203 "There should be no packets being dropped due to full queue");
204
206
207 item = queue->Dequeue();
208 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the first packet");
209 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
210 5 * modeSize,
211 "There should be five packets in queue");
212 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p1->GetUid(), "was this the first packet ?");
213
214 item = queue->Dequeue();
215 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the second packet");
216 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
217 4 * modeSize,
218 "There should be four packets in queue");
219 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(),
220 p2->GetUid(),
221 "Was this the second packet ?");
222
223 item = queue->Dequeue();
224 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the third packet");
225 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
226 3 * modeSize,
227 "There should be three packets in queue");
228 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p3->GetUid(), "Was this the third packet ?");
229
230 item = queue->Dequeue();
231 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the forth packet");
232 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
233 2 * modeSize,
234 "There should be two packets in queue");
235 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(),
236 p4->GetUid(),
237 "Was this the fourth packet ?");
238
239 item = queue->Dequeue();
240 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the fifth packet");
241 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
242 1 * modeSize,
243 "There should be one packet in queue");
244 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p5->GetUid(), "Was this the fifth packet ?");
245
246 item = queue->Dequeue();
247 NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the last packet");
248 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
249 0 * modeSize,
250 "There should be zero packet in queue");
251 NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p6->GetUid(), "Was this the sixth packet ?");
252
253 item = queue->Dequeue();
254 NS_TEST_ASSERT_MSG_EQ(item, nullptr, "There are really no packets in queue");
255
257 queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
258 0,
259 "There should be no packet drops according to Cobalt algorithm");
260}
261
268{
269 public:
271 void DoRun() override;
278 void Enqueue(Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt);
283 void RunDropTest(QueueSizeUnit mode);
293};
294
296 : TestCase("Drop tests verification for both packets and bytes mode")
297{
298}
299
300void
302
303{
304 uint32_t pktSize = 1500;
305 uint32_t modeSize = 0;
306 Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc>();
307
308 if (mode == QueueSizeUnit::BYTES)
309 {
310 modeSize = pktSize;
311 }
312 else if (mode == QueueSizeUnit::PACKETS)
313 {
314 modeSize = 1;
315 }
316
317 queue = CreateObject<CobaltQueueDisc>();
319 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, modeSize * 100))),
320 true,
321 "Verify that we can actually set the attribute MaxSize");
322 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("BlueThreshold", TimeValue(Time::Max())),
323 true,
324 "Disable Blue enhancement");
325 queue->Initialize();
326
327 if (mode == QueueSizeUnit::BYTES)
328 {
329 EnqueueWithDelay(queue, pktSize, 200);
330 }
331 else
332 {
333 EnqueueWithDelay(queue, 1, 200);
334 }
335
338
339 QueueDisc::Stats st = queue->GetStats();
340
341 // The Pdrop value should increase, from it's default value of zero
342 NS_TEST_ASSERT_MSG_NE(queue->GetPdrop(), 0, "Pdrop should be non-zero");
344 0,
345 "Drops due to queue overflow should be non-zero");
346}
347
348void
350{
351 Address dest;
352 double delay = 0.01; // enqueue packets with delay
353 for (uint32_t i = 0; i < nPkt; i++)
354 {
355 Simulator::Schedule(Time(Seconds((i + 1) * delay)),
357 this,
358 queue,
359 size,
360 1);
361 }
362}
363
364void
366{
367 Address dest;
368 for (uint32_t i = 0; i < nPkt; i++)
369 {
370 queue->Enqueue(Create<CobaltQueueDiscTestItem>(Create<Packet>(size), dest, true));
371 }
372}
373
374void
376{
377 RunDropTest(QueueSizeUnit::PACKETS);
378 RunDropTest(QueueSizeUnit::BYTES);
380}
381
388{
389 public:
396 void DoRun() override;
397
398 private:
406 void Enqueue(Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt, bool ecnCapable);
413 void Dequeue(Ptr<CobaltQueueDisc> queue, uint32_t modeSize, uint32_t testCase);
419 void DropNextTracer(int64_t oldVal, int64_t newVal);
424};
425
427 : TestCase("Basic mark operations")
428{
429 m_mode = mode;
430 m_dropNextCount = 0;
431}
432
433void
434CobaltQueueDiscMarkTest::DropNextTracer(int64_t /* oldVal */, int64_t /* newVal */)
435{
437}
438
439void
441{
442 // Test is divided into 3 sub test cases:
443 // 1) Packets are not ECN capable.
444 // 2) Packets are ECN capable.
445 // 3) Some packets are ECN capable.
446
447 // Test case 1
448 Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc>();
449 uint32_t pktSize = 1000;
450 uint32_t modeSize = 0;
453
454 if (m_mode == QueueSizeUnit::BYTES)
455 {
456 modeSize = pktSize;
457 }
458 else if (m_mode == QueueSizeUnit::PACKETS)
459 {
460 modeSize = 1;
461 }
462
464 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
465 true,
466 "Verify that we can actually set the attribute MaxSize");
467 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(false)),
468 true,
469 "Verify that we can actually set the attribute UseEcn");
470 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("BlueThreshold", TimeValue(Time::Max())),
471 true,
472 "Disable Blue enhancement");
473 queue->Initialize();
474
475 // Not-ECT traffic to induce packet drop
476 Enqueue(queue, pktSize, 20, false);
477 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
478 20 * modeSize,
479 "There should be 20 packets in queue.");
480
481 // Although the first dequeue occurs with a sojourn time above target
482 // there should not be any dropped packets in this interval
483 Time waitUntilFirstDequeue = 2 * queue->GetTarget();
484 Simulator::Schedule(waitUntilFirstDequeue,
486 this,
487 queue,
488 modeSize,
489 1);
490
491 // This dequeue should cause a packet to be dropped
492 Time waitUntilSecondDequeue = waitUntilFirstDequeue + 2 * queue->GetInterval();
493 Simulator::Schedule(waitUntilSecondDequeue,
495 this,
496 queue,
497 modeSize,
498 1);
499
502
503 // Test case 2, queue with ECN capable traffic for marking of packets instead of dropping
504 queue = CreateObject<CobaltQueueDisc>();
506 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
507 true,
508 "Verify that we can actually set the attribute MaxSize");
509 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
510 true,
511 "Verify that we can actually set the attribute UseEcn");
512 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("BlueThreshold", TimeValue(Time::Max())),
513 true,
514 "Disable Blue enhancement");
515 queue->Initialize();
516
517 // ECN capable traffic
518 Enqueue(queue, pktSize, 20, true);
519 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
520 20 * modeSize,
521 "There should be 20 packets in queue.");
522
523 // Although the first dequeue occurs with a sojourn time above target
524 // there should not be any marked packets in this interval
525 Simulator::Schedule(waitUntilFirstDequeue,
527 this,
528 queue,
529 modeSize,
530 2);
531
532 // This dequeue should cause a packet to be marked
533 Simulator::Schedule(waitUntilSecondDequeue,
535 this,
536 queue,
537 modeSize,
538 2);
539
540 // This dequeue should cause a packet to be marked as dropnext is equal to current time
541 Simulator::Schedule(waitUntilSecondDequeue,
543 this,
544 queue,
545 modeSize,
546 2);
547
548 // In dropping phase and it's time for next packet to be marked
549 // the dequeue should cause additional packet to be marked
550 Simulator::Schedule(waitUntilSecondDequeue * 2,
552 this,
553 queue,
554 modeSize,
555 2);
556
559
560 // Test case 3, some packets are ECN capable
561 queue = CreateObject<CobaltQueueDisc>();
563 queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(m_mode, modeSize * 500))),
564 true,
565 "Verify that we can actually set the attribute MaxSize");
566 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
567 true,
568 "Verify that we can actually set the attribute UseEcn");
569 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("BlueThreshold", TimeValue(Time::Max())),
570 true,
571 "Disable Blue enhancement");
572 queue->Initialize();
573
574 // First 3 packets in the queue are ecnCapable
575 Enqueue(queue, pktSize, 3, true);
576 // Rest of the packet are not ecnCapable
577 Enqueue(queue, pktSize, 17, false);
578 NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
579 20 * modeSize,
580 "There should be 20 packets in queue.");
581
582 // Although the first dequeue occurs with a sojourn time above target
583 // there should not be any marked packets in this interval
584 Simulator::Schedule(waitUntilFirstDequeue,
586 this,
587 queue,
588 modeSize,
589 3);
590
591 // This dequeue should cause a packet to be marked
592 Simulator::Schedule(waitUntilSecondDequeue,
594 this,
595 queue,
596 modeSize,
597 3);
598
599 // This dequeue should cause a packet to be marked as dropnext is equal to current time
600 Simulator::Schedule(waitUntilSecondDequeue,
602 this,
603 queue,
604 modeSize,
605 3);
606
607 // In dropping phase and it's time for next packet to be dropped as packets are not ECN capable
608 // the dequeue should cause packet to be dropped
609 Simulator::Schedule(waitUntilSecondDequeue * 2,
611 this,
612 queue,
613 modeSize,
614 3);
615
618}
619
620void
622 uint32_t size,
623 uint32_t nPkt,
624 bool ecnCapable)
625{
626 Address dest;
627 for (uint32_t i = 0; i < nPkt; i++)
628 {
629 queue->Enqueue(Create<CobaltQueueDiscTestItem>(Create<Packet>(size), dest, ecnCapable));
630 }
631}
632
633void
635{
636 uint32_t initialMarkCount = queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK);
637 uint32_t initialQSize = queue->GetCurrentSize().GetValue();
638 uint32_t initialDropNext = queue->GetDropNext();
639 Time currentTime = Simulator::Now();
640 uint32_t currentDropCount = 0;
641 uint32_t currentMarkCount = 0;
642
643 if (initialMarkCount > 0 && currentTime.GetNanoSeconds() > initialDropNext && testCase == 3)
644 {
645 queue->TraceConnectWithoutContext(
646 "DropNext",
648 }
649
650 if (initialQSize != 0)
651 {
652 Ptr<QueueDiscItem> item = queue->Dequeue();
653 if (testCase == 1)
654 {
655 currentDropCount =
656 queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP);
657 if (currentDropCount != 0)
658 {
659 nPacketsBeforeFirstDrop = initialQSize;
660 }
661 }
662 if (testCase == 2)
663 {
664 if (initialMarkCount == 0 && currentTime > queue->GetTarget())
665 {
666 if (currentTime < queue->GetInterval())
667 {
668 currentDropCount =
669 queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP);
670 currentMarkCount =
671 queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK);
672 NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
673 initialQSize - modeSize,
674 "There should be 1 packet dequeued.");
675 NS_TEST_EXPECT_MSG_EQ(currentDropCount,
676 0,
677 "There should not be any packet drops");
678 NS_TEST_EXPECT_MSG_EQ(currentMarkCount,
679 0,
680 "We are not in dropping state."
681 "Sojourn time has just gone above target from below."
682 "Hence, there should be no marked packets");
683 }
684 else if (currentTime >= queue->GetInterval())
685 {
686 nPacketsBeforeFirstMark = initialQSize;
687 currentDropCount =
688 queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP);
689 currentMarkCount =
690 queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK);
692 queue->GetCurrentSize().GetValue(),
693 initialQSize - modeSize,
694 "Sojourn time has been above target for at least interval."
695 "We enter the dropping state and perform initial packet marking"
696 "So there should be only 1 more packet dequeued.");
697 NS_TEST_EXPECT_MSG_EQ(currentDropCount,
698 0,
699 "There should not be any packet drops");
700 NS_TEST_EXPECT_MSG_EQ(currentMarkCount, 1, "There should be 1 marked packet");
701 }
702 }
703 else if (initialMarkCount > 0)
704 {
705 if (currentTime.GetNanoSeconds() <= initialDropNext)
706 {
707 currentDropCount =
708 queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP);
709 currentMarkCount =
710 queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK);
711 NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
712 initialQSize - modeSize,
713 "We are in dropping state."
714 "Sojourn is still above target."
715 "There should be only 1 more packet dequeued");
716 NS_TEST_EXPECT_MSG_EQ(currentDropCount,
717 0,
718 "There should not be any packet drops");
719 NS_TEST_EXPECT_MSG_EQ(currentMarkCount,
720 2,
721 "There should be 2 marked packet as."
722 "current dropnext is equal to current time.");
723 }
724 else if (currentTime.GetNanoSeconds() > initialDropNext)
725 {
726 currentDropCount =
727 queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP);
728 currentMarkCount =
729 queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK);
730 NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
731 initialQSize - modeSize,
732 "We are in dropping state."
733 "It's time for packet to be marked"
734 "So there should be only 1 more packet dequeued");
735 NS_TEST_EXPECT_MSG_EQ(currentDropCount,
736 0,
737 "There should not be any packet drops");
738 NS_TEST_EXPECT_MSG_EQ(currentMarkCount, 3, "There should be 3 marked packet");
742 "Number of packets in the queue before drop should be equal"
743 "to number of packets in the queue before first mark as the behavior until "
744 "packet N should be the same.");
745 }
746 }
747 }
748 else if (testCase == 3)
749 {
750 if (initialMarkCount == 0 && currentTime > queue->GetTarget())
751 {
752 if (currentTime < queue->GetInterval())
753 {
754 currentDropCount =
755 queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP);
756 currentMarkCount =
757 queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK);
758 NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
759 initialQSize - modeSize,
760 "There should be 1 packet dequeued.");
761 NS_TEST_EXPECT_MSG_EQ(currentDropCount,
762 0,
763 "There should not be any packet drops");
764 NS_TEST_EXPECT_MSG_EQ(currentMarkCount,
765 0,
766 "We are not in dropping state."
767 "Sojourn time has just gone above target from below."
768 "Hence, there should be no marked packets");
769 }
770 else if (currentTime >= queue->GetInterval())
771 {
772 currentDropCount =
773 queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP);
774 currentMarkCount =
775 queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK);
777 queue->GetCurrentSize().GetValue(),
778 initialQSize - modeSize,
779 "Sojourn time has been above target for at least interval."
780 "We enter the dropping state and perform initial packet marking"
781 "So there should be only 1 more packet dequeued.");
782 NS_TEST_EXPECT_MSG_EQ(currentDropCount,
783 0,
784 "There should not be any packet drops");
785 NS_TEST_EXPECT_MSG_EQ(currentMarkCount, 1, "There should be 1 marked packet");
786 }
787 }
788 else if (initialMarkCount > 0)
789 {
790 if (currentTime.GetNanoSeconds() <= initialDropNext)
791 {
792 currentDropCount =
793 queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP);
794 currentMarkCount =
795 queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK);
796 NS_TEST_EXPECT_MSG_EQ(queue->GetCurrentSize().GetValue(),
797 initialQSize - modeSize,
798 "We are in dropping state."
799 "Sojourn is still above target."
800 "So there should be only 1 more packet dequeued");
801 NS_TEST_EXPECT_MSG_EQ(currentDropCount,
802 0,
803 "There should not be any packet drops");
804 NS_TEST_EXPECT_MSG_EQ(currentMarkCount,
805 2,
806 "There should be 2 marked packet"
807 "as dropnext is equal to current time");
808 }
809 else if (currentTime.GetNanoSeconds() > initialDropNext)
810 {
811 currentDropCount =
812 queue->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP);
813 currentMarkCount =
814 queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK);
816 queue->GetCurrentSize().GetValue(),
817 initialQSize - (m_dropNextCount + 1) * modeSize,
818 "We are in dropping state."
819 "It's time for packet to be dropped as packets are not ecnCapable"
820 "The number of packets dequeued equals to the number of times m_dropNext "
821 "is updated plus initial dequeue");
823 currentDropCount,
825 "The number of drops equals to the number of times m_dropNext is updated");
826 NS_TEST_EXPECT_MSG_EQ(currentMarkCount,
827 2,
828 "There should still be only 2 marked packet");
829 }
830 }
831 }
832 }
833}
834
841{
842 public:
850
851 private:
852 void DoRun() override;
859 void Enqueue(Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt);
867 void EnqueueWithDelay(Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt, Time delay);
873 void Dequeue(Ptr<CobaltQueueDisc> queue, uint32_t modeSize);
881 void DequeueWithDelay(Ptr<CobaltQueueDisc> queue, uint32_t modeSize, uint32_t nPkt, Time delay);
883};
884
886 : TestCase("Test CE Threshold marking")
887{
888 m_mode = mode;
889}
890
892{
893}
894
895void
897{
898 Address dest;
899 for (uint32_t i = 0; i < nPkt; i++)
900 {
901 queue->Enqueue(Create<CobaltQueueDiscTestItem>(Create<Packet>(size), dest, true));
902 }
903}
904
905void
907 uint32_t size,
908 uint32_t nPkt,
909 Time delay)
910{
911 for (uint32_t i = 0; i < nPkt; i++)
912 {
913 Simulator::Schedule(Time(Seconds((i + 1) * delay.GetSeconds())),
915 this,
916 queue,
917 size,
918 1);
919 }
920}
921
922void
924{
925 Ptr<QueueDiscItem> item = queue->Dequeue();
926
928 {
930 queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
931 1,
932 "There should be only 1 packet"
933 "mark, the delay between the enqueueing of the packets decreased after the"
934 "1st mark (packet enqueued at 11ms) and increased for the packet enqueued after 20.6ms."
935 "Queue delay remains below or equal to 1ms for the packet enqueued before 28ms");
936 }
937 if (Simulator::Now() > MilliSeconds(31))
938 {
940 queue->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
941 3,
942 "There should be 3 packet"
943 "marks, the delay between the enqueueing of the packets decreased after 1st mark"
944 "(packet enqueued at 11ms) and increased for the packet enqueued after 20.6ms."
945 "Queue delay remains below 1ms for the packets enqueued before 28ms and increases"
946 "for the packets enqueued after 28ms.");
947 }
948}
949
950void
952 uint32_t modeSize,
953 uint32_t nPkt,
954 Time delay)
955{
956 for (uint32_t i = 0; i < nPkt; i++)
957 {
958 Simulator::Schedule(Time(Seconds((i + 1) * delay.GetSeconds())),
960 this,
961 queue,
962 modeSize);
963 }
964}
965
966void
968{
969 Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc>();
970 uint32_t pktSize = 1000;
971 uint32_t modeSize = 0;
972
973 if (m_mode == QueueSizeUnit::BYTES)
974 {
975 modeSize = pktSize;
976 }
977 else if (m_mode == QueueSizeUnit::PACKETS)
978 {
979 modeSize = 1;
980 }
981
982 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
983 true,
984 "Verify that we can actually set the attribute UseEcn");
985 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("CeThreshold", TimeValue(MilliSeconds(1))),
986 true,
987 "Verify that we can actually set the attribute UseEcn");
988 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("BlueThreshold", TimeValue(Time::Max())),
989 true,
990 "Disable Blue enhancement");
991 queue->Initialize();
992
993 // Enqueue 11 packets every 1ms
994 EnqueueWithDelay(queue, pktSize, 11, MilliSeconds(1));
995
996 // With every dequeue, queue delay increases by 0.1ms as packet enqueues every 1ms while
997 // dequeues at 1.1ms so at 11th dequeue, the dequeued packet should be marked.
998 Time dequeueInterval = MicroSeconds(1100);
999 DequeueWithDelay(queue, modeSize, 11, dequeueInterval);
1000
1001 // First mark occurred for the packet enqueued at 11ms, ideally TCP would decrease sending rate
1002 // which can be simulated by increasing interval between subsequent enqueues, so packets are now
1003 // enqueued with a delay 1.2ms.
1004 Time waitUntilFirstMark = MilliSeconds(11);
1005 Simulator::Schedule(waitUntilFirstMark,
1007 this,
1008 queue,
1009 pktSize,
1010 9,
1011 MicroSeconds(1200));
1012
1013 // Keep dequeueing with the same delay
1014 Simulator::Schedule(waitUntilFirstMark,
1016 this,
1017 queue,
1018 modeSize,
1019 9,
1020 dequeueInterval);
1021
1022 // Queue delay becomes 0.2ms for the packet enqueued at 20.6ms, time to decrease interval
1023 // between subsequent enqueues, as ideally TCP would again start increasing sending rate
1024 Time waitUntilDecreasingEnqueueDelay = waitUntilFirstMark + MilliSeconds(9);
1025 Simulator::Schedule(waitUntilDecreasingEnqueueDelay,
1027 this,
1028 queue,
1029 pktSize,
1030 10,
1031 MilliSeconds(1));
1032
1033 // Keep dequeueing with the same delay
1034 Simulator::Schedule(waitUntilFirstMark,
1036 this,
1037 queue,
1038 modeSize,
1039 10,
1040 dequeueInterval);
1041
1044}
1045
1059{
1060 public:
1068
1069 private:
1070 void DoRun() override;
1077 void Enqueue(Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt);
1082 void Dequeue(Ptr<CobaltQueueDisc> queue);
1089 void DequeueWithDelay(Ptr<CobaltQueueDisc> queue, uint32_t nPkt, Time delay);
1091};
1092
1094 : TestCase("Enhanced Blue tests verification for both packets and bytes mode")
1095{
1096 m_mode = mode;
1097}
1098
1100{
1101}
1102
1103void
1105
1106{
1107 uint32_t pktSize = 1500;
1108 uint32_t modeSize = 0;
1109 Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc>();
1110
1111 if (m_mode == QueueSizeUnit::BYTES)
1112 {
1113 modeSize = pktSize;
1114 }
1115 else if (m_mode == QueueSizeUnit::PACKETS)
1116 {
1117 modeSize = 1;
1118 }
1119 queue->Initialize();
1120 queue->AssignStreams(1);
1121 Enqueue(queue, modeSize, 200);
1122 DequeueWithDelay(queue, 100, MilliSeconds(10));
1123
1126
1127 QueueDisc::Stats st = queue->GetStats();
1128
1129 // The Pdrop value should increase, from it's default value of zero
1131 queue->GetPdrop(),
1132 0.234375,
1133 "Pdrop should be increased by 1/256 for every packet whose sojourn time is above 400ms."
1134 " From the 41st dequeue until the last one, sojourn time is above 400ms, so 60 packets "
1135 "have sojourn time above 400ms"
1136 "hence Pdrop should be increased 60*(1/256) which is 0.234375");
1138 49,
1139 "There should a fixed number of drops (49 here)");
1141
1142 queue = CreateObject<CobaltQueueDisc>();
1143 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
1144 true,
1145 "Verify that we can actually set the attribute UseEcn");
1146 NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("BlueThreshold", TimeValue(Time::Max())),
1147 true,
1148 "Disable Blue enhancement");
1149 queue->Initialize();
1150 Enqueue(queue, modeSize, 200);
1151 DequeueWithDelay(queue, 100, MilliSeconds(10));
1152
1155
1156 st = queue->GetStats();
1157
1158 NS_TEST_ASSERT_MSG_EQ(queue->GetPdrop(), 0, "Pdrop should be zero");
1160 0,
1161 "There should not any dropped packets");
1163}
1164
1165void
1167{
1168 Address dest;
1169 for (uint32_t i = 0; i < nPkt; i++)
1170 {
1171 queue->Enqueue(Create<CobaltQueueDiscTestItem>(Create<Packet>(size), dest, true));
1172 }
1173}
1174
1175void
1177{
1178 Ptr<QueueDiscItem> item = queue->Dequeue();
1179}
1180
1181void
1183 uint32_t nPkt,
1184 Time delay)
1185{
1186 for (uint32_t i = 0; i < nPkt; i++)
1187 {
1188 Simulator::Schedule(Time(Seconds((i + 1) * delay.GetSeconds())),
1190 this,
1191 queue);
1192 }
1193}
1194
1200{
1201 public:
1203 : TestSuite("cobalt-queue-disc", UNIT)
1204 {
1205 // Test 1: simple enqueue/dequeue with no drops
1208 // Test 2: Drop test
1210 // Test 3: Mark test
1213 // Test 4: CE threshold marking test
1216 // Test 4: Blue enhancement test
1219 }
Test 1: simple enqueue/dequeue with no drops.
QueueSizeUnit m_mode
Queue test size function.
void DoRun() override
Implementation to actually run this TestCase.
CobaltQueueDiscBasicEnqueueDequeue(QueueSizeUnit mode)
Constructor.
Test 4: Cobalt Queue Disc CE Threshold marking Test Item.
CobaltQueueDiscCeThresholdTest(QueueSizeUnit mode)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
void DequeueWithDelay(Ptr< CobaltQueueDisc > queue, uint32_t modeSize, uint32_t nPkt, Time delay)
Dequeue with delay function.
void Enqueue(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
void EnqueueWithDelay(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt, Time delay)
Enqueue with delay function.
void Dequeue(Ptr< CobaltQueueDisc > queue, uint32_t modeSize)
Dequeue function.
Test 2: Cobalt Queue Disc Drop Test Item.
void DoRun() override
Implementation to actually run this TestCase.
void RunDropTest(QueueSizeUnit mode)
Run Cobalt test function.
void Enqueue(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
void EnqueueWithDelay(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue the given number of packets, each of the given size, at different times.
Test 5: Cobalt Queue Disc Enhanced Blue Test Item This test checks that the Blue Enhancement is worki...
CobaltQueueDiscEnhancedBlueTest(QueueSizeUnit mode)
Constructor.
void Dequeue(Ptr< CobaltQueueDisc > queue)
Dequeue function.
void DoRun() override
Implementation to actually run this TestCase.
void Enqueue(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
void DequeueWithDelay(Ptr< CobaltQueueDisc > queue, uint32_t nPkt, Time delay)
Dequeue with delay function.
Test 3: Cobalt Queue Disc ECN marking Test Item.
CobaltQueueDiscMarkTest(QueueSizeUnit mode)
Constructor.
uint32_t nPacketsBeforeFirstMark
Number of packets in the queue before first mark.
void Enqueue(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt, bool ecnCapable)
Enqueue function.
void DropNextTracer(int64_t oldVal, int64_t newVal)
Drop next tracer function.
uint32_t nPacketsBeforeFirstDrop
Number of packets in the queue before first drop.
void DoRun() override
Implementation to actually run this TestCase.
void Dequeue(Ptr< CobaltQueueDisc > queue, uint32_t modeSize, uint32_t testCase)
Dequeue function.
uint32_t m_dropNextCount
count the number of times m_dropNext is recalculated
Cobalt Queue Disc Test Item.
bool m_ecnCapablePacket
ECN capable packet?
CobaltQueueDiscTestItem()=delete
CobaltQueueDiscTestItem & operator=(const CobaltQueueDiscTestItem &)=delete
void AddHeader() override
Add the header to the packet.
CobaltQueueDiscTestItem(const CobaltQueueDiscTestItem &)=delete
bool Mark() override
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification.
The COBALT queue disc test suite.
a polymophic address class
Definition: address.h:100
AttributeValue implementation for Boolean.
Definition: boolean.h:37
static constexpr const char * CE_THRESHOLD_EXCEEDED_MARK
Sojourn time above CE threshold.
static constexpr const char * TARGET_EXCEEDED_DROP
Sojourn time above target.
static constexpr const char * FORCED_MARK
forced marks by Codel on ECN-enabled
static constexpr const char * OVERLIMIT_DROP
Overlimit dropped packet.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
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.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:140
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
static void Run()
Run the simulation.
Definition: simulator.cc:176
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:184
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1060
@ QUICK
Fast test.
Definition: test.h:1065
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 GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:417
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:402
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition: nstime.h:296
AttributeValue implementation for Time.
Definition: nstime.h:1423
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
#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 MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
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
CobaltQueueDiscTestSuite g_cobaltQueueTestSuite
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
STL namespace.
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:188
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
Definition: queue-disc.cc:111
uint32_t pktSize
packet size used for the simulation (in bytes)