A Discrete-Event Network Simulator
API
queue-disc-traces-test-suite.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2018 Universita' degli Studi di Napoli Federico II
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Authors: Stefano Avallone <stavallo@unina.it>
19 *
20 */
21
22#include "ns3/test.h"
23#include "ns3/queue-disc.h"
24#include "ns3/drop-tail-queue.h"
25#include "ns3/packet.h"
26#include "ns3/simulator.h"
27#include <map>
28
29using namespace ns3;
30
38{
39public:
46 qdTestItem (Ptr<Packet> p, const Address & addr);
47 virtual ~qdTestItem ();
48 virtual void AddHeader (void);
49 virtual bool Mark (void);
50};
51
53 : QueueDiscItem (p, addr, 0)
54{
55}
56
58{
59}
60
61void
63{
64}
65
66bool
68{
69 return false;
70}
71
72
80{
81public:
86 virtual ~TestChildQueueDisc ();
87 virtual bool DoEnqueue (Ptr<QueueDiscItem> item);
88 virtual Ptr<QueueDiscItem> DoDequeue (void);
89 virtual bool CheckConfig (void);
90 virtual void InitializeParams (void);
91
92 // Reasons for dropping packets
93 static constexpr const char* BEFORE_ENQUEUE = "Before enqueue";
94 static constexpr const char* AFTER_DEQUEUE = "After dequeue";
95};
96
99{
100}
101
103{
104}
105
106bool
108{
109 // Drop the packet if there are already 4 packets queued
110 if (GetNPackets () >= 4)
111 {
113 return false;
114 }
115 return GetInternalQueue (0)->Enqueue (item);
116}
117
120{
121 Ptr<QueueDiscItem> item = GetInternalQueue (0)->Dequeue ();
122
123 // Drop the packet if at least 2 packets remain in the queue
124 while (GetNPackets () >= 2)
125 {
127 item = GetInternalQueue (0)->Dequeue ();
128 }
129 return item;
130}
131
132bool
134{
136 return true;
137}
138
139void
141{
142}
143
144
152{
153public:
158 virtual ~TestParentQueueDisc ();
159 virtual bool DoEnqueue (Ptr<QueueDiscItem> item);
160 virtual Ptr<QueueDiscItem> DoDequeue (void);
161 virtual bool CheckConfig (void);
162 virtual void InitializeParams (void);
163};
164
167{
168}
169
171{
172}
173
174bool
176{
177 return GetQueueDiscClass (0)->GetQueueDisc ()->Enqueue (item);
178}
179
182{
183 return GetQueueDiscClass (0)->GetQueueDisc ()->Dequeue ();
184}
185
186bool
188{
189 Ptr<QueueDiscClass> c = CreateObject<QueueDiscClass> ();
190 c->SetQueueDisc (CreateObject<TestChildQueueDisc> ());
192 return true;
193}
194
195void
197{
198}
199
200
208{
209public:
213 TestCounter ();
214 virtual ~TestCounter ();
215
221
222private:
238 void PacketDbe (Ptr<const QueueDiscItem> item, const char* reason);
244 void PacketDad (Ptr<const QueueDiscItem> item, const char* reason);
245
252
254};
255
257 : m_nPackets (0),
258 m_nBytes (0),
259 m_nDbePackets (0),
260 m_nDbeBytes (0),
261 m_nDadPackets (0),
262 m_nDadBytes (0)
263{
264}
265
267{
268}
269
270void
272{
273 m_nPackets++;
274 m_nBytes += item->GetSize ();
275}
276
277void
279{
280 m_nPackets--;
281 m_nBytes -= item->GetSize ();
282}
283
284void
286{
288 m_nDbeBytes += item->GetSize ();
289}
290
291
292void
294{
296 m_nDadBytes += item->GetSize ();
297}
298
299void
301{
304 qd->TraceConnectWithoutContext ("DropBeforeEnqueue", MakeCallback (&TestCounter::PacketDbe, this));
305 qd->TraceConnectWithoutContext ("DropAfterDequeue", MakeCallback (&TestCounter::PacketDad, this));
306}
307
308
326{
327public:
329 virtual void DoRun (void);
330
337 void CheckQueued (Ptr<QueueDisc> qd, uint32_t nPackets, uint32_t nBytes);
344 void CheckDroppedBeforeEnqueue (Ptr<QueueDisc> qd, uint32_t nDbePackets, uint32_t nDbeBytes);
351 void CheckDroppedAfterDequeue (Ptr<QueueDisc> qd, uint32_t nDadPackets, uint32_t nDadBytes);
352
353private:
354 std::map<Ptr<QueueDisc>,TestCounter> m_counter;
355};
356
358 : TestCase ("Sanity check on the queue disc traces and statistics")
359{
360}
361
362void
364{
365 NS_TEST_ASSERT_MSG_EQ (qd->GetNPackets (), nPackets,
366 "Verify that the number of queued packets is computed correctly");
367 NS_TEST_ASSERT_MSG_EQ (m_counter[qd].m_nPackets, nPackets,
368 "Verify that the number of queued packets is computed correctly");
369
370 NS_TEST_ASSERT_MSG_EQ (qd->GetNBytes (), nBytes,
371 "Verify that the number of queued bytes is computed correctly");
372 NS_TEST_ASSERT_MSG_EQ (m_counter[qd].m_nBytes, nBytes,
373 "Verify that the number of queued bytes is computed correctly");
374}
375
376void
378{
379 QueueDisc::Stats stats = qd->GetStats ();
380
382 "Verify that the number of packets dropped before enqueue is computed correctly");
383 NS_TEST_ASSERT_MSG_EQ (m_counter[qd].m_nDbePackets, nDbePackets,
384 "Verify that the number of packets dropped before enqueue is computed correctly");
385
387 "Verify that the number of bytes dropped before enqueue is computed correctly");
388 NS_TEST_ASSERT_MSG_EQ (m_counter[qd].m_nDbeBytes, nDbeBytes,
389 "Verify that the number of bytes dropped before enqueue is computed correctly");
390}
391
392void
394{
395 QueueDisc::Stats stats = qd->GetStats ();
396
398 "Verify that the number of packets dropped after dequeue is computed correctly");
399 NS_TEST_ASSERT_MSG_EQ (m_counter[qd].m_nDadPackets, nDadPackets,
400 "Verify that the number of packets dropped after dequeue is computed correctly");
401
403 "Verify that the number of bytes dropped after dequeue is computed correctly");
404 NS_TEST_ASSERT_MSG_EQ (m_counter[qd].m_nDadBytes, nDadBytes,
405 "Verify that the number of bytes dropped after dequeue is computed correctly");
406}
407
408void
410{
411 Address dest;
412 uint32_t pktSizeUnit = 100;
414
415 // Create queue discs
416 Ptr<QueueDisc> root = CreateObject<TestParentQueueDisc> ();
417 root->Initialize ();
418
419 Ptr<QueueDisc> child = root->GetQueueDiscClass (0)->GetQueueDisc ();
420
421 NS_TEST_ASSERT_MSG_NE (child, 0, "The child queue disc has not been created");
422
423 // Create counters and connect traces to the counters
424 m_counter.emplace (root, TestCounter ());
425 m_counter.emplace (child, TestCounter ());
426
427 m_counter[root].ConnectTraces (root);
428 m_counter[child].ConnectTraces (child);
429
430 // Enqueue 4 packets. They must all be enqueued
431 for (uint16_t i = 1; i <= 4; i++)
432 {
433 root->Enqueue (Create<qdTestItem> (Create<Packet>(pktSizeUnit * i), dest));
434
435 CheckQueued (root, i, pktSizeUnit * i * (i+1) / 2);
436 CheckDroppedBeforeEnqueue (root, 0, 0);
437 CheckDroppedAfterDequeue (root, 0, 0);
438
439 CheckQueued (child, i, pktSizeUnit * i * (i+1) / 2);
440 CheckDroppedBeforeEnqueue (child, 0, 0);
441 CheckDroppedAfterDequeue (child, 0, 0);
442 }
443
444 // The fifth packet is dropped before enqueue by the child queue disc.
445 // The packet drop is notified to the root queue disc.
446 root->Enqueue (Create<qdTestItem> (Create<Packet>(pktSizeUnit * 5), dest));
447
448 CheckQueued (root, 4, pktSizeUnit * 10);
449 CheckDroppedBeforeEnqueue (root, 1, pktSizeUnit * 5);
450 CheckDroppedAfterDequeue (root, 0, 0);
451
452 CheckQueued (child, 4, pktSizeUnit * 10);
453 CheckDroppedBeforeEnqueue (child, 1, pktSizeUnit * 5);
454 CheckDroppedAfterDequeue (child, 0, 0);
455
456 // Peek one packet. The default DoPeek method asks the root queue disc to dequeue
457 // a packet, even though the statistics are not updated and the dequeue trace is
458 // not fired. The root queue disc asks the child queue disc to dequeue a packet.
459 // In this case, two packets (those having size of 100 and 200 bytes) are dequeued
460 // and dropped by the child queue disc. Therefore, the dequeue trace of the root
461 // queue disc is fired twice and the packet drops are notified to the root queue
462 // disc to reflect the fact that two packets are no longer in the queue disc.
463 // The peeked packet is still part of the root queue disc, but no longer part
464 // of the child queue disc.
465 item = root->Peek ();
466
467 NS_TEST_ASSERT_MSG_NE (item, 0, "A packet must have been returned");
468 NS_TEST_ASSERT_MSG_EQ (item->GetSize (), pktSizeUnit * 3, "The peeked packet has not the expected size");
469
470 CheckQueued (root, 2, pktSizeUnit * 7);
471 CheckDroppedBeforeEnqueue (root, 1, pktSizeUnit * 5);
472 CheckDroppedAfterDequeue (root, 2, pktSizeUnit * 3);
473
474 CheckQueued (child, 1, pktSizeUnit * 4);
475 CheckDroppedBeforeEnqueue (child, 1, pktSizeUnit * 5);
476 CheckDroppedAfterDequeue (child, 2, pktSizeUnit * 3);
477
478 // Peek again. Nothing changes.
479 item = root->Peek ();
480
481 NS_TEST_ASSERT_MSG_NE (item, 0, "A packet must have been returned");
482 NS_TEST_ASSERT_MSG_EQ (item->GetSize (), pktSizeUnit * 3, "The peeked packet has not the expected size");
483
484 CheckQueued (root, 2, pktSizeUnit * 7);
485 CheckDroppedBeforeEnqueue (root, 1, pktSizeUnit * 5);
486 CheckDroppedAfterDequeue (root, 2, pktSizeUnit * 3);
487
488 CheckQueued (child, 1, pktSizeUnit * 4);
489 CheckDroppedBeforeEnqueue (child, 1, pktSizeUnit * 5);
490 CheckDroppedAfterDequeue (child, 2, pktSizeUnit * 3);
491
492 // Dequeue one packet. The root queue disc returns the previously peeked packet.
493 item = root->Dequeue ();
494
495 NS_TEST_ASSERT_MSG_NE (item, 0, "A packet must have been returned");
496 NS_TEST_ASSERT_MSG_EQ (item->GetSize (), pktSizeUnit * 3, "The dequeued packet has not the expected size");
497
498 CheckQueued (root, 1, pktSizeUnit * 4);
499 CheckDroppedBeforeEnqueue (root, 1, pktSizeUnit * 5);
500 CheckDroppedAfterDequeue (root, 2, pktSizeUnit * 3);
501
502 CheckQueued (child, 1, pktSizeUnit * 4);
503 CheckDroppedBeforeEnqueue (child, 1, pktSizeUnit * 5);
504 CheckDroppedAfterDequeue (child, 2, pktSizeUnit * 3);
505
506 // Dequeue the last packet.
507 item = root->Dequeue ();
508
509 NS_TEST_ASSERT_MSG_NE (item, 0, "A packet must have been returned");
510 NS_TEST_ASSERT_MSG_EQ (item->GetSize (), pktSizeUnit * 4, "The dequeued packet has not the expected size");
511
512 CheckQueued (root, 0, 0);
513 CheckDroppedBeforeEnqueue (root, 1, pktSizeUnit * 5);
514 CheckDroppedAfterDequeue (root, 2, pktSizeUnit * 3);
515
516 CheckQueued (child, 0, 0);
517 CheckDroppedBeforeEnqueue (child, 1, pktSizeUnit * 5);
518 CheckDroppedAfterDequeue (child, 2, pktSizeUnit * 3);
519
520 // Peek a packet. No packet is left.
521 item = root->Peek ();
522
523 NS_TEST_ASSERT_MSG_EQ (item, 0, "No packet must have been returned");
524
525 CheckQueued (root, 0, 0);
526 CheckDroppedBeforeEnqueue (root, 1, pktSizeUnit * 5);
527 CheckDroppedAfterDequeue (root, 2, pktSizeUnit * 3);
528
529 CheckQueued (child, 0, 0);
530 CheckDroppedBeforeEnqueue (child, 1, pktSizeUnit * 5);
531 CheckDroppedAfterDequeue (child, 2, pktSizeUnit * 3);
532
533 // Enqueue one packet.
534 root->Enqueue (Create<qdTestItem> (Create<Packet>(pktSizeUnit), dest));
535
536 CheckQueued (root, 1, pktSizeUnit);
537 CheckDroppedBeforeEnqueue (root, 1, pktSizeUnit * 5);
538 CheckDroppedAfterDequeue (root, 2, pktSizeUnit * 3);
539
540 CheckQueued (child, 1, pktSizeUnit);
541 CheckDroppedBeforeEnqueue (child, 1, pktSizeUnit * 5);
542 CheckDroppedAfterDequeue (child, 2, pktSizeUnit * 3);
543
544 // Dequeue one packet.
545 item = root->Dequeue ();
546
547 NS_TEST_ASSERT_MSG_NE (item, 0, "A packet must have been returned");
548 NS_TEST_ASSERT_MSG_EQ (item->GetSize (), pktSizeUnit, "The dequeued packet has not the expected size");
549
550 CheckQueued (root, 0, 0);
551 CheckDroppedBeforeEnqueue (root, 1, pktSizeUnit * 5);
552 CheckDroppedAfterDequeue (root, 2, pktSizeUnit * 3);
553
554 CheckQueued (child, 0, 0);
555 CheckDroppedBeforeEnqueue (child, 1, pktSizeUnit * 5);
556 CheckDroppedAfterDequeue (child, 2, pktSizeUnit * 3);
557
558 Simulator::Destroy ();
559}
560
561
569{
570public:
572 : TestSuite ("queue-disc-traces", UNIT)
573 {
574 AddTestCase (new QueueDiscTracesTestCase (), TestCase::QUICK);
575 }
Queue Disc Traces Test Case.
virtual void DoRun(void)
Implementation to actually run this TestCase.
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.
std::map< Ptr< QueueDisc >, TestCounter > m_counter
counters for the queue discs
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.
virtual bool CheckConfig(void)
Check whether the current configuration is correct.
virtual bool DoEnqueue(Ptr< QueueDiscItem > item)
This function actually enqueues a packet into the queue disc.
virtual void InitializeParams(void)
Initialize parameters (if any) before the first packet is enqueued.
static constexpr const char * BEFORE_ENQUEUE
Drop before enqueue.
virtual Ptr< QueueDiscItem > DoDequeue(void)
This function actually extracts a packet from the queue disc.
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.
virtual Ptr< QueueDiscItem > DoDequeue(void)
This function actually extracts a packet from the queue disc.
virtual bool DoEnqueue(Ptr< QueueDiscItem > item)
This function actually enqueues a packet into the queue disc.
virtual bool CheckConfig(void)
Check whether the current configuration is correct.
virtual void InitializeParams(void)
Initialize parameters (if any) before the first packet is enqueued.
a polymophic address class
Definition: address.h:91
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:364
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition: queue-disc.h:181
void AddInternalQueue(Ptr< InternalQueue > queue)
Add an internal queue to the tail of the list of queues.
Definition: queue-disc.cc:579
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:632
uint32_t GetNBytes(void) const
Get the amount of bytes stored by the queue disc.
Definition: queue-disc.cc:445
Ptr< const QueueDiscItem > Peek(void)
Get a copy of the next packet the queue discipline will extract.
Definition: queue-disc.cc:928
Ptr< InternalQueue > GetInternalQueue(std::size_t i) const
Get the i-th internal queue.
Definition: queue-disc.cc:599
Ptr< QueueDiscItem > Dequeue(void)
Extract from the queue disc the packet that has been dequeued by calling Peek, if any,...
Definition: queue-disc.cc:894
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
uint32_t GetNPackets(void) const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:438
Ptr< QueueDiscClass > GetQueueDiscClass(std::size_t i) const
Get the i-th queue disc class.
Definition: queue-disc.cc:660
const Stats & GetStats(void)
Retrieve all the collected statistics.
Definition: queue-disc.cc:419
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:727
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:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1197
Queue Disc Test Item.
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification.
qdTestItem(Ptr< Packet > p, const Address &addr)
Constructor.
virtual void AddHeader(void)
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:576
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:141
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition: test.h:542
QueueDiscTracesTestSuite g_queueDiscTracesTestSuite
the test suite
QueueDiscSizePolicy
Enumeration of the available policies to handle the queue disc size.
Definition: queue-disc.h:104
@ SINGLE_INTERNAL_QUEUE
Used by queue discs with single internal queue.
Definition: queue-disc.h:105
@ SINGLE_CHILD_QUEUE_DISC
Used by queue discs with single child queue disc.
Definition: queue-disc.h:106
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:186
uint64_t nTotalDroppedBytesBeforeEnqueue
Total bytes dropped before enqueue.
Definition: queue-disc.h:216
uint64_t nTotalDroppedBytesAfterDequeue
Total bytes dropped after dequeue.
Definition: queue-disc.h:220
uint32_t nTotalDroppedPacketsBeforeEnqueue
Total packets dropped before enqueue.
Definition: queue-disc.h:206
uint32_t nTotalDroppedPacketsAfterDequeue
Total packets dropped after dequeue.
Definition: queue-disc.h:210