A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
fq-cobalt-queue-disc-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 Universita' degli Studi di Napoli Federico II
3 * Copyright (c) 2020 NITK Surathkal (adapted for COBALT)
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 * Authors: Pasquale Imputato <p.imputato@gmail.com>
8 * Stefano Avallone <stefano.avallone@unina.it>
9 * Modified by: Bhaskar Kataria <bhaskar.k7920@gmail.com> (COBALT changes)
10 */
11
12#include "ns3/cobalt-queue-disc.h"
13#include "ns3/fq-cobalt-queue-disc.h"
14#include "ns3/ipv4-address.h"
15#include "ns3/ipv4-header.h"
16#include "ns3/ipv4-packet-filter.h"
17#include "ns3/ipv4-queue-disc-item.h"
18#include "ns3/ipv6-header.h"
19#include "ns3/ipv6-packet-filter.h"
20#include "ns3/ipv6-queue-disc-item.h"
21#include "ns3/pointer.h"
22#include "ns3/simulator.h"
23#include "ns3/string.h"
24#include "ns3/tcp-header.h"
25#include "ns3/test.h"
26#include "ns3/udp-header.h"
27
28using namespace ns3;
29
30/// Variable to assign g_hash to a new packet's flow
32
33/**
34 * \ingroup system-tests-tc
35 *
36 * Simple test packet filter able to classify IPv4 packets.
37 */
39{
40 public:
41 /**
42 * \brief Get the type ID.
43 * \return the object TypeId
44 */
45 static TypeId GetTypeId();
46
49
50 private:
51 /**
52 * Classify a QueueDiscItem
53 * \param item The item to classify (unused).
54 * \return a pre-set hash value.
55 */
56 int32_t DoClassify(Ptr<QueueDiscItem> item) const override;
57
58 /**
59 * Check the protocol.
60 * \param item The item to check (unused).
61 * \return true.
62 */
63 bool CheckProtocol(Ptr<QueueDiscItem> item) const override;
64};
65
68{
69 static TypeId tid = TypeId("ns3::Ipv4FqCobaltTestPacketFilter")
71 .SetGroupName("Internet")
72 .AddConstructor<Ipv4FqCobaltTestPacketFilter>();
73 return tid;
74}
75
79
83
89
90bool
95
96/**
97 * \ingroup system-tests-tc
98 *
99 * This class tests packets for which there is no suitable filter.
100 */
102{
103 public:
106
107 private:
108 void DoRun() override;
109};
110
112 : TestCase("Test packets that are not classified by any filter")
113{
114}
115
119
120void
122{
123 // Packets that cannot be classified by the available filters should be dropped
124 Ptr<FqCobaltQueueDisc> queueDisc =
127 queueDisc->AddPacketFilter(filter);
128
129 g_hash = -1;
130 queueDisc->SetQuantum(1500);
131 queueDisc->Initialize();
132
133 Ptr<Packet> p;
134 p = Create<Packet>();
136 Ipv6Header ipv6Header;
137 Address dest;
138 item = Create<Ipv6QueueDiscItem>(p, dest, 0, ipv6Header);
139 queueDisc->Enqueue(item);
140 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetNQueueDiscClasses(),
141 0,
142 "no flow queue should have been created");
143
144 p = Create<Packet>(reinterpret_cast<const uint8_t*>("hello, world"), 12);
145 item = Create<Ipv6QueueDiscItem>(p, dest, 0, ipv6Header);
146 queueDisc->Enqueue(item);
147 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetNQueueDiscClasses(),
148 0,
149 "no flow queue should have been created");
150
152}
153
154/**
155 * \ingroup system-tests-tc
156 *
157 * This class tests the IP flows separation and the packet limit.
158 */
160{
161 public:
164
165 private:
166 void DoRun() override;
167 /**
168 * Enqueue a packet.
169 * \param queue The queue disc.
170 * \param hdr The IPv4 header.
171 */
173};
174
179
184
185void
194
195void
197{
198 Ptr<FqCobaltQueueDisc> queueDisc =
200
201 queueDisc->SetQuantum(1500);
202 queueDisc->Initialize();
203
204 Ipv4Header hdr;
205 hdr.SetPayloadSize(100);
206 hdr.SetSource(Ipv4Address("10.10.1.1"));
207 hdr.SetDestination(Ipv4Address("10.10.1.2"));
208 hdr.SetProtocol(7);
209
210 // Add three packets from the first flow
211 AddPacket(queueDisc, hdr);
212 AddPacket(queueDisc, hdr);
213 AddPacket(queueDisc, hdr);
214 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
215 3,
216 "unexpected number of packets in the queue disc");
217 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
218 3,
219 "unexpected number of packets in the flow queue");
220
221 // Add two packets from the second flow
222 hdr.SetDestination(Ipv4Address("10.10.1.7"));
223 // Add the first packet
224 AddPacket(queueDisc, hdr);
225 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
226 4,
227 "unexpected number of packets in the queue disc");
228 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
229 3,
230 "unexpected number of packets in the flow queue");
231 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
232 1,
233 "unexpected number of packets in the flow queue");
234 // Add the second packet that causes two packets to be dropped from the fat flow (max backlog =
235 // 300, threshold = 150)
236 AddPacket(queueDisc, hdr);
237 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
238 3,
239 "unexpected number of packets in the queue disc");
240 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
241 1,
242 "unexpected number of packets in the flow queue");
243 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
244 2,
245 "unexpected number of packets in the flow queue");
246
248}
249
250/**
251 * \ingroup system-tests-tc
252 *
253 * This class tests the deficit per flow.
254 */
256{
257 public:
259 ~FqCobaltQueueDiscDeficit() override;
260
261 private:
262 void DoRun() override;
263 /**
264 * Enqueue a packet.
265 * \param queue The queue disc.
266 * \param hdr The IPv4 header.
267 */
269};
270
272 : TestCase("Test credits and flows status")
273{
274}
275
279
280void
282{
284 Address dest;
286 queue->Enqueue(item);
287}
288
289void
291{
293
294 queueDisc->SetQuantum(90);
295 queueDisc->Initialize();
296
297 Ipv4Header hdr;
298 hdr.SetPayloadSize(100);
299 hdr.SetSource(Ipv4Address("10.10.1.1"));
300 hdr.SetDestination(Ipv4Address("10.10.1.2"));
301 hdr.SetProtocol(7);
302
303 // Add a packet from the first flow
304 AddPacket(queueDisc, hdr);
305 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
306 1,
307 "unexpected number of packets in the queue disc");
308 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
309 1,
310 "unexpected number of packets in the first flow queue");
311 Ptr<FqCobaltFlow> flow1 = StaticCast<FqCobaltFlow>(queueDisc->GetQueueDiscClass(0));
312 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(),
313 static_cast<int32_t>(queueDisc->GetQuantum()),
314 "the deficit of the first flow must equal the quantum");
315 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
317 "the first flow must be in the list of new queues");
318 // Dequeue a packet
319 queueDisc->Dequeue();
320 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
321 0,
322 "unexpected number of packets in the queue disc");
323 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
324 0,
325 "unexpected number of packets in the first flow queue");
326 // the deficit for the first flow becomes 90 - (100+20) = -30
327 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -30, "unexpected deficit for the first flow");
328
329 // Add two packets from the first flow
330 AddPacket(queueDisc, hdr);
331 AddPacket(queueDisc, hdr);
332 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
333 2,
334 "unexpected number of packets in the queue disc");
335 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
336 2,
337 "unexpected number of packets in the first flow queue");
338 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
340 "the first flow must still be in the list of new queues");
341
342 // Add two packets from the second flow
343 hdr.SetDestination(Ipv4Address("10.10.1.10"));
344 AddPacket(queueDisc, hdr);
345 AddPacket(queueDisc, hdr);
346 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
347 4,
348 "unexpected number of packets in the queue disc");
349 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
350 2,
351 "unexpected number of packets in the first flow queue");
352 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
353 2,
354 "unexpected number of packets in the second flow queue");
355 Ptr<FqCobaltFlow> flow2 = StaticCast<FqCobaltFlow>(queueDisc->GetQueueDiscClass(1));
356 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(),
357 static_cast<int32_t>(queueDisc->GetQuantum()),
358 "the deficit of the second flow must equal the quantum");
359 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
361 "the second flow must be in the list of new queues");
362
363 // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
364 queueDisc->Dequeue();
365 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
366 3,
367 "unexpected number of packets in the queue disc");
368 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
369 2,
370 "unexpected number of packets in the first flow queue");
371 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
372 1,
373 "unexpected number of packets in the second flow queue");
374 // the first flow got a quantum of deficit (-30+90=60) and has been moved to the end of the list
375 // of old queues
376 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 60, "unexpected deficit for the first flow");
377 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
379 "the first flow must be in the list of old queues");
380 // the second flow has a negative deficit (-30) and is still in the list of new queues
381 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), -30, "unexpected deficit for the second flow");
382 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
384 "the second flow must be in the list of new queues");
385
386 // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
387 queueDisc->Dequeue();
388 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
389 2,
390 "unexpected number of packets in the queue disc");
391 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
392 1,
393 "unexpected number of packets in the first flow queue");
394 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
395 1,
396 "unexpected number of packets in the second flow queue");
397 // the first flow has a negative deficit (60-(100+20)= -60) and stays in the list of old queues
398 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -60, "unexpected deficit for the first flow");
399 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
401 "the first flow must be in the list of old queues");
402 // the second flow got a quantum of deficit (-30+90=60) and has been moved to the end of the
403 // list of old queues
404 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 60, "unexpected deficit for the second flow");
405 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
407 "the second flow must be in the list of new queues");
408
409 // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
410 queueDisc->Dequeue();
411 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
412 1,
413 "unexpected number of packets in the queue disc");
414 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
415 1,
416 "unexpected number of packets in the first flow queue");
417 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
418 0,
419 "unexpected number of packets in the second flow queue");
420 // the first flow got a quantum of deficit (-60+90=30) and has been moved to the end of the list
421 // of old queues
422 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 30, "unexpected deficit for the first flow");
423 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
425 "the first flow must be in the list of old queues");
426 // the second flow has a negative deficit (60-(100+20)= -60)
427 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), -60, "unexpected deficit for the second flow");
428 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
430 "the second flow must be in the list of new queues");
431
432 // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
433 queueDisc->Dequeue();
434 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
435 0,
436 "unexpected number of packets in the queue disc");
437 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
438 0,
439 "unexpected number of packets in the first flow queue");
440 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
441 0,
442 "unexpected number of packets in the second flow queue");
443 // the first flow has a negative deficit (30-(100+20)= -90)
444 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -90, "unexpected deficit for the first flow");
445 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
447 "the first flow must be in the list of old queues");
448 // the second flow got a quantum of deficit (-60+90=30) and has been moved to the end of the
449 // list of old queues
450 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 30, "unexpected deficit for the second flow");
451 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
453 "the second flow must be in the list of new queues");
454
455 // Dequeue a packet
456 queueDisc->Dequeue();
457 // the first flow is at the head of the list of old queues but has a negative deficit, thus it
458 // gets a quantun of deficit (-90+90=0) and is moved to the end of the list of old queues. Then,
459 // the second flow (which has a positive deficit) is selected, but the second flow is empty and
460 // thus it is set to inactive. The first flow is reconsidered, but it has a null deficit, hence
461 // it gets another quantum of deficit (0+90=90). Then, the first flow is reconsidered again, now
462 // it has a positive deficit and hence it is selected. But, it is empty and therefore is set to
463 // inactive, too.
464 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 90, "unexpected deficit for the first flow");
465 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
467 "the first flow must be inactive");
468 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 30, "unexpected deficit for the second flow");
469 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
471 "the second flow must be inactive");
472
474}
475
476/**
477 * \ingroup system-tests-tc
478 *
479 * This class tests the TCP flows separation.
480 */
482{
483 public:
486
487 private:
488 void DoRun() override;
489 /**
490 * Enqueue a packet.
491 * \param queue The queue disc.
492 * \param ipHdr The IPv4 header.
493 * \param tcpHdr The TCP header.
494 */
495 void AddPacket(Ptr<FqCobaltQueueDisc> queue, Ipv4Header ipHdr, TcpHeader tcpHdr);
496};
497
502
506
507void
509 Ipv4Header ipHdr,
510 TcpHeader tcpHdr)
511{
513 p->AddHeader(tcpHdr);
514 Address dest;
515 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, ipHdr);
516 queue->Enqueue(item);
517}
518
519void
521{
522 Ptr<FqCobaltQueueDisc> queueDisc =
524
525 queueDisc->SetQuantum(1500);
526 queueDisc->Initialize();
527
528 Ipv4Header hdr;
529 hdr.SetPayloadSize(100);
530 hdr.SetSource(Ipv4Address("10.10.1.1"));
531 hdr.SetDestination(Ipv4Address("10.10.1.2"));
532 hdr.SetProtocol(6);
533
534 TcpHeader tcpHdr;
535 tcpHdr.SetSourcePort(7);
536 tcpHdr.SetDestinationPort(27);
537
538 // Add three packets from the first flow
539 AddPacket(queueDisc, hdr, tcpHdr);
540 AddPacket(queueDisc, hdr, tcpHdr);
541 AddPacket(queueDisc, hdr, tcpHdr);
542 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
543 3,
544 "unexpected number of packets in the queue disc");
545 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
546 3,
547 "unexpected number of packets in the first flow queue");
548
549 // Add a packet from the second flow
550 tcpHdr.SetSourcePort(8);
551 AddPacket(queueDisc, hdr, tcpHdr);
552 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
553 4,
554 "unexpected number of packets in the queue disc");
555 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
556 3,
557 "unexpected number of packets in the first flow queue");
558 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
559 1,
560 "unexpected number of packets in the second flow queue");
561
562 // Add a packet from the third flow
563 tcpHdr.SetDestinationPort(28);
564 AddPacket(queueDisc, hdr, tcpHdr);
565 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
566 5,
567 "unexpected number of packets in the queue disc");
568 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
569 3,
570 "unexpected number of packets in the first flow queue");
571 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
572 1,
573 "unexpected number of packets in the second flow queue");
574 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
575 1,
576 "unexpected number of packets in the third flow queue");
577
578 // Add two packets from the fourth flow
579 tcpHdr.SetSourcePort(7);
580 AddPacket(queueDisc, hdr, tcpHdr);
581 AddPacket(queueDisc, hdr, tcpHdr);
582 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
583 7,
584 "unexpected number of packets in the queue disc");
585 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
586 3,
587 "unexpected number of packets in the first flow queue");
588 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
589 1,
590 "unexpected number of packets in the second flow queue");
591 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
592 1,
593 "unexpected number of packets in the third flow queue");
594 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
595 2,
596 "unexpected number of packets in the third flow queue");
597
599}
600
601/**
602 * \ingroup system-tests-tc
603 *
604 * This class tests the UDP flows separation
605 */
607{
608 public:
611
612 private:
613 void DoRun() override;
614 /**
615 * Enqueue a packet.
616 * \param queue the queue disc
617 * \param ipHdr the IPv4 header
618 * \param udpHdr the UDP header
619 */
620 void AddPacket(Ptr<FqCobaltQueueDisc> queue, Ipv4Header ipHdr, UdpHeader udpHdr);
621};
622
627
631
632void
634 Ipv4Header ipHdr,
635 UdpHeader udpHdr)
636{
638 p->AddHeader(udpHdr);
639 Address dest;
640 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, ipHdr);
641 queue->Enqueue(item);
642}
643
644void
646{
647 Ptr<FqCobaltQueueDisc> queueDisc =
649
650 queueDisc->SetQuantum(1500);
651 queueDisc->Initialize();
652
653 Ipv4Header hdr;
654 hdr.SetPayloadSize(100);
655 hdr.SetSource(Ipv4Address("10.10.1.1"));
656 hdr.SetDestination(Ipv4Address("10.10.1.2"));
657 hdr.SetProtocol(17);
658
659 UdpHeader udpHdr;
660 udpHdr.SetSourcePort(7);
661 udpHdr.SetDestinationPort(27);
662
663 // Add three packets from the first flow
664 AddPacket(queueDisc, hdr, udpHdr);
665 AddPacket(queueDisc, hdr, udpHdr);
666 AddPacket(queueDisc, hdr, udpHdr);
667 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
668 3,
669 "unexpected number of packets in the queue disc");
670 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
671 3,
672 "unexpected number of packets in the first flow queue");
673
674 // Add a packet from the second flow
675 udpHdr.SetSourcePort(8);
676 AddPacket(queueDisc, hdr, udpHdr);
677 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
678 4,
679 "unexpected number of packets in the queue disc");
680 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
681 3,
682 "unexpected number of packets in the first flow queue");
683 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
684 1,
685 "unexpected number of packets in the second flow queue");
686
687 // Add a packet from the third flow
688 udpHdr.SetDestinationPort(28);
689 AddPacket(queueDisc, hdr, udpHdr);
690 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
691 5,
692 "unexpected number of packets in the queue disc");
693 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
694 3,
695 "unexpected number of packets in the first flow queue");
696 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
697 1,
698 "unexpected number of packets in the second flow queue");
699 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
700 1,
701 "unexpected number of packets in the third flow queue");
702
703 // Add two packets from the fourth flow
704 udpHdr.SetSourcePort(7);
705 AddPacket(queueDisc, hdr, udpHdr);
706 AddPacket(queueDisc, hdr, udpHdr);
707 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
708 7,
709 "unexpected number of packets in the queue disc");
710 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
711 3,
712 "unexpected number of packets in the first flow queue");
713 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
714 1,
715 "unexpected number of packets in the second flow queue");
716 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
717 1,
718 "unexpected number of packets in the third flow queue");
719 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
720 2,
721 "unexpected number of packets in the third flow queue");
722
724}
725
726/**
727 * \ingroup system-tests-tc
728 *
729 * \brief This class tests ECN marking.
730 *
731 * The test is divided into 3 sub test cases.
732 * 1) CE threshold disabled
733 * This test enqueues 100 packets in the beginning of the test and dequeues 60 (some packets are
734 * dropped too) packets with the delay of 110ms. This test checks that ECT0 packets are marked and
735 * are marked appropriately and NotECT packets are dropped.
736 *
737 * 2) CE threshold enabled.
738 * This test enqueues 100 packets in the beginning of the test and dequeues 60 packets with delay of
739 * 1ms. This test checks that the ECT0 packets are marked appropriately at CE threshold.
740 *
741 * 3) CE threshold enabled with higher queue delay.
742 * This test is similar to the 2nd sub test cases just with higher queue delay and aims to test that
743 * the packets are not marked twice Any future classifier options (e.g. SetAssociativehash) should
744 * be disabled to prevent a hash collision on this test case.
745 */
747{
748 public:
751
752 private:
753 void DoRun() override;
754 /**
755 * Enqueue the given number of packets.
756 * \param queue The queue disc.
757 * \param hdr The IPv4 header.
758 * \param nPkt The number of packets.
759 * \param nPktEnqueued The expected number of enqueued packets.
760 * \param nQueueFlows The expected number of flow queues.
761 */
763 Ipv4Header hdr,
764 uint32_t nPkt,
765 uint32_t nPktEnqueued,
766 uint32_t nQueueFlows);
767 /**
768 * Dequeue the given number of packets.
769 * \param queue The queue disc.
770 * \param nPkt The number of packets.
771 */
772 void Dequeue(Ptr<FqCobaltQueueDisc> queue, uint32_t nPkt);
773 /**
774 * Dequeue the given number of packets at different times.
775 * \param queue The queue disc.
776 * \param delay The time between two consecutive dequeue operations.
777 * \param nPkt The number of packets.
778 */
779 void DequeueWithDelay(Ptr<FqCobaltQueueDisc> queue, double delay, uint32_t nPkt);
780 /**
781 * Tracer for the DropNext attribute
782 * \param oldVal Old value.
783 * \param newVal New value.
784 */
785 void DropNextTracer(int64_t oldVal, int64_t newVal);
786 uint32_t m_dropNextCount; ///< count the number of times m_dropNext is recalculated
787};
788
794
798
799void
801 Ipv4Header hdr,
802 uint32_t nPkt,
803 uint32_t nPktEnqueued,
804 uint32_t nQueueFlows)
805{
806 Address dest;
808 for (uint32_t i = 0; i < nPkt; i++)
809 {
811 queue->Enqueue(item);
812 }
813 NS_TEST_EXPECT_MSG_EQ(queue->GetNQueueDiscClasses(),
814 nQueueFlows,
815 "unexpected number of flow queues");
816 NS_TEST_EXPECT_MSG_EQ(queue->GetNPackets(),
817 nPktEnqueued,
818 "unexpected number of enqueued packets");
819}
820
821void
823{
825 queue->GetQueueDiscClass(3)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
826
827 // Trace DropNext after the first dequeue as m_dropNext value is set after the first dequeue
828 if (q3->GetNPackets() == 19)
829 {
830 q3->TraceConnectWithoutContext(
831 "DropNext",
833 }
834
835 for (uint32_t i = 0; i < nPkt; i++)
836 {
837 Ptr<QueueDiscItem> item = queue->Dequeue();
838 }
839}
840
841void
843 double delay,
844 uint32_t nPkt)
845{
846 for (uint32_t i = 0; i < nPkt; i++)
847 {
848 Simulator::Schedule(Time(Seconds((i + 1) * delay)),
850 this,
851 queue,
852 1);
853 }
854}
855
856void
857FqCobaltQueueDiscEcnMarking::DropNextTracer(int64_t /* oldVal */, int64_t /* newVal */)
858{
860}
861
862void
864{
865 // Test is divided into 3 sub test cases:
866 // 1) CeThreshold disabled
867 // 2) CeThreshold enabled
868 // 3) Same as 2 but with higher queue delay
869
870 // Test case 1, CeThreshold disabled
871 Ptr<FqCobaltQueueDisc> queueDisc =
873 StringValue("10240p"),
874 "UseEcn",
875 BooleanValue(true),
876 "Perturbation",
877 UintegerValue(0),
878 "BlueThreshold",
880
881 queueDisc->SetQuantum(1514);
882 queueDisc->Initialize();
883 Ipv4Header hdr;
884 hdr.SetPayloadSize(100);
885 hdr.SetSource(Ipv4Address("10.10.1.1"));
886 hdr.SetDestination(Ipv4Address("10.10.1.2"));
887 hdr.SetProtocol(7);
889
890 // Add 20 ECT0 (ECN capable) packets from the first flow
893 this,
894 queueDisc,
895 hdr,
896 20,
897 20,
898 1);
899
900 // Add 20 ECT0 (ECN capable) packets from second flow
901 hdr.SetDestination(Ipv4Address("10.10.1.10"));
904 this,
905 queueDisc,
906 hdr,
907 20,
908 40,
909 2);
910
911 // Add 20 ECT0 (ECN capable) packets from third flow
912 hdr.SetDestination(Ipv4Address("10.10.1.20"));
915 this,
916 queueDisc,
917 hdr,
918 20,
919 60,
920 3);
921
922 // Add 20 NotECT packets from fourth flow
923 hdr.SetDestination(Ipv4Address("10.10.1.30"));
927 this,
928 queueDisc,
929 hdr,
930 20,
931 80,
932 4);
933
934 // Add 20 NotECT packets from fifth flow
935 hdr.SetDestination(Ipv4Address("10.10.1.40"));
938 this,
939 queueDisc,
940 hdr,
941 20,
942 100,
943 5);
944
945 // Dequeue 60 packets with delay 110ms to induce packet drops and keep some remaining packets in
946 // each queue
947 DequeueWithDelay(queueDisc, 0.11, 60);
951 queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
953 queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
955 queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
957 queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
959 queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
960
961 // As packets in flow queues are ECN capable
962 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
963 19,
964 "There should be 19 marked packets."
965 "As there is no CoDel minBytes parameter so all the packets apart from "
966 "the first one gets marked. As q3 and q4 have"
967 "NotEct packets and the queue delay is much higher than 5ms so the queue "
968 "gets empty pretty quickly so more"
969 "packets from q0 can be dequeued.");
970 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
971 0,
972 "There should not be any dropped packets");
973 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
974 16,
975 "There should be 16 marked packets"
976 "As there is no CoDel minBytes parameter so all the packets apart from "
977 "the first one until no more packets are dequeued"
978 "are marked.");
979 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
980 0,
981 "There should not be any dropped packets");
982 NS_TEST_EXPECT_MSG_EQ(q2->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
983 12,
984 "There should be 12 marked packets"
985 "Each packet size is 120 bytes and the quantum is 1500 bytes so in the "
986 "first turn (1514/120 = 12.61) 13 packets are"
987 "dequeued and apart from the first one, all the packets are marked.");
988 NS_TEST_EXPECT_MSG_EQ(q2->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
989 0,
990 "There should not be any dropped packets");
991
992 // As packets in flow queues are not ECN capable
993 NS_TEST_EXPECT_MSG_EQ(q3->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
995 "The number of drops should"
996 "be equal to the number of times m_dropNext is updated");
997 NS_TEST_EXPECT_MSG_EQ(q3->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
998 0,
999 "There should not be any marked packets");
1000 NS_TEST_EXPECT_MSG_EQ(q4->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1002 "The number of drops should"
1003 "be equal to the number of times m_dropNext is updated");
1004 NS_TEST_EXPECT_MSG_EQ(q4->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
1005 0,
1006 "There should not be any marked packets");
1007
1009
1010 // Test case 2, CeThreshold set to 2ms
1012 StringValue("10240p"),
1013 "UseEcn",
1014 BooleanValue(true),
1015 "CeThreshold",
1017 queueDisc->SetQuantum(1514);
1018 queueDisc->Initialize();
1019
1020 // Add 20 ECT0 (ECN capable) packets from first flow
1021 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1025 this,
1026 queueDisc,
1027 hdr,
1028 20,
1029 20,
1030 1);
1031
1032 // Add 20 ECT0 (ECN capable) packets from second flow
1033 hdr.SetDestination(Ipv4Address("10.10.1.10"));
1036 this,
1037 queueDisc,
1038 hdr,
1039 20,
1040 40,
1041 2);
1042
1043 // Add 20 ECT0 (ECN capable) packets from third flow
1044 hdr.SetDestination(Ipv4Address("10.10.1.20"));
1047 this,
1048 queueDisc,
1049 hdr,
1050 20,
1051 60,
1052 3);
1053
1054 // Add 20 NotECT packets from fourth flow
1055 hdr.SetDestination(Ipv4Address("10.10.1.30"));
1059 this,
1060 queueDisc,
1061 hdr,
1062 20,
1063 80,
1064 4);
1065
1066 // Add 20 NotECT packets from fifth flow
1067 hdr.SetDestination(Ipv4Address("10.10.1.40"));
1070 this,
1071 queueDisc,
1072 hdr,
1073 20,
1074 100,
1075 5);
1076
1077 // Dequeue 60 packets with delay 0.1ms to induce packet drops and keep some remaining packets in
1078 // each queue
1079 DequeueWithDelay(queueDisc, 0.0001, 60);
1082 q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1083 q1 = queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1084 q2 = queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1085 q3 = queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1086 q4 = queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1087
1088 // As packets in flow queues are ECN capable
1089 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1090 0,
1091 "There should not be any dropped packets");
1093 q0->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1094 0,
1095 "There should not be any marked packets"
1096 "with quantum of 1514, 13 packets of size 120 bytes can be dequeued. sojourn time of 13th "
1097 "packet is 1.3ms which is"
1098 "less than CE threshold");
1099 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1100 0,
1101 "There should not be any dropped packets");
1103 q1->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1104 6,
1105 "There should be 6 marked packets"
1106 "with quantum of 1514, 13 packets of size 120 bytes can be dequeued. sojourn time of 8th "
1107 "packet is 2.1ms which is greater"
1108 "than CE threshold and subsequent packet also have sojourn time more 8th packet hence "
1109 "remaining packet are marked.");
1110 NS_TEST_EXPECT_MSG_EQ(q2->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1111 0,
1112 "There should not be any dropped packets");
1114 q2->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1115 13,
1116 "There should be 13 marked packets"
1117 "with quantum of 1514, 13 packets of size 120 bytes can be dequeued and all of them have "
1118 "sojourn time more than CE threshold");
1119
1120 // As packets in flow queues are not ECN capable
1122 q3->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1123 0,
1124 "There should not be any marked packets");
1125 NS_TEST_EXPECT_MSG_EQ(q3->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1126 0,
1127 "There should not be any dropped packets");
1129 q4->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1130 0,
1131 "There should not be any marked packets");
1132 NS_TEST_EXPECT_MSG_EQ(q4->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1133 1,
1134 "There should 1 dropped packet. As the queue"
1135 "delay for the first dequeue is greater than the target (5ms), Cobalt "
1136 "overloads the m_dropNext field as an activity timeout"
1137 "and dropNext is to set to the current Time value so on the next dequeue "
1138 "a packet is dropped.");
1139
1141
1142 // Test case 3, CeThreshold set to 2ms with higher queue delay. This test is mainly to check
1143 // that the packets are not getting marked twice.
1145 StringValue("10240p"),
1146 "UseEcn",
1147 BooleanValue(true),
1148 "CeThreshold",
1150 "BlueThreshold",
1151 TimeValue(Time::Max()));
1152 queueDisc->SetQuantum(1514);
1153 queueDisc->Initialize();
1154
1155 // Add 20 ECT0 (ECN capable) packets from first flow
1156 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1160 this,
1161 queueDisc,
1162 hdr,
1163 20,
1164 20,
1165 1);
1166
1167 // Add 20 ECT0 (ECN capable) packets from second flow
1168 hdr.SetDestination(Ipv4Address("10.10.1.10"));
1171 this,
1172 queueDisc,
1173 hdr,
1174 20,
1175 40,
1176 2);
1177
1178 // Add 20 ECT0 (ECN capable) packets from third flow
1179 hdr.SetDestination(Ipv4Address("10.10.1.20"));
1182 this,
1183 queueDisc,
1184 hdr,
1185 20,
1186 60,
1187 3);
1188
1189 // Add 20 NotECT packets from fourth flow
1190 hdr.SetDestination(Ipv4Address("10.10.1.30"));
1194 this,
1195 queueDisc,
1196 hdr,
1197 20,
1198 80,
1199 4);
1200
1201 // Add 20 NotECT packets from fifth flow
1202 hdr.SetDestination(Ipv4Address("10.10.1.40"));
1205 this,
1206 queueDisc,
1207 hdr,
1208 20,
1209 100,
1210 5);
1211
1212 // Reset m_dropNextCount value;
1213 m_dropNextCount = 0;
1214
1215 // Dequeue 60 packets with delay 110ms to induce packet drops and keep some remaining packets in
1216 // each queue
1217 DequeueWithDelay(queueDisc, 0.110, 60);
1220 q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1221 q1 = queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1222 q2 = queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1223 q3 = queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1224 q4 = queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1225
1226 // As packets in flow queues are ECN capable
1227 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1228 0,
1229 "There should not be any dropped packets");
1231 q0->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK) +
1232 q0->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
1233 20 - q0->GetNPackets(),
1234 "Number of CE threshold"
1235 " exceeded marks plus Number of Target exceeded marks should be equal to total number of "
1236 "packets dequeued");
1237 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1238 0,
1239 "There should not be any dropped packets");
1241 q1->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK) +
1242 q1->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
1243 20 - q1->GetNPackets(),
1244 "Number of CE threshold"
1245 " exceeded marks plus Number of Target exceeded marks should be equal to total number of "
1246 "packets dequeued");
1247 NS_TEST_EXPECT_MSG_EQ(q2->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1248 0,
1249 "There should not be any dropped packets");
1251 q2->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK) +
1252 q2->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
1253 20 - q2->GetNPackets(),
1254 "Number of CE threshold"
1255 " exceeded marks plus Number of Target exceeded marks should be equal to total number of "
1256 "packets dequeued");
1257
1258 // As packets in flow queues are not ECN capable
1260 q3->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1261 0,
1262 "There should not be any marked packets");
1263 NS_TEST_EXPECT_MSG_EQ(q3->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1265 "The number of drops should"
1266 "be equal to the number of times m_dropNext is updated");
1268 q4->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1269 0,
1270 "There should not be any marked packets");
1271 NS_TEST_EXPECT_MSG_EQ(q4->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1273 "The number of drops should"
1274 "be equal to the number of times m_dropNext is updated");
1275
1277}
1278
1279/**
1280 * \ingroup system-tests-tc
1281 *
1282 * \brief This class tests linear probing, collision response, and set
1283 * creation capability of set associative hashing in FqCobalt.
1284 *
1285 * We modified DoClassify () and CheckProtocol () so that we could control
1286 * the hash returned for each packet. In the beginning, we use flow hashes
1287 * ranging from 0 to 7. These must go into different queues in the same set.
1288 * The set number for these is obtained using outerhash, which is 0.
1289 * When a new packet arrives with flow hash 1024, outerhash = 0 is obtained
1290 * and the first set is iteratively searched.
1291 * The packet is eventually added to queue 0 since the tags of queues
1292 * in the set do not match with the hash of the flow. The tag of queue 0 is
1293 * updated as 1024. When a packet with hash 1025 arrives, outerhash = 0
1294 * is obtained and the first set is iteratively searched.
1295 * Since there is no match, it is added to queue 0 and the tag of queue 0 is
1296 * updated to 1025.
1297 *
1298 * The variable outerhash stores the nearest multiple of 8 that is lesser than
1299 * the hash. When a flow hash of 20 arrives, the value of outerhash
1300 * is 16. Since m_flowIndices[16] wasn't previously allotted, a new flow
1301 * is created, and the tag corresponding to this queue is set to 20.
1302 */
1304{
1305 public:
1308
1309 private:
1310 void DoRun() override;
1311 /**
1312 * Enqueue a packet.
1313 * \param queue The queue disc.
1314 * \param hdr The IPv4 header.
1315 */
1317};
1318
1320 : TestCase("Test credits and flows status")
1321{
1322}
1323
1327
1328void
1330{
1331 Ptr<Packet> p = Create<Packet>(100);
1332 Address dest;
1333 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, hdr);
1334 queue->Enqueue(item);
1335}
1336
1337void
1339{
1340 Ptr<FqCobaltQueueDisc> queueDisc =
1341 CreateObjectWithAttributes<FqCobaltQueueDisc>("EnableSetAssociativeHash",
1342 BooleanValue(true));
1343 queueDisc->SetQuantum(90);
1344 queueDisc->Initialize();
1345
1347 queueDisc->AddPacketFilter(filter);
1348
1349 Ipv4Header hdr;
1350 hdr.SetPayloadSize(100);
1351 hdr.SetSource(Ipv4Address("10.10.1.1"));
1352 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1353 hdr.SetProtocol(7);
1354
1355 g_hash = 0;
1356 AddPacket(queueDisc, hdr);
1357 g_hash = 1;
1358 AddPacket(queueDisc, hdr);
1359 AddPacket(queueDisc, hdr);
1360 g_hash = 2;
1361 AddPacket(queueDisc, hdr);
1362 g_hash = 3;
1363 AddPacket(queueDisc, hdr);
1364 g_hash = 4;
1365 AddPacket(queueDisc, hdr);
1366 AddPacket(queueDisc, hdr);
1367 g_hash = 5;
1368 AddPacket(queueDisc, hdr);
1369 g_hash = 6;
1370 AddPacket(queueDisc, hdr);
1371 g_hash = 7;
1372 AddPacket(queueDisc, hdr);
1373 g_hash = 1024;
1374 AddPacket(queueDisc, hdr);
1375
1376 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
1377 11,
1378 "unexpected number of packets in the queue disc");
1379 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
1380 2,
1381 "unexpected number of packets in the first flow queue of set one");
1382 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
1383 2,
1384 "unexpected number of packets in the second flow queue of set one");
1385 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
1386 1,
1387 "unexpected number of packets in the third flow queue of set one");
1388 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
1389 1,
1390 "unexpected number of packets in the fourth flow queue of set one");
1391 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetNPackets(),
1392 2,
1393 "unexpected number of packets in the fifth flow queue of set one");
1394 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(5)->GetQueueDisc()->GetNPackets(),
1395 1,
1396 "unexpected number of packets in the sixth flow queue of set one");
1397 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(6)->GetQueueDisc()->GetNPackets(),
1398 1,
1399 "unexpected number of packets in the seventh flow queue of set one");
1400 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(7)->GetQueueDisc()->GetNPackets(),
1401 1,
1402 "unexpected number of packets in the eighth flow queue of set one");
1403 g_hash = 1025;
1404 AddPacket(queueDisc, hdr);
1405 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
1406 3,
1407 "unexpected number of packets in the first flow of set one");
1408 g_hash = 10;
1409 AddPacket(queueDisc, hdr);
1410 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(8)->GetQueueDisc()->GetNPackets(),
1411 1,
1412 "unexpected number of packets in the first flow of set two");
1414}
1415
1416/**
1417 * \ingroup system-tests-tc
1418 *
1419 * \brief This class tests L4S mode.
1420 *
1421 * This test is divided to sub test one without hash collisions and so ECT0 and ECT1 flows are
1422 * classified into different flows.
1423 *
1424 * Sub Test 1
1425 * 70 packets are enqueued into both the flows with the delay of 0.5ms between two enqueues, and
1426 * dequeued with the delay of 1ms between two dequeues. Sub Test 2 140(70 ECT0 + 70 ECT1) packets
1427 * are enqueued such that ECT1 packets are enqueued at 0.5ms, 1.5ms, 2.5ms and so on, and ECT0
1428 * packets are enqueued are enqueued at 1ms, 2ms, 3ms and so on Any future classifier options (e.g.
1429 * SetAssociativehash) should be disabled to prevent a hash collision on this test case.
1430 */
1432{
1433 public:
1435 ~FqCobaltQueueDiscL4sMode() override;
1436
1437 private:
1438 void DoRun() override;
1439 /**
1440 * Enqueue the given number of packets.
1441 * \param queue The queue disc.
1442 * \param hdr The IPv4 header.
1443 * \param nPkt The number of packets.
1444 */
1445 void AddPacket(Ptr<FqCobaltQueueDisc> queue, Ipv4Header hdr, uint32_t nPkt);
1446 /**
1447 * Enqueue the given number of packets at different times.
1448 * \param queue The queue disc.
1449 * \param hdr The IPv4 header.
1450 * \param delay The time between two consecutive enqueue operations.
1451 * \param nPkt The number of packets.
1452 */
1454 Ipv4Header hdr,
1455 double delay,
1456 uint32_t nPkt);
1457 /**
1458 * Dequeue the given number of packets.
1459 * \param queue The queue disc.
1460 * \param nPkt The number of packets.
1461 */
1462 void Dequeue(Ptr<FqCobaltQueueDisc> queue, uint32_t nPkt);
1463 /**
1464 * Dequeue the given number of packets at different times.
1465 * \param queue The queue disc.
1466 * \param delay The time between two consecutive dequeue operations.
1467 * \param nPkt The number of packets.
1468 */
1469 void DequeueWithDelay(Ptr<FqCobaltQueueDisc> queue, double delay, uint32_t nPkt);
1470};
1471
1476
1480
1481void
1483{
1484 Address dest;
1485 Ptr<Packet> p = Create<Packet>(100);
1486 for (uint32_t i = 0; i < nPkt; i++)
1487 {
1488 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, hdr);
1489 queue->Enqueue(item);
1490 }
1491}
1492
1493void
1495 Ipv4Header hdr,
1496 double delay,
1497 uint32_t nPkt)
1498{
1499 for (uint32_t i = 0; i < nPkt; i++)
1500 {
1501 Simulator::Schedule(Time(Seconds((i + 1) * delay)),
1503 this,
1504 queue,
1505 hdr,
1506 1);
1507 }
1508}
1509
1510void
1512{
1513 for (uint32_t i = 0; i < nPkt; i++)
1514 {
1515 Ptr<QueueDiscItem> item = queue->Dequeue();
1516 }
1517}
1518
1519void
1521 double delay,
1522 uint32_t nPkt)
1523{
1524 for (uint32_t i = 0; i < nPkt; i++)
1525 {
1526 Simulator::Schedule(Time(Seconds((i + 1) * delay)),
1528 this,
1529 queue,
1530 1);
1531 }
1532}
1533
1534void
1536{
1537 // Test is divided into 2 sub test cases:
1538 // 1) Without hash collisions
1539 // 2) With hash collisions
1540
1541 // Test case 1, Without hash collisions
1542 Ptr<FqCobaltQueueDisc> queueDisc =
1544 StringValue("10240p"),
1545 "UseEcn",
1546 BooleanValue(true),
1547 "Perturbation",
1548 UintegerValue(0),
1549 "UseL4s",
1550 BooleanValue(true),
1551 "CeThreshold",
1553
1554 queueDisc->SetQuantum(1514);
1555 queueDisc->Initialize();
1556 Ipv4Header hdr;
1557 hdr.SetPayloadSize(100);
1558 hdr.SetSource(Ipv4Address("10.10.1.1"));
1559 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1560 hdr.SetProtocol(7);
1562
1563 // Add 70 ECT1 (ECN capable) packets from the first flow
1564 // Set delay = 0.5ms
1565 double delay = 0.0005;
1568 this,
1569 queueDisc,
1570 hdr,
1571 delay,
1572 70);
1573
1574 // Add 70 ECT0 (ECN capable) packets from second flow
1576 hdr.SetDestination(Ipv4Address("10.10.1.10"));
1579 this,
1580 queueDisc,
1581 hdr,
1582 delay,
1583 70);
1584
1585 // Dequeue 140 packets with delay 1ms
1586 delay = 0.001;
1587 DequeueWithDelay(queueDisc, delay, 140);
1591 queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1593 queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1594
1596 q0->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1597 66,
1598 "There should be 66 marked packets"
1599 "4th packet is enqueued at 2ms and dequeued at 4ms hence the delay of 2ms which not "
1600 "greater than CE threshold"
1601 "5th packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and "
1602 "subsequent packet also do have delay"
1603 "greater than CE threshold so all the packets after 4th packet are marked");
1604 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1605 0,
1606 "There should not be any dropped packets");
1607 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
1608 0,
1609 "There should not be any marked packets");
1610 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
1611 2,
1612 "There should be 2 marked packets. Packets are dequeued"
1613 "from q0 first, which leads to delay greater than 5ms for the first "
1614 "dequeue from q1. Because of inactivity (started with high queue delay)"
1615 "Cobalt keeps drop_next as now and the next packet is marked. With "
1616 "second dequeue count increases to 2, drop_next becomes now plus around"
1617 "70ms which is less than the running time(140), and as the queue delay "
1618 "is persistently higher than 5ms, second packet is marked.");
1619 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1620 0,
1621 "There should not be any dropped packets");
1622
1624
1625 // Test case 2, With hash collisions
1627 StringValue("10240p"),
1628 "UseEcn",
1629 BooleanValue(true),
1630 "Perturbation",
1631 UintegerValue(0),
1632 "UseL4s",
1633 BooleanValue(true),
1634 "CeThreshold",
1636
1637 queueDisc->SetQuantum(1514);
1638 queueDisc->Initialize();
1639 hdr.SetPayloadSize(100);
1640 hdr.SetSource(Ipv4Address("10.10.1.1"));
1641 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1642 hdr.SetProtocol(7);
1644
1645 // Add 70 ECT1 (ECN capable) packets from the first flow
1646 // Set delay = 1ms
1647 delay = 0.001;
1650 this,
1651 queueDisc,
1652 hdr,
1653 1);
1656 this,
1657 queueDisc,
1658 hdr,
1659 delay,
1660 69);
1661
1662 // Add 70 ECT0 (ECN capable) packets from first flow
1666 this,
1667 queueDisc,
1668 hdr,
1669 delay,
1670 70);
1671
1672 // Dequeue 140 packets with delay 1ms
1673 DequeueWithDelay(queueDisc, delay, 140);
1676 q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1677 q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CobaltQueueDisc>();
1678
1680 q0->GetStats().GetNMarkedPackets(CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1681 68,
1682 "There should be 68 marked packets"
1683 "2nd ECT1 packet is enqueued at 1.5ms and dequeued at 3ms hence the delay of 1.5ms which "
1684 "not greater than CE threshold"
1685 "3rd packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and "
1686 "subsequent packet also do have delay"
1687 "greater than CE threshold so all the packets after 2nd packet are marked");
1688 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(CobaltQueueDisc::TARGET_EXCEEDED_DROP),
1689 0,
1690 "There should not be any dropped packets");
1691 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNMarkedPackets(CobaltQueueDisc::FORCED_MARK),
1692 1,
1693 "There should be 1 marked packets");
1694
1696}
1697
1698/**
1699 * \ingroup system-tests-tc
1700 *
1701 * FQ-COBALT queue disc test suite.
1702 */
1704{
1705 public:
1707};
1708
1710 : TestSuite("fq-cobalt-queue-disc", Type::UNIT)
1711{
1712 AddTestCase(new FqCobaltQueueDiscNoSuitableFilter, TestCase::Duration::QUICK);
1713 AddTestCase(new FqCobaltQueueDiscIPFlowsSeparationAndPacketLimit, TestCase::Duration::QUICK);
1714 AddTestCase(new FqCobaltQueueDiscDeficit, TestCase::Duration::QUICK);
1715 AddTestCase(new FqCobaltQueueDiscTCPFlowsSeparation, TestCase::Duration::QUICK);
1716 AddTestCase(new FqCobaltQueueDiscUDPFlowsSeparation, TestCase::Duration::QUICK);
1717 AddTestCase(new FqCobaltQueueDiscEcnMarking, TestCase::Duration::QUICK);
1718 AddTestCase(new FqCobaltQueueDiscSetLinearProbing, TestCase::Duration::QUICK);
1719 AddTestCase(new FqCobaltQueueDiscL4sMode, TestCase::Duration::QUICK);
1720}
1721
1722/// Do not forget to allocate an instance of this TestSuite.
This class tests the deficit per flow.
void DoRun() override
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
uint32_t m_dropNextCount
count the number of times m_dropNext is recalculated
void DequeueWithDelay(Ptr< FqCobaltQueueDisc > queue, double delay, uint32_t nPkt)
Dequeue the given number of packets at different times.
void Dequeue(Ptr< FqCobaltQueueDisc > queue, uint32_t nPkt)
Dequeue the given number of packets.
void DropNextTracer(int64_t oldVal, int64_t newVal)
Tracer for the DropNext attribute.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr, uint32_t nPkt, uint32_t nPktEnqueued, uint32_t nQueueFlows)
Enqueue the given number of packets.
void DoRun() override
Implementation to actually run this TestCase.
This class tests the IP flows separation and the packet limit.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
void DoRun() override
Implementation to actually run this TestCase.
void DequeueWithDelay(Ptr< FqCobaltQueueDisc > queue, double delay, uint32_t nPkt)
Dequeue the given number of packets at different times.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr, uint32_t nPkt)
Enqueue the given number of packets.
void DoRun() override
Implementation to actually run this TestCase.
void Dequeue(Ptr< FqCobaltQueueDisc > queue, uint32_t nPkt)
Dequeue the given number of packets.
void AddPacketWithDelay(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr, double delay, uint32_t nPkt)
Enqueue the given number of packets at different times.
This class tests packets for which there is no suitable filter.
void DoRun() override
Implementation to actually run this TestCase.
This class tests linear probing, collision response, and set creation capability of set associative h...
void DoRun() override
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
This class tests the TCP flows separation.
void DoRun() override
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header ipHdr, TcpHeader tcpHdr)
Enqueue a packet.
This class tests the UDP flows separation.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header ipHdr, UdpHeader udpHdr)
Enqueue a packet.
void DoRun() override
Implementation to actually run this TestCase.
Simple test packet filter able to classify IPv4 packets.
int32_t DoClassify(Ptr< QueueDiscItem > item) const override
Classify a QueueDiscItem.
bool CheckProtocol(Ptr< QueueDiscItem > item) const override
Check the protocol.
static TypeId GetTypeId()
Get the type ID.
a polymophic address class
Definition address.h:90
AttributeValue implementation for Boolean.
Definition boolean.h:26
Cobalt packet queue disc.
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
Ipv4 addresses are stored in host order in this class.
Packet header for IPv4.
Definition ipv4-header.h:23
void SetDestination(Ipv4Address destination)
void SetPayloadSize(uint16_t size)
void SetEcn(EcnType ecn)
Set ECN Field.
void SetProtocol(uint8_t num)
void SetSource(Ipv4Address source)
Ipv4PacketFilter is the abstract base class for filters defined for IPv4 packets.
Packet header for IPv6.
Definition ipv6-header.h:24
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Hold variables of type string.
Definition string.h:45
Header for the Transmission Control Protocol.
Definition tcp-header.h:36
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition tcp-header.cc:59
void SetSourcePort(uint16_t port)
Set the source port.
Definition tcp-header.cc:53
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition nstime.h:286
AttributeValue implementation for Time.
Definition nstime.h:1395
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Packet header for UDP packets.
Definition udp-header.h:30
void SetSourcePort(uint16_t port)
Definition udp-header.cc:31
void SetDestinationPort(uint16_t port)
Definition udp-header.cc:25
Hold an unsigned integer type.
Definition uinteger.h:34
static FqCobaltQueueDiscTestSuite g_fqCobaltQueueDiscTestSuite
Do not forget to allocate an instance of this TestSuite.
static int32_t g_hash
Variable to assign g_hash to a new packet's flow.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#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:134
#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:241
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
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:684
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:587