A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
fq-pie-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 (modified for FQ-PIE)
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 for FQ-PIE by: Bhaskar Kataria <bhaskar.k7920@gmail.com>
10 * Tom Henderson <tomhend@u.washington.edu>
11 * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
12 * Vivek Jain <jain.vivek.anand@gmail.com>
13 * Ankit Deepak <adadeepak8@gmail.com>
14 *
15 */
16
17#include "ns3/fq-pie-queue-disc.h"
18#include "ns3/ipv4-address.h"
19#include "ns3/ipv4-header.h"
20#include "ns3/ipv4-packet-filter.h"
21#include "ns3/ipv4-queue-disc-item.h"
22#include "ns3/ipv6-header.h"
23#include "ns3/ipv6-packet-filter.h"
24#include "ns3/ipv6-queue-disc-item.h"
25#include "ns3/pie-queue-disc.h"
26#include "ns3/pointer.h"
27#include "ns3/simulator.h"
28#include "ns3/string.h"
29#include "ns3/tcp-header.h"
30#include "ns3/test.h"
31#include "ns3/udp-header.h"
32
33using namespace ns3;
34
35/// Variable to assign g_hash to a new packet's flow
37
38/**
39 * \ingroup system-tests-tc
40 *
41 * Simple test packet filter able to classify IPv4 packets.
42 */
44{
45 public:
46 /**
47 * \brief Get the type ID.
48 * \return the object TypeId
49 */
50 static TypeId GetTypeId();
51
54
55 private:
56 /**
57 * Classify a QueueDiscItem
58 * \param item The item to classify (unused).
59 * \return a pre-set hash value.
60 */
61 int32_t DoClassify(Ptr<QueueDiscItem> item) const override;
62
63 /**
64 * Check the protocol.
65 * \param item The item to check (unused).
66 * \return true.
67 */
68 bool CheckProtocol(Ptr<QueueDiscItem> item) const override;
69};
70
73{
74 static TypeId tid = TypeId("ns3::Ipv4FqPieTestPacketFilter")
76 .SetGroupName("Internet")
77 .AddConstructor<Ipv4FqPieTestPacketFilter>();
78 return tid;
79}
80
84
88
94
95bool
100
101/**
102 * \ingroup system-tests-tc
103 *
104 * This class tests packets for which there is no suitable filter.
105 */
107{
108 public:
111
112 private:
113 void DoRun() override;
114};
115
117 : TestCase("Test packets that are not classified by any filter")
118{
119}
120
124
125void
127{
128 // Packets that cannot be classified by the available filters should be dropped
129 Ptr<FqPieQueueDisc> queueDisc =
132 queueDisc->AddPacketFilter(filter);
133
134 g_hash = -1;
135 queueDisc->SetQuantum(1500);
136 queueDisc->Initialize();
137
138 Ptr<Packet> p;
139 p = Create<Packet>();
141 Ipv6Header ipv6Header;
142 Address dest;
143 item = Create<Ipv6QueueDiscItem>(p, dest, 0, ipv6Header);
144 queueDisc->Enqueue(item);
145 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetNQueueDiscClasses(),
146 0,
147 "no flow queue should have been created");
148
149 p = Create<Packet>(reinterpret_cast<const uint8_t*>("hello, world"), 12);
150 item = Create<Ipv6QueueDiscItem>(p, dest, 0, ipv6Header);
151 queueDisc->Enqueue(item);
152 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetNQueueDiscClasses(),
153 0,
154 "no flow queue should have been created");
155
157}
158
159/**
160 * \ingroup system-tests-tc
161 *
162 * This class tests the IP flows separation and the packet limit.
163 */
165{
166 public:
169
170 private:
171 void DoRun() override;
172 /**
173 * Enqueue a packet.
174 * \param queue the queue disc
175 * \param hdr the IPv4 header
176 */
178};
179
184
188
189void
197
198void
200{
201 Ptr<FqPieQueueDisc> queueDisc =
203
204 queueDisc->SetQuantum(1500);
205 queueDisc->Initialize();
206
207 Ipv4Header hdr;
208 hdr.SetPayloadSize(100);
209 hdr.SetSource(Ipv4Address("10.10.1.1"));
210 hdr.SetDestination(Ipv4Address("10.10.1.2"));
211 hdr.SetProtocol(7);
212
213 // Add three packets from the first flow
214 AddPacket(queueDisc, hdr);
215 AddPacket(queueDisc, hdr);
216 AddPacket(queueDisc, hdr);
217 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
218 3,
219 "unexpected number of packets in the queue disc");
220 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
221 3,
222 "unexpected number of packets in the flow queue");
223
224 // Add two packets from the second flow
225 hdr.SetDestination(Ipv4Address("10.10.1.7"));
226 // Add the first packet
227 AddPacket(queueDisc, hdr);
228 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
229 4,
230 "unexpected number of packets in the queue disc");
231 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
232 3,
233 "unexpected number of packets in the flow queue");
234 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
235 1,
236 "unexpected number of packets in the flow queue");
237 // Add the second packet that causes two packets to be dropped from the fat flow (max backlog =
238 // 300, threshold = 150)
239 AddPacket(queueDisc, hdr);
240 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
241 3,
242 "unexpected number of packets in the queue disc");
243 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
244 1,
245 "unexpected number of packets in the flow queue");
246 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
247 2,
248 "unexpected number of packets in the flow queue");
249
251}
252
253/**
254 * \ingroup system-tests-tc
255 *
256 * This class tests the deficit per flow.
257 */
259{
260 public:
262 ~FqPieQueueDiscDeficit() override;
263
264 private:
265 void DoRun() override;
266 /**
267 * Enqueue a packet.
268 * \param queue The queue disc.
269 * \param hdr The IPv4 header.
270 */
272};
273
275 : TestCase("Test credits and flows status")
276{
277}
278
282
283void
285{
287 Address dest;
289 queue->Enqueue(item);
290}
291
292void
294{
296
297 queueDisc->SetQuantum(90);
298 queueDisc->Initialize();
299
300 Ipv4Header hdr;
301 hdr.SetPayloadSize(100);
302 hdr.SetSource(Ipv4Address("10.10.1.1"));
303 hdr.SetDestination(Ipv4Address("10.10.1.2"));
304 hdr.SetProtocol(7);
305
306 // Add a packet from the first flow
307 AddPacket(queueDisc, hdr);
308 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
309 1,
310 "unexpected number of packets in the queue disc");
311 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
312 1,
313 "unexpected number of packets in the first flow queue");
314 Ptr<FqPieFlow> flow1 = StaticCast<FqPieFlow>(queueDisc->GetQueueDiscClass(0));
315 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(),
316 static_cast<int32_t>(queueDisc->GetQuantum()),
317 "the deficit of the first flow must equal the quantum");
318 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
320 "the first flow must be in the list of new queues");
321 // Dequeue a packet
322 queueDisc->Dequeue();
323 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
324 0,
325 "unexpected number of packets in the queue disc");
326 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
327 0,
328 "unexpected number of packets in the first flow queue");
329 // the deficit for the first flow becomes 90 - (100+20) = -30
330 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -30, "unexpected deficit for the first flow");
331
332 // Add two packets from the first flow
333 AddPacket(queueDisc, hdr);
334 AddPacket(queueDisc, hdr);
335 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
336 2,
337 "unexpected number of packets in the queue disc");
338 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
339 2,
340 "unexpected number of packets in the first flow queue");
341 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
343 "the first flow must still be in the list of new queues");
344
345 // Add two packets from the second flow
346 hdr.SetDestination(Ipv4Address("10.10.1.10"));
347 AddPacket(queueDisc, hdr);
348 AddPacket(queueDisc, hdr);
349 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
350 4,
351 "unexpected number of packets in the queue disc");
352 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
353 2,
354 "unexpected number of packets in the first flow queue");
355 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
356 2,
357 "unexpected number of packets in the second flow queue");
358 Ptr<FqPieFlow> flow2 = StaticCast<FqPieFlow>(queueDisc->GetQueueDiscClass(1));
359 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(),
360 static_cast<int32_t>(queueDisc->GetQuantum()),
361 "the deficit of the second flow must equal the quantum");
362 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
364 "the second flow must be in the list of new queues");
365
366 // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
367 queueDisc->Dequeue();
368 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
369 3,
370 "unexpected number of packets in the queue disc");
371 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
372 2,
373 "unexpected number of packets in the first flow queue");
374 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
375 1,
376 "unexpected number of packets in the second flow queue");
377 // the first flow got a quantum of deficit (-30+90=60) and has been moved to the end of the list
378 // of old queues
379 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 60, "unexpected deficit for the first flow");
380 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
382 "the first flow must be in the list of old queues");
383 // the second flow has a negative deficit (-30) and is still in the list of new queues
384 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), -30, "unexpected deficit for the second flow");
385 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
387 "the second flow must be in the list of new queues");
388
389 // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
390 queueDisc->Dequeue();
391 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
392 2,
393 "unexpected number of packets in the queue disc");
394 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
395 1,
396 "unexpected number of packets in the first flow queue");
397 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
398 1,
399 "unexpected number of packets in the second flow queue");
400 // the first flow has a negative deficit (60-(100+20)= -60) and stays in the list of old queues
401 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -60, "unexpected deficit for the first flow");
402 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
404 "the first flow must be in the list of old queues");
405 // the second flow got a quantum of deficit (-30+90=60) and has been moved to the end of the
406 // list of old queues
407 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 60, "unexpected deficit for the second flow");
408 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
410 "the second flow must be in the list of new queues");
411
412 // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
413 queueDisc->Dequeue();
414 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
415 1,
416 "unexpected number of packets in the queue disc");
417 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
418 1,
419 "unexpected number of packets in the first flow queue");
420 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
421 0,
422 "unexpected number of packets in the second flow queue");
423 // the first flow got a quantum of deficit (-60+90=30) and has been moved to the end of the list
424 // of old queues
425 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 30, "unexpected deficit for the first flow");
426 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
428 "the first flow must be in the list of old queues");
429 // the second flow has a negative deficit (60-(100+20)= -60)
430 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), -60, "unexpected deficit for the second flow");
431 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
433 "the second flow must be in the list of new queues");
434
435 // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
436 queueDisc->Dequeue();
437 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
438 0,
439 "unexpected number of packets in the queue disc");
440 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
441 0,
442 "unexpected number of packets in the first flow queue");
443 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
444 0,
445 "unexpected number of packets in the second flow queue");
446 // the first flow has a negative deficit (30-(100+20)= -90)
447 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -90, "unexpected deficit for the first flow");
448 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
450 "the first flow must be in the list of old queues");
451 // the second flow got a quantum of deficit (-60+90=30) and has been moved to the end of the
452 // list of old queues
453 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 30, "unexpected deficit for the second flow");
454 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
456 "the second flow must be in the list of new queues");
457
458 // Dequeue a packet
459 queueDisc->Dequeue();
460 // the first flow is at the head of the list of old queues but has a negative deficit, thus it
461 // gets a quantun of deficit (-90+90=0) and is moved to the end of the list of old queues. Then,
462 // the second flow (which has a positive deficit) is selected, but the second flow is empty and
463 // thus it is set to inactive. The first flow is reconsidered, but it has a null deficit, hence
464 // it gets another quantum of deficit (0+90=90). Then, the first flow is reconsidered again, now
465 // it has a positive deficit and hence it is selected. But, it is empty and therefore is set to
466 // inactive, too.
467 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 90, "unexpected deficit for the first flow");
468 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
470 "the first flow must be inactive");
471 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 30, "unexpected deficit for the second flow");
472 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
474 "the second flow must be inactive");
475
477}
478
479/**
480 * \ingroup system-tests-tc
481 *
482 * This class tests the TCP flows separation.
483 */
485{
486 public:
489
490 private:
491 void DoRun() override;
492 /**
493 * Enqueue a packet.
494 * \param queue The queue disc.
495 * \param ipHdr The IPv4 header.
496 * \param tcpHdr The TCP header.
497 */
498 void AddPacket(Ptr<FqPieQueueDisc> queue, Ipv4Header ipHdr, TcpHeader tcpHdr);
499};
500
505
509
510void
512 Ipv4Header ipHdr,
513 TcpHeader tcpHdr)
514{
516 p->AddHeader(tcpHdr);
517 Address dest;
518 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, ipHdr);
519 queue->Enqueue(item);
520}
521
522void
524{
525 Ptr<FqPieQueueDisc> queueDisc =
527
528 queueDisc->SetQuantum(1500);
529 queueDisc->Initialize();
530
531 Ipv4Header hdr;
532 hdr.SetPayloadSize(100);
533 hdr.SetSource(Ipv4Address("10.10.1.1"));
534 hdr.SetDestination(Ipv4Address("10.10.1.2"));
535 hdr.SetProtocol(6);
536
537 TcpHeader tcpHdr;
538 tcpHdr.SetSourcePort(7);
539 tcpHdr.SetDestinationPort(27);
540
541 // Add three packets from the first flow
542 AddPacket(queueDisc, hdr, tcpHdr);
543 AddPacket(queueDisc, hdr, tcpHdr);
544 AddPacket(queueDisc, hdr, tcpHdr);
545 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
546 3,
547 "unexpected number of packets in the queue disc");
548 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
549 3,
550 "unexpected number of packets in the first flow queue");
551
552 // Add a packet from the second flow
553 tcpHdr.SetSourcePort(8);
554 AddPacket(queueDisc, hdr, tcpHdr);
555 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
556 4,
557 "unexpected number of packets in the queue disc");
558 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
559 3,
560 "unexpected number of packets in the first flow queue");
561 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
562 1,
563 "unexpected number of packets in the second flow queue");
564
565 // Add a packet from the third flow
566 tcpHdr.SetDestinationPort(28);
567 AddPacket(queueDisc, hdr, tcpHdr);
568 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
569 5,
570 "unexpected number of packets in the queue disc");
571 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
572 3,
573 "unexpected number of packets in the first flow queue");
574 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
575 1,
576 "unexpected number of packets in the second flow queue");
577 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
578 1,
579 "unexpected number of packets in the third flow queue");
580
581 // Add two packets from the fourth flow
582 tcpHdr.SetSourcePort(7);
583 AddPacket(queueDisc, hdr, tcpHdr);
584 AddPacket(queueDisc, hdr, tcpHdr);
585 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
586 7,
587 "unexpected number of packets in the queue disc");
588 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
589 3,
590 "unexpected number of packets in the first flow queue");
591 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
592 1,
593 "unexpected number of packets in the second flow queue");
594 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
595 1,
596 "unexpected number of packets in the third flow queue");
597 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
598 2,
599 "unexpected number of packets in the third flow queue");
600
602}
603
604/**
605 * \ingroup system-tests-tc
606 *
607 * This class tests the UDP flows separation
608 */
610{
611 public:
614
615 private:
616 void DoRun() override;
617 /**
618 * Enqueue a packet.
619 * \param queue The queue disc.
620 * \param ipHdr The IPv4 header.
621 * \param udpHdr The UDP header.
622 */
623 void AddPacket(Ptr<FqPieQueueDisc> queue, Ipv4Header ipHdr, UdpHeader udpHdr);
624};
625
630
634
635void
637 Ipv4Header ipHdr,
638 UdpHeader udpHdr)
639{
641 p->AddHeader(udpHdr);
642 Address dest;
643 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, ipHdr);
644 queue->Enqueue(item);
645}
646
647void
649{
650 Ptr<FqPieQueueDisc> queueDisc =
652
653 queueDisc->SetQuantum(1500);
654 queueDisc->Initialize();
655
656 Ipv4Header hdr;
657 hdr.SetPayloadSize(100);
658 hdr.SetSource(Ipv4Address("10.10.1.1"));
659 hdr.SetDestination(Ipv4Address("10.10.1.2"));
660 hdr.SetProtocol(17);
661
662 UdpHeader udpHdr;
663 udpHdr.SetSourcePort(7);
664 udpHdr.SetDestinationPort(27);
665
666 // Add three packets from the first flow
667 AddPacket(queueDisc, hdr, udpHdr);
668 AddPacket(queueDisc, hdr, udpHdr);
669 AddPacket(queueDisc, hdr, udpHdr);
670 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
671 3,
672 "unexpected number of packets in the queue disc");
673 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
674 3,
675 "unexpected number of packets in the first flow queue");
676
677 // Add a packet from the second flow
678 udpHdr.SetSourcePort(8);
679 AddPacket(queueDisc, hdr, udpHdr);
680 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
681 4,
682 "unexpected number of packets in the queue disc");
683 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
684 3,
685 "unexpected number of packets in the first flow queue");
686 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
687 1,
688 "unexpected number of packets in the second flow queue");
689
690 // Add a packet from the third flow
691 udpHdr.SetDestinationPort(28);
692 AddPacket(queueDisc, hdr, udpHdr);
693 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
694 5,
695 "unexpected number of packets in the queue disc");
696 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
697 3,
698 "unexpected number of packets in the first flow queue");
699 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
700 1,
701 "unexpected number of packets in the second flow queue");
702 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
703 1,
704 "unexpected number of packets in the third flow queue");
705
706 // Add two packets from the fourth flow
707 udpHdr.SetSourcePort(7);
708 AddPacket(queueDisc, hdr, udpHdr);
709 AddPacket(queueDisc, hdr, udpHdr);
710 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
711 7,
712 "unexpected number of packets in the queue disc");
713 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
714 3,
715 "unexpected number of packets in the first flow queue");
716 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
717 1,
718 "unexpected number of packets in the second flow queue");
719 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
720 1,
721 "unexpected number of packets in the third flow queue");
722 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
723 2,
724 "unexpected number of packets in the third flow queue");
725
727}
728
729/**
730 * \ingroup system-tests-tc
731 *
732 * \brief This class tests linear probing, collision response, and set
733 * creation capability of set associative hashing in FqPIE.
734 *
735 * This class tests linear probing, collision response, and set
736 * creation capability of set associative hashing in FqPIE.
737 * We modified DoClassify () and CheckProtocol () so that we could control
738 * the hash returned for each packet. In the beginning, we use flow hashes
739 * ranging from 0 to 7. These must go into different queues in the same set.
740 * The set number for these is obtained using outerhash, which is 0.
741 * When a new packet arrives with flow hash 1024, outerhash = 0 is obtained
742 * and the first set is iteratively searched.
743 * The packet is eventually added to queue 0 since the tags of queues
744 * in the set do not match with the hash of the flow. The tag of queue 0 is
745 * updated as 1024. When a packet with hash 1025 arrives, outerhash = 0
746 * is obtained and the first set is iteratively searched.
747 * Since there is no match, it is added to queue 0 and the tag of queue 0 is
748 * updated to 1025.
749 *
750 * The variable outerhash stores the nearest multiple of 8 that is lesser than
751 * the hash. When a flow hash of 20 arrives, the value of outerhash
752 * is 16. Since m_flowIndices[16] wasn't previously allotted, a new flow
753 * is created, and the tag corresponding to this queue is set to 20.
754 */
756{
757 public:
760
761 private:
762 void DoRun() override;
763 /**
764 * Enqueue a packet.
765 * \param queue The queue disc.
766 * \param hdr The IPv4 header.
767 */
769};
770
772 : TestCase("Test credits and flows status")
773{
774}
775
779
780void
782{
784 Address dest;
786 queue->Enqueue(item);
787}
788
789void
791{
792 Ptr<FqPieQueueDisc> queueDisc =
793 CreateObjectWithAttributes<FqPieQueueDisc>("EnableSetAssociativeHash", BooleanValue(true));
794 queueDisc->SetQuantum(90);
795 queueDisc->Initialize();
796
798 queueDisc->AddPacketFilter(filter);
799
800 Ipv4Header hdr;
801 hdr.SetPayloadSize(100);
802 hdr.SetSource(Ipv4Address("10.10.1.1"));
803 hdr.SetDestination(Ipv4Address("10.10.1.2"));
804 hdr.SetProtocol(7);
805
806 g_hash = 0;
807 AddPacket(queueDisc, hdr);
808 g_hash = 1;
809 AddPacket(queueDisc, hdr);
810 AddPacket(queueDisc, hdr);
811 g_hash = 2;
812 AddPacket(queueDisc, hdr);
813 g_hash = 3;
814 AddPacket(queueDisc, hdr);
815 g_hash = 4;
816 AddPacket(queueDisc, hdr);
817 AddPacket(queueDisc, hdr);
818 g_hash = 5;
819 AddPacket(queueDisc, hdr);
820 g_hash = 6;
821 AddPacket(queueDisc, hdr);
822 g_hash = 7;
823 AddPacket(queueDisc, hdr);
824 g_hash = 1024;
825 AddPacket(queueDisc, hdr);
826
827 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
828 11,
829 "unexpected number of packets in the queue disc");
830 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
831 2,
832 "unexpected number of packets in the first flow queue of set one");
833 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
834 2,
835 "unexpected number of packets in the second flow queue of set one");
836 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
837 1,
838 "unexpected number of packets in the third flow queue of set one");
839 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
840 1,
841 "unexpected number of packets in the fourth flow queue of set one");
842 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetNPackets(),
843 2,
844 "unexpected number of packets in the fifth flow queue of set one");
845 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(5)->GetQueueDisc()->GetNPackets(),
846 1,
847 "unexpected number of packets in the sixth flow queue of set one");
848 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(6)->GetQueueDisc()->GetNPackets(),
849 1,
850 "unexpected number of packets in the seventh flow queue of set one");
851 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(7)->GetQueueDisc()->GetNPackets(),
852 1,
853 "unexpected number of packets in the eighth flow queue of set one");
854 g_hash = 1025;
855 AddPacket(queueDisc, hdr);
856 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
857 3,
858 "unexpected number of packets in the first flow of set one");
859 g_hash = 10;
860 AddPacket(queueDisc, hdr);
861 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(8)->GetQueueDisc()->GetNPackets(),
862 1,
863 "unexpected number of packets in the first flow of set two");
865}
866
867/**
868 * \ingroup system-tests-tc
869 *
870 * \brief This class tests L4S mode.
871 *
872 * This test is divided to sub test one without hash collisions and so ECT0 and ECT1 flows are
873 * classified into different flows.
874 * Sub Test 1
875 * 70 packets are enqueued into both the flows with the delay of 0.5ms between two enqueues, and
876 * dequeued with the delay of 1ms between two dequeues. Sub Test 2 140(70 ECT0 + 70 ECT1) packets
877 * are enqueued such that ECT1 packets are enqueued at 0.5ms, 1.5ms, 2.5ms and so on, and ECT0
878 * packets are enqueued are enqueued at 1ms, 2ms, 3ms and so on Any future classifier options (e.g.
879 * SetAssociativehash) should be disabled to prevent a hash collision on this test case.
880 */
882{
883 public:
885 ~FqPieQueueDiscL4sMode() override;
886
887 private:
888 void DoRun() override;
889 /**
890 * Enqueue the given number of packets.
891 * \param queue The queue disc.
892 * \param hdr The IPv4 header.
893 * \param nPkt The number of packets.
894 */
895 void AddPacket(Ptr<FqPieQueueDisc> queue, Ipv4Header hdr, uint32_t nPkt);
896 /**
897 * Enqueue the given number of packets at different times.
898 * \param queue The queue disc.
899 * \param hdr The IPv4 header.
900 * \param delay The time between two consecutive enqueue operations.
901 * \param nPkt The number of packets.
902 */
903 void AddPacketWithDelay(Ptr<FqPieQueueDisc> queue, Ipv4Header hdr, double delay, uint32_t nPkt);
904 /**
905 * Dequeue the given number of packets.
906 * \param queue The queue disc.
907 * \param nPkt The number of packets.
908 */
909 void Dequeue(Ptr<FqPieQueueDisc> queue, uint32_t nPkt);
910 /**
911 * Dequeue the given number of packets at different times.
912 * \param queue The queue disc.
913 * \param delay The time between two consecutive dequeue operations.
914 * \param nPkt The number of packets.
915 */
916 void DequeueWithDelay(Ptr<FqPieQueueDisc> queue, double delay, uint32_t nPkt);
917};
918
923
927
928void
930{
931 Address dest;
933 for (uint32_t i = 0; i < nPkt; i++)
934 {
936 queue->Enqueue(item);
937 }
938}
939
940void
942 Ipv4Header hdr,
943 double delay,
944 uint32_t nPkt)
945{
946 for (uint32_t i = 0; i < nPkt; i++)
947 {
948 Simulator::Schedule(Time(Seconds((i + 1) * delay)),
950 this,
951 queue,
952 hdr,
953 1);
954 }
955}
956
957void
959{
960 for (uint32_t i = 0; i < nPkt; i++)
961 {
962 Ptr<QueueDiscItem> item = queue->Dequeue();
963 }
964}
965
966void
968{
969 for (uint32_t i = 0; i < nPkt; i++)
970 {
971 Simulator::Schedule(Time(Seconds((i + 1) * delay)),
973 this,
974 queue,
975 1);
976 }
977}
978
979void
981{
982 // Test is divided into 2 sub test cases:
983 // 1) Without hash collisions
984 // 2) With hash collisions
985
986 // Test case 1, Without hash collisions
987 Ptr<FqPieQueueDisc> queueDisc =
989 StringValue("10240p"),
990 "UseEcn",
991 BooleanValue(true),
992 "Perturbation",
993 UintegerValue(0),
994 "UseL4s",
995 BooleanValue(true),
996 "CeThreshold",
998
999 queueDisc->SetQuantum(1514);
1000 queueDisc->Initialize();
1001 Ipv4Header hdr;
1002 hdr.SetPayloadSize(100);
1003 hdr.SetSource(Ipv4Address("10.10.1.1"));
1004 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1005 hdr.SetProtocol(7);
1007
1008 // Add 70 ECT1 (ECN capable) packets from the first flow
1009 // Set delay = 0.5ms
1010 double delay = 0.0005;
1013 this,
1014 queueDisc,
1015 hdr,
1016 delay,
1017 70);
1018
1019 // Add 70 ECT0 (ECN capable) packets from second flow
1021 hdr.SetDestination(Ipv4Address("10.10.1.10"));
1024 this,
1025 queueDisc,
1026 hdr,
1027 delay,
1028 70);
1029
1030 // Dequeue 140 packets with delay 1ms
1031 delay = 0.001;
1032 DequeueWithDelay(queueDisc, delay, 140);
1033 Simulator::Stop(Seconds(10.0));
1035
1037 queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<PieQueueDisc>();
1039 queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetObject<PieQueueDisc>();
1040
1042 q0->GetStats().GetNMarkedPackets(PieQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1043 66,
1044 "There should be 66 marked packets"
1045 "4th packet is enqueued at 2ms and dequeued at 4ms hence the delay of 2ms which not "
1046 "greater than CE threshold"
1047 "5th packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and "
1048 "subsequent packet also do have delay"
1049 "greater than CE threshold so all the packets after 4th packet are marked");
1050 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
1051 0,
1052 "Queue delay is less than max burst allowance so"
1053 "There should not be any dropped packets");
1054 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK),
1055 0,
1056 "There should not be any marked packets");
1057 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK),
1058 0,
1059 "There should not be marked packets.");
1060 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
1061 0,
1062 "There should not be any dropped packets");
1063
1065
1066 // Test case 2, With hash collisions
1067 queueDisc = CreateObjectWithAttributes<FqPieQueueDisc>("MaxSize",
1068 StringValue("10240p"),
1069 "UseEcn",
1070 BooleanValue(true),
1071 "Perturbation",
1072 UintegerValue(0),
1073 "UseL4s",
1074 BooleanValue(true),
1075 "CeThreshold",
1077
1078 queueDisc->SetQuantum(1514);
1079 queueDisc->Initialize();
1080 hdr.SetPayloadSize(100);
1081 hdr.SetSource(Ipv4Address("10.10.1.1"));
1082 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1083 hdr.SetProtocol(7);
1085
1086 // Add 70 ECT1 (ECN capable) packets from the first flow
1087 // Set delay = 1ms
1088 delay = 0.001;
1091 this,
1092 queueDisc,
1093 hdr,
1094 1);
1097 this,
1098 queueDisc,
1099 hdr,
1100 delay,
1101 69);
1102
1103 // Add 70 ECT0 (ECN capable) packets from first flow
1107 this,
1108 queueDisc,
1109 hdr,
1110 delay,
1111 70);
1112
1113 // Dequeue 140 packets with delay 1ms
1114 DequeueWithDelay(queueDisc, delay, 140);
1117 q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<PieQueueDisc>();
1118 q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<PieQueueDisc>();
1119
1121 q0->GetStats().GetNMarkedPackets(PieQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1122 68,
1123 "There should be 68 marked packets"
1124 "2nd ECT1 packet is enqueued at 1.5ms and dequeued at 3ms hence the delay of 1.5ms which "
1125 "not greater than CE threshold"
1126 "3rd packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and "
1127 "subsequent packet also do have delay"
1128 "greater than CE threshold so all the packets after 2nd packet are marked");
1129 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
1130 0,
1131 "Queue delay is less than max burst allowance so"
1132 "There should not be any dropped packets");
1133 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK),
1134 0,
1135 "There should not be any marked packets");
1136
1138}
1139
1140/**
1141 * \ingroup system-tests-tc
1142 *
1143 * FQ-PIE queue disc test suite.
1144 */
1146{
1147 public:
1149};
1150
1152 : TestSuite("fq-pie-queue-disc", Type::UNIT)
1153{
1154 AddTestCase(new FqPieQueueDiscNoSuitableFilter, TestCase::Duration::QUICK);
1155 AddTestCase(new FqPieQueueDiscIPFlowsSeparationAndPacketLimit, TestCase::Duration::QUICK);
1156 AddTestCase(new FqPieQueueDiscDeficit, TestCase::Duration::QUICK);
1157 AddTestCase(new FqPieQueueDiscTCPFlowsSeparation, TestCase::Duration::QUICK);
1158 AddTestCase(new FqPieQueueDiscUDPFlowsSeparation, TestCase::Duration::QUICK);
1159 AddTestCase(new FqPieQueueDiscSetLinearProbing, TestCase::Duration::QUICK);
1160 AddTestCase(new FqPieQueueDiscL4sMode, TestCase::Duration::QUICK);
1161}
1162
1163/// 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< FqPieQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
This class tests the IP flows separation and the packet limit.
void AddPacket(Ptr< FqPieQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
void DoRun() override
Implementation to actually run this TestCase.
void AddPacketWithDelay(Ptr< FqPieQueueDisc > queue, Ipv4Header hdr, double delay, uint32_t nPkt)
Enqueue the given number of packets at different times.
void DoRun() override
Implementation to actually run this TestCase.
void DequeueWithDelay(Ptr< FqPieQueueDisc > queue, double delay, uint32_t nPkt)
Dequeue the given number of packets at different times.
void AddPacket(Ptr< FqPieQueueDisc > queue, Ipv4Header hdr, uint32_t nPkt)
Enqueue the given number of packets.
void Dequeue(Ptr< FqPieQueueDisc > queue, uint32_t nPkt)
Dequeue the given number of packets.
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< FqPieQueueDisc > 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< FqPieQueueDisc > queue, Ipv4Header ipHdr, TcpHeader tcpHdr)
Enqueue a packet.
FQ-PIE queue disc test suite.
This class tests the UDP flows separation.
void DoRun() override
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqPieQueueDisc > queue, Ipv4Header ipHdr, UdpHeader udpHdr)
Enqueue a packet.
Simple test packet filter able to classify IPv4 packets.
static TypeId GetTypeId()
Get the type ID.
bool CheckProtocol(Ptr< QueueDiscItem > item) const override
Check the protocol.
int32_t DoClassify(Ptr< QueueDiscItem > item) const override
Classify a QueueDiscItem.
a polymophic address class
Definition address.h:90
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
Implements PIE Active Queue Management discipline.
static constexpr const char * UNFORCED_DROP
Early probability drops: proactive.
static constexpr const char * CE_THRESHOLD_EXCEEDED_MARK
Early probability marks: proactive.
static constexpr const char * UNFORCED_MARK
Early probability marks: proactive.
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
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 FqPieQueueDiscTestSuite g_fqPieQueueDiscTestSuite
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.
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:587