A Discrete-Event Network Simulator
API
pie-queue-disc-test-suite.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 NITK Surathkal
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Authors: Shravya Ks <shravya.ks0@gmail.com>
18  * Smriti Murali <m.smriti.95@gmail.com>
19  * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
20  *
21  */
22 
23 #include "ns3/double.h"
24 #include "ns3/log.h"
25 #include "ns3/packet.h"
26 #include "ns3/pie-queue-disc.h"
27 #include "ns3/simulator.h"
28 #include "ns3/string.h"
29 #include "ns3/test.h"
30 #include "ns3/uinteger.h"
31 
32 using namespace ns3;
33 
40 {
41  public:
49  PieQueueDiscTestItem(Ptr<Packet> p, const Address& addr, bool ecnCapable);
50 
51  // Delete default constructor, copy constructor and assignment operator to avoid misuse
55 
56  void AddHeader() override;
57  bool Mark() override;
58 
59  // ** Variables for testing m_isCapDropAdjustment
60  double m_maxDropProbDiff =
61  0.0;
62  double m_prevDropProb = 0.0;
63  bool m_checkProb = false;
64 
65  // ** Variable for testing ECN
66  double m_maxDropProb = 0.0;
67  bool m_ecnCapable = false;
68 
69  // ** Variables for testing Derandomization
70  bool m_checkAccuProb = false;
71  bool m_constAccuProb = false;
72  bool m_checkMaxAccuProb = false;
73  double m_accuProbError = 0.0;
74  double m_prevAccuProb = 0.0;
75  double m_setAccuProb = 0.0;
76  uint32_t m_expectedDrops = 0;
77 
78  private:
80 };
81 
83  : QueueDiscItem(p, addr, 0),
84  m_ecnCapablePacket(ecnCapable)
85 {
86 }
87 
88 void
90 {
91 }
92 
93 bool
95 {
97  {
98  return true;
99  }
100  return false;
101 }
102 
109 {
110  public:
112  void DoRun() override;
113 
114  private:
122  void Enqueue(Ptr<PieQueueDisc> queue,
123  uint32_t size,
124  uint32_t nPkt,
125  Ptr<PieQueueDiscTestItem> testAttributes);
134  uint32_t size,
135  uint32_t nPkt,
136  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);
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  // test 1: simple enqueue/dequeue with defaults, no drops
192  Address dest;
193  // PieQueueDiscItem pointer for attributes
194  Ptr<PieQueueDiscTestItem> testAttributes =
195  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
200  // mode
201  pktSize = 1000;
202  modeSize = pktSize;
203  qSize = qSize * modeSize;
204  }
205 
207  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
208  true,
209  "Verify that we can actually set the attribute MaxSize");
210 
211  Ptr<Packet> p1;
212  Ptr<Packet> p2;
213  Ptr<Packet> p3;
214  Ptr<Packet> p4;
215  Ptr<Packet> p5;
216  Ptr<Packet> p6;
217  Ptr<Packet> p7;
218  Ptr<Packet> p8;
219  p1 = Create<Packet>(pktSize);
220  p2 = Create<Packet>(pktSize);
221  p3 = Create<Packet>(pktSize);
222  p4 = Create<Packet>(pktSize);
223  p5 = Create<Packet>(pktSize);
224  p6 = Create<Packet>(pktSize);
225  p7 = Create<Packet>(pktSize);
226  p8 = Create<Packet>(pktSize);
227 
228  queue->Initialize();
229  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
230  0 * modeSize,
231  "There should be no packets in there");
232  queue->Enqueue(Create<PieQueueDiscTestItem>(p1, dest, false));
233  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
234  1 * modeSize,
235  "There should be one packet in there");
236  queue->Enqueue(Create<PieQueueDiscTestItem>(p2, dest, false));
237  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
238  2 * modeSize,
239  "There should be two packets in there");
240  queue->Enqueue(Create<PieQueueDiscTestItem>(p3, dest, false));
241  queue->Enqueue(Create<PieQueueDiscTestItem>(p4, dest, false));
242  queue->Enqueue(Create<PieQueueDiscTestItem>(p5, dest, false));
243  queue->Enqueue(Create<PieQueueDiscTestItem>(p6, dest, false));
244  queue->Enqueue(Create<PieQueueDiscTestItem>(p7, dest, false));
245  queue->Enqueue(Create<PieQueueDiscTestItem>(p8, dest, false));
246  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
247  8 * modeSize,
248  "There should be eight packets in there");
249 
250  Ptr<QueueDiscItem> item;
251 
252  item = queue->Dequeue();
253  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the first packet");
254  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
255  7 * modeSize,
256  "There should be seven packets in there");
257  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p1->GetUid(), "was this the first packet ?");
258 
259  item = queue->Dequeue();
260  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the second packet");
261  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
262  6 * modeSize,
263  "There should be six packet in there");
264  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(),
265  p2->GetUid(),
266  "Was this the second packet ?");
267 
268  item = queue->Dequeue();
269  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the third packet");
270  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
271  5 * modeSize,
272  "There should be five packets in there");
273  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p3->GetUid(), "Was this the third packet ?");
274 
275  item = queue->Dequeue();
276  item = queue->Dequeue();
277  item = queue->Dequeue();
278  item = queue->Dequeue();
279  item = queue->Dequeue();
280 
281  item = queue->Dequeue();
282  NS_TEST_ASSERT_MSG_EQ(item, nullptr, "There are really no packets in there");
283 
284  // test 2: more data with defaults, unforced drops but no forced drops
285  queue = CreateObject<PieQueueDisc>();
286  // PieQueueDiscItem pointer for attributes
287  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
288  pktSize = 1000; // pktSize != 0 because DequeueThreshold always works in bytes
290  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
291  true,
292  "Verify that we can actually set the attribute MaxSize");
293  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Tupdate", TimeValue(Seconds(0.03))),
294  true,
295  "Verify that we can actually set the attribute Tupdate");
296  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("DequeueThreshold", UintegerValue(10000)),
297  true,
298  "Verify that we can actually set the attribute DequeueThreshold");
300  queue->SetAttributeFailSafe("QueueDelayReference", TimeValue(Seconds(0.02))),
301  true,
302  "Verify that we can actually set the attribute QueueDelayReference");
303  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxBurstAllowance", TimeValue(Seconds(0.1))),
304  true,
305  "Verify that we can actually set the attribute MaxBurstAllowance");
306  queue->Initialize();
307  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
308  DequeueWithDelay(queue, 0.012, 400);
309  Simulator::Stop(Seconds(8.0));
310  Simulator::Run();
311  QueueDisc::Stats st = queue->GetStats();
312  uint32_t test2 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
313  NS_TEST_ASSERT_MSG_NE(test2, 0, "There should be some unforced drops");
314  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
315  0,
316  "There should be zero forced drops");
317 
318  // test 3: same as test 2, but with higher QueueDelayReference
319  queue = CreateObject<PieQueueDisc>();
320  // PieQueueDiscItem pointer for attributes
321  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
323  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
324  true,
325  "Verify that we can actually set the attribute MaxSize");
326  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Tupdate", TimeValue(Seconds(0.03))),
327  true,
328  "Verify that we can actually set the attribute Tupdate");
329  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("DequeueThreshold", UintegerValue(10000)),
330  true,
331  "Verify that we can actually set the attribute DequeueThreshold");
333  queue->SetAttributeFailSafe("QueueDelayReference", TimeValue(Seconds(0.08))),
334  true,
335  "Verify that we can actually set the attribute QueueDelayReference");
336  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxBurstAllowance", TimeValue(Seconds(0.1))),
337  true,
338  "Verify that we can actually set the attribute MaxBurstAllowance");
339  queue->Initialize();
340  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
341  DequeueWithDelay(queue, 0.012, 400);
342  Simulator::Stop(Seconds(8.0));
343  Simulator::Run();
344  st = queue->GetStats();
345  uint32_t test3 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
346  NS_TEST_ASSERT_MSG_LT(test3, test2, "Test 3 should have less unforced drops than test 2");
347  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
348  0,
349  "There should be zero forced drops");
350 
351  // test 4: same as test 2, but with reduced dequeue rate
352  queue = CreateObject<PieQueueDisc>();
353  // PieQueueDiscItem pointer for attributes
354  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
356  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
357  true,
358  "Verify that we can actually set the attribute MaxSize");
359  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Tupdate", TimeValue(Seconds(0.03))),
360  true,
361  "Verify that we can actually set the attribute Tupdate");
362  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("DequeueThreshold", UintegerValue(10000)),
363  true,
364  "Verify that we can actually set the attribute DequeueThreshold");
366  queue->SetAttributeFailSafe("QueueDelayReference", TimeValue(Seconds(0.02))),
367  true,
368  "Verify that we can actually set the attribute QueueDelayReference");
369  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxBurstAllowance", TimeValue(Seconds(0.1))),
370  true,
371  "Verify that we can actually set the attribute MaxBurstAllowance");
372  queue->Initialize();
373  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
374  DequeueWithDelay(queue, 0.015, 400); // delay between two successive dequeue events is increased
375  Simulator::Stop(Seconds(8.0));
376  Simulator::Run();
377  st = queue->GetStats();
378  uint32_t test4 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
379  NS_TEST_ASSERT_MSG_GT(test4, test2, "Test 4 should have more unforced drops than test 2");
380  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
381  0,
382  "There should be zero forced drops");
383 
384  // test 5: same dequeue rate as test 4, but with higher Tupdate
385  queue = CreateObject<PieQueueDisc>();
386  // PieQueueDiscItem pointer for attributes
387  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
389  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
390  true,
391  "Verify that we can actually set the attribute MaxSize");
392  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Tupdate", TimeValue(Seconds(0.09))),
393  true,
394  "Verify that we can actually set the attribute Tupdate");
395  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("DequeueThreshold", UintegerValue(10000)),
396  true,
397  "Verify that we can actually set the attribute DequeueThreshold");
399  queue->SetAttributeFailSafe("QueueDelayReference", TimeValue(Seconds(0.02))),
400  true,
401  "Verify that we can actually set the attribute QueueDelayReference");
402  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxBurstAllowance", TimeValue(Seconds(0.1))),
403  true,
404  "Verify that we can actually set the attribute MaxBurstAllowance");
405  queue->Initialize();
406  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
407  DequeueWithDelay(queue, 0.015, 400);
408  Simulator::Stop(Seconds(8.0));
409  Simulator::Run();
410  st = queue->GetStats();
411  uint32_t test5 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
412  NS_TEST_ASSERT_MSG_LT(test5, test4, "Test 5 should have less unforced drops than test 4");
413  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
414  0,
415  "There should be zero forced drops");
416 
417  // test 6: same as test 2, but with UseDequeueRateEstimator enabled
418  queue = CreateObject<PieQueueDisc>();
419  // PieQueueDiscItem pointer for attributes
420  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
422  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
423  true,
424  "Verify that we can actually set the attribute MaxSize");
426  queue->SetAttributeFailSafe("UseDequeueRateEstimator", BooleanValue(true)),
427  true,
428  "Verify that we can actually set the attribute UseTimestamp");
429  queue->Initialize();
430  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
431  DequeueWithDelay(queue, 0.014, 400);
432  Simulator::Stop(Seconds(8.0));
433  Simulator::Run();
434  st = queue->GetStats();
435  uint32_t test6 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
436  NS_TEST_ASSERT_MSG_NE(test6, 0, "There should be some unforced drops");
437  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
438  0,
439  "There should be zero forced drops");
440 
441  // test 7: test with CapDropAdjustment disabled
442  queue = CreateObject<PieQueueDisc>();
443  // PieQueueDiscItem pointer for attributes
444  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
446  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
447  true,
448  "Verify that we can actually set the attribute MaxSize");
449  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseCapDropAdjustment", BooleanValue(false)),
450  true,
451  "Verify that we can actually set the attribute UseCapDropAdjustment");
452  queue->Initialize();
453  testAttributes->m_checkProb = true;
454  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
455  DequeueWithDelay(queue, 0.014, 400);
456  Simulator::Stop(Seconds(8.0));
457  Simulator::Run();
458  st = queue->GetStats();
459  uint32_t test7 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
460  NS_TEST_ASSERT_MSG_NE(test7, 0, "There should be some unforced drops");
461  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
462  0,
463  "There should be zero forced drops");
464  NS_TEST_ASSERT_MSG_GT(testAttributes->m_maxDropProbDiff,
465  0.02,
466  "Maximum increase in drop probability should be greater than 0.02");
467 
468  // test 8: test with CapDropAdjustment enabled
469  queue = CreateObject<PieQueueDisc>();
470  // PieQueueDiscItem pointer for attributes
471  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
473  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
474  true,
475  "Verify that we can actually set the attribute MaxSize");
476  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseCapDropAdjustment", BooleanValue(true)),
477  true,
478  "Verify that we can actually set the attribute UseCapDropAdjustment");
479  queue->Initialize();
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 test8 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
487  NS_TEST_ASSERT_MSG_NE(test8, 0, "There should be some unforced drops");
488  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
489  0,
490  "There should be zero forced drops");
492  testAttributes->m_maxDropProbDiff,
493  0.0200000000000001,
494  "Maximum increase in drop probability should be less than or equal to 0.02");
495 
496  // test 9: PIE queue disc is ECN enabled, but packets are not ECN capable
497  queue = CreateObject<PieQueueDisc>();
498  // PieQueueDiscItem pointer for attributes
499  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
501  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
502  true,
503  "Verify that we can actually set the attribute MaxSize");
504  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
505  true,
506  "Verify that we can actually set the attribute UseEcn");
507  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MarkEcnThreshold", DoubleValue(0.3)),
508  true,
509  "Verify that we can actually set the attribute MarkEcnThreshold");
510  queue->Initialize();
511  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
512  DequeueWithDelay(queue, 0.014, 400);
513  Simulator::Stop(Seconds(8.0));
514  Simulator::Run();
515  st = queue->GetStats();
516  uint32_t test9 = st.GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK);
517  NS_TEST_ASSERT_MSG_EQ(test9, 0, "There should be zero unforced marks");
518  NS_TEST_ASSERT_MSG_NE(st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
519  0,
520  "There should be some unforced drops");
521  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
522  0,
523  "There should be zero forced drops");
524 
525  // test 10: Packets are ECN capable, but PIE queue disc is not ECN enabled
526  queue = CreateObject<PieQueueDisc>();
527  // PieQueueDiscItem pointer for attributes
528  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
530  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
531  true,
532  "Verify that we can actually set the attribute MaxSize");
533  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(false)),
534  true,
535  "Verify that we can actually set the attribute UseEcn");
536  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MarkEcnThreshold", DoubleValue(0.3)),
537  true,
538  "Verify that we can actually set the attribute MarkEcnThreshold");
539  queue->Initialize();
540  testAttributes->m_ecnCapable = true;
541  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
542  DequeueWithDelay(queue, 0.014, 400);
543  Simulator::Stop(Seconds(8.0));
544  Simulator::Run();
545  st = queue->GetStats();
546  uint32_t test10 = st.GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK);
547  NS_TEST_ASSERT_MSG_EQ(test10, 0, "There should be zero unforced marks");
548  NS_TEST_ASSERT_MSG_NE(st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
549  0,
550  "There should be some unforced drops");
551  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
552  0,
553  "There should be zero forced drops");
554 
555  // test 11: Packets and PIE queue disc both are ECN capable
556  queue = CreateObject<PieQueueDisc>();
557  // PieQueueDiscItem pointer for attributes
558  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
560  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
561  true,
562  "Verify that we can actually set the attribute MaxSize");
563  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
564  true,
565  "Verify that we can actually set the attribute UseEcn");
566  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MarkEcnThreshold", DoubleValue(0.3)),
567  true,
568  "Verify that we can actually set the attribute MarkEcnThreshold");
569  queue->Initialize();
570  testAttributes->m_ecnCapable = true;
571  testAttributes->m_checkProb = true;
572  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
573  DequeueWithDelay(queue, 0.014, 400);
574  Simulator::Stop(Seconds(8.0));
575  Simulator::Run();
576  st = queue->GetStats();
577  uint32_t test11 = st.GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK);
578  NS_TEST_ASSERT_MSG_NE(test11, 0, "There should be some unforced marks");
579  // There are unforced drops because the value of m_maxDropProb goes beyond 0.3 in this test.
580  // PIE drops the packets even when they are ECN capable if drop probability is more than 30%.
581  NS_TEST_ASSERT_MSG_NE(st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
582  0,
583  "There should be some unforced drops");
584  // Confirm that m_maxDropProb goes above 0.3 in this test
585  NS_TEST_ASSERT_MSG_GT(testAttributes->m_maxDropProb,
586  0.3,
587  "Maximum Drop probability should be greater than 0.3");
588  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
589  0,
590  "There should be zero forced drops");
591 
592  // test 12: test with derandomization enabled
593  queue = CreateObject<PieQueueDisc>();
594  // PieQueueDiscItem pointer for attributes
595  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
597  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
598  true,
599  "Verify that we can actually set the attribute MaxSize");
600  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseDerandomization", BooleanValue(true)),
601  true,
602  "Verify that we can actually set the attribute UseDerandomization");
603  queue->Initialize();
604  testAttributes->m_checkAccuProb = true;
605  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
606  DequeueWithDelay(queue, 0.014, 400);
607  Simulator::Stop(Seconds(8.0));
608  Simulator::Run();
609  st = queue->GetStats();
610  uint32_t test12 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
611  NS_TEST_ASSERT_MSG_NE(test12, 0, "There should be some unforced drops");
612  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
613  0,
614  "There should be zero forced drops");
615  NS_TEST_ASSERT_MSG_EQ(testAttributes->m_accuProbError,
616  0.0,
617  "There should not be any error in setting accuProb");
618 
619  // test 13: same as test 11 but with accumulated drop probability set below the low threshold
620  queue = CreateObject<PieQueueDisc>();
621  // PieQueueDiscItem pointer for attributes
622  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
624  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
625  true,
626  "Verify that we can actually set the attribute MaxSize");
627  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseDerandomization", BooleanValue(true)),
628  true,
629  "Verify that we can actually set the attribute UseDerandomization");
630  queue->Initialize();
631  testAttributes->m_constAccuProb = true;
632  // Final value of accumulated drop probability to drop packet will be maximum 0.84 while
633  // threshold to drop packet is 0.85
634  testAttributes->m_setAccuProb = -0.16;
635  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
636  DequeueWithDelay(queue, 0.014, 400);
637  Simulator::Stop(Seconds(8.0));
638  Simulator::Run();
639  st = queue->GetStats();
640  uint32_t test13 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
641  NS_TEST_ASSERT_MSG_EQ(test13, 0, "There should be zero unforced drops");
642  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
643  0,
644  "There should be zero forced drops");
645 
646  // test 14: same as test 12 but with accumulated drop probability set above the high threshold
647  queue = CreateObject<PieQueueDisc>();
648  // PieQueueDiscItem pointer for attributes
649  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
651  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
652  true,
653  "Verify that we can actually set the attribute MaxSize");
654  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxBurstAllowance", TimeValue(Seconds(0.0))),
655  true,
656  "Verify that we can actually set the attribute MaxBurstAllowance");
657  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseDerandomization", BooleanValue(true)),
658  true,
659  "Verify that we can actually set the attribute UseDerandomization");
660  queue->Initialize();
661  testAttributes->m_constAccuProb = true;
662  testAttributes->m_checkMaxAccuProb = true;
663  // Final value of accumulated drop probability to drop packet will be minimum 8.6 while
664  // threshold to drop packet is 8.5
665  testAttributes->m_setAccuProb = 8.6;
666  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
667  DequeueWithDelay(queue, 0.014, 400);
668  Simulator::Stop(Seconds(8.0));
669  Simulator::Run();
670  st = queue->GetStats();
671  uint32_t test14 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
673  test14,
674  testAttributes->m_expectedDrops,
675  "The number of unforced drops should be equal to number of expected unforced drops");
676  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
677  0,
678  "There should be zero forced drops");
679 
680  // test 15: tests Active/Inactive feature, ActiveThreshold set to a high value so PIE never
681  // starts and there should not be any drops
682  queue = CreateObject<PieQueueDisc>();
683  // PieQueueDiscItem pointer for attributes
684  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
685  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize)));
686  queue->SetAttributeFailSafe("ActiveThreshold", TimeValue(Seconds(1)));
687  queue->Initialize();
688 
689  EnqueueWithDelay(queue, pktSize, 100, testAttributes);
690  DequeueWithDelay(queue, 0.02, 100);
691  Simulator::Stop(Seconds(8.0));
692  Simulator::Run();
693  st = queue->GetStats();
694  uint32_t test15 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
695  NS_TEST_ASSERT_MSG_EQ(test15, 0, "There should not be any drops.");
696  NS_TEST_ASSERT_MSG_EQ(st.GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK),
697  0,
698  "There should be zero marks");
699 
700  // test 16: tests Active/Inactive feature, ActiveThreshold set to a low value so PIE starts
701  // early and some packets should be dropped.
702  queue = CreateObject<PieQueueDisc>();
703  // PieQueueDiscItem pointer for attributes
704  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
705  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize)));
706  queue->SetAttributeFailSafe("ActiveThreshold", TimeValue(Seconds(0.001)));
707  queue->Initialize();
708 
709  EnqueueWithDelay(queue, pktSize, 100, testAttributes);
710  DequeueWithDelay(queue, 0.02, 100);
711  Simulator::Stop(Seconds(8.0));
712  Simulator::Run();
713  st = queue->GetStats();
714  uint32_t test16 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
715  NS_TEST_ASSERT_MSG_NE(test16, 0, "There should be some drops.");
716  NS_TEST_ASSERT_MSG_EQ(st.GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK),
717  0,
718  "There should be zero marks");
719 }
720 
721 void
723  uint32_t size,
724  uint32_t nPkt,
725  Ptr<PieQueueDiscTestItem> testAttributes)
726 {
727  Address dest;
728  for (uint32_t i = 0; i < nPkt; i++)
729  {
730  if (testAttributes->m_constAccuProb)
731  {
732  queue->m_accuProb = testAttributes->m_setAccuProb;
733  if (testAttributes->m_checkMaxAccuProb)
734  {
735  CheckMaxAccuProb(queue, testAttributes);
736  }
737  }
738  queue->Enqueue(
739  Create<PieQueueDiscTestItem>(Create<Packet>(size), dest, testAttributes->m_ecnCapable));
740  if (testAttributes->m_checkProb)
741  {
742  CheckDropProb(queue, testAttributes);
743  }
744  if (testAttributes->m_checkAccuProb)
745  {
746  CheckAccuProb(queue, testAttributes);
747  }
748  }
749 }
750 
751 void
753  Ptr<PieQueueDiscTestItem> testAttributes)
754 {
755  double dropProb = queue->m_dropProb;
756  if (testAttributes->m_maxDropProb < dropProb)
757  {
758  testAttributes->m_maxDropProb = dropProb;
759  }
760  if (testAttributes->m_prevDropProb > 0.1)
761  {
762  double currentDiff = dropProb - testAttributes->m_prevDropProb;
763  if (testAttributes->m_maxDropProbDiff < currentDiff)
764  {
765  testAttributes->m_maxDropProbDiff = currentDiff;
766  }
767  }
768  testAttributes->m_prevDropProb = dropProb;
769 }
770 
771 void
773  Ptr<PieQueueDiscTestItem> testAttributes)
774 {
775  double dropProb = queue->m_dropProb;
776  double accuProb = queue->m_accuProb;
777  if (accuProb != 0)
778  {
779  double expectedAccuProb = testAttributes->m_prevAccuProb + dropProb;
780  testAttributes->m_accuProbError = accuProb - expectedAccuProb;
781  }
782  testAttributes->m_prevAccuProb = accuProb;
783 }
784 
785 void
787  Ptr<PieQueueDiscTestItem> testAttributes)
788 {
789  queue->m_dropProb = 0.001;
790  QueueSize queueSize = queue->GetCurrentSize();
791  if ((queueSize.GetUnit() == QueueSizeUnit::PACKETS && queueSize.GetValue() > 2) ||
792  (queueSize.GetUnit() == QueueSizeUnit::BYTES && queueSize.GetValue() > 2000))
793  {
794  testAttributes->m_expectedDrops = testAttributes->m_expectedDrops + 1;
795  }
796 }
797 
798 void
800  uint32_t size,
801  uint32_t nPkt,
802  Ptr<PieQueueDiscTestItem> testAttributes)
803 {
804  Address dest;
805  double delay = 0.01; // enqueue packets with delay
806  for (uint32_t i = 0; i < nPkt; i++)
807  {
808  Simulator::Schedule(Time(Seconds((i + 1) * delay)),
810  this,
811  queue,
812  size,
813  1,
814  testAttributes);
815  }
816 }
817 
818 void
820 {
821  for (uint32_t i = 0; i < nPkt; i++)
822  {
823  Ptr<QueueDiscItem> item = queue->Dequeue();
824  }
825 }
826 
827 void
829 {
830  for (uint32_t i = 0; i < nPkt; i++)
831  {
832  Simulator::Schedule(Time(Seconds((i + 1) * delay)),
834  this,
835  queue,
836  1);
837  }
838 }
839 
840 void
842 {
845  Simulator::Destroy();
846 }
847 
853 static class PieQueueDiscTestSuite : public TestSuite
854 {
855  public:
857  : TestSuite("pie-queue-disc", UNIT)
858  {
859  AddTestCase(new PieQueueDiscTestCase(), TestCase::QUICK);
860  }
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.
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.
void DoRun() override
Implementation to actually run this TestCase.
Pie Queue Disc Test Item.
bool m_ecnCapablePacket
ECN capable packet?
PieQueueDiscTestItem(const PieQueueDiscTestItem &)=delete
PieQueueDiscTestItem()=delete
PieQueueDiscTestItem & operator=(const PieQueueDiscTestItem &)=delete
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.
Pie Queue Disc Test Suite.
a polymophic address class
Definition: address.h:100
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:42
uint64_t GetUid() const
Returns the packet's Uid.
Definition: packet.cc:412
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:96
QueueSizeUnit GetUnit() const
Get the underlying unit.
Definition: queue-size.cc:176
uint32_t GetValue() const
Get the underlying value.
Definition: queue-size.cc:183
AttributeValue implementation for QueueSize.
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
AttributeValue implementation for Time.
Definition: nstime.h:1423
Hold an unsigned integer type.
Definition: uinteger.h:45
QueueSizeUnit
Enumeration of the operating modes of queues.
Definition: queue-size.h:44
@ BYTES
Use number of bytes for queue size.
Definition: queue-size.h:46
@ PACKETS
Use number of packets for queue size.
Definition: queue-size.h:45
#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:709
#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:144
#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:564
#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:874
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
PieQueueDiscTestSuite g_pieQueueTestSuite
the test suite
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:848
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:188
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
Definition: queue-disc.cc:111
uint32_t GetNMarkedPackets(std::string reason) const
Get the number of packets marked for the given reason.
Definition: queue-disc.cc:153
uint32_t pktSize
packet size used for the simulation (in bytes)