A Discrete-Event Network Simulator
API
queue-disc-traces-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Universita' degli Studi di Napoli Federico II
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Authors: Stefano Avallone <stavallo@unina.it>
18 *
19 */
20
21#include "ns3/drop-tail-queue.h"
22#include "ns3/packet.h"
23#include "ns3/queue-disc.h"
24#include "ns3/simulator.h"
25#include "ns3/test.h"
26
27#include <map>
28
29using namespace ns3;
30
38{
39 public:
46 qdTestItem(Ptr<Packet> p, const Address& addr);
47 ~qdTestItem() override;
48 void AddHeader() override;
49 bool Mark() override;
50};
51
53 : QueueDiscItem(p, addr, 0)
54{
55}
56
58{
59}
60
61void
63{
64}
65
66bool
68{
69 return false;
70}
71
79{
80 public:
85 ~TestChildQueueDisc() override;
86 bool DoEnqueue(Ptr<QueueDiscItem> item) override;
88 bool CheckConfig() override;
89 void InitializeParams() override;
90
91 // Reasons for dropping packets
92 static constexpr const char* BEFORE_ENQUEUE = "Before enqueue";
93 static constexpr const char* AFTER_DEQUEUE = "After dequeue";
94};
95
98{
99}
100
102{
103}
104
105bool
107{
108 // Drop the packet if there are already 4 packets queued
109 if (GetNPackets() >= 4)
110 {
112 return false;
113 }
114 return GetInternalQueue(0)->Enqueue(item);
115}
116
119{
120 Ptr<QueueDiscItem> item = GetInternalQueue(0)->Dequeue();
121
122 // Drop the packet if at least 2 packets remain in the queue
123 while (GetNPackets() >= 2)
124 {
126 item = GetInternalQueue(0)->Dequeue();
127 }
128 return item;
129}
130
131bool
133{
135 return true;
136}
137
138void
140{
141}
142
150{
151 public:
156 ~TestParentQueueDisc() override;
157 bool DoEnqueue(Ptr<QueueDiscItem> item) override;
158 Ptr<QueueDiscItem> DoDequeue() override;
159 bool CheckConfig() override;
160 void InitializeParams() override;
161};
162
165{
166}
167
169{
170}
171
172bool
174{
175 return GetQueueDiscClass(0)->GetQueueDisc()->Enqueue(item);
176}
177
180{
181 return GetQueueDiscClass(0)->GetQueueDisc()->Dequeue();
182}
183
184bool
186{
187 Ptr<QueueDiscClass> c = CreateObject<QueueDiscClass>();
188 c->SetQueueDisc(CreateObject<TestChildQueueDisc>());
190 return true;
191}
192
193void
195{
196}
197
205{
206 public:
210 TestCounter();
211 virtual ~TestCounter();
212
218
219 private:
235 void PacketDbe(Ptr<const QueueDiscItem> item, const char* reason);
241 void PacketDad(Ptr<const QueueDiscItem> item, const char* reason);
242
249
251};
252
254 : m_nPackets(0),
255 m_nBytes(0),
256 m_nDbePackets(0),
257 m_nDbeBytes(0),
258 m_nDadPackets(0),
259 m_nDadBytes(0)
260{
261}
262
264{
265}
266
267void
269{
270 m_nPackets++;
271 m_nBytes += item->GetSize();
272}
273
274void
276{
277 m_nPackets--;
278 m_nBytes -= item->GetSize();
279}
280
281void
283{
285 m_nDbeBytes += item->GetSize();
286}
287
288void
290{
292 m_nDadBytes += item->GetSize();
293}
294
295void
297{
300 qd->TraceConnectWithoutContext("DropBeforeEnqueue",
302 qd->TraceConnectWithoutContext("DropAfterDequeue", MakeCallback(&TestCounter::PacketDad, this));
303}
304
322{
323 public:
325 void DoRun() override;
326
333 void CheckQueued(Ptr<QueueDisc> qd, uint32_t nPackets, uint32_t nBytes);
340 void CheckDroppedBeforeEnqueue(Ptr<QueueDisc> qd, uint32_t nDbePackets, uint32_t nDbeBytes);
347 void CheckDroppedAfterDequeue(Ptr<QueueDisc> qd, uint32_t nDadPackets, uint32_t nDadBytes);
348
349 private:
350 std::map<Ptr<QueueDisc>, TestCounter> m_counter;
351};
352
354 : TestCase("Sanity check on the queue disc traces and statistics")
355{
356}
357
358void
360{
362 nPackets,
363 "Verify that the number of queued packets is computed correctly");
364 NS_TEST_ASSERT_MSG_EQ(m_counter[qd].m_nPackets,
365 nPackets,
366 "Verify that the number of queued packets is computed correctly");
367
369 nBytes,
370 "Verify that the number of queued bytes is computed correctly");
371 NS_TEST_ASSERT_MSG_EQ(m_counter[qd].m_nBytes,
372 nBytes,
373 "Verify that the number of queued bytes is computed correctly");
374}
375
376void
378 uint32_t nDbePackets,
379 uint32_t nDbeBytes)
380{
381 QueueDisc::Stats stats = qd->GetStats();
382
385 nDbePackets,
386 "Verify that the number of packets dropped before enqueue is computed correctly");
388 m_counter[qd].m_nDbePackets,
389 nDbePackets,
390 "Verify that the number of packets dropped before enqueue is computed correctly");
391
394 nDbeBytes,
395 "Verify that the number of bytes dropped before enqueue is computed correctly");
397 m_counter[qd].m_nDbeBytes,
398 nDbeBytes,
399 "Verify that the number of bytes dropped before enqueue is computed correctly");
400}
401
402void
404 uint32_t nDadPackets,
405 uint32_t nDadBytes)
406{
407 QueueDisc::Stats stats = qd->GetStats();
408
411 nDadPackets,
412 "Verify that the number of packets dropped after dequeue is computed correctly");
414 m_counter[qd].m_nDadPackets,
415 nDadPackets,
416 "Verify that the number of packets dropped after dequeue is computed correctly");
417
420 nDadBytes,
421 "Verify that the number of bytes dropped after dequeue is computed correctly");
423 m_counter[qd].m_nDadBytes,
424 nDadBytes,
425 "Verify that the number of bytes dropped after dequeue is computed correctly");
426}
427
428void
430{
431 Address dest;
432 uint32_t pktSizeUnit = 100;
434
435 // Create queue discs
436 Ptr<QueueDisc> root = CreateObject<TestParentQueueDisc>();
437 root->Initialize();
438
439 Ptr<QueueDisc> child = root->GetQueueDiscClass(0)->GetQueueDisc();
440
441 NS_TEST_ASSERT_MSG_NE(child, nullptr, "The child queue disc has not been created");
442
443 // Create counters and connect traces to the counters
444 m_counter.emplace(root, TestCounter());
445 m_counter.emplace(child, TestCounter());
446
447 m_counter[root].ConnectTraces(root);
448 m_counter[child].ConnectTraces(child);
449
450 // Enqueue 4 packets. They must all be enqueued
451 for (uint16_t i = 1; i <= 4; i++)
452 {
453 root->Enqueue(Create<qdTestItem>(Create<Packet>(pktSizeUnit * i), dest));
454
455 CheckQueued(root, i, pktSizeUnit * i * (i + 1) / 2);
456 CheckDroppedBeforeEnqueue(root, 0, 0);
457 CheckDroppedAfterDequeue(root, 0, 0);
458
459 CheckQueued(child, i, pktSizeUnit * i * (i + 1) / 2);
460 CheckDroppedBeforeEnqueue(child, 0, 0);
461 CheckDroppedAfterDequeue(child, 0, 0);
462 }
463
464 // The fifth packet is dropped before enqueue by the child queue disc.
465 // The packet drop is notified to the root queue disc.
466 root->Enqueue(Create<qdTestItem>(Create<Packet>(pktSizeUnit * 5), dest));
467
468 CheckQueued(root, 4, pktSizeUnit * 10);
469 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
470 CheckDroppedAfterDequeue(root, 0, 0);
471
472 CheckQueued(child, 4, pktSizeUnit * 10);
473 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
474 CheckDroppedAfterDequeue(child, 0, 0);
475
476 // Peek one packet. The default DoPeek method asks the root queue disc to dequeue
477 // a packet, even though the statistics are not updated and the dequeue trace is
478 // not fired. The root queue disc asks the child queue disc to dequeue a packet.
479 // In this case, two packets (those having size of 100 and 200 bytes) are dequeued
480 // and dropped by the child queue disc. Therefore, the dequeue trace of the root
481 // queue disc is fired twice and the packet drops are notified to the root queue
482 // disc to reflect the fact that two packets are no longer in the queue disc.
483 // The peeked packet is still part of the root queue disc, but no longer part
484 // of the child queue disc.
485 item = root->Peek();
486
487 NS_TEST_ASSERT_MSG_NE(item, nullptr, "A packet must have been returned");
488 NS_TEST_ASSERT_MSG_EQ(item->GetSize(),
489 pktSizeUnit * 3,
490 "The peeked packet has not the expected size");
491
492 CheckQueued(root, 2, pktSizeUnit * 7);
493 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
494 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
495
496 CheckQueued(child, 1, pktSizeUnit * 4);
497 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
498 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
499
500 // Peek again. Nothing changes.
501 item = root->Peek();
502
503 NS_TEST_ASSERT_MSG_NE(item, nullptr, "A packet must have been returned");
504 NS_TEST_ASSERT_MSG_EQ(item->GetSize(),
505 pktSizeUnit * 3,
506 "The peeked packet has not the expected size");
507
508 CheckQueued(root, 2, pktSizeUnit * 7);
509 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
510 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
511
512 CheckQueued(child, 1, pktSizeUnit * 4);
513 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
514 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
515
516 // Dequeue one packet. The root queue disc returns the previously peeked packet.
517 item = root->Dequeue();
518
519 NS_TEST_ASSERT_MSG_NE(item, nullptr, "A packet must have been returned");
520 NS_TEST_ASSERT_MSG_EQ(item->GetSize(),
521 pktSizeUnit * 3,
522 "The dequeued packet has not the expected size");
523
524 CheckQueued(root, 1, pktSizeUnit * 4);
525 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
526 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
527
528 CheckQueued(child, 1, pktSizeUnit * 4);
529 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
530 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
531
532 // Dequeue the last packet.
533 item = root->Dequeue();
534
535 NS_TEST_ASSERT_MSG_NE(item, nullptr, "A packet must have been returned");
536 NS_TEST_ASSERT_MSG_EQ(item->GetSize(),
537 pktSizeUnit * 4,
538 "The dequeued packet has not the expected size");
539
540 CheckQueued(root, 0, 0);
541 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
542 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
543
544 CheckQueued(child, 0, 0);
545 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
546 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
547
548 // Peek a packet. No packet is left.
549 item = root->Peek();
550
551 NS_TEST_ASSERT_MSG_EQ(item, nullptr, "No packet must have been returned");
552
553 CheckQueued(root, 0, 0);
554 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
555 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
556
557 CheckQueued(child, 0, 0);
558 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
559 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
560
561 // Enqueue one packet.
562 root->Enqueue(Create<qdTestItem>(Create<Packet>(pktSizeUnit), dest));
563
564 CheckQueued(root, 1, pktSizeUnit);
565 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
566 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
567
568 CheckQueued(child, 1, pktSizeUnit);
569 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
570 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
571
572 // Dequeue one packet.
573 item = root->Dequeue();
574
575 NS_TEST_ASSERT_MSG_NE(item, nullptr, "A packet must have been returned");
576 NS_TEST_ASSERT_MSG_EQ(item->GetSize(),
577 pktSizeUnit,
578 "The dequeued packet has not the expected size");
579
580 CheckQueued(root, 0, 0);
581 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
582 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
583
584 CheckQueued(child, 0, 0);
585 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
586 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
587
588 Simulator::Destroy();
589}
590
598{
599 public:
601 : TestSuite("queue-disc-traces", UNIT)
602 {
603 AddTestCase(new QueueDiscTracesTestCase(), TestCase::QUICK);
604 }
Queue Disc Traces Test Case.
void DoRun() override
Implementation to actually run this TestCase.
std::map< Ptr< QueueDisc >, TestCounter > m_counter
counters for the queue discs
void CheckDroppedAfterDequeue(Ptr< QueueDisc > qd, uint32_t nDadPackets, uint32_t nDadBytes)
Check that packets/bytes dropped after dequeue are consistent with what is expected.
void CheckDroppedBeforeEnqueue(Ptr< QueueDisc > qd, uint32_t nDbePackets, uint32_t nDbeBytes)
Check that packets/bytes dropped before enqueue are consistent with what is expected.
void CheckQueued(Ptr< QueueDisc > qd, uint32_t nPackets, uint32_t nBytes)
Check that queued packets/bytes are consistent with what is expected.
Queue Disc Traces Test Suite.
Test Child Queue Disc that may drop packets before enqueue or after dequeue.
static constexpr const char * AFTER_DEQUEUE
Drop after dequeue.
bool DoEnqueue(Ptr< QueueDiscItem > item) override
This function actually enqueues a packet into the queue disc.
Ptr< QueueDiscItem > DoDequeue() override
This function actually extracts a packet from the queue disc.
void InitializeParams() override
Initialize parameters (if any) before the first packet is enqueued.
static constexpr const char * BEFORE_ENQUEUE
Drop before enqueue.
bool CheckConfig() override
Check whether the current configuration is correct.
Keep statistics based on traces.
void PacketDequeued(Ptr< const QueueDiscItem > item)
Update statistics after a packet has been dequeued.
void PacketDad(Ptr< const QueueDiscItem > item, const char *reason)
Update statistics after a packet has been dropped after dequeue.
void PacketDbe(Ptr< const QueueDiscItem > item, const char *reason)
Update statistics after a packet has been dropped before enqueue.
uint32_t m_nDbeBytes
Number of packets dropped before enqueue.
void PacketEnqueued(Ptr< const QueueDiscItem > item)
Update statistics after a packet has been enqueued.
uint32_t m_nPackets
Number of queued packets.
uint32_t m_nBytes
Number of queued bytes.
uint32_t m_nDbePackets
Number of packets dropped before enqueue.
uint32_t m_nDadBytes
Number of packets dropped after dequeue.
uint32_t m_nDadPackets
Number of packets dropped after dequeue.
void ConnectTraces(Ptr< QueueDisc > qd)
Connect private methods to the queue disc traces.
Test Parent Queue Disc having a child of type TestChildQueueDisc.
Ptr< QueueDiscItem > DoDequeue() override
This function actually extracts a packet from the queue disc.
bool CheckConfig() override
Check whether the current configuration is correct.
void InitializeParams() override
Initialize parameters (if any) before the first packet is enqueued.
bool DoEnqueue(Ptr< QueueDiscItem > item) override
This function actually enqueues a packet into the queue disc.
a polymophic address class
Definition: address.h:92
Introspection did not find any typical Config paths.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:369
void Initialize()
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:186
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition: queue-disc.h:184
void AddInternalQueue(Ptr< InternalQueue > queue)
Add an internal queue to the tail of the list of queues.
Definition: queue-disc.cc:577
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:628
uint32_t GetNPackets() const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:436
uint32_t GetNBytes() const
Get the amount of bytes stored by the queue disc.
Definition: queue-disc.cc:443
Ptr< InternalQueue > GetInternalQueue(std::size_t i) const
Get the i-th internal queue.
Definition: queue-disc.cc:595
void DropAfterDequeue(Ptr< const QueueDiscItem > item, const char *reason)
Perform the actions required when the queue disc is notified of a packet dropped after dequeue.
Definition: queue-disc.cc:766
const Stats & GetStats()
Retrieve all the collected statistics.
Definition: queue-disc.cc:416
Ptr< QueueDiscClass > GetQueueDiscClass(std::size_t i) const
Get the i-th queue disc class.
Definition: queue-disc.cc:658
Ptr< QueueDiscItem > Dequeue()
Extract from the queue disc the packet that has been dequeued by calling Peek, if any,...
Definition: queue-disc.cc:894
Ptr< const QueueDiscItem > Peek()
Get a copy of the next packet the queue discipline will extract.
Definition: queue-disc.cc:928
void DropBeforeEnqueue(Ptr< const QueueDiscItem > item, const char *reason)
Perform the actions required when the queue disc is notified of a packet dropped before enqueue.
Definition: queue-disc.cc:726
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
Definition: queue-disc.cc:859
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:133
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
Queue Disc Test Item.
bool Mark() override
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification.
qdTestItem(Ptr< Packet > p, const Address &addr)
Constructor.
void AddHeader() override
Add the header to the packet.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition: object.h:579
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:144
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition: test.h:564
QueueDiscTracesTestSuite g_queueDiscTracesTestSuite
the test suite
QueueDiscSizePolicy
Enumeration of the available policies to handle the queue disc size.
Definition: queue-disc.h:107
@ SINGLE_INTERNAL_QUEUE
Used by queue discs with single internal queue.
Definition: queue-disc.h:108
@ SINGLE_CHILD_QUEUE_DISC
Used by queue discs with single child queue disc.
Definition: queue-disc.h:109
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:691
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:188
uint64_t nTotalDroppedBytesBeforeEnqueue
Total bytes dropped before enqueue.
Definition: queue-disc.h:218
uint64_t nTotalDroppedBytesAfterDequeue
Total bytes dropped after dequeue.
Definition: queue-disc.h:222
uint32_t nTotalDroppedPacketsBeforeEnqueue
Total packets dropped before enqueue.
Definition: queue-disc.h:208
uint32_t nTotalDroppedPacketsAfterDequeue
Total packets dropped after dequeue.
Definition: queue-disc.h:212