A Discrete-Event Network Simulator
API
cobalt-queue-disc-test-suite.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2019 NITK Surathkal
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Ported to ns-3 by: Vignesh Kannan <vignesh2496@gmail.com>
19 * Harsh Lara <harshapplefan@gmail.com>
20 * Jendaipou Palmei <jendaipoupalmei@gmail.com>
21 * Shefali Gupta <shefaligups11@gmail.com>
22 * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
23 */
24
25#include "ns3/test.h"
26#include "ns3/cobalt-queue-disc.h"
27#include "ns3/packet.h"
28#include "ns3/uinteger.h"
29#include "ns3/string.h"
30#include "ns3/double.h"
31#include "ns3/log.h"
32#include "ns3/simulator.h"
33
34using namespace ns3;
42{
43public:
52 CobaltQueueDiscTestItem (Ptr<Packet> p, const Address & addr,uint16_t protocol, bool ecnCapable);
53 virtual ~CobaltQueueDiscTestItem ();
54
55 // Delete copy constructor and assignment operator to avoid misuse
58
59 virtual void AddHeader (void);
60 virtual bool Mark (void);
61
62private:
64
66};
67
68CobaltQueueDiscTestItem::CobaltQueueDiscTestItem (Ptr<Packet> p, const Address & addr,uint16_t protocol, bool ecnCapable)
69 : QueueDiscItem (p, addr, ecnCapable),
70 m_ecnCapablePacket (ecnCapable)
71{
72}
73
75{
76}
77
78void
80{
81}
82
83bool
85{
87 {
88 return true;
89 }
90 return false;
91}
92
100{
101public:
108 virtual void DoRun (void);
109
118private:
120};
121
123 : TestCase ("Basic enqueue and dequeue operations, and attribute setting" + std::to_string (mode))
124{
125 m_mode = mode;
126}
127
128void
130{
131 Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
132
133 uint32_t pktSize = 1000;
134 uint32_t modeSize = 0;
135
136 Address dest;
137
138 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("Interval", StringValue ("50ms")), true,
139 "Verify that we can actually set the attribute Interval");
140 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("Target", StringValue ("4ms")), true,
141 "Verify that we can actually set the attribute Target");
142 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
143 "Disable Blue enhancement");
144
146 {
147 modeSize = pktSize;
148 }
149 else if (m_mode == QueueSizeUnit::PACKETS)
150 {
151 modeSize = 1;
152 }
153 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 1500))),
154 true, "Verify that we can actually set the attribute MaxSize");
155 queue->Initialize ();
156
157 Ptr<Packet> p1, p2, p3, p4, p5, p6;
158 p1 = Create<Packet> (pktSize);
159 p2 = Create<Packet> (pktSize);
160 p3 = Create<Packet> (pktSize);
161 p4 = Create<Packet> (pktSize);
162 p5 = Create<Packet> (pktSize);
163 p6 = Create<Packet> (pktSize);
164
165 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 0 * modeSize, "There should be no packets in queue");
166 queue->Enqueue (Create<CobaltQueueDiscTestItem> (p1, dest,0, false));
167 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 1 * modeSize, "There should be one packet in queue");
168 queue->Enqueue (Create<CobaltQueueDiscTestItem> (p2, dest,0, false));
169 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 2 * modeSize, "There should be two packets in queue");
170 queue->Enqueue (Create<CobaltQueueDiscTestItem> (p3, dest,0, false));
171 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 3 * modeSize, "There should be three packets in queue");
172 queue->Enqueue (Create<CobaltQueueDiscTestItem> (p4, dest,0, false));
173 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 4 * modeSize, "There should be four packets in queue");
174 queue->Enqueue (Create<CobaltQueueDiscTestItem> (p5, dest,0, false));
175 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 5 * modeSize, "There should be five packets in queue");
176 queue->Enqueue (Create<CobaltQueueDiscTestItem> (p6, dest,0, false));
177 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 6 * modeSize, "There should be six packets in queue");
178
179 NS_TEST_ASSERT_MSG_EQ (queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::OVERLIMIT_DROP), 0, "There should be no packets being dropped due to full queue");
180
182
183 item = queue->Dequeue ();
184 NS_TEST_ASSERT_MSG_EQ ((item != 0), true, "I want to remove the first packet");
185 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 5 * modeSize, "There should be five packets in queue");
186 NS_TEST_ASSERT_MSG_EQ (item->GetPacket ()->GetUid (), p1->GetUid (), "was this the first packet ?");
187
188 item = queue->Dequeue ();
189 NS_TEST_ASSERT_MSG_EQ ((item != 0), true, "I want to remove the second packet");
190 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 4 * modeSize, "There should be four packets in queue");
191 NS_TEST_ASSERT_MSG_EQ (item->GetPacket ()->GetUid (), p2->GetUid (), "Was this the second packet ?");
192
193 item = queue->Dequeue ();
194 NS_TEST_ASSERT_MSG_EQ ((item != 0), true, "I want to remove the third packet");
195 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 3 * modeSize, "There should be three packets in queue");
196 NS_TEST_ASSERT_MSG_EQ (item->GetPacket ()->GetUid (), p3->GetUid (), "Was this the third packet ?");
197
198 item = queue->Dequeue ();
199 NS_TEST_ASSERT_MSG_EQ ((item != 0), true, "I want to remove the forth packet");
200 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 2 * modeSize, "There should be two packets in queue");
201 NS_TEST_ASSERT_MSG_EQ (item->GetPacket ()->GetUid (), p4->GetUid (), "Was this the fourth packet ?");
202
203 item = queue->Dequeue ();
204 NS_TEST_ASSERT_MSG_EQ ((item != 0), true, "I want to remove the fifth packet");
205 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 1 * modeSize, "There should be one packet in queue");
206 NS_TEST_ASSERT_MSG_EQ (item->GetPacket ()->GetUid (), p5->GetUid (), "Was this the fifth packet ?");
207
208 item = queue->Dequeue ();
209 NS_TEST_ASSERT_MSG_EQ ((item != 0), true, "I want to remove the last packet");
210 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 0 * modeSize, "There should be zero packet in queue");
211 NS_TEST_ASSERT_MSG_EQ (item->GetPacket ()->GetUid (), p6->GetUid (), "Was this the sixth packet ?");
212
213 item = queue->Dequeue ();
214 NS_TEST_ASSERT_MSG_EQ ((item == 0), true, "There are really no packets in queue");
215
216 NS_TEST_ASSERT_MSG_EQ (queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should be no packet drops according to Cobalt algorithm");
217}
218
226{
227public:
229 virtual void DoRun (void);
236 void Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt);
241 void RunDropTest (QueueSizeUnit mode);
251
252};
253
255 : TestCase ("Drop tests verification for both packets and bytes mode")
256{
257}
258
259void
261
262{
263 uint32_t pktSize = 1500;
264 uint32_t modeSize = 0;
265 Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
266
267 if (mode == QueueSizeUnit::BYTES)
268 {
269 modeSize = pktSize;
270 }
271 else if (mode == QueueSizeUnit::PACKETS)
272 {
273 modeSize = 1;
274 }
275
276 queue = CreateObject<CobaltQueueDisc> ();
277 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, modeSize * 100))),
278 true, "Verify that we can actually set the attribute MaxSize");
279 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
280 "Disable Blue enhancement");
281 queue->Initialize ();
282
283 if (mode == QueueSizeUnit::BYTES)
284 {
285 EnqueueWithDelay (queue, pktSize, 200);
286 }
287 else
288 {
289 EnqueueWithDelay (queue, 1, 200);
290 }
291
292 Simulator::Stop (Seconds (8.0));
293 Simulator::Run ();
294
295 QueueDisc::Stats st = queue->GetStats ();
296
297// The Pdrop value should increase, from it's default value of zero
298 NS_TEST_ASSERT_MSG_NE (queue->GetPdrop (), 0, "Pdrop should be non-zero");
299 NS_TEST_ASSERT_MSG_NE (st.GetNDroppedPackets (CobaltQueueDisc::OVERLIMIT_DROP), 0, "Drops due to queue overflow should be non-zero");
300}
301
302void
304{
305 Address dest;
306 double delay = 0.01; // enqueue packets with delay
307 for (uint32_t i = 0; i < nPkt; i++)
308 {
309 Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &CobaltQueueDiscDropTest::Enqueue, this, queue, size, 1);
310 }
311}
312
313void
315{
316 Address dest;
317 for (uint32_t i = 0; i < nPkt; i++)
318 {
319 queue->Enqueue (Create<CobaltQueueDiscTestItem> (Create<Packet> (size), dest, 0, true));
320 }
321}
322
323void
325{
328 Simulator::Destroy ();
329}
330
338{
339public:
346 virtual void DoRun (void);
347
348private:
356 void Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt, bool ecnCapable);
363 void Dequeue (Ptr<CobaltQueueDisc> queue, uint32_t modeSize, uint32_t testCase);
369 void DropNextTracer (int64_t oldVal, int64_t newVal);
374};
375
377 : TestCase ("Basic mark operations")
378{
379 m_mode = mode;
380 m_dropNextCount = 0;
381}
382
383void
384CobaltQueueDiscMarkTest::DropNextTracer ([[maybe_unused]] int64_t oldVal, [[maybe_unused]] int64_t newVal)
385{
387}
388
389void
391{
392 // Test is divided into 3 sub test cases:
393 // 1) Packets are not ECN capable.
394 // 2) Packets are ECN capable.
395 // 3) Some packets are ECN capable.
396
397 // Test case 1
398 Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
399 uint32_t pktSize = 1000;
400 uint32_t modeSize = 0;
403
405 {
406 modeSize = pktSize;
407 }
408 else if (m_mode == QueueSizeUnit::PACKETS)
409 {
410 modeSize = 1;
411 }
412
413 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 500))),
414 true, "Verify that we can actually set the attribute MaxSize");
415 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (false)),
416 true, "Verify that we can actually set the attribute UseEcn");
417 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
418 "Disable Blue enhancement");
419 queue->Initialize ();
420
421 // Not-ECT traffic to induce packet drop
422 Enqueue (queue, pktSize, 20, false);
423 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 20 * modeSize, "There should be 20 packets in queue.");
424
425 // Although the first dequeue occurs with a sojourn time above target
426 // there should not be any dropped packets in this interval
427 Time waitUntilFirstDequeue = 2 * queue->GetTarget ();
428 Simulator::Schedule (waitUntilFirstDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 1);
429
430 // This dequeue should cause a packet to be dropped
431 Time waitUntilSecondDequeue = waitUntilFirstDequeue + 2 * queue->GetInterval ();
432 Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 1);
433
434 Simulator::Run ();
435 Simulator::Destroy ();
436
437 // Test case 2, queue with ECN capable traffic for marking of packets instead of dropping
438 queue = CreateObject<CobaltQueueDisc> ();
439 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 500))),
440 true, "Verify that we can actually set the attribute MaxSize");
441 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)),
442 true, "Verify that we can actually set the attribute UseEcn");
443 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
444 "Disable Blue enhancement");
445 queue->Initialize ();
446
447 // ECN capable traffic
448 Enqueue (queue, pktSize, 20, true);
449 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 20 * modeSize, "There should be 20 packets in queue.");
450
451 // Although the first dequeue occurs with a sojourn time above target
452 // there should not be any marked packets in this interval
453 Simulator::Schedule (waitUntilFirstDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
454
455 // This dequeue should cause a packet to be marked
456 Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
457
458 // This dequeue should cause a packet to be marked as dropnext is equal to current time
459 Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
460
461 // In dropping phase and it's time for next packet to be marked
462 // the dequeue should cause additional packet to be marked
463 Simulator::Schedule (waitUntilSecondDequeue * 2, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
464
465 Simulator::Run ();
466 Simulator::Destroy ();
467
468 // Test case 3, some packets are ECN capable
469 queue = CreateObject<CobaltQueueDisc> ();
470 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 500))),
471 true, "Verify that we can actually set the attribute MaxSize");
472 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)),
473 true, "Verify that we can actually set the attribute UseEcn");
474 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
475 "Disable Blue enhancement");
476 queue->Initialize ();
477
478 // First 3 packets in the queue are ecnCapable
479 Enqueue (queue, pktSize, 3, true);
480 // Rest of the packet are not ecnCapable
481 Enqueue (queue, pktSize, 17, false);
482 NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 20 * modeSize, "There should be 20 packets in queue.");
483
484 // Although the first dequeue occurs with a sojourn time above target
485 // there should not be any marked packets in this interval
486 Simulator::Schedule (waitUntilFirstDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
487
488 // This dequeue should cause a packet to be marked
489 Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
490
491 // This dequeue should cause a packet to be marked as dropnext is equal to current time
492 Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
493
494 // In dropping phase and it's time for next packet to be dropped as packets are not ECN capable
495 // the dequeue should cause packet to be dropped
496 Simulator::Schedule (waitUntilSecondDequeue * 2, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
497
498 Simulator::Run ();
499 Simulator::Destroy ();
500}
501
502void
504{
505 Address dest;
506 for (uint32_t i = 0; i < nPkt; i++)
507 {
508 queue->Enqueue (Create<CobaltQueueDiscTestItem> (Create<Packet> (size), dest, 0, ecnCapable));
509 }
510}
511
512void
514{
515 uint32_t initialMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
516 uint32_t initialQSize = queue->GetCurrentSize ().GetValue ();
517 uint32_t initialDropNext = queue->GetDropNext ();
518 Time currentTime = Simulator::Now ();
519 uint32_t currentDropCount = 0;
520 uint32_t currentMarkCount = 0;
521
522 if (initialMarkCount > 0 && currentTime.GetNanoSeconds () > initialDropNext && testCase == 3)
523 {
524 queue->TraceConnectWithoutContext ("DropNext", MakeCallback (&CobaltQueueDiscMarkTest::DropNextTracer, this));
525 }
526
527 if (initialQSize != 0)
528 {
529 Ptr<QueueDiscItem> item = queue->Dequeue ();
530 if (testCase == 1)
531 {
532 currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
533 if (currentDropCount != 0)
534 {
535 nPacketsBeforeFirstDrop = initialQSize;
536 }
537 }
538 if (testCase == 2)
539 {
540 if (initialMarkCount == 0 && currentTime > queue->GetTarget ())
541 {
542 if (currentTime < queue->GetInterval ())
543 {
544 currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
545 currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
546 NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "There should be 1 packet dequeued.");
547 NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
548 NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 0, "We are not in dropping state."
549 "Sojourn time has just gone above target from below."
550 "Hence, there should be no marked packets");
551 }
552 else if (currentTime >= queue->GetInterval ())
553 {
554 nPacketsBeforeFirstMark = initialQSize;
555 currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
556 currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
557 NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize,
558 "Sojourn time has been above target for at least interval."
559 "We enter the dropping state and perform initial packet marking"
560 "So there should be only 1 more packet dequeued.");
561 NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
562 NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 1, "There should be 1 marked packet");
563 }
564 }
565 else if (initialMarkCount > 0)
566 {
567 if (currentTime.GetNanoSeconds () <= initialDropNext)
568 {
569 currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
570 currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
571 NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "We are in dropping state."
572 "Sojourn is still above target."
573 "There should be only 1 more packet dequeued");
574 NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
575 NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 2, "There should be 2 marked packet as."
576 "current dropnext is equal to current time.");
577 }
578 else if (currentTime.GetNanoSeconds () > initialDropNext)
579 {
580 currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
581 currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
582 NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "We are in dropping state."
583 "It's time for packet to be marked"
584 "So there should be only 1 more packet dequeued");
585 NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
586 NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 3, "There should be 3 marked packet");
587 NS_TEST_EXPECT_MSG_EQ (nPacketsBeforeFirstDrop, nPacketsBeforeFirstMark, "Number of packets in the queue before drop should be equal"
588 "to number of packets in the queue before first mark as the behavior until packet N should be the same.");
589 }
590 }
591 }
592 else if (testCase == 3)
593 {
594 if (initialMarkCount == 0 && currentTime > queue->GetTarget ())
595 {
596 if (currentTime < queue->GetInterval ())
597 {
598 currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
599 currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
600 NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "There should be 1 packet dequeued.");
601 NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
602 NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 0, "We are not in dropping state."
603 "Sojourn time has just gone above target from below."
604 "Hence, there should be no marked packets");
605 }
606 else if (currentTime >= queue->GetInterval ())
607 {
608 currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
609 currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
610 NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize,
611 "Sojourn time has been above target for at least interval."
612 "We enter the dropping state and perform initial packet marking"
613 "So there should be only 1 more packet dequeued.");
614 NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
615 NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 1, "There should be 1 marked packet");
616 }
617 }
618 else if (initialMarkCount > 0)
619 {
620 if (currentTime.GetNanoSeconds () <= initialDropNext)
621 {
622 currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
623 currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
624 NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "We are in dropping state."
625 "Sojourn is still above target."
626 "So there should be only 1 more packet dequeued");
627 NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
628 NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 2, "There should be 2 marked packet"
629 "as dropnext is equal to current time");
630 }
631 else if (currentTime.GetNanoSeconds () > initialDropNext)
632 {
633 currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
634 currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
635 NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - (m_dropNextCount + 1) * modeSize, "We are in dropping state."
636 "It's time for packet to be dropped as packets are not ecnCapable"
637 "The number of packets dequeued equals to the number of times m_dropNext is updated plus initial dequeue");
638 NS_TEST_EXPECT_MSG_EQ (currentDropCount, m_dropNextCount, "The number of drops equals to the number of times m_dropNext is updated");
639 NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 2, "There should still be only 2 marked packet");
640 }
641 }
642 }
643 }
644}
645
653{
654public:
662
663private:
664 virtual void DoRun (void);
671 void Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt);
679 void EnqueueWithDelay (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt, Time delay);
685 void Dequeue (Ptr<CobaltQueueDisc> queue, uint32_t modeSize);
693 void DequeueWithDelay (Ptr<CobaltQueueDisc> queue, uint32_t modeSize, uint32_t nPkt, Time delay);
695};
696
698 : TestCase ("Test CE Threshold marking")
699{
700 m_mode = mode;
701}
702
704{
705}
706
707void
709{
710 Address dest;
711 for (uint32_t i = 0; i < nPkt; i++)
712 {
713 queue->Enqueue (Create<CobaltQueueDiscTestItem> (Create<Packet> (size), dest, 0, true));
714 }
715}
716
717void
719{
720 for (uint32_t i = 0; i < nPkt; i++)
721 {
722 Simulator::Schedule (Time (Seconds ((i + 1) * delay.GetSeconds ())), &CobaltQueueDiscCeThresholdTest::Enqueue, this, queue, size, 1);
723 }
724}
725
726void
728{
729 Ptr<QueueDiscItem> item = queue->Dequeue ();
730
731 if (Simulator::Now () > MilliSeconds (11) && Simulator::Now () < MilliSeconds (28))
732 {
733 NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 1, "There should be only 1 packet"
734 "mark, the delay between the enqueueing of the packets decreased after the"
735 "1st mark (packet enqueued at 11ms) and increased for the packet enqueued after 20.6ms."
736 "Queue delay remains below or equal to 1ms for the packet enqueued before 28ms");
737 }
738 if (Simulator::Now () > MilliSeconds (31) )
739 {
740 NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 3, "There should be 3 packet"
741 "marks, the delay between the enqueueing of the packets decreased after 1st mark"
742 "(packet enqueued at 11ms) and increased for the packet enqueued after 20.6ms."
743 "Queue delay remains below 1ms for the packets enqueued before 28ms and increases"
744 "for the packets enqueued after 28ms.");
745 }
746}
747
748void
750{
751 for (uint32_t i = 0; i < nPkt; i++)
752 {
753 Simulator::Schedule (Time (Seconds ((i + 1) * delay.GetSeconds ())), &CobaltQueueDiscCeThresholdTest::Dequeue, this, queue, modeSize);
754 }
755}
756
757void
759{
760 Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
761 uint32_t pktSize = 1000;
762 uint32_t modeSize = 0;
763
765 {
766 modeSize = pktSize;
767 }
768 else if (m_mode == QueueSizeUnit::PACKETS)
769 {
770 modeSize = 1;
771 }
772
773 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)),
774 true, "Verify that we can actually set the attribute UseEcn");
775 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("CeThreshold", TimeValue (MilliSeconds (1))),
776 true, "Verify that we can actually set the attribute UseEcn");
777 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
778 "Disable Blue enhancement");
779 queue->Initialize ();
780
781 // Enqueue 11 packets every 1ms
782 EnqueueWithDelay (queue, pktSize, 11, MilliSeconds (1));
783
784 // With every dequeue, queue delay increases by 0.1ms as packet enqueues every 1ms while dequeues at 1.1ms
785 // so at 11th dequeue, the dequeued packet should be marked.
786 Time dequeueInterval = MicroSeconds (1100);
787 DequeueWithDelay (queue, modeSize, 11, dequeueInterval);
788
789 // First mark occured for the packet enqueued at 11ms, ideally TCP would decrease sending rate
790 // which can be simulated by increasing interval between subsequent enqueues, so packets are now enqueued with a delay 1.2ms.
791 Time waitUntilFirstMark = MilliSeconds(11);
792 Simulator::Schedule (waitUntilFirstMark, &CobaltQueueDiscCeThresholdTest::EnqueueWithDelay, this, queue, pktSize, 9, MicroSeconds (1200));
793
794 // Keep dequeueing with the same delay
795 Simulator::Schedule (waitUntilFirstMark, &CobaltQueueDiscCeThresholdTest::DequeueWithDelay, this, queue, modeSize, 9, dequeueInterval);
796
797 // Queue delay becomes 0.2ms for the packet enqueued at 20.6ms, time to decrease interval between subsequent enqueues,
798 // as ideally TCP would again start increasing sending rate
799 Time waitUntilDecreasingEnqueueDelay = waitUntilFirstMark + MilliSeconds(9);
800 Simulator::Schedule (waitUntilDecreasingEnqueueDelay, &CobaltQueueDiscCeThresholdTest::EnqueueWithDelay, this, queue, pktSize, 10, MilliSeconds (1));
801
802 // Keep dequeueing with the same delay
803 Simulator::Schedule (waitUntilFirstMark, &CobaltQueueDiscCeThresholdTest::DequeueWithDelay, this, queue, modeSize, 10, dequeueInterval);
804
805 Simulator::Run ();
806 Simulator::Destroy ();
807}
808
809
823{
824public:
832
833private:
834 virtual void DoRun (void);
841 void Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt);
846 void Dequeue (Ptr<CobaltQueueDisc> queue);
853 void DequeueWithDelay (Ptr<CobaltQueueDisc> queue, uint32_t nPkt, Time delay);
855};
856
858 : TestCase ("Enhanced Blue tests verification for both packets and bytes mode")
859{
860 m_mode = mode;
861}
862
864{
865}
866
867void
869
870{
871 uint32_t pktSize = 1500;
872 uint32_t modeSize = 0;
873 Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
874
876 {
877 modeSize = pktSize;
878 }
879 else if (m_mode == QueueSizeUnit::PACKETS)
880 {
881 modeSize = 1;
882 }
883 queue->Initialize ();
884 queue->AssignStreams (1);
885 Enqueue (queue, modeSize, 200);
886 DequeueWithDelay (queue, 100, MilliSeconds (10));
887
888 Simulator::Stop (Seconds (8.0));
889 Simulator::Run ();
890
891 QueueDisc::Stats st = queue->GetStats ();
892
893 // The Pdrop value should increase, from it's default value of zero
894 NS_TEST_ASSERT_MSG_EQ (queue->GetPdrop (), 0.234375, "Pdrop should be increased by 1/256 for every packet whose sojourn time is above 400ms."
895 " From the 41st dequeue until the last one, sojourn time is above 400ms, so 60 packets have sojourn time above 400ms"
896 "hence Pdrop should be increased 60*(1/256) which is 0.234375");
897 NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 49, "There should a fixed number of drops (49 here)");
898 Simulator::Destroy ();
899
900
901 queue = CreateObject<CobaltQueueDisc> ();
902 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)),
903 true, "Verify that we can actually set the attribute UseEcn");
904 NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
905 "Disable Blue enhancement");
906 queue->Initialize ();
907 Enqueue (queue, modeSize, 200);
908 DequeueWithDelay (queue, 100, MilliSeconds (10));
909
910 Simulator::Stop (Seconds (8.0));
911 Simulator::Run ();
912
913 st = queue->GetStats ();
914
915 NS_TEST_ASSERT_MSG_EQ (queue->GetPdrop (), 0, "Pdrop should be zero");
916 NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not any dropped packets");
917 Simulator::Destroy ();
918}
919
920void
922{
923 Address dest;
924 for (uint32_t i = 0; i < nPkt; i++)
925 {
926 queue->Enqueue (Create<CobaltQueueDiscTestItem> (Create<Packet> (size), dest, 0, true));
927 }
928}
929
930void
932{
933 Ptr<QueueDiscItem> item = queue->Dequeue ();
934}
935
936void
938{
939 for (uint32_t i = 0; i < nPkt; i++)
940 {
941 Simulator::Schedule (Time (Seconds ((i + 1) * delay.GetSeconds ())), &CobaltQueueDiscEnhancedBlueTest::Dequeue, this, queue);
942 }
943}
944
945
950{
951public:
953 : TestSuite ("cobalt-queue-disc", UNIT)
954 {
955 // Test 1: simple enqueue/dequeue with no drops
958 // Test 2: Drop test
959 AddTestCase (new CobaltQueueDiscDropTest (), TestCase::QUICK);
960 // Test 3: Mark test
961 AddTestCase (new CobaltQueueDiscMarkTest (PACKETS), TestCase::QUICK);
962 AddTestCase (new CobaltQueueDiscMarkTest (BYTES), TestCase::QUICK);
963 // Test 4: CE threshold marking test
964 AddTestCase (new CobaltQueueDiscCeThresholdTest (PACKETS), TestCase::QUICK);
965 AddTestCase (new CobaltQueueDiscCeThresholdTest (BYTES), TestCase::QUICK);
966 // Test 4: Blue enhancement test
967 AddTestCase (new CobaltQueueDiscEnhancedBlueTest (PACKETS), TestCase::QUICK);
968 AddTestCase (new CobaltQueueDiscEnhancedBlueTest (BYTES), TestCase::QUICK);
969 }
#define Max(a, b)
Test 1: simple enqueue/dequeue with no drops.
QueueSizeUnit m_mode
Queue test size function.
CobaltQueueDiscBasicEnqueueDequeue(QueueSizeUnit mode)
Constructor.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Test 4: Cobalt Queue Disc CE Threshold marking Test Item.
CobaltQueueDiscCeThresholdTest(QueueSizeUnit mode)
Constructor.
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.
virtual void DoRun(void)
Implementation to actually run this TestCase.
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 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.
virtual void DoRun(void)
Implementation to actually run this TestCase.
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 Enqueue(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
virtual void DoRun(void)
Implementation to actually run this TestCase.
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.
virtual void DoRun(void)
Implementation to actually run this TestCase.
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 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?
virtual void AddHeader(void)
Add the header to the packet.
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification.
CobaltQueueDiscTestItem & operator=(const CobaltQueueDiscTestItem &)=delete
CobaltQueueDiscTestItem(const CobaltQueueDiscTestItem &)=delete
The COBALT queue disc test suite.
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:390
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:95
AttributeValue implementation for QueueSize.
Hold variables of type string.
Definition: string.h:41
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1197
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:391
AttributeValue implementation for Time.
Definition: nstime.h:1308
CobaltQueueDiscTestSuite g_cobaltQueueTestSuite
the test suite
QueueSizeUnit
Enumeration of the operating modes of queues.
Definition: queue-size.h:43
@ BYTES
Use number of bytes for queue size.
Definition: queue-size.h:45
@ PACKETS
Use number of packets for queue size.
Definition: queue-size.h:44
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
#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:141
#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:240
#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:542
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
STL namespace.
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:186
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
Definition: queue-disc.cc:109
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:89