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:
51  PieQueueDiscTestItem (Ptr<Packet> p, const Address & addr, bool ecnCapable);
52  virtual ~PieQueueDiscTestItem ();
53 
54  // Delete copy constructor and assignment operator to avoid misuse
56  PieQueueDiscTestItem & operator = (const PieQueueDiscTestItem &) = delete;
57 
58  virtual void AddHeader (void);
59  virtual bool Mark (void);
60 
61  // ** Variables for testing m_isCapDropAdjustment
62  double m_maxDropProbDiff = 0.0;
63  double m_prevDropProb = 0.0;
64  bool m_checkProb = false;
65 
66  // ** Variable for testing ECN
67  double m_maxDropProb = 0.0;
68  bool m_ecnCapable = false;
69 
70  // ** Variables for testing Derandomization
71  bool m_checkAccuProb = false;
72  bool m_constAccuProb = false;
73  bool m_checkMaxAccuProb = false;
74  double m_accuProbError = 0.0;
75  double m_prevAccuProb = 0.0;
76  double m_setAccuProb = 0.0;
77  uint32_t m_expectedDrops = 0;
78 
79 private:
81 
83 };
84 
86  : QueueDiscItem (p, addr, 0), m_ecnCapablePacket (ecnCapable)
87 {
88 }
89 
91 {
92 }
93 
94 void
96 {
97 }
98 
99 bool
101 {
102  if (m_ecnCapablePacket)
103  {
104  return true;
105  }
106  return false;
107 }
108 
116 {
117 public:
119  virtual void DoRun (void);
120 private:
128  void Enqueue (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt, Ptr<PieQueueDiscTestItem> testAttributes);
136  void EnqueueWithDelay (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt, Ptr<PieQueueDiscTestItem> testAttributes);
142  void Dequeue (Ptr<PieQueueDisc> queue, uint32_t nPkt);
149  void DequeueWithDelay (Ptr<PieQueueDisc> queue, double delay, uint32_t nPkt);
154  void RunPieTest (QueueSizeUnit mode);
160  void CheckDropProb (Ptr<PieQueueDisc> queue, Ptr<PieQueueDiscTestItem> testAttributes);
166  void CheckAccuProb (Ptr<PieQueueDisc> queue, Ptr<PieQueueDiscTestItem> testAttributes);
172  void CheckMaxAccuProb (Ptr<PieQueueDisc> queue, Ptr<PieQueueDiscTestItem> testAttributes);
173 };
174 
176  : TestCase ("Sanity check on the pie queue disc implementation")
177 {
178 }
179 
180 void
182 {
183  uint32_t pktSize = 0;
184 
185  // 1 for packets; pktSize for bytes
186  uint32_t modeSize = 1;
187 
188  uint32_t qSize = 300;
189  Ptr<PieQueueDisc> queue = CreateObject<PieQueueDisc> ();
190 
191 
192  // test 1: simple enqueue/dequeue with defaults, no drops
193  Address dest;
194  // PieQueueDiscItem pointer for attributes
195  Ptr<PieQueueDiscTestItem> testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
196 
197  if (mode == QueueSizeUnit::BYTES)
198  {
199  // pktSize should be same as MeanPktSize to avoid performance gap between byte and packet mode
200  pktSize = 1000;
201  modeSize = pktSize;
202  qSize = qSize * modeSize;
203  }
204 
205  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
206  true, "Verify that we can actually set the attribute MaxSize");
207 
208  Ptr<Packet> p1, p2, p3, p4, p5, p6, p7, p8;
209  p1 = Create<Packet> (pktSize);
210  p2 = Create<Packet> (pktSize);
211  p3 = Create<Packet> (pktSize);
212  p4 = Create<Packet> (pktSize);
213  p5 = Create<Packet> (pktSize);
214  p6 = Create<Packet> (pktSize);
215  p7 = Create<Packet> (pktSize);
216  p8 = Create<Packet> (pktSize);
217 
218  queue->Initialize ();
219  NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 0 * modeSize, "There should be no packets in there");
220  queue->Enqueue (Create<PieQueueDiscTestItem> (p1, dest, false));
221  NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 1 * modeSize, "There should be one packet in there");
222  queue->Enqueue (Create<PieQueueDiscTestItem> (p2, dest, false));
223  NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 2 * modeSize, "There should be two packets in there");
224  queue->Enqueue (Create<PieQueueDiscTestItem> (p3, dest, false));
225  queue->Enqueue (Create<PieQueueDiscTestItem> (p4, dest, false));
226  queue->Enqueue (Create<PieQueueDiscTestItem> (p5, dest, false));
227  queue->Enqueue (Create<PieQueueDiscTestItem> (p6, dest, false));
228  queue->Enqueue (Create<PieQueueDiscTestItem> (p7, dest, false));
229  queue->Enqueue (Create<PieQueueDiscTestItem> (p8, dest, false));
230  NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 8 * modeSize, "There should be eight packets in there");
231 
232  Ptr<QueueDiscItem> item;
233 
234  item = queue->Dequeue ();
235  NS_TEST_ASSERT_MSG_EQ ((item != 0), true, "I want to remove the first packet");
236  NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 7 * modeSize, "There should be seven packets in there");
237  NS_TEST_ASSERT_MSG_EQ (item->GetPacket ()->GetUid (), p1->GetUid (), "was this the first packet ?");
238 
239  item = queue->Dequeue ();
240  NS_TEST_ASSERT_MSG_EQ ((item != 0), true, "I want to remove the second packet");
241  NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 6 * modeSize, "There should be six packet in there");
242  NS_TEST_ASSERT_MSG_EQ (item->GetPacket ()->GetUid (), p2->GetUid (), "Was this the second packet ?");
243 
244  item = queue->Dequeue ();
245  NS_TEST_ASSERT_MSG_EQ ((item != 0), true, "I want to remove the third packet");
246  NS_TEST_ASSERT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 5 * modeSize, "There should be five packets in there");
247  NS_TEST_ASSERT_MSG_EQ (item->GetPacket ()->GetUid (), p3->GetUid (), "Was this the third packet ?");
248 
249  item = queue->Dequeue ();
250  item = queue->Dequeue ();
251  item = queue->Dequeue ();
252  item = queue->Dequeue ();
253  item = queue->Dequeue ();
254 
255  item = queue->Dequeue ();
256  NS_TEST_ASSERT_MSG_EQ ((item == 0), true, "There are really no packets in there");
257 
258 
259  // test 2: more data with defaults, unforced drops but no forced drops
260  queue = CreateObject<PieQueueDisc> ();
261  // PieQueueDiscItem pointer for attributes
262  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
263  pktSize = 1000; // pktSize != 0 because DequeueThreshold always works in bytes
264  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
265  true, "Verify that we can actually set the attribute MaxSize");
266  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true,
267  "Verify that we can actually set the attribute Tupdate");
268  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
269  "Verify that we can actually set the attribute DequeueThreshold");
270  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true,
271  "Verify that we can actually set the attribute QueueDelayReference");
272  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
273  "Verify that we can actually set the attribute MaxBurstAllowance");
274  queue->Initialize ();
275  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
276  DequeueWithDelay (queue, 0.012, 400);
277  Simulator::Stop (Seconds (8.0));
278  Simulator::Run ();
279  QueueDisc::Stats st = queue->GetStats ();
280  uint32_t test2 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
281  NS_TEST_ASSERT_MSG_NE (test2, 0, "There should be some unforced drops");
282  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
283 
284 
285  // test 3: same as test 2, but with higher QueueDelayReference
286  queue = CreateObject<PieQueueDisc> ();
287  // PieQueueDiscItem pointer for attributes
288  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
289  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
290  true, "Verify that we can actually set the attribute MaxSize");
291  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true,
292  "Verify that we can actually set the attribute Tupdate");
293  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
294  "Verify that we can actually set the attribute DequeueThreshold");
295  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.08))), true,
296  "Verify that we can actually set the attribute QueueDelayReference");
297  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
298  "Verify that we can actually set the attribute MaxBurstAllowance");
299  queue->Initialize ();
300  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
301  DequeueWithDelay (queue, 0.012, 400);
302  Simulator::Stop (Seconds (8.0));
303  Simulator::Run ();
304  st = queue->GetStats ();
305  uint32_t test3 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
306  NS_TEST_ASSERT_MSG_LT (test3, test2, "Test 3 should have less unforced drops than test 2");
307  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
308 
309 
310  // test 4: same as test 2, but with reduced dequeue rate
311  queue = CreateObject<PieQueueDisc> ();
312  // PieQueueDiscItem pointer for attributes
313  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
314  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
315  true, "Verify that we can actually set the attribute MaxSize");
316  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true,
317  "Verify that we can actually set the attribute Tupdate");
318  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
319  "Verify that we can actually set the attribute DequeueThreshold");
320  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true,
321  "Verify that we can actually set the attribute QueueDelayReference");
322  NS_TEST_ASSERT_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, testAttributes);
326  DequeueWithDelay (queue, 0.015, 400); // delay between two successive dequeue events is increased
327  Simulator::Stop (Seconds (8.0));
328  Simulator::Run ();
329  st = queue->GetStats ();
330  uint32_t test4 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
331  NS_TEST_ASSERT_MSG_GT (test4, test2, "Test 4 should have more unforced drops than test 2");
332  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
333 
334 
335  // test 5: same dequeue rate as test 4, but with higher Tupdate
336  queue = CreateObject<PieQueueDisc> ();
337  // PieQueueDiscItem pointer for attributes
338  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
339  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
340  true, "Verify that we can actually set the attribute MaxSize");
341  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.09))), true,
342  "Verify that we can actually set the attribute Tupdate");
343  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
344  "Verify that we can actually set the attribute DequeueThreshold");
345  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true,
346  "Verify that we can actually set the attribute QueueDelayReference");
347  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
348  "Verify that we can actually set the attribute MaxBurstAllowance");
349  queue->Initialize ();
350  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
351  DequeueWithDelay (queue, 0.015, 400);
352  Simulator::Stop (Seconds (8.0));
353  Simulator::Run ();
354  st = queue->GetStats ();
355  uint32_t test5 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
356  NS_TEST_ASSERT_MSG_LT (test5, test4, "Test 5 should have less unforced drops than test 4");
357  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
358 
359 
360  // test 6: same as test 2, but with UseDequeueRateEstimator enabled
361  queue = CreateObject<PieQueueDisc> ();
362  // PieQueueDiscItem pointer for attributes
363  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
364  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
365  true, "Verify that we can actually set the attribute MaxSize");
366  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseDequeueRateEstimator", BooleanValue (true)), true,
367  "Verify that we can actually set the attribute UseTimestamp");
368  queue->Initialize ();
369  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
370  DequeueWithDelay (queue, 0.014, 400);
371  Simulator::Stop (Seconds (8.0));
372  Simulator::Run ();
373  st = queue->GetStats ();
374  uint32_t test6 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
375  NS_TEST_ASSERT_MSG_NE (test6, 0, "There should be some unforced drops");
376  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
377 
378 
379  // test 7: test with CapDropAdjustment disabled
380  queue = CreateObject<PieQueueDisc> ();
381  // PieQueueDiscItem pointer for attributes
382  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
383  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
384  true, "Verify that we can actually set the attribute MaxSize");
385  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseCapDropAdjustment", BooleanValue (false)), true,
386  "Verify that we can actually set the attribute UseCapDropAdjustment");
387  queue->Initialize ();
388  testAttributes->m_checkProb = true;
389  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
390  DequeueWithDelay (queue, 0.014, 400);
391  Simulator::Stop (Seconds (8.0));
392  Simulator::Run ();
393  st = queue->GetStats ();
394  uint32_t test7 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
395  NS_TEST_ASSERT_MSG_NE (test7, 0, "There should be some unforced drops");
396  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
397  NS_TEST_ASSERT_MSG_GT (testAttributes->m_maxDropProbDiff, 0.02,
398  "Maximum increase in drop probability should be greater than 0.02");
399 
400 
401  // test 8: test with CapDropAdjustment enabled
402  queue = CreateObject<PieQueueDisc> ();
403  // PieQueueDiscItem pointer for attributes
404  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
405  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
406  true, "Verify that we can actually set the attribute MaxSize");
407  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseCapDropAdjustment", BooleanValue (true)), true,
408  "Verify that we can actually set the attribute UseCapDropAdjustment");
409  queue->Initialize ();
410  testAttributes->m_checkProb = true;
411  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
412  DequeueWithDelay (queue, 0.014, 400);
413  Simulator::Stop (Seconds (8.0));
414  Simulator::Run ();
415  st = queue->GetStats ();
416  uint32_t test8 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
417  NS_TEST_ASSERT_MSG_NE (test8, 0, "There should be some unforced drops");
418  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
419  NS_TEST_ASSERT_MSG_LT (testAttributes->m_maxDropProbDiff, 0.0200000000000001,
420  "Maximum increase in drop probability should be less than or equal to 0.02");
421 
422 
423  // test 9: PIE queue disc is ECN enabled, but packets are not ECN capable
424  queue = CreateObject<PieQueueDisc> ();
425  // PieQueueDiscItem pointer for attributes
426  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
427  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
428  true, "Verify that we can actually set the attribute MaxSize");
429  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)), true,
430  "Verify that we can actually set the attribute UseEcn");
431  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MarkEcnThreshold", DoubleValue (0.3)), true,
432  "Verify that we can actually set the attribute MarkEcnThreshold");
433  queue->Initialize ();
434  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
435  DequeueWithDelay (queue, 0.014, 400);
436  Simulator::Stop (Seconds (8.0));
437  Simulator::Run ();
438  st = queue->GetStats ();
439  uint32_t test9 = st.GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK);
440  NS_TEST_ASSERT_MSG_EQ (test9, 0, "There should be zero unforced marks");
441  NS_TEST_ASSERT_MSG_NE (st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP), 0, "There should be some unforced drops");
442  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
443 
444 
445  // test 10: Packets are ECN capable, but PIE queue disc is not ECN enabled
446  queue = CreateObject<PieQueueDisc> ();
447  // PieQueueDiscItem pointer for attributes
448  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
449  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
450  true, "Verify that we can actually set the attribute MaxSize");
451  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (false)), true,
452  "Verify that we can actually set the attribute UseEcn");
453  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MarkEcnThreshold", DoubleValue (0.3)), true,
454  "Verify that we can actually set the attribute MarkEcnThreshold");
455  queue->Initialize ();
456  testAttributes->m_ecnCapable = true;
457  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
458  DequeueWithDelay (queue, 0.014, 400);
459  Simulator::Stop (Seconds (8.0));
460  Simulator::Run ();
461  st = queue->GetStats ();
462  uint32_t test10 = st.GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK);
463  NS_TEST_ASSERT_MSG_EQ (test10, 0, "There should be zero unforced marks");
464  NS_TEST_ASSERT_MSG_NE (st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP), 0, "There should be some unforced drops");
465  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
466 
467 
468  // test 11: Packets and PIE queue disc both are ECN capable
469  queue = CreateObject<PieQueueDisc> ();
470  // PieQueueDiscItem pointer for attributes
471  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
472  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
473  true, "Verify that we can actually set the attribute MaxSize");
474  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)), true,
475  "Verify that we can actually set the attribute UseEcn");
476  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MarkEcnThreshold", DoubleValue (0.3)), true,
477  "Verify that we can actually set the attribute MarkEcnThreshold");
478  queue->Initialize ();
479  testAttributes->m_ecnCapable = true;
480  testAttributes->m_checkProb = true;
481  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
482  DequeueWithDelay (queue, 0.014, 400);
483  Simulator::Stop (Seconds (8.0));
484  Simulator::Run ();
485  st = queue->GetStats ();
486  uint32_t test11 = st.GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK);
487  NS_TEST_ASSERT_MSG_NE (test11, 0, "There should be some unforced marks");
488  // There are unforced drops because the value of m_maxDropProb goes beyond 0.3 in this test.
489  // PIE drops the packets even when they are ECN capable if drop probability is more than 30%.
490  NS_TEST_ASSERT_MSG_NE (st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP), 0, "There should be some unforced drops");
491  // Confirm that m_maxDropProb goes above 0.3 in this test
492  NS_TEST_ASSERT_MSG_GT (testAttributes->m_maxDropProb, 0.3, "Maximum Drop probability should be greater than 0.3");
493  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
494 
495 
496  // test 12: test with derandomization enabled
497  queue = CreateObject<PieQueueDisc> ();
498  // PieQueueDiscItem pointer for attributes
499  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
500  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
501  true, "Verify that we can actually set the attribute MaxSize");
502  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseDerandomization", BooleanValue (true)), true,
503  "Verify that we can actually set the attribute UseDerandomization");
504  queue->Initialize ();
505  testAttributes->m_checkAccuProb = true;
506  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
507  DequeueWithDelay (queue, 0.014, 400);
508  Simulator::Stop (Seconds (8.0));
509  Simulator::Run ();
510  st = queue->GetStats ();
511  uint32_t test12 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
512  NS_TEST_ASSERT_MSG_NE (test12, 0, "There should be some unforced drops");
513  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
514  NS_TEST_ASSERT_MSG_EQ (testAttributes->m_accuProbError, 0.0, "There should not be any error in setting accuProb");
515 
516 
517  // test 13: same as test 11 but with accumulated drop probability set below the low threshold
518  queue = CreateObject<PieQueueDisc> ();
519  // PieQueueDiscItem pointer for attributes
520  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
521  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
522  true, "Verify that we can actually set the attribute MaxSize");
523  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseDerandomization", BooleanValue (true)), true,
524  "Verify that we can actually set the attribute UseDerandomization");
525  queue->Initialize ();
526  testAttributes->m_constAccuProb = true;
527  // Final value of accumulated drop probability to drop packet will be maximum 0.84 while threshold to drop packet is 0.85
528  testAttributes->m_setAccuProb = -0.16;
529  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
530  DequeueWithDelay (queue, 0.014, 400);
531  Simulator::Stop (Seconds (8.0));
532  Simulator::Run ();
533  st = queue->GetStats ();
534  uint32_t test13 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
535  NS_TEST_ASSERT_MSG_EQ (test13, 0, "There should be zero unforced drops");
536  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
537 
538 
539  // test 14: same as test 12 but with accumulated drop probability set above the high threshold
540  queue = CreateObject<PieQueueDisc> ();
541  // PieQueueDiscItem pointer for attributes
542  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
543  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
544  true, "Verify that we can actually set the attribute MaxSize");
545  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.0))), true,
546  "Verify that we can actually set the attribute MaxBurstAllowance");
547  NS_TEST_ASSERT_MSG_EQ (queue->SetAttributeFailSafe ("UseDerandomization", BooleanValue (true)), true,
548  "Verify that we can actually set the attribute UseDerandomization");
549  queue->Initialize ();
550  testAttributes->m_constAccuProb = true;
551  testAttributes->m_checkMaxAccuProb = true;
552  // Final value of accumulated drop probability to drop packet will be minimum 8.6 while threshold to drop packet is 8.5
553  testAttributes->m_setAccuProb = 8.6;
554  EnqueueWithDelay (queue, pktSize, 400, testAttributes);
555  DequeueWithDelay (queue, 0.014, 400);
556  Simulator::Stop (Seconds (8.0));
557  Simulator::Run ();
558  st = queue->GetStats ();
559  uint32_t test14 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
560  NS_TEST_ASSERT_MSG_EQ (test14, testAttributes->m_expectedDrops,
561  "The number of unforced drops should be equal to number of expected unforced drops");
562  NS_TEST_ASSERT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
563 
564 
565  // test 15: tests Active/Inactive feature, ActiveThreshold set to a high value so PIE never starts and there should
566  // not be any drops
567  queue = CreateObject<PieQueueDisc> ();
568  // PieQueueDiscItem pointer for attributes
569  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
570  queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize)));
571  queue->SetAttributeFailSafe ("ActiveThreshold", TimeValue (Seconds (1)));
572  queue->Initialize ();
573 
574  EnqueueWithDelay (queue, pktSize, 100, testAttributes);
575  DequeueWithDelay (queue, 0.02, 100);
576  Simulator::Stop (Seconds (8.0));
577  Simulator::Run ();
578  st = queue->GetStats ();
579  uint32_t test15 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
580  NS_TEST_ASSERT_MSG_EQ (test15, 0, "There should not be any drops.");
581  NS_TEST_ASSERT_MSG_EQ (st.GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK), 0, "There should be zero marks");
582 
583 
584  // test 16: tests Active/Inactive feature, ActiveThreshold set to a low value so PIE starts early
585  // and some packets should be dropped.
586  queue = CreateObject<PieQueueDisc> ();
587  // PieQueueDiscItem pointer for attributes
588  testAttributes = Create<PieQueueDiscTestItem> (Create<Packet> (pktSize), dest, false);
589  queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize)));
590  queue->SetAttributeFailSafe ("ActiveThreshold", TimeValue (Seconds (0.001)));
591  queue->Initialize ();
592 
593  EnqueueWithDelay (queue, pktSize, 100, testAttributes);
594  DequeueWithDelay (queue, 0.02, 100);
595  Simulator::Stop (Seconds (8.0));
596  Simulator::Run ();
597  st = queue->GetStats ();
598  uint32_t test16 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
599  NS_TEST_ASSERT_MSG_NE (test16, 0, "There should be some drops.");
600  NS_TEST_ASSERT_MSG_EQ (st.GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK), 0, "There should be zero marks");
601 }
602 
603 void
604 PieQueueDiscTestCase::Enqueue (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt, Ptr<PieQueueDiscTestItem> testAttributes)
605 {
606  Address dest;
607  for (uint32_t i = 0; i < nPkt; i++)
608  {
609  if (testAttributes->m_constAccuProb)
610  {
611  queue->m_accuProb = testAttributes->m_setAccuProb;
612  if (testAttributes->m_checkMaxAccuProb)
613  {
614  CheckMaxAccuProb (queue, testAttributes);
615  }
616  }
617  queue->Enqueue (Create<PieQueueDiscTestItem> (Create<Packet> (size), dest, testAttributes->m_ecnCapable));
618  if (testAttributes->m_checkProb)
619  {
620  CheckDropProb (queue, testAttributes);
621  }
622  if (testAttributes->m_checkAccuProb)
623  {
624  CheckAccuProb (queue, testAttributes);
625  }
626  }
627 }
628 
629 void
631 {
632  double dropProb = queue->m_dropProb;
633  if (testAttributes->m_maxDropProb < dropProb)
634  {
635  testAttributes->m_maxDropProb = dropProb;
636  }
637  if (testAttributes->m_prevDropProb > 0.1)
638  {
639  double currentDiff = dropProb - testAttributes->m_prevDropProb;
640  if (testAttributes->m_maxDropProbDiff < currentDiff)
641  {
642  testAttributes->m_maxDropProbDiff = currentDiff;
643  }
644  }
645  testAttributes->m_prevDropProb = dropProb;
646 }
647 
648 void
650 {
651  double dropProb = queue->m_dropProb;
652  double accuProb = queue->m_accuProb;
653  if (accuProb != 0)
654  {
655  double expectedAccuProb = testAttributes->m_prevAccuProb + dropProb;
656  testAttributes->m_accuProbError = accuProb - expectedAccuProb;
657  }
658  testAttributes->m_prevAccuProb = accuProb;
659 }
660 
661 void
663 {
664  queue->m_dropProb = 0.001;
665  QueueSize queueSize = queue->GetCurrentSize ();
666  if ((queueSize.GetUnit () == QueueSizeUnit::PACKETS && queueSize.GetValue () > 2) || (queueSize.GetUnit () == QueueSizeUnit::BYTES && queueSize.GetValue () > 2000))
667  {
668  testAttributes->m_expectedDrops = testAttributes->m_expectedDrops + 1;
669  }
670 }
671 
672 void
673 PieQueueDiscTestCase::EnqueueWithDelay (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt, Ptr<PieQueueDiscTestItem> testAttributes)
674 {
675  Address dest;
676  double delay = 0.01; // enqueue packets with delay
677  for (uint32_t i = 0; i < nPkt; i++)
678  {
679  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &PieQueueDiscTestCase::Enqueue, this, queue, size, 1, testAttributes);
680  }
681 }
682 
683 void
685 {
686  for (uint32_t i = 0; i < nPkt; i++)
687  {
688  Ptr<QueueDiscItem> item = queue->Dequeue ();
689  }
690 }
691 
692 void
693 PieQueueDiscTestCase::DequeueWithDelay (Ptr<PieQueueDisc> queue, double delay, uint32_t nPkt)
694 {
695  for (uint32_t i = 0; i < nPkt; i++)
696  {
697  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &PieQueueDiscTestCase::Dequeue, this, queue, 1);
698  }
699 }
700 
701 void
703 {
706  Simulator::Destroy ();
707 }
708 
715 static class PieQueueDiscTestSuite : public TestSuite
716 {
717 public:
719  : TestSuite ("pie-queue-disc", UNIT)
720  {
721  AddTestCase (new PieQueueDiscTestCase (), TestCase::QUICK);
722  }
Pie Queue Disc Test Case.
void Dequeue(Ptr< PieQueueDisc > queue, uint32_t nPkt)
Dequeue function.
void RunPieTest(QueueSizeUnit mode)
Run test function.
void CheckMaxAccuProb(Ptr< PieQueueDisc > queue, Ptr< PieQueueDiscTestItem > testAttributes)
Check Maximum Accumulated Drop Probability.
void EnqueueWithDelay(Ptr< PieQueueDisc > queue, uint32_t size, uint32_t nPkt, Ptr< PieQueueDiscTestItem > testAttributes)
Enqueue with delay function.
void CheckAccuProb(Ptr< PieQueueDisc > queue, Ptr< PieQueueDiscTestItem > testAttributes)
Check Accumulated Drop Probability.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void CheckDropProb(Ptr< PieQueueDisc > queue, Ptr< PieQueueDiscTestItem > testAttributes)
Check Drop Probability.
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, Ptr< PieQueueDiscTestItem > testAttributes)
Enqueue function.
Pie Queue Disc Test Item.
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification.
bool m_ecnCapablePacket
ECN capable packet?
PieQueueDiscTestItem(const PieQueueDiscTestItem &)=delete
virtual void AddHeader(void)
Add the header to the packet.
Pie Queue Disc Test Suite.
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:390
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:133
Class for representing queue sizes.
Definition: queue-size.h:95
QueueSizeUnit GetUnit() const
Get the underlying unit.
Definition: queue-size.cc:168
uint32_t GetValue() const
Get the underlying value.
Definition: queue-size.cc:174
AttributeValue implementation for QueueSize.
Definition: queue-size.h:221
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
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
AttributeValue implementation for Time.
Definition: nstime.h:1308
Hold an unsigned integer type.
Definition: uinteger.h:44
QueueSizeUnit
Enumeration of the operating modes of queues.
Definition: queue-size.h:43
@ BYTES
Use number of bytes for queue size.
Definition: queue-size.h:45
@ PACKETS
Use number of packets for queue size.
Definition: queue-size.h:44
#define NS_TEST_ASSERT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report and abort if not.
Definition: test.h:675
#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
#define NS_TEST_ASSERT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report and abort if not.
Definition: test.h:825
PieQueueDiscTestSuite g_pieQueueTestSuite
the test suite
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:186
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
Definition: queue-disc.cc:109
uint32_t GetNMarkedPackets(std::string reason) const
Get the number of packets marked for the given reason.
Definition: queue-disc.cc:151
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:89