A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
fq-codel-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 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Pasquale Imputato <p.imputato@gmail.com>
7 * Stefano Avallone <stefano.avallone@unina.it>
8 */
9
10#include "ns3/codel-queue-disc.h"
11#include "ns3/fq-codel-queue-disc.h"
12#include "ns3/ipv4-address.h"
13#include "ns3/ipv4-header.h"
14#include "ns3/ipv4-packet-filter.h"
15#include "ns3/ipv4-queue-disc-item.h"
16#include "ns3/ipv6-header.h"
17#include "ns3/ipv6-packet-filter.h"
18#include "ns3/ipv6-queue-disc-item.h"
19#include "ns3/pointer.h"
20#include "ns3/simulator.h"
21#include "ns3/string.h"
22#include "ns3/tcp-header.h"
23#include "ns3/test.h"
24#include "ns3/udp-header.h"
25
26using namespace ns3;
27
28/// Variable to assign g_hash to a new packet's flow
30
31/**
32 * \ingroup system-tests-tc
33 *
34 * Simple test packet filter able to classify IPv4 packets.
35 */
37{
38 public:
39 /**
40 * \brief Get the type ID.
41 * \return the object TypeId
42 */
43 static TypeId GetTypeId();
44
46 ~Ipv4TestPacketFilter() override;
47
48 private:
49 /**
50 * Classify a QueueDiscItem
51 * \param item The item to classify (unused).
52 * \return a pre-set hash value.
53 */
54 int32_t DoClassify(Ptr<QueueDiscItem> item) const override;
55
56 /**
57 * Check the protocol.
58 * \param item The item to check (unused).
59 * \return true.
60 */
61 bool CheckProtocol(Ptr<QueueDiscItem> item) const override;
62};
63
66{
67 static TypeId tid = TypeId("ns3::Ipv4TestPacketFilter")
69 .SetGroupName("Internet")
70 .AddConstructor<Ipv4TestPacketFilter>();
71 return tid;
72}
73
77
81
87
88bool
90{
91 return true;
92}
93
94/**
95 * \ingroup system-tests-tc
96 *
97 * This class tests packets for which there is no suitable filter.
98 */
100{
101 public:
104
105 private:
106 void DoRun() override;
107};
108
110 : TestCase("Test packets that are not classified by any filter")
111{
112}
113
117
118void
120{
121 // Packets that cannot be classified by the available filters should be dropped
122 Ptr<FqCoDelQueueDisc> queueDisc =
125 queueDisc->AddPacketFilter(filter);
126
127 g_hash = -1;
128 queueDisc->SetQuantum(1500);
129 queueDisc->Initialize();
130
131 Ptr<Packet> p;
132 p = Create<Packet>();
134 Ipv6Header ipv6Header;
135 Address dest;
136 item = Create<Ipv6QueueDiscItem>(p, dest, 0, ipv6Header);
137 queueDisc->Enqueue(item);
138 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetNQueueDiscClasses(),
139 0,
140 "no flow queue should have been created");
141
142 p = Create<Packet>(reinterpret_cast<const uint8_t*>("hello, world"), 12);
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
150}
151
152/**
153 * \ingroup system-tests-tc
154 *
155 * This class tests the IP flows separation and the packet limit.
156 */
158{
159 public:
162
163 private:
164 void DoRun() override;
165 /**
166 * Enqueue a packet.
167 * \param queue The queue disc.
168 * \param hdr The IPv4 header.
169 */
171};
172
177
181
182void
191
192void
194{
195 Ptr<FqCoDelQueueDisc> queueDisc =
197
198 queueDisc->SetQuantum(1500);
199 queueDisc->Initialize();
200
201 Ipv4Header hdr;
202 hdr.SetPayloadSize(100);
203 hdr.SetSource(Ipv4Address("10.10.1.1"));
204 hdr.SetDestination(Ipv4Address("10.10.1.2"));
205 hdr.SetProtocol(7);
206
207 // Add three packets from the first flow
208 AddPacket(queueDisc, hdr);
209 AddPacket(queueDisc, hdr);
210 AddPacket(queueDisc, hdr);
211 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
212 3,
213 "unexpected number of packets in the queue disc");
214 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
215 3,
216 "unexpected number of packets in the flow queue");
217
218 // Add two packets from the second flow
219 hdr.SetDestination(Ipv4Address("10.10.1.7"));
220 // Add the first packet
221 AddPacket(queueDisc, hdr);
222 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
223 4,
224 "unexpected number of packets in the queue disc");
225 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
226 3,
227 "unexpected number of packets in the flow queue");
228 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
229 1,
230 "unexpected number of packets in the flow queue");
231 // Add the second packet that causes two packets to be dropped from the fat flow (max backlog =
232 // 300, threshold = 150)
233 AddPacket(queueDisc, hdr);
234 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
235 3,
236 "unexpected number of packets in the queue disc");
237 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
238 1,
239 "unexpected number of packets in the flow queue");
240 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
241 2,
242 "unexpected number of packets in the flow queue");
243
245}
246
247/**
248 * \ingroup system-tests-tc
249 *
250 * This class tests the deficit per flow.
251 */
253{
254 public:
256 ~FqCoDelQueueDiscDeficit() override;
257
258 private:
259 void DoRun() override;
260 /**
261 * Enqueue a packet.
262 * \param queue The queue disc.
263 * \param hdr The IPv4 header.
264 */
266};
267
269 : TestCase("Test credits and flows status")
270{
271}
272
276
277void
279{
281 Address dest;
283 queue->Enqueue(item);
284}
285
286void
288{
290
291 queueDisc->SetQuantum(90);
292 queueDisc->Initialize();
293
294 Ipv4Header hdr;
295 hdr.SetPayloadSize(100);
296 hdr.SetSource(Ipv4Address("10.10.1.1"));
297 hdr.SetDestination(Ipv4Address("10.10.1.2"));
298 hdr.SetProtocol(7);
299
300 // Add a packet from the first flow
301 AddPacket(queueDisc, hdr);
302 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
303 1,
304 "unexpected number of packets in the queue disc");
305 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
306 1,
307 "unexpected number of packets in the first flow queue");
308 Ptr<FqCoDelFlow> flow1 = StaticCast<FqCoDelFlow>(queueDisc->GetQueueDiscClass(0));
309 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(),
310 static_cast<int32_t>(queueDisc->GetQuantum()),
311 "the deficit of the first flow must equal the quantum");
312 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
314 "the first flow must be in the list of new queues");
315 // Dequeue a packet
316 queueDisc->Dequeue();
317 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
318 0,
319 "unexpected number of packets in the queue disc");
320 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
321 0,
322 "unexpected number of packets in the first flow queue");
323 // the deficit for the first flow becomes 90 - (100+20) = -30
324 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -30, "unexpected deficit for the first flow");
325
326 // Add two packets from the first flow
327 AddPacket(queueDisc, hdr);
328 AddPacket(queueDisc, hdr);
329 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
330 2,
331 "unexpected number of packets in the queue disc");
332 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
333 2,
334 "unexpected number of packets in the first flow queue");
335 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
337 "the first flow must still be in the list of new queues");
338
339 // Add two packets from the second flow
340 hdr.SetDestination(Ipv4Address("10.10.1.10"));
341 AddPacket(queueDisc, hdr);
342 AddPacket(queueDisc, hdr);
343 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
344 4,
345 "unexpected number of packets in the queue disc");
346 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
347 2,
348 "unexpected number of packets in the first flow queue");
349 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
350 2,
351 "unexpected number of packets in the second flow queue");
352 Ptr<FqCoDelFlow> flow2 = StaticCast<FqCoDelFlow>(queueDisc->GetQueueDiscClass(1));
353 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(),
354 static_cast<int32_t>(queueDisc->GetQuantum()),
355 "the deficit of the second flow must equal the quantum");
356 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
358 "the second flow must be in the list of new queues");
359
360 // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
361 queueDisc->Dequeue();
362 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
363 3,
364 "unexpected number of packets in the queue disc");
365 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
366 2,
367 "unexpected number of packets in the first flow queue");
368 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
369 1,
370 "unexpected number of packets in the second flow queue");
371 // the first flow got a quantum of deficit (-30+90=60) and has been moved to the end of the list
372 // of old queues
373 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 60, "unexpected deficit for the first flow");
374 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
376 "the first flow must be in the list of old queues");
377 // the second flow has a negative deficit (-30) and is still in the list of new queues
378 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), -30, "unexpected deficit for the second flow");
379 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
381 "the second flow must be in the list of new queues");
382
383 // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
384 queueDisc->Dequeue();
385 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
386 2,
387 "unexpected number of packets in the queue disc");
388 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
389 1,
390 "unexpected number of packets in the first flow queue");
391 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
392 1,
393 "unexpected number of packets in the second flow queue");
394 // the first flow has a negative deficit (60-(100+20)= -60) and stays in the list of old queues
395 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -60, "unexpected deficit for the first flow");
396 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
398 "the first flow must be in the list of old queues");
399 // the second flow got a quantum of deficit (-30+90=60) and has been moved to the end of the
400 // list of old queues
401 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 60, "unexpected deficit for the second flow");
402 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
404 "the second flow must be in the list of new queues");
405
406 // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
407 queueDisc->Dequeue();
408 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
409 1,
410 "unexpected number of packets in the queue disc");
411 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
412 1,
413 "unexpected number of packets in the first flow queue");
414 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
415 0,
416 "unexpected number of packets in the second flow queue");
417 // the first flow got a quantum of deficit (-60+90=30) and has been moved to the end of the list
418 // of old queues
419 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 30, "unexpected deficit for the first flow");
420 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
422 "the first flow must be in the list of old queues");
423 // the second flow has a negative deficit (60-(100+20)= -60)
424 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), -60, "unexpected deficit for the second flow");
425 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
427 "the second flow must be in the list of new queues");
428
429 // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
430 queueDisc->Dequeue();
431 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
432 0,
433 "unexpected number of packets in the queue disc");
434 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
435 0,
436 "unexpected number of packets in the first flow queue");
437 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
438 0,
439 "unexpected number of packets in the second flow queue");
440 // the first flow has a negative deficit (30-(100+20)= -90)
441 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -90, "unexpected deficit for the first flow");
442 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
444 "the first flow must be in the list of old queues");
445 // the second flow got a quantum of deficit (-60+90=30) and has been moved to the end of the
446 // list of old queues
447 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 30, "unexpected deficit for the second flow");
448 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
450 "the second flow must be in the list of new queues");
451
452 // Dequeue a packet
453 queueDisc->Dequeue();
454 // the first flow is at the head of the list of old queues but has a negative deficit, thus it
455 // gets a quantun of deficit (-90+90=0) and is moved to the end of the list of old queues. Then,
456 // the second flow (which has a positive deficit) is selected, but the second flow is empty and
457 // thus it is set to inactive. The first flow is reconsidered, but it has a null deficit, hence
458 // it gets another quantum of deficit (0+90=90). Then, the first flow is reconsidered again, now
459 // it has a positive deficit and hence it is selected. But, it is empty and therefore is set to
460 // inactive, too.
461 NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 90, "unexpected deficit for the first flow");
462 NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
464 "the first flow must be inactive");
465 NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 30, "unexpected deficit for the second flow");
466 NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
468 "the second flow must be inactive");
469
471}
472
473/**
474 * \ingroup system-tests-tc
475 *
476 * This class tests the TCP flows separation.
477 */
479{
480 public:
483
484 private:
485 void DoRun() override;
486 /**
487 * Enqueue a packet.
488 * \param queue The queue disc.
489 * \param ipHdr The IPv4 header.
490 * \param tcpHdr The TCP header.
491 */
492 void AddPacket(Ptr<FqCoDelQueueDisc> queue, Ipv4Header ipHdr, TcpHeader tcpHdr);
493};
494
499
503
504void
506 Ipv4Header ipHdr,
507 TcpHeader tcpHdr)
508{
510 p->AddHeader(tcpHdr);
511 Address dest;
512 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, ipHdr);
513 queue->Enqueue(item);
514}
515
516void
518{
519 Ptr<FqCoDelQueueDisc> queueDisc =
521
522 queueDisc->SetQuantum(1500);
523 queueDisc->Initialize();
524
525 Ipv4Header hdr;
526 hdr.SetPayloadSize(100);
527 hdr.SetSource(Ipv4Address("10.10.1.1"));
528 hdr.SetDestination(Ipv4Address("10.10.1.2"));
529 hdr.SetProtocol(6);
530
531 TcpHeader tcpHdr;
532 tcpHdr.SetSourcePort(7);
533 tcpHdr.SetDestinationPort(27);
534
535 // Add three packets from the first flow
536 AddPacket(queueDisc, hdr, tcpHdr);
537 AddPacket(queueDisc, hdr, tcpHdr);
538 AddPacket(queueDisc, hdr, tcpHdr);
539 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
540 3,
541 "unexpected number of packets in the queue disc");
542 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
543 3,
544 "unexpected number of packets in the first flow queue");
545
546 // Add a packet from the second flow
547 tcpHdr.SetSourcePort(8);
548 AddPacket(queueDisc, hdr, tcpHdr);
549 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
550 4,
551 "unexpected number of packets in the queue disc");
552 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
553 3,
554 "unexpected number of packets in the first flow queue");
555 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
556 1,
557 "unexpected number of packets in the second flow queue");
558
559 // Add a packet from the third flow
560 tcpHdr.SetDestinationPort(28);
561 AddPacket(queueDisc, hdr, tcpHdr);
562 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
563 5,
564 "unexpected number of packets in the queue disc");
565 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
566 3,
567 "unexpected number of packets in the first flow queue");
568 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
569 1,
570 "unexpected number of packets in the second flow queue");
571 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
572 1,
573 "unexpected number of packets in the third flow queue");
574
575 // Add two packets from the fourth flow
576 tcpHdr.SetSourcePort(7);
577 AddPacket(queueDisc, hdr, tcpHdr);
578 AddPacket(queueDisc, hdr, tcpHdr);
579 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
580 7,
581 "unexpected number of packets in the queue disc");
582 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
583 3,
584 "unexpected number of packets in the first flow queue");
585 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
586 1,
587 "unexpected number of packets in the second flow queue");
588 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
589 1,
590 "unexpected number of packets in the third flow queue");
591 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
592 2,
593 "unexpected number of packets in the third flow queue");
594
596}
597
598/**
599 * \ingroup system-tests-tc
600 *
601 * This class tests the UDP flows separation
602 */
604{
605 public:
608
609 private:
610 void DoRun() override;
611 /**
612 * Enqueue a packet.
613 * \param queue The queue disc.
614 * \param ipHdr The IPv4 header.
615 * \param udpHdr The UDP header.
616 */
617 void AddPacket(Ptr<FqCoDelQueueDisc> queue, Ipv4Header ipHdr, UdpHeader udpHdr);
618};
619
624
628
629void
631 Ipv4Header ipHdr,
632 UdpHeader udpHdr)
633{
635 p->AddHeader(udpHdr);
636 Address dest;
637 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, ipHdr);
638 queue->Enqueue(item);
639}
640
641void
643{
644 Ptr<FqCoDelQueueDisc> queueDisc =
646
647 queueDisc->SetQuantum(1500);
648 queueDisc->Initialize();
649
650 Ipv4Header hdr;
651 hdr.SetPayloadSize(100);
652 hdr.SetSource(Ipv4Address("10.10.1.1"));
653 hdr.SetDestination(Ipv4Address("10.10.1.2"));
654 hdr.SetProtocol(17);
655
656 UdpHeader udpHdr;
657 udpHdr.SetSourcePort(7);
658 udpHdr.SetDestinationPort(27);
659
660 // Add three packets from the first flow
661 AddPacket(queueDisc, hdr, udpHdr);
662 AddPacket(queueDisc, hdr, udpHdr);
663 AddPacket(queueDisc, hdr, udpHdr);
664 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
665 3,
666 "unexpected number of packets in the queue disc");
667 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
668 3,
669 "unexpected number of packets in the first flow queue");
670
671 // Add a packet from the second flow
672 udpHdr.SetSourcePort(8);
673 AddPacket(queueDisc, hdr, udpHdr);
674 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
675 4,
676 "unexpected number of packets in the queue disc");
677 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
678 3,
679 "unexpected number of packets in the first flow queue");
680 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
681 1,
682 "unexpected number of packets in the second flow queue");
683
684 // Add a packet from the third flow
685 udpHdr.SetDestinationPort(28);
686 AddPacket(queueDisc, hdr, udpHdr);
687 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
688 5,
689 "unexpected number of packets in the queue disc");
690 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
691 3,
692 "unexpected number of packets in the first flow queue");
693 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
694 1,
695 "unexpected number of packets in the second flow queue");
696 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
697 1,
698 "unexpected number of packets in the third flow queue");
699
700 // Add two packets from the fourth flow
701 udpHdr.SetSourcePort(7);
702 AddPacket(queueDisc, hdr, udpHdr);
703 AddPacket(queueDisc, hdr, udpHdr);
704 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
705 7,
706 "unexpected number of packets in the queue disc");
707 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
708 3,
709 "unexpected number of packets in the first flow queue");
710 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
711 1,
712 "unexpected number of packets in the second flow queue");
713 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
714 1,
715 "unexpected number of packets in the third flow queue");
716 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
717 2,
718 "unexpected number of packets in the third flow queue");
719
721}
722
723/**
724 * \ingroup system-tests-tc
725 *
726 * \brief This class tests ECN marking.
727 *
728 * Any future classifier options (e.g. SetAssociativeHash) should be
729 * disabled to prevent a hash collision on this test case.
730 */
732{
733 public:
736
737 private:
738 void DoRun() override;
739 /**
740 * Enqueue some packets.
741 * \param queue The queue disc.
742 * \param hdr The IPv4 header.
743 * \param nPkt The number of packets to enqueue.
744 * \param nPktEnqueued The expected number of queue disc classes.
745 * \param nQueueFlows The expected number of flows in the queue.
746 */
748 Ipv4Header hdr,
749 uint32_t nPkt,
750 uint32_t nPktEnqueued,
751 uint32_t nQueueFlows);
752 /**
753 * Dequeue some packets.
754 * \param queue The queue disc.
755 * \param nPkt The number of packets to dequeue.
756 */
757 void Dequeue(Ptr<FqCoDelQueueDisc> queue, uint32_t nPkt);
758 /**
759 * Dequeue some packets with delay.
760 * \param queue The queue disc.
761 * \param delay Delay [seconds].
762 * \param nPkt The number of packets to dequeue.
763 */
764 void DequeueWithDelay(Ptr<FqCoDelQueueDisc> queue, double delay, uint32_t nPkt);
765};
766
771
775
776void
778 Ipv4Header hdr,
779 uint32_t nPkt,
780 uint32_t nPktEnqueued,
781 uint32_t nQueueFlows)
782{
783 Address dest;
785 for (uint32_t i = 0; i < nPkt; i++)
786 {
788 queue->Enqueue(item);
789 }
790 NS_TEST_EXPECT_MSG_EQ(queue->GetNQueueDiscClasses(),
791 nQueueFlows,
792 "unexpected number of flow queues");
793 NS_TEST_EXPECT_MSG_EQ(queue->GetNPackets(),
794 nPktEnqueued,
795 "unexpected number of enqueued packets");
796}
797
798void
800{
801 for (uint32_t i = 0; i < nPkt; i++)
802 {
803 Ptr<QueueDiscItem> item = queue->Dequeue();
804 }
805}
806
807void
809 double delay,
810 uint32_t nPkt)
811{
812 for (uint32_t i = 0; i < nPkt; i++)
813 {
814 Simulator::Schedule(Time(Seconds((i + 1) * delay)),
816 this,
817 queue,
818 1);
819 }
820}
821
822void
824{
825 // Test is divided into 3 sub test cases:
826 // 1) CeThreshold disabled
827 // 2) CeThreshold enabled
828 // 3) Same as 2 but with higher queue delay, leading to both mark types, and checks that the
829 // same packet is not marked twice
830
831 // Test case 1, CeThreshold disabled
832 Ptr<FqCoDelQueueDisc> queueDisc =
834 StringValue("10240p"),
835 "UseEcn",
836 BooleanValue(true),
837 "Perturbation",
838 UintegerValue(0));
839
840 queueDisc->SetQuantum(1514);
841 queueDisc->Initialize();
842 Ipv4Header hdr;
843 hdr.SetPayloadSize(100);
844 hdr.SetSource(Ipv4Address("10.10.1.1"));
845 hdr.SetDestination(Ipv4Address("10.10.1.2"));
846 hdr.SetProtocol(7);
848
849 // Add 20 ECT0 (ECN capable) packets from the first flow
852 this,
853 queueDisc,
854 hdr,
855 20,
856 20,
857 1);
858
859 // Add 20 ECT0 (ECN capable) packets from second flow
860 hdr.SetDestination(Ipv4Address("10.10.1.10"));
863 this,
864 queueDisc,
865 hdr,
866 20,
867 40,
868 2);
869
870 // Add 20 ECT0 (ECN capable) packets from third flow
871 hdr.SetDestination(Ipv4Address("10.10.1.20"));
874 this,
875 queueDisc,
876 hdr,
877 20,
878 60,
879 3);
880
881 // Add 20 NotECT packets from fourth flow
882 hdr.SetDestination(Ipv4Address("10.10.1.30"));
886 this,
887 queueDisc,
888 hdr,
889 20,
890 80,
891 4);
892
893 // Add 20 NotECT packets from fifth flow
894 hdr.SetDestination(Ipv4Address("10.10.1.40"));
897 this,
898 queueDisc,
899 hdr,
900 20,
901 100,
902 5);
903
904 // Dequeue 60 packets with delay 110ms to induce packet drops and keep some remaining packets in
905 // each queue
906 DequeueWithDelay(queueDisc, 0.11, 60);
910 queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
912 queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
914 queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
916 queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
918 queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
919
920 // Ensure there are some remaining packets in the flow queues to check for flow queues with ECN
921 // capable packets
922 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
923 0,
924 "There should be some remaining packets");
925 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
926 0,
927 "There should be some remaining packets");
928 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
929 0,
930 "There should be some remaining packets");
931 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
932 0,
933 "There should be some remaining packets");
934 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetNPackets(),
935 0,
936 "There should be some remaining packets");
937
938 // As packets in flow queues are ECN capable
939 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
940 6,
941 "There should be 6 marked packets"
942 "with 20 packets, total bytes in the queue = 120 * 20 = 2400. First "
943 "packet dequeues at 110ms which is greater than"
944 "test's default target value 5ms. Sojourn time has just gone above "
945 "target from below, need to stay above for at"
946 "least q->interval before packet can be dropped. Second packet dequeues "
947 "at 220ms which is greater than last dequeue"
948 "time plus q->interval(test default 100ms) so the packet is marked. "
949 "Third packet dequeues at 330ms and the sojourn"
950 "time stayed above the target and dropnext value is less than 320 hence "
951 "the packet is marked. 4 subsequent packets"
952 "are marked as the sojourn time stays above the target. With 8th dequeue "
953 "number of bytes in queue = 120 * 12 = 1440"
954 "which is less m_minBytes(test's default value 1500 bytes) hence the "
955 "packets stop getting marked");
956 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
957 0,
958 "There should not be any dropped packets");
959 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
960 6,
961 "There should be 6 marked packets");
962 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
963 0,
964 "There should not be any dropped packets");
965 NS_TEST_EXPECT_MSG_EQ(q2->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
966 6,
967 "There should be 6 marked packets");
968 NS_TEST_EXPECT_MSG_EQ(q2->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
969 0,
970 "There should not be any dropped packets");
971
972 // As packets in flow queues are not ECN capable
974 q3->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
975 4,
976 "There should be 4 dropped packets"
977 "with 20 packets, total bytes in the queue = 120 * 20 = 2400. First packet dequeues at "
978 "110ms which is greater than"
979 "test's default target value 5ms. Sojourn time has just gone above target from below, need "
980 "to stay above for at"
981 "least q->interval before packet can be dropped. Second packet dequeues at 220ms which is "
982 "greater than last dequeue"
983 "time plus q->interval(test default 100ms) so packet is dropped and next is dequeued. 4th "
984 "packet dequeues at 330ms"
985 "and the sojourn time stayed above the target and dropnext value is less than 320 hence "
986 "the packet is dropped and next"
987 "packet is dequeued. 6th packet dequeues at 440ms and 2 more packets are dropped as "
988 "dropnext value is increased twice."
989 "12 Packets remaining in the queue, total number of bytes int the queue = 120 * 12 = 1440 "
990 "which is less"
991 "m_minBytes(test's default value 1500 bytes) hence the packets stop getting dropped");
992 NS_TEST_EXPECT_MSG_EQ(q3->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
993 0,
994 "There should not be any marked packets");
995 NS_TEST_EXPECT_MSG_EQ(q4->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
996 4,
997 "There should be 4 dropped packets");
998 NS_TEST_EXPECT_MSG_EQ(q4->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
999 0,
1000 "There should not be any marked packets");
1001 // Ensure flow queue 0,1 and 2 have ECN capable packets
1002 // Peek () changes the stats of the queue and that is reason to be keep this test at last
1004 NS_TEST_EXPECT_MSG_NE(pktQ0->GetHeader().GetEcn(),
1006 "flow queue should have ECT0 packets");
1008 NS_TEST_EXPECT_MSG_NE(pktQ1->GetHeader().GetEcn(),
1010 "flow queue should have ECT0 packets");
1012 NS_TEST_EXPECT_MSG_NE(pktQ2->GetHeader().GetEcn(),
1014 "flow queue should have ECT0 packets");
1015
1017
1018 // Test case 2, CeThreshold set to 2ms
1020 StringValue("10240p"),
1021 "UseEcn",
1022 BooleanValue(true),
1023 "CeThreshold",
1025 queueDisc->SetQuantum(1514);
1026 queueDisc->Initialize();
1027
1028 // Add 20 ECT0 (ECN capable) packets from first flow
1029 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1033 this,
1034 queueDisc,
1035 hdr,
1036 20,
1037 20,
1038 1);
1039
1040 // Add 20 ECT0 (ECN capable) packets from second flow
1041 hdr.SetDestination(Ipv4Address("10.10.1.10"));
1044 this,
1045 queueDisc,
1046 hdr,
1047 20,
1048 40,
1049 2);
1050
1051 // Add 20 ECT0 (ECN capable) packets from third flow
1052 hdr.SetDestination(Ipv4Address("10.10.1.20"));
1055 this,
1056 queueDisc,
1057 hdr,
1058 20,
1059 60,
1060 3);
1061
1062 // Add 20 NotECT packets from fourth flow
1063 hdr.SetDestination(Ipv4Address("10.10.1.30"));
1067 this,
1068 queueDisc,
1069 hdr,
1070 20,
1071 80,
1072 4);
1073
1074 // Add 20 NotECT packets from fifth flow
1075 hdr.SetDestination(Ipv4Address("10.10.1.40"));
1078 this,
1079 queueDisc,
1080 hdr,
1081 20,
1082 100,
1083 5);
1084
1085 // Dequeue 60 packets with delay 0.1ms to induce packet drops and keep some remaining packets in
1086 // each queue
1087 DequeueWithDelay(queueDisc, 0.0001, 60);
1090 q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1091 q1 = queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1092 q2 = queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1093 q3 = queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1094 q4 = queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1095
1096 // Ensure there are some remaining packets in the flow queues to check for flow queues with ECN
1097 // capable packets
1098 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
1099 0,
1100 "There should be some remaining packets");
1101 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
1102 0,
1103 "There should be some remaining packets");
1104 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
1105 0,
1106 "There should be some remaining packets");
1107 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
1108 0,
1109 "There should be some remaining packets");
1110 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetNPackets(),
1111 0,
1112 "There should be some remaining packets");
1113
1114 // As packets in flow queues are ECN capable
1115 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1116 0,
1117 "There should not be any dropped packets");
1119 q0->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1120 0,
1121 "There should not be any marked packets"
1122 "with quantum of 1514, 13 packets of size 120 bytes can be dequeued. sojourn time of 13th "
1123 "packet is 1.3ms which is"
1124 "less than CE threshold");
1125 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1126 0,
1127 "There should not be any dropped packets");
1129 q1->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1130 6,
1131 "There should be 6 marked packets"
1132 "with quantum of 1514, 13 packets of size 120 bytes can be dequeued. sojourn time of 8th "
1133 "packet is 2.1ms which is greater"
1134 "than CE threshold and subsequent packet also have sojourn time more 8th packet hence "
1135 "remaining packet are marked.");
1136 NS_TEST_EXPECT_MSG_EQ(q2->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1137 0,
1138 "There should not be any dropped packets");
1140 q2->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1141 13,
1142 "There should be 13 marked packets"
1143 "with quantum of 1514, 13 packets of size 120 bytes can be dequeued and all of them have "
1144 "sojourn time more than CE threshold");
1145
1146 // As packets in flow queues are not ECN capable
1148 q3->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1149 0,
1150 "There should not be any marked packets");
1151 NS_TEST_EXPECT_MSG_EQ(q3->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1152 0,
1153 "There should not be any dropped packets");
1155 q4->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1156 0,
1157 "There should not be any marked packets");
1158 NS_TEST_EXPECT_MSG_EQ(q4->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1159 0,
1160 "There should not be any dropped packets");
1161
1162 // Ensure flow queue 0,1 and 2 have ECN capable packets
1163 // Peek () changes the stats of the queue and that is reason to be keep this test at last
1164 pktQ0 = DynamicCast<const Ipv4QueueDiscItem>(q0->Peek());
1165 NS_TEST_EXPECT_MSG_NE(pktQ0->GetHeader().GetEcn(),
1167 "flow queue should have ECT0 packets");
1168 pktQ1 = DynamicCast<const Ipv4QueueDiscItem>(q1->Peek());
1169 NS_TEST_EXPECT_MSG_NE(pktQ1->GetHeader().GetEcn(),
1171 "flow queue should have ECT0 packets");
1172 pktQ2 = DynamicCast<const Ipv4QueueDiscItem>(q2->Peek());
1173 NS_TEST_EXPECT_MSG_NE(pktQ2->GetHeader().GetEcn(),
1175 "flow queue should have ECT0 packets");
1176
1178
1179 // Test case 3, CeThreshold set to 2ms with higher queue delay
1181 StringValue("10240p"),
1182 "UseEcn",
1183 BooleanValue(true),
1184 "CeThreshold",
1186 queueDisc->SetQuantum(1514);
1187 queueDisc->Initialize();
1188
1189 // Add 20 ECT0 (ECN capable) packets from first flow
1190 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1194 this,
1195 queueDisc,
1196 hdr,
1197 20,
1198 20,
1199 1);
1200
1201 // Add 20 ECT0 (ECN capable) packets from second flow
1202 hdr.SetDestination(Ipv4Address("10.10.1.10"));
1205 this,
1206 queueDisc,
1207 hdr,
1208 20,
1209 40,
1210 2);
1211
1212 // Add 20 ECT0 (ECN capable) packets from third flow
1213 hdr.SetDestination(Ipv4Address("10.10.1.20"));
1216 this,
1217 queueDisc,
1218 hdr,
1219 20,
1220 60,
1221 3);
1222
1223 // Add 20 NotECT packets from fourth flow
1224 hdr.SetDestination(Ipv4Address("10.10.1.30"));
1228 this,
1229 queueDisc,
1230 hdr,
1231 20,
1232 80,
1233 4);
1234
1235 // Add 20 NotECT packets from fifth flow
1236 hdr.SetDestination(Ipv4Address("10.10.1.40"));
1239 this,
1240 queueDisc,
1241 hdr,
1242 20,
1243 100,
1244 5);
1245
1246 // Dequeue 60 packets with delay 110ms to induce packet drops and keep some remaining packets in
1247 // each queue
1248 DequeueWithDelay(queueDisc, 0.110, 60);
1251 q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1252 q1 = queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1253 q2 = queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1254 q3 = queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1255 q4 = queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1256
1257 // Ensure there are some remaining packets in the flow queues to check for flow queues with ECN
1258 // capable packets
1259 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
1260 0,
1261 "There should be some remaining packets");
1262 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
1263 0,
1264 "There should be some remaining packets");
1265 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
1266 0,
1267 "There should be some remaining packets");
1268 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
1269 0,
1270 "There should be some remaining packets");
1271 NS_TEST_EXPECT_MSG_NE(queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetNPackets(),
1272 0,
1273 "There should be some remaining packets");
1274
1275 // As packets in flow queues are ECN capable
1276 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1277 0,
1278 "There should not be any dropped packets");
1280 q0->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK) +
1281 q0->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
1282 20 - q0->GetNPackets(),
1283 "Number of CE threshold"
1284 " exceeded marks plus Number of Target exceeded marks should be equal to total number of "
1285 "packets dequeued");
1286 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1287 0,
1288 "There should not be any dropped packets");
1290 q1->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK) +
1291 q1->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
1292 20 - q1->GetNPackets(),
1293 "Number of CE threshold"
1294 " exceeded marks plus Number of Target exceeded marks should be equal to total number of "
1295 "packets dequeued");
1296 NS_TEST_EXPECT_MSG_EQ(q2->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1297 0,
1298 "There should not be any dropped packets");
1300 q2->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK) +
1301 q2->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
1302 20 - q2->GetNPackets(),
1303 "Number of CE threshold"
1304 " exceeded marks plus Number of Target exceeded marks should be equal to total number of "
1305 "packets dequeued");
1306
1307 // As packets in flow queues are not ECN capable
1309 q3->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1310 0,
1311 "There should not be any marked packets");
1313 q3->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1314 4,
1315 "There should be 4 dropped packets"
1316 " As queue delay is same as in test case 1, number of dropped packets should also be same");
1318 q4->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1319 0,
1320 "There should not be any marked packets");
1321 NS_TEST_EXPECT_MSG_EQ(q4->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1322 4,
1323 "There should be 4 dropped packets");
1324
1325 // Ensure flow queue 0,1 and 2 have ECN capable packets
1326 // Peek () changes the stats of the queue and that is reason to be keep this test at last
1327 pktQ0 = DynamicCast<const Ipv4QueueDiscItem>(q0->Peek());
1328 NS_TEST_EXPECT_MSG_NE(pktQ0->GetHeader().GetEcn(),
1330 "flow queue should have ECT0 packets");
1331 pktQ1 = DynamicCast<const Ipv4QueueDiscItem>(q1->Peek());
1332 NS_TEST_EXPECT_MSG_NE(pktQ1->GetHeader().GetEcn(),
1334 "flow queue should have ECT0 packets");
1335 pktQ2 = DynamicCast<const Ipv4QueueDiscItem>(q2->Peek());
1336 NS_TEST_EXPECT_MSG_NE(pktQ2->GetHeader().GetEcn(),
1338 "flow queue should have ECT0 packets");
1339
1341}
1342
1343/**
1344 * \ingroup system-tests-tc
1345 *
1346 * \brief This class tests linear probing, collision response, and set
1347 * creation capability of set associative hashing in FqCodel.
1348 *
1349 * We modified DoClassify () and CheckProtocol () so that we could control
1350 * the hash returned for each packet. In the beginning, we use flow hashes
1351 * ranging from 0 to 7. These must go into different queues in the same set.
1352 * The set number for these is obtained using outerHash, which is 0.
1353 * When a new packet arrives with flow hash 1024, outerHash = 0 is obtained
1354 * and the first set is iteratively searched.
1355 * The packet is eventually added to queue 0 since the tags of queues
1356 * in the set do not match with the hash of the flow. The tag of queue 0 is
1357 * updated as 1024. When a packet with hash 1025 arrives, outerHash = 0
1358 * is obtained and the first set is iteratively searched.
1359 * Since there is no match, it is added to queue 0 and the tag of queue 0 is
1360 * updated to 1025.
1361 *
1362 * The variable outerHash stores the nearest multiple of 8 that is lesser than
1363 * the hash. When a flow hash of 20 arrives, the value of outerHash
1364 * is 16. Since m_flowIndices[16] wasn't previously allotted, a new flow
1365 * is created, and the tag corresponding to this queue is set to 20.
1366 */
1368{
1369 public:
1372
1373 private:
1374 void DoRun() override;
1375 /**
1376 * Enqueue a packet.
1377 * \param queue The queue disc.
1378 * \param hdr The IPv4 header.
1379 */
1381};
1382
1384 : TestCase("Test credits and flows status")
1385{
1386}
1387
1391
1392void
1394{
1395 Ptr<Packet> p = Create<Packet>(100);
1396 Address dest;
1397 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, hdr);
1398 queue->Enqueue(item);
1399}
1400
1401void
1403{
1404 Ptr<FqCoDelQueueDisc> queueDisc =
1405 CreateObjectWithAttributes<FqCoDelQueueDisc>("EnableSetAssociativeHash",
1406 BooleanValue(true));
1407 queueDisc->SetQuantum(90);
1408 queueDisc->Initialize();
1409
1411 queueDisc->AddPacketFilter(filter);
1412
1413 Ipv4Header hdr;
1414 hdr.SetPayloadSize(100);
1415 hdr.SetSource(Ipv4Address("10.10.1.1"));
1416 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1417 hdr.SetProtocol(7);
1418
1419 g_hash = 0;
1420 AddPacket(queueDisc, hdr);
1421 g_hash = 1;
1422 AddPacket(queueDisc, hdr);
1423 AddPacket(queueDisc, hdr);
1424 g_hash = 2;
1425 AddPacket(queueDisc, hdr);
1426 g_hash = 3;
1427 AddPacket(queueDisc, hdr);
1428 g_hash = 4;
1429 AddPacket(queueDisc, hdr);
1430 AddPacket(queueDisc, hdr);
1431 g_hash = 5;
1432 AddPacket(queueDisc, hdr);
1433 g_hash = 6;
1434 AddPacket(queueDisc, hdr);
1435 g_hash = 7;
1436 AddPacket(queueDisc, hdr);
1437 g_hash = 1024;
1438 AddPacket(queueDisc, hdr);
1439
1440 NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
1441 11,
1442 "unexpected number of packets in the queue disc");
1443 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
1444 2,
1445 "unexpected number of packets in the first flow queue of set one");
1446 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
1447 2,
1448 "unexpected number of packets in the second flow queue of set one");
1449 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
1450 1,
1451 "unexpected number of packets in the third flow queue of set one");
1452 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
1453 1,
1454 "unexpected number of packets in the fourth flow queue of set one");
1455 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetNPackets(),
1456 2,
1457 "unexpected number of packets in the fifth flow queue of set one");
1458 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(5)->GetQueueDisc()->GetNPackets(),
1459 1,
1460 "unexpected number of packets in the sixth flow queue of set one");
1461 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(6)->GetQueueDisc()->GetNPackets(),
1462 1,
1463 "unexpected number of packets in the seventh flow queue of set one");
1464 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(7)->GetQueueDisc()->GetNPackets(),
1465 1,
1466 "unexpected number of packets in the eighth flow queue of set one");
1467 g_hash = 1025;
1468 AddPacket(queueDisc, hdr);
1469 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
1470 3,
1471 "unexpected number of packets in the first flow of set one");
1472 g_hash = 10;
1473 AddPacket(queueDisc, hdr);
1474 NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(8)->GetQueueDisc()->GetNPackets(),
1475 1,
1476 "unexpected number of packets in the first flow of set two");
1478}
1479
1480/**
1481 * \ingroup system-tests-tc
1482 *
1483 * \brief This class tests L4S mode.
1484 * Any future classifier options (e.g. SetAssociativeHash) should be
1485 * disabled to prevent a hash collision on this test case.
1486 */
1488{
1489 public:
1491 ~FqCoDelQueueDiscL4sMode() override;
1492
1493 private:
1494 void DoRun() override;
1495
1496 /**
1497 * Enqueue some packets.
1498 * \param queue The queue disc.
1499 * \param hdr The IPv4 header.
1500 * \param nPkt The number of packets to enqueue.
1501 */
1502 void AddPacket(Ptr<FqCoDelQueueDisc> queue, Ipv4Header hdr, uint32_t nPkt);
1503
1504 /**
1505 * Enqueue some packets with delay.
1506 * \param queue The queue disc.
1507 * \param hdr The IPv4 header.
1508 * \param delay Delay [seconds].
1509 * \param nPkt The number of packets to enqueue.
1510 */
1512 Ipv4Header hdr,
1513 double delay,
1514 uint32_t nPkt);
1515
1516 /**
1517 * Dequeue some packets.
1518 * \param queue The queue disc.
1519 * \param nPkt The number of packets to dequeue.
1520 */
1521 void Dequeue(Ptr<FqCoDelQueueDisc> queue, uint32_t nPkt);
1522 /**
1523 * Dequeue some packets with delay.
1524 * \param queue The queue disc.
1525 * \param delay Delay [seconds].
1526 * \param nPkt The number of packets to dequeue.
1527 */
1528 void DequeueWithDelay(Ptr<FqCoDelQueueDisc> queue, double delay, uint32_t nPkt);
1529};
1530
1535
1539
1540void
1542{
1543 Address dest;
1544 Ptr<Packet> p = Create<Packet>(100);
1545 for (uint32_t i = 0; i < nPkt; i++)
1546 {
1547 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, hdr);
1548 queue->Enqueue(item);
1549 }
1550}
1551
1552void
1554 Ipv4Header hdr,
1555 double delay,
1556 uint32_t nPkt)
1557{
1558 for (uint32_t i = 0; i < nPkt; i++)
1559 {
1560 Simulator::Schedule(Time(Seconds((i + 1) * delay)),
1562 this,
1563 queue,
1564 hdr,
1565 1);
1566 }
1567}
1568
1569void
1571{
1572 for (uint32_t i = 0; i < nPkt; i++)
1573 {
1574 Ptr<QueueDiscItem> item = queue->Dequeue();
1575 }
1576}
1577
1578void
1580{
1581 for (uint32_t i = 0; i < nPkt; i++)
1582 {
1583 Simulator::Schedule(Time(Seconds((i + 1) * delay)),
1585 this,
1586 queue,
1587 1);
1588 }
1589}
1590
1591void
1593{
1594 // Test is divided into 2 sub test cases:
1595 // 1) Without hash collisions
1596 // 2) With hash collisions
1597
1598 // Test case 1, Without hash collisions
1599 Ptr<FqCoDelQueueDisc> queueDisc =
1601 StringValue("10240p"),
1602 "UseEcn",
1603 BooleanValue(true),
1604 "Perturbation",
1605 UintegerValue(0),
1606 "UseL4s",
1607 BooleanValue(true),
1608 "CeThreshold",
1610
1611 queueDisc->SetQuantum(1514);
1612 queueDisc->Initialize();
1613 Ipv4Header hdr;
1614 hdr.SetPayloadSize(100);
1615 hdr.SetSource(Ipv4Address("10.10.1.1"));
1616 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1617 hdr.SetProtocol(7);
1619
1620 // Add 70 ECT1 (ECN capable) packets from the first flow
1621 // Set delay = 0.5ms
1622 double delay = 0.0005;
1625 this,
1626 queueDisc,
1627 hdr,
1628 delay,
1629 70);
1630
1631 // Add 70 ECT0 (ECN capable) packets from second flow
1633 hdr.SetDestination(Ipv4Address("10.10.1.10"));
1636 this,
1637 queueDisc,
1638 hdr,
1639 delay,
1640 70);
1641
1642 // Dequeue 140 packets with delay 1ms
1643 delay = 0.001;
1644 DequeueWithDelay(queueDisc, delay, 140);
1648 queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1650 queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1651
1653 q0->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1654 66,
1655 "There should be 66 marked packets"
1656 "4th packet is enqueued at 2ms and dequeued at 4ms hence the delay of 2ms which not "
1657 "greater than CE threshold"
1658 "5th packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and "
1659 "subsequent packet also do have delay"
1660 "greater than CE threshold so all the packets after 4th packet are marked");
1661 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1662 0,
1663 "There should not be any dropped packets");
1664 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
1665 0,
1666 "There should not be any marked packets");
1667 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
1668 1,
1669 "There should be 1 marked packets");
1670 NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1671 0,
1672 "There should not be any dropped packets");
1673
1675
1676 // Test case 2, With hash collisions
1678 StringValue("10240p"),
1679 "UseEcn",
1680 BooleanValue(true),
1681 "Perturbation",
1682 UintegerValue(0),
1683 "UseL4s",
1684 BooleanValue(true),
1685 "CeThreshold",
1687
1688 queueDisc->SetQuantum(1514);
1689 queueDisc->Initialize();
1690 hdr.SetPayloadSize(100);
1691 hdr.SetSource(Ipv4Address("10.10.1.1"));
1692 hdr.SetDestination(Ipv4Address("10.10.1.2"));
1693 hdr.SetProtocol(7);
1695
1696 // Add 70 ECT1 (ECN capable) packets from the first flow
1697 // Set delay = 1ms
1698 delay = 0.001;
1701 this,
1702 queueDisc,
1703 hdr,
1704 1);
1707 this,
1708 queueDisc,
1709 hdr,
1710 delay,
1711 69);
1712
1713 // Add 70 ECT0 (ECN capable) packets from first flow
1717 this,
1718 queueDisc,
1719 hdr,
1720 delay,
1721 70);
1722
1723 // Dequeue 140 packets with delay 1ms
1724 DequeueWithDelay(queueDisc, delay, 140);
1727 q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<CoDelQueueDisc>();
1728
1730 q0->GetStats().GetNMarkedPackets(CoDelQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1731 68,
1732 "There should be 68 marked packets"
1733 "2nd ECT1 packet is enqueued at 1.5ms and dequeued at 3ms hence the delay of 1.5ms which "
1734 "not greater than CE threshold"
1735 "3rd packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and "
1736 "subsequent packet also do have delay"
1737 "greater than CE threshold so all the packets after 2nd packet are marked");
1738 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(CoDelQueueDisc::TARGET_EXCEEDED_DROP),
1739 0,
1740 "There should not be any dropped packets");
1741 NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNMarkedPackets(CoDelQueueDisc::TARGET_EXCEEDED_MARK),
1742 1,
1743 "There should be 1 marked packets");
1744
1746}
1747
1748/**
1749 * \ingroup system-tests-tc
1750 *
1751 * FQ-CoDel queue disc test suite.
1752 */
1754{
1755 public:
1757};
1758
1760 : TestSuite("fq-codel-queue-disc", Type::UNIT)
1761{
1762 AddTestCase(new FqCoDelQueueDiscNoSuitableFilter, TestCase::Duration::QUICK);
1763 AddTestCase(new FqCoDelQueueDiscIPFlowsSeparationAndPacketLimit, TestCase::Duration::QUICK);
1764 AddTestCase(new FqCoDelQueueDiscDeficit, TestCase::Duration::QUICK);
1765 AddTestCase(new FqCoDelQueueDiscTCPFlowsSeparation, TestCase::Duration::QUICK);
1766 AddTestCase(new FqCoDelQueueDiscUDPFlowsSeparation, TestCase::Duration::QUICK);
1767 AddTestCase(new FqCoDelQueueDiscECNMarking, TestCase::Duration::QUICK);
1768 AddTestCase(new FqCoDelQueueDiscSetLinearProbing, TestCase::Duration::QUICK);
1769 AddTestCase(new FqCoDelQueueDiscL4sMode, TestCase::Duration::QUICK);
1770}
1771
1772/// Do not forget to allocate an instance of this TestSuite.
This class tests the deficit per flow.
void AddPacket(Ptr< FqCoDelQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
void DoRun() override
Implementation to actually run this TestCase.
void Dequeue(Ptr< FqCoDelQueueDisc > queue, uint32_t nPkt)
Dequeue some packets.
void DoRun() override
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqCoDelQueueDisc > queue, Ipv4Header hdr, uint32_t nPkt, uint32_t nPktEnqueued, uint32_t nQueueFlows)
Enqueue some packets.
void DequeueWithDelay(Ptr< FqCoDelQueueDisc > queue, double delay, uint32_t nPkt)
Dequeue some packets with delay.
This class tests the IP flows separation and the packet limit.
void DoRun() override
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqCoDelQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
void DoRun() override
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqCoDelQueueDisc > queue, Ipv4Header hdr, uint32_t nPkt)
Enqueue some packets.
void AddPacketWithDelay(Ptr< FqCoDelQueueDisc > queue, Ipv4Header hdr, double delay, uint32_t nPkt)
Enqueue some packets with delay.
void DequeueWithDelay(Ptr< FqCoDelQueueDisc > queue, double delay, uint32_t nPkt)
Dequeue some packets with delay.
void Dequeue(Ptr< FqCoDelQueueDisc > queue, uint32_t nPkt)
Dequeue some 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 AddPacket(Ptr< FqCoDelQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
void DoRun() override
Implementation to actually run this TestCase.
This class tests the TCP flows separation.
void DoRun() override
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqCoDelQueueDisc > queue, Ipv4Header ipHdr, TcpHeader tcpHdr)
Enqueue a packet.
FQ-CoDel queue disc test suite.
This class tests the UDP flows separation.
void AddPacket(Ptr< FqCoDelQueueDisc > 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.
bool CheckProtocol(Ptr< QueueDiscItem > item) const override
Check the protocol.
int32_t DoClassify(Ptr< QueueDiscItem > item) const override
Classify a QueueDiscItem.
static TypeId GetTypeId()
Get the type ID.
a polymophic address class
Definition address.h:90
A CoDel packet queue disc.
static constexpr const char * TARGET_EXCEEDED_DROP
Sojourn time above target.
static constexpr const char * CE_THRESHOLD_EXCEEDED_MARK
Sojourn time above CE threshold.
static constexpr const char * TARGET_EXCEEDED_MARK
Sojourn time above target.
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
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 FqCoDelQueueDiscTestSuite g_fqCoDelQueueDiscTestSuite
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_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
Definition test.h:656
#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 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:587