A Discrete-Event Network Simulator
API
pie-queue-disc-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) 2016 NITK Surathkal
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: Shravya Ks <shravya.ks0@gmail.com>
19  * Smriti Murali <m.smriti.95@gmail.com>
20  * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
21  *
22  */
23 
24 #include "ns3/test.h"
25 #include "ns3/pie-queue-disc.h"
26 #include "ns3/packet.h"
27 #include "ns3/uinteger.h"
28 #include "ns3/string.h"
29 #include "ns3/double.h"
30 #include "ns3/log.h"
31 #include "ns3/simulator.h"
32 
33 using namespace ns3;
34 
42 {
43 public:
50  PieQueueDiscTestItem (Ptr<Packet> p, const Address & addr);
51  virtual ~PieQueueDiscTestItem ();
52  virtual void AddHeader (void);
53  virtual bool Mark (void);
54 
55 private:
67  PieQueueDiscTestItem &operator = (const PieQueueDiscTestItem &);
68 };
69 
71  : QueueDiscItem (p, addr, 0)
72 {
73 }
74 
76 {
77 }
78 
79 void
81 {
82 }
83 
84 bool
86 {
87  return false;
88 }
89 
97 {
98 public:
100  virtual void DoRun (void);
101 private:
108  void Enqueue (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt);
115  void EnqueueWithDelay (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt);
121  void Dequeue (Ptr<PieQueueDisc> queue, uint32_t nPkt);
128  void DequeueWithDelay (Ptr<PieQueueDisc> queue, double delay, uint32_t nPkt);
133  void RunPieTest (QueueSizeUnit mode);
134 };
135 
137  : TestCase ("Sanity check on the pie queue disc implementation")
138 {
139 }
140 
141 void
143 {
144  uint32_t pktSize = 0;
145 
146  // 1 for packets; pktSize for bytes
147  uint32_t modeSize = 1;
148 
149  uint32_t qSize = 300;
150  Ptr<PieQueueDisc> queue = CreateObject<PieQueueDisc> ();
151 
152 
153  // test 1: simple enqueue/dequeue with defaults, no drops
154  Address dest;
155 
156  if (mode == QueueSizeUnit::BYTES)
157  {
158  // pktSize should be same as MeanPktSize to avoid performance gap between byte and packet mode
159  pktSize = 1000;
160  modeSize = pktSize;
161  qSize = qSize * modeSize;
162  }
163 
164  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
165  true, "Verify that we can actually set the attribute MaxSize");
166 
167  Ptr<Packet> p1, p2, p3, p4, p5, p6, p7, p8;
168  p1 = Create<Packet> (pktSize);
169  p2 = Create<Packet> (pktSize);
170  p3 = Create<Packet> (pktSize);
171  p4 = Create<Packet> (pktSize);
172  p5 = Create<Packet> (pktSize);
173  p6 = Create<Packet> (pktSize);
174  p7 = Create<Packet> (pktSize);
175  p8 = Create<Packet> (pktSize);
176 
177  queue->Initialize ();
178  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 0 * modeSize, "There should be no packets in there");
179  queue->Enqueue (Create<PieQueueDiscTestItem> (p1, dest));
180  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 1 * modeSize, "There should be one packet in there");
181  queue->Enqueue (Create<PieQueueDiscTestItem> (p2, dest));
182  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 2 * modeSize, "There should be two packets in there");
183  queue->Enqueue (Create<PieQueueDiscTestItem> (p3, dest));
184  queue->Enqueue (Create<PieQueueDiscTestItem> (p4, dest));
185  queue->Enqueue (Create<PieQueueDiscTestItem> (p5, dest));
186  queue->Enqueue (Create<PieQueueDiscTestItem> (p6, dest));
187  queue->Enqueue (Create<PieQueueDiscTestItem> (p7, dest));
188  queue->Enqueue (Create<PieQueueDiscTestItem> (p8, dest));
189  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 8 * modeSize, "There should be eight packets in there");
190 
191  Ptr<QueueDiscItem> item;
192 
193  item = queue->Dequeue ();
194  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the first packet");
195  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 7 * modeSize, "There should be seven packets in there");
196  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p1->GetUid (), "was this the first packet ?");
197 
198  item = queue->Dequeue ();
199  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the second packet");
200  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 6 * modeSize, "There should be six packet in there");
201  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p2->GetUid (), "Was this the second packet ?");
202 
203  item = queue->Dequeue ();
204  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the third packet");
205  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 5 * modeSize, "There should be five packets in there");
206  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p3->GetUid (), "Was this the third packet ?");
207 
208  item = queue->Dequeue ();
209  item = queue->Dequeue ();
210  item = queue->Dequeue ();
211  item = queue->Dequeue ();
212  item = queue->Dequeue ();
213 
214  item = queue->Dequeue ();
215  NS_TEST_EXPECT_MSG_EQ ((item == 0), true, "There are really no packets in there");
216 
217 
218  // test 2: more data with defaults, unforced drops but no forced drops
219  queue = CreateObject<PieQueueDisc> ();
220  pktSize = 1000; // pktSize != 0 because DequeueThreshold always works in bytes
221  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
222  true, "Verify that we can actually set the attribute MaxSize");
223  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true,
224  "Verify that we can actually set the attribute A");
225  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true,
226  "Verify that we can actually set the attribute B");
227  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true,
228  "Verify that we can actually set the attribute Tupdate");
229  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true,
230  "Verify that we can actually set the attribute Supdate");
231  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
232  "Verify that we can actually set the attribute DequeueThreshold");
233  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true,
234  "Verify that we can actually set the attribute QueueDelayReference");
235  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
236  "Verify that we can actually set the attribute MaxBurstAllowance");
237  queue->Initialize ();
238  EnqueueWithDelay (queue, pktSize, 400);
239  DequeueWithDelay (queue, 0.012, 400);
240  Simulator::Stop (Seconds (8.0));
241  Simulator::Run ();
242  QueueDisc::Stats st = queue->GetStats ();
243  uint32_t test2 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
244  NS_TEST_EXPECT_MSG_NE (test2, 0, "There should be some unforced drops");
245  NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
246 
247 
248  // test 3: same as test 2, but with higher QueueDelayReference
249  queue = CreateObject<PieQueueDisc> ();
250  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
251  true, "Verify that we can actually set the attribute MaxSize");
252  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true,
253  "Verify that we can actually set the attribute A");
254  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true,
255  "Verify that we can actually set the attribute B");
256  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true,
257  "Verify that we can actually set the attribute Tupdate");
258  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true,
259  "Verify that we can actually set the attribute Supdate");
260  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
261  "Verify that we can actually set the attribute DequeueThreshold");
262  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.08))), true,
263  "Verify that we can actually set the attribute QueueDelayReference");
264  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
265  "Verify that we can actually set the attribute MaxBurstAllowance");
266  queue->Initialize ();
267  EnqueueWithDelay (queue, pktSize, 400);
268  DequeueWithDelay (queue, 0.012, 400);
269  Simulator::Stop (Seconds (8.0));
270  Simulator::Run ();
271  st = queue->GetStats ();
272  uint32_t test3 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
273  NS_TEST_EXPECT_MSG_LT (test3, test2, "Test 3 should have less unforced drops than test 2");
274  NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
275 
276 
277  // test 4: same as test 2, but with reduced dequeue rate
278  queue = CreateObject<PieQueueDisc> ();
279  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
280  true, "Verify that we can actually set the attribute MaxSize");
281  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true,
282  "Verify that we can actually set the attribute A");
283  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true,
284  "Verify that we can actually set the attribute B");
285  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true,
286  "Verify that we can actually set the attribute Tupdate");
287  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true,
288  "Verify that we can actually set the attribute Supdate");
289  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
290  "Verify that we can actually set the attribute DequeueThreshold");
291  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true,
292  "Verify that we can actually set the attribute QueueDelayReference");
293  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
294  "Verify that we can actually set the attribute MaxBurstAllowance");
295  queue->Initialize ();
296  EnqueueWithDelay (queue, pktSize, 400);
297  DequeueWithDelay (queue, 0.015, 400); // delay between two successive dequeue events is increased
298  Simulator::Stop (Seconds (8.0));
299  Simulator::Run ();
300  st = queue->GetStats ();
301  uint32_t test4 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
302  NS_TEST_EXPECT_MSG_GT (test4, test2, "Test 4 should have more unforced drops than test 2");
303  NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
304 
305 
306  // test 5: same dequeue rate as test 4, but with higher Tupdate
307  queue = CreateObject<PieQueueDisc> ();
308  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
309  true, "Verify that we can actually set the attribute MaxSize");
310  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true,
311  "Verify that we can actually set the attribute A");
312  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true,
313  "Verify that we can actually set the attribute B");
314  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.09))), true,
315  "Verify that we can actually set the attribute Tupdate");
316  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true,
317  "Verify that we can actually set the attribute Supdate");
318  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
319  "Verify that we can actually set the attribute DequeueThreshold");
320  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true,
321  "Verify that we can actually set the attribute QueueDelayReference");
322  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
323  "Verify that we can actually set the attribute MaxBurstAllowance");
324  queue->Initialize ();
325  EnqueueWithDelay (queue, pktSize, 400);
326  DequeueWithDelay (queue, 0.015, 400);
327  Simulator::Stop (Seconds (8.0));
328  Simulator::Run ();
329  st = queue->GetStats ();
330  uint32_t test5 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
331  NS_TEST_EXPECT_MSG_LT (test5, test4, "Test 5 should have less unforced drops than test 4");
332  NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
333 }
334 
335 void
336 PieQueueDiscTestCase::Enqueue (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt)
337 {
338  Address dest;
339  for (uint32_t i = 0; i < nPkt; i++)
340  {
341  queue->Enqueue (Create<PieQueueDiscTestItem> (Create<Packet> (size), dest));
342  }
343 }
344 
345 void
346 PieQueueDiscTestCase::EnqueueWithDelay (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt)
347 {
348  Address dest;
349  double delay = 0.01; // enqueue packets with delay
350  for (uint32_t i = 0; i < nPkt; i++)
351  {
352  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &PieQueueDiscTestCase::Enqueue, this, queue, size, 1);
353  }
354 }
355 
356 void
358 {
359  for (uint32_t i = 0; i < nPkt; i++)
360  {
361  Ptr<QueueDiscItem> item = queue->Dequeue ();
362  }
363 }
364 
365 void
366 PieQueueDiscTestCase::DequeueWithDelay (Ptr<PieQueueDisc> queue, double delay, uint32_t nPkt)
367 {
368  for (uint32_t i = 0; i < nPkt; i++)
369  {
370  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &PieQueueDiscTestCase::Dequeue, this, queue, 1);
371  }
372 }
373 
374 void
376 {
379  Simulator::Destroy ();
380 }
381 
388 static class PieQueueDiscTestSuite : public TestSuite
389 {
390 public:
392  : TestSuite ("pie-queue-disc", UNIT)
393  {
394  AddTestCase (new PieQueueDiscTestCase (), TestCase::QUICK);
395  }
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:185
Pie Queue Disc Test Case.
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification...
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Class for representing queue sizes.
Definition: queue-size.h:94
void RunPieTest(QueueSizeUnit mode)
Run test function.
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
Definition: queue-disc.cc:825
QueueSizeUnit
Enumeration of the operating modes of queues.
Definition: queue-size.h:42
QueueSize GetCurrentSize(void)
Get the current size of the queue disc in bytes, if operating in bytes mode, or packets, otherwise.
Definition: queue-disc.cc:523
A suite of tests to run.
Definition: test.h:1342
void Dequeue(Ptr< PieQueueDisc > queue, uint32_t nPkt)
Dequeue function.
#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
bool SetAttributeFailSafe(std::string name, const AttributeValue &value)
Set a single attribute without raising errors.
Definition: object-base.cc:205
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:148
encapsulates test code
Definition: test.h:1155
This test suite implements a Unit Test.
Definition: test.h:1352
uint32_t GetValue() const
Get the underlying value.
Definition: queue-size.cc:175
a polymophic address class
Definition: address.h:90
virtual void DoRun(void)
Implementation to actually run this TestCase.
AttributeValue implementation for Time.
Definition: nstime.h:1069
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
Hold an unsigned integer type.
Definition: uinteger.h:44
Use number of packets for queue size.
Definition: queue-size.h:44
virtual void AddHeader(void)
Add the header to the packet.
const Stats & GetStats(void)
Retrieve all the collected statistics.
Definition: queue-disc.cc:421
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
Definition: queue-disc.cc:113
Ptr< QueueDiscItem > Dequeue(void)
Request the queue discipline to extract a packet.
Definition: queue-disc.cc:860
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
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report if not.
Definition: test.h:1090
void EnqueueWithDelay(Ptr< PieQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue with delay function.
Pie Queue Disc Test Item.
PieQueueDiscTestSuite g_pieQueueTestSuite
the test suite
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1007
#define NS_TEST_EXPECT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report if not.
Definition: test.h:903
Pie Queue Disc Test Suite.
void DequeueWithDelay(Ptr< PieQueueDisc > queue, double delay, uint32_t nPkt)
Dequeue with delay function.
void Enqueue(Ptr< PieQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
This class can be used to hold variables of floating point type such as 'double' or 'float'...
Definition: double.h:41
Use number of bytes for queue size.
Definition: queue-size.h:45
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183