A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Stefano Avallone <stavallo@unina.it>
7 *
8 */
9
10#include "ns3/drop-tail-queue.h"
11#include "ns3/packet.h"
12#include "ns3/queue-disc.h"
13#include "ns3/simulator.h"
14#include "ns3/test.h"
15
16#include <map>
17
18using namespace ns3;
19
20/**
21 * \ingroup traffic-control-test
22 *
23 * \brief Queue Disc Test Item
24 */
26{
27 public:
28 /**
29 * Constructor
30 *
31 * \param p the packet
32 * \param addr the address
33 */
34 QdTestItem(Ptr<Packet> p, const Address& addr);
35 ~QdTestItem() override;
36 void AddHeader() override;
37 bool Mark() override;
38};
39
41 : QueueDiscItem(p, addr, 0)
42{
43}
44
48
49void
53
54bool
56{
57 return false;
58}
59
60/**
61 * \ingroup traffic-control-test
62 *
63 * \brief Test Child Queue Disc that may drop packets before enqueue or after dequeue
64 */
66{
67 public:
68 /**
69 * Constructor
70 */
72 ~TestChildQueueDisc() override;
73 bool DoEnqueue(Ptr<QueueDiscItem> item) override;
75 bool CheckConfig() override;
76 void InitializeParams() override;
77
78 // Reasons for dropping packets
79 static constexpr const char* BEFORE_ENQUEUE = "Before enqueue"; //!< Drop before enqueue
80 static constexpr const char* AFTER_DEQUEUE = "After dequeue"; //!< Drop after dequeue
81};
82
87
91
92bool
94{
95 // Drop the packet if there are already 4 packets queued
96 if (GetNPackets() >= 4)
97 {
99 return false;
100 }
101 return GetInternalQueue(0)->Enqueue(item);
102}
103
106{
107 Ptr<QueueDiscItem> item = GetInternalQueue(0)->Dequeue();
108
109 // Drop the packet if at least 2 packets remain in the queue
110 while (GetNPackets() >= 2)
111 {
113 item = GetInternalQueue(0)->Dequeue();
114 }
115 return item;
116}
117
118bool
124
125void
129
130/**
131 * \ingroup traffic-control-test
132 *
133 * \brief Test Parent Queue Disc having a child of type TestChildQueueDisc
134 */
136{
137 public:
138 /**
139 * Constructor
140 */
142 ~TestParentQueueDisc() override;
143 bool DoEnqueue(Ptr<QueueDiscItem> item) override;
144 Ptr<QueueDiscItem> DoDequeue() override;
145 bool CheckConfig() override;
146 void InitializeParams() override;
147};
148
153
157
158bool
160{
161 return GetQueueDiscClass(0)->GetQueueDisc()->Enqueue(item);
162}
163
166{
167 return GetQueueDiscClass(0)->GetQueueDisc()->Dequeue();
168}
169
170bool
178
179void
183
184/**
185 * \ingroup traffic-control-test
186 *
187 * \brief Keep statistics based on traces
188 */
190{
191 public:
192 /**
193 * Constructor
194 */
195 TestCounter();
196 virtual ~TestCounter();
197
198 /**
199 * Connect private methods to the queue disc traces
200 * \param qd the queue disc
201 */
203
204 private:
205 /**
206 * Update statistics after a packet has been enqueued
207 * \param item the enqueued packet
208 */
210 /**
211 * Update statistics after a packet has been dequeued
212 * \param item the dequeued packet
213 */
215 /**
216 * Update statistics after a packet has been dropped before enqueue
217 * \param item the dropped packet
218 * \param reason the reason why the packet was dropped
219 */
220 void PacketDbe(Ptr<const QueueDiscItem> item, const char* reason);
221 /**
222 * Update statistics after a packet has been dropped after dequeue
223 * \param item the dropped packet
224 * \param reason the reason why the packet was dropped
225 */
226 void PacketDad(Ptr<const QueueDiscItem> item, const char* reason);
227
228 uint32_t m_nPackets; //!< Number of queued packets
229 uint32_t m_nBytes; //!< Number of queued bytes
230 uint32_t m_nDbePackets; //!< Number of packets dropped before enqueue
231 uint32_t m_nDbeBytes; //!< Number of packets dropped before enqueue
232 uint32_t m_nDadPackets; //!< Number of packets dropped after dequeue
233 uint32_t m_nDadBytes; //!< Number of packets dropped after dequeue
234
235 friend class QueueDiscTracesTestCase; //!< Needs to access private members
236};
237
239 : m_nPackets(0),
240 m_nBytes(0),
241 m_nDbePackets(0),
242 m_nDbeBytes(0),
243 m_nDadPackets(0),
244 m_nDadBytes(0)
245{
246}
247
251
252void
254{
255 m_nPackets++;
256 m_nBytes += item->GetSize();
257}
258
259void
261{
262 m_nPackets--;
263 m_nBytes -= item->GetSize();
264}
265
266void
268{
270 m_nDbeBytes += item->GetSize();
271}
272
273void
275{
277 m_nDadBytes += item->GetSize();
278}
279
280void
282{
283 qd->TraceConnectWithoutContext("Enqueue", MakeCallback(&TestCounter::PacketEnqueued, this));
284 qd->TraceConnectWithoutContext("Dequeue", MakeCallback(&TestCounter::PacketDequeued, this));
285 qd->TraceConnectWithoutContext("DropBeforeEnqueue",
287 qd->TraceConnectWithoutContext("DropAfterDequeue", MakeCallback(&TestCounter::PacketDad, this));
288}
289
290/**
291 * \ingroup traffic-control-test
292 *
293 * \brief Queue Disc Traces Test Case
294 *
295 * This test case makes use of a test queue disc acting as root queue disc and
296 * having a single child queue disc, which has a single DropTail queue. The
297 * Enqueue, Dequeue, DropBeforeEnqueue and DropAfterDequeue traces of both queue
298 * discs are connected to the methods of TestCounter objects that keep track of
299 * the amount of packets/bytes queued inside each queue disc and the cumulative
300 * amount of packets/bytes dropped before enqueue and after dequeue. A series of
301 * enqueue, dequeue and peek operations are performed on the root queue disc and
302 * both the statistics kept by the QueueDisc class and the values computed by the
303 * TestCounter objects are compared with the expected values.
304 */
306{
307 public:
309 void DoRun() override;
310
311 /**
312 * Check that queued packets/bytes are consistent with what is expected
313 * \param qd the queue disc
314 * \param nPackets the expected number of packets
315 * \param nBytes the expected number of bytes
316 */
317 void CheckQueued(Ptr<QueueDisc> qd, uint32_t nPackets, uint32_t nBytes);
318 /**
319 * Check that packets/bytes dropped before enqueue are consistent with what is expected
320 * \param qd the queue disc
321 * \param nDbePackets the expected number of packets
322 * \param nDbeBytes the expected number of bytes
323 */
324 void CheckDroppedBeforeEnqueue(Ptr<QueueDisc> qd, uint32_t nDbePackets, uint32_t nDbeBytes);
325 /**
326 * Check that packets/bytes dropped after dequeue are consistent with what is expected
327 * \param qd the queue disc
328 * \param nDadPackets the expected number of packets
329 * \param nDadBytes the expected number of bytes
330 */
331 void CheckDroppedAfterDequeue(Ptr<QueueDisc> qd, uint32_t nDadPackets, uint32_t nDadBytes);
332
333 private:
334 std::map<Ptr<QueueDisc>, TestCounter> m_counter; //!< counters for the queue discs
335};
336
338 : TestCase("Sanity check on the queue disc traces and statistics")
339{
340}
341
342void
344{
345 NS_TEST_ASSERT_MSG_EQ(qd->GetNPackets(),
346 nPackets,
347 "Verify that the number of queued packets is computed correctly");
348 NS_TEST_ASSERT_MSG_EQ(m_counter[qd].m_nPackets,
349 nPackets,
350 "Verify that the number of queued packets is computed correctly");
351
352 NS_TEST_ASSERT_MSG_EQ(qd->GetNBytes(),
353 nBytes,
354 "Verify that the number of queued bytes is computed correctly");
355 NS_TEST_ASSERT_MSG_EQ(m_counter[qd].m_nBytes,
356 nBytes,
357 "Verify that the number of queued bytes is computed correctly");
358}
359
360void
362 uint32_t nDbePackets,
363 uint32_t nDbeBytes)
364{
365 QueueDisc::Stats stats = qd->GetStats();
366
369 nDbePackets,
370 "Verify that the number of packets dropped before enqueue is computed correctly");
372 m_counter[qd].m_nDbePackets,
373 nDbePackets,
374 "Verify that the number of packets dropped before enqueue is computed correctly");
375
378 nDbeBytes,
379 "Verify that the number of bytes dropped before enqueue is computed correctly");
381 m_counter[qd].m_nDbeBytes,
382 nDbeBytes,
383 "Verify that the number of bytes dropped before enqueue is computed correctly");
384}
385
386void
388 uint32_t nDadPackets,
389 uint32_t nDadBytes)
390{
391 QueueDisc::Stats stats = qd->GetStats();
392
395 nDadPackets,
396 "Verify that the number of packets dropped after dequeue is computed correctly");
398 m_counter[qd].m_nDadPackets,
399 nDadPackets,
400 "Verify that the number of packets dropped after dequeue is computed correctly");
401
404 nDadBytes,
405 "Verify that the number of bytes dropped after dequeue is computed correctly");
407 m_counter[qd].m_nDadBytes,
408 nDadBytes,
409 "Verify that the number of bytes dropped after dequeue is computed correctly");
410}
411
412void
414{
415 Address dest;
416 uint32_t pktSizeUnit = 100;
418
419 // Create queue discs
421 root->Initialize();
422
423 Ptr<QueueDisc> child = root->GetQueueDiscClass(0)->GetQueueDisc();
424
425 NS_TEST_ASSERT_MSG_NE(child, nullptr, "The child queue disc has not been created");
426
427 // Create counters and connect traces to the counters
428 m_counter.emplace(root, TestCounter());
429 m_counter.emplace(child, TestCounter());
430
431 m_counter[root].ConnectTraces(root);
432 m_counter[child].ConnectTraces(child);
433
434 // Enqueue 4 packets. They must all be enqueued
435 for (uint16_t i = 1; i <= 4; i++)
436 {
437 root->Enqueue(Create<QdTestItem>(Create<Packet>(pktSizeUnit * i), dest));
438
439 CheckQueued(root, i, pktSizeUnit * i * (i + 1) / 2);
440 CheckDroppedBeforeEnqueue(root, 0, 0);
441 CheckDroppedAfterDequeue(root, 0, 0);
442
443 CheckQueued(child, i, pktSizeUnit * i * (i + 1) / 2);
444 CheckDroppedBeforeEnqueue(child, 0, 0);
445 CheckDroppedAfterDequeue(child, 0, 0);
446 }
447
448 // The fifth packet is dropped before enqueue by the child queue disc.
449 // The packet drop is notified to the root queue disc.
450 root->Enqueue(Create<QdTestItem>(Create<Packet>(pktSizeUnit * 5), dest));
451
452 CheckQueued(root, 4, pktSizeUnit * 10);
453 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
454 CheckDroppedAfterDequeue(root, 0, 0);
455
456 CheckQueued(child, 4, pktSizeUnit * 10);
457 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
458 CheckDroppedAfterDequeue(child, 0, 0);
459
460 // Peek one packet. The default DoPeek method asks the root queue disc to dequeue
461 // a packet, even though the statistics are not updated and the dequeue trace is
462 // not fired. The root queue disc asks the child queue disc to dequeue a packet.
463 // In this case, two packets (those having size of 100 and 200 bytes) are dequeued
464 // and dropped by the child queue disc. Therefore, the dequeue trace of the root
465 // queue disc is fired twice and the packet drops are notified to the root queue
466 // disc to reflect the fact that two packets are no longer in the queue disc.
467 // The peeked packet is still part of the root queue disc, but no longer part
468 // of the child queue disc.
469 item = root->Peek();
470
471 NS_TEST_ASSERT_MSG_NE(item, nullptr, "A packet must have been returned");
472 NS_TEST_ASSERT_MSG_EQ(item->GetSize(),
473 pktSizeUnit * 3,
474 "The peeked packet has not the expected size");
475
476 CheckQueued(root, 2, pktSizeUnit * 7);
477 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
478 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
479
480 CheckQueued(child, 1, pktSizeUnit * 4);
481 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
482 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
483
484 // Peek again. Nothing changes.
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 // Dequeue one packet. The root queue disc returns the previously peeked packet.
501 item = root->Dequeue();
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 dequeued packet has not the expected size");
507
508 CheckQueued(root, 1, pktSizeUnit * 4);
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 the last 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 * 4,
522 "The dequeued packet has not the expected size");
523
524 CheckQueued(root, 0, 0);
525 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
526 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
527
528 CheckQueued(child, 0, 0);
529 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
530 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
531
532 // Peek a packet. No packet is left.
533 item = root->Peek();
534
535 NS_TEST_ASSERT_MSG_EQ(item, nullptr, "No packet must have been returned");
536
537 CheckQueued(root, 0, 0);
538 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
539 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
540
541 CheckQueued(child, 0, 0);
542 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
543 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
544
545 // Enqueue one packet.
546 root->Enqueue(Create<QdTestItem>(Create<Packet>(pktSizeUnit), dest));
547
548 CheckQueued(root, 1, pktSizeUnit);
549 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
550 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
551
552 CheckQueued(child, 1, pktSizeUnit);
553 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
554 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
555
556 // Dequeue one packet.
557 item = root->Dequeue();
558
559 NS_TEST_ASSERT_MSG_NE(item, nullptr, "A packet must have been returned");
560 NS_TEST_ASSERT_MSG_EQ(item->GetSize(),
561 pktSizeUnit,
562 "The dequeued packet has not the expected size");
563
564 CheckQueued(root, 0, 0);
565 CheckDroppedBeforeEnqueue(root, 1, pktSizeUnit * 5);
566 CheckDroppedAfterDequeue(root, 2, pktSizeUnit * 3);
567
568 CheckQueued(child, 0, 0);
569 CheckDroppedBeforeEnqueue(child, 1, pktSizeUnit * 5);
570 CheckDroppedAfterDequeue(child, 2, pktSizeUnit * 3);
571
573}
574
575/**
576 * \ingroup traffic-control-test
577 *
578 * \brief Queue Disc Traces Test Suite
579 */
581{
582 public:
584 : TestSuite("queue-disc-traces", Type::UNIT)
585 {
586 AddTestCase(new QueueDiscTracesTestCase(), TestCase::Duration::QUICK);
587 }
588} g_queueDiscTracesTestSuite; ///< the test suite
Queue Disc Test Item.
void AddHeader() override
Add the header to the packet.
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.
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:90
A FIFO packet queue that drops tail-end packets on overflow.
Smart pointer class similar to boost::intrusive_ptr.
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition queue-disc.h:173
void AddInternalQueue(Ptr< InternalQueue > queue)
Add an internal queue to the tail of the list of queues.
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
uint32_t GetNPackets() const
Get the number of packets stored by the queue disc.
Ptr< InternalQueue > GetInternalQueue(std::size_t i) const
Get the i-th internal queue.
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.
Ptr< QueueDiscClass > GetQueueDiscClass(std::size_t i) const
Get the i-th queue disc class.
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.
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition queue-item.h:122
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
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
static constexpr auto UNIT
Definition test.h:1291
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
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_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:554
QueueDiscTracesTestSuite g_queueDiscTracesTestSuite
the test suite
QueueDiscSizePolicy
Enumeration of the available policies to handle the queue disc size.
Definition queue-disc.h:96
@ SINGLE_INTERNAL_QUEUE
Used by queue discs with single internal queue.
Definition queue-disc.h:97
@ SINGLE_CHILD_QUEUE_DISC
Used by queue discs with single child queue disc.
Definition queue-disc.h:98
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Structure that keeps the queue disc statistics.
Definition queue-disc.h:177
uint64_t nTotalDroppedBytesBeforeEnqueue
Total bytes dropped before enqueue.
Definition queue-disc.h:207
uint64_t nTotalDroppedBytesAfterDequeue
Total bytes dropped after dequeue.
Definition queue-disc.h:211
uint32_t nTotalDroppedPacketsBeforeEnqueue
Total packets dropped before enqueue.
Definition queue-disc.h:197
uint32_t nTotalDroppedPacketsAfterDequeue
Total packets dropped after dequeue.
Definition queue-disc.h:201