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 
29 using namespace ns3;
30 
37 class qdTestItem : public QueueDiscItem
38 {
39 public:
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 
61 void
63 {
64 }
65 
66 bool
68 {
69  return false;
70 }
71 
72 
80 {
81 public:
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 
106 bool
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 
132 bool
134 {
136  return true;
137 }
138 
139 void
141 {
142 }
143 
144 
152 {
153 public:
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 
174 bool
176 {
177  return GetQueueDiscClass (0)->GetQueueDisc ()->Enqueue (item);
178 }
179 
182 {
183  return GetQueueDiscClass (0)->GetQueueDisc ()->Dequeue ();
184 }
185 
186 bool
188 {
189  Ptr<QueueDiscClass> c = CreateObject<QueueDiscClass> ();
190  c->SetQueueDisc (CreateObject<TestChildQueueDisc> ());
191  AddQueueDiscClass (c);
192  return true;
193 }
194 
195 void
197 {
198 }
199 
200 
208 {
209 public:
213  TestCounter ();
214  virtual ~TestCounter ();
215 
220  void ConnectTraces (Ptr<QueueDisc> qd);
221 
222 private:
238  void PacketDbe (Ptr<const QueueDiscItem> item, const char* reason);
244  void PacketDad (Ptr<const QueueDiscItem> item, const char* reason);
245 
246  uint32_t m_nPackets;
247  uint32_t m_nBytes;
248  uint32_t m_nDbePackets;
249  uint32_t m_nDbeBytes;
250  uint32_t m_nDadPackets;
251  uint32_t m_nDadBytes;
252 
253  friend class QueueDiscTracesTestCase;
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 
270 void
272 {
273  m_nPackets++;
274  m_nBytes += item->GetSize ();
275 }
276 
277 void
279 {
280  m_nPackets--;
281  m_nBytes -= item->GetSize ();
282 }
283 
284 void
286 {
287  m_nDbePackets++;
288  m_nDbeBytes += item->GetSize ();
289 }
290 
291 
292 void
294 {
295  m_nDadPackets++;
296  m_nDadBytes += item->GetSize ();
297 }
298 
299 void
301 {
304  qd->TraceConnectWithoutContext ("DropBeforeEnqueue", MakeCallback (&TestCounter::PacketDbe, this));
305  qd->TraceConnectWithoutContext ("DropAfterDequeue", MakeCallback (&TestCounter::PacketDad, this));
306 }
307 
308 
326 {
327 public:
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 
353 private:
354  std::map<Ptr<QueueDisc>,TestCounter> m_counter;
355 };
356 
358  : TestCase ("Sanity check on the queue disc traces and statistics")
359 {
360 }
361 
362 void
363 QueueDiscTracesTestCase::CheckQueued (Ptr<QueueDisc> qd, uint32_t nPackets, uint32_t nBytes)
364 {
365  NS_TEST_EXPECT_MSG_EQ (qd->GetNPackets (), nPackets,
366  "Verify that the number of queued packets is computed correctly");
367  NS_TEST_EXPECT_MSG_EQ (m_counter[qd].m_nPackets, nPackets,
368  "Verify that the number of queued packets is computed correctly");
369 
370  NS_TEST_EXPECT_MSG_EQ (qd->GetNBytes (), nBytes,
371  "Verify that the number of queued bytes is computed correctly");
372  NS_TEST_EXPECT_MSG_EQ (m_counter[qd].m_nBytes, nBytes,
373  "Verify that the number of queued bytes is computed correctly");
374 }
375 
376 void
377 QueueDiscTracesTestCase::CheckDroppedBeforeEnqueue (Ptr<QueueDisc> qd, uint32_t nDbePackets, uint32_t nDbeBytes)
378 {
379  QueueDisc::Stats stats = qd->GetStats ();
380 
382  "Verify that the number of packets dropped before enqueue is computed correctly");
383  NS_TEST_EXPECT_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_EXPECT_MSG_EQ (m_counter[qd].m_nDbeBytes, nDbeBytes,
389  "Verify that the number of bytes dropped before enqueue is computed correctly");
390 }
391 
392 void
393 QueueDiscTracesTestCase::CheckDroppedAfterDequeue (Ptr<QueueDisc> qd, uint32_t nDadPackets, uint32_t nDadBytes)
394 {
395  QueueDisc::Stats stats = qd->GetStats ();
396 
398  "Verify that the number of packets dropped after dequeue is computed correctly");
399  NS_TEST_EXPECT_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_EXPECT_MSG_EQ (m_counter[qd].m_nDadBytes, nDadBytes,
405  "Verify that the number of bytes dropped after dequeue is computed correctly");
406 }
407 
408 void
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_EXPECT_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_EXPECT_MSG_NE (item, 0, "A packet must have been returned");
468  NS_TEST_EXPECT_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_EXPECT_MSG_NE (item, 0, "A packet must have been returned");
482  NS_TEST_EXPECT_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_EXPECT_MSG_NE (item, 0, "A packet must have been returned");
496  NS_TEST_EXPECT_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_EXPECT_MSG_NE (item, 0, "A packet must have been returned");
510  NS_TEST_EXPECT_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_EXPECT_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_EXPECT_MSG_NE (item, 0, "A packet must have been returned");
548  NS_TEST_EXPECT_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 
568 static class QueueDiscTracesTestSuite : public TestSuite
569 {
570 public:
572  : TestSuite ("queue-disc-traces", UNIT)
573  {
574  AddTestCase (new QueueDiscTracesTestCase (), TestCase::QUICK);
575  }
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:185
Ptr< const QueueDiscItem > Peek(void)
Get a copy of the next packet the queue discipline will extract.
Definition: queue-disc.cc:922
virtual bool DoEnqueue(Ptr< QueueDiscItem > item)
This function actually enqueues a packet into the queue disc.
uint32_t GetNPackets(void) const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:435
void PacketDad(Ptr< const QueueDiscItem > item, const char *reason)
Update statistics after a packet has been dropped after dequeue.
uint32_t m_nDadBytes
Number of packets dropped after dequeue.
virtual bool CheckConfig(void)
Check whether the current configuration is correct.
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:629
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:721
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
Definition: queue-disc.cc:853
void PacketEnqueued(Ptr< const QueueDiscItem > item)
Update statistics after a packet has been enqueued.
A suite of tests to run.
Definition: test.h:1342
std::map< Ptr< QueueDisc >, TestCounter > m_counter
counters for the queue discs
void SetQueueDisc(Ptr< QueueDisc > qd)
Set the queue disc attached to this class.
Definition: queue-disc.cc:80
Test Child Queue Disc that may drop packets before enqueue or after dequeue.
#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:285
static constexpr const char * BEFORE_ENQUEUE
Drop before enqueue.
uint32_t GetNBytes(void) const
Get the amount of bytes stored by the queue disc.
Definition: queue-disc.cc:442
Queue Disc Traces Test Case.
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:148
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition: queue-disc.h:181
encapsulates test code
Definition: test.h:1155
QueueDiscTracesTestSuite g_queueDiscTracesTestSuite
the test suite
Used by queue discs with single child queue disc.
Definition: queue-disc.h:106
uint32_t nTotalDroppedPacketsBeforeEnqueue
Total packets dropped before enqueue.
Definition: queue-disc.h:206
virtual bool CheckConfig(void)
Check whether the current configuration is correct.
a polymophic address class
Definition: address.h:90
void PacketDequeued(Ptr< const QueueDiscItem > item)
Update statistics after a packet has been dequeued.
void CheckDroppedBeforeEnqueue(Ptr< QueueDisc > qd, uint32_t nDbePackets, uint32_t nDbeBytes)
Check that packets/bytes dropped before enqueue are consistent with what is expected.
virtual Ptr< QueueDiscItem > DoDequeue(void)
This function actually extracts a packet from the queue disc.
void ConnectTraces(Ptr< QueueDisc > qd)
Connect private methods to the queue disc traces.
Queue Disc Test Item.
void AddInternalQueue(Ptr< InternalQueue > queue)
Add an internal queue to the tail of the list of queues.
Definition: queue-disc.cc:576
void CheckDroppedAfterDequeue(Ptr< QueueDisc > qd, uint32_t nDadPackets, uint32_t nDadBytes)
Check that packets/bytes dropped after dequeue are consistent with what is expected.
virtual uint32_t GetSize(void) const
Use this method (instead of GetPacket ()->GetSize ()) to get the packet size.
Definition: queue-item.cc:49
uint32_t m_nDbeBytes
Number of packets dropped before enqueue.
qdTestItem(Ptr< Packet > p, const Address &addr)
Constructor.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
Queue Disc Traces Test Suite.
Ptr< InternalQueue > GetInternalQueue(std::size_t i) const
Get the i-th internal queue.
Definition: queue-disc.cc:596
uint32_t m_nBytes
Number of queued bytes.
static constexpr const char * AFTER_DEQUEUE
Drop after dequeue.
virtual void InitializeParams(void)
Initialize parameters (if any) before the first packet is enqueued.
uint32_t m_nDbePackets
Number of packets dropped before enqueue.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
const Stats & GetStats(void)
Retrieve all the collected statistics.
Definition: queue-disc.cc:416
uint64_t nTotalDroppedBytesBeforeEnqueue
Total bytes dropped before enqueue.
Definition: queue-disc.h:216
Ptr< QueueDiscClass > GetQueueDiscClass(std::size_t i) const
Get the i-th queue disc class.
Definition: queue-disc.cc:654
void CheckQueued(Ptr< QueueDisc > qd, uint32_t nPackets, uint32_t nBytes)
Check that queued packets/bytes are consistent with what is expected.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Ptr< QueueDiscItem > Dequeue(void)
Extract from the queue disc the packet that has been dequeued by calling Peek, if any...
Definition: queue-disc.cc:888
Introspection did not find any typical Config paths.
uint32_t m_nPackets
Number of queued packets.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:293
uint32_t nTotalDroppedPacketsAfterDequeue
Total packets dropped after dequeue.
Definition: queue-disc.h:210
Every class exported by the ns3 library is enclosed in the ns3 namespace.
#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:739
Keep statistics based on traces.
QueueDiscSizePolicy
Enumeration of the available policies to handle the queue disc size.
Definition: queue-disc.h:103
virtual Ptr< QueueDiscItem > DoDequeue(void)
This function actually extracts a packet from the queue disc.
Used by queue discs with single internal queue.
Definition: queue-disc.h:105
uint64_t nTotalDroppedBytesAfterDequeue
Total bytes dropped after dequeue.
Definition: queue-disc.h:220
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification...
virtual void AddHeader(void)
Add the header to the packet.
Test Parent Queue Disc having a child of type TestChildQueueDisc.
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:760
uint32_t m_nDadPackets
Number of packets dropped after dequeue.
Ptr< T > CreateObject(void)
Create an object by type, with varying number of constructor parameters.
Definition: object.h:528
virtual void InitializeParams(void)
Initialize parameters (if any) before the first packet is enqueued.
This test suite implements a Unit Test.
Definition: test.h:1351
void PacketDbe(Ptr< const QueueDiscItem > item, const char *reason)
Update statistics after a packet has been dropped before enqueue.
virtual bool DoEnqueue(Ptr< QueueDiscItem > item)
This function actually enqueues a packet into the queue disc.
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183