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 {
96  return m_ecnCapablePacket;
97 }
98 
105 {
106  public:
108  void DoRun() override;
109 
110  private:
118  void Enqueue(Ptr<PieQueueDisc> queue,
119  uint32_t size,
120  uint32_t nPkt,
121  Ptr<PieQueueDiscTestItem> testAttributes);
130  uint32_t size,
131  uint32_t nPkt,
132  Ptr<PieQueueDiscTestItem> testAttributes);
138  void Dequeue(Ptr<PieQueueDisc> queue, uint32_t nPkt);
145  void DequeueWithDelay(Ptr<PieQueueDisc> queue, double delay, uint32_t nPkt);
150  void RunPieTest(QueueSizeUnit mode);
156  void CheckDropProb(Ptr<PieQueueDisc> queue, Ptr<PieQueueDiscTestItem> testAttributes);
162  void CheckAccuProb(Ptr<PieQueueDisc> queue, Ptr<PieQueueDiscTestItem> testAttributes);
169 };
170 
172  : TestCase("Sanity check on the pie queue disc implementation")
173 {
174 }
175 
176 void
178 {
179  uint32_t pktSize = 0;
180 
181  // 1 for packets; pktSize for bytes
182  uint32_t modeSize = 1;
183 
184  uint32_t qSize = 300;
185  Ptr<PieQueueDisc> queue = CreateObject<PieQueueDisc>();
186 
187  // test 1: simple enqueue/dequeue with defaults, no drops
188  Address dest;
189  // PieQueueDiscItem pointer for attributes
190  Ptr<PieQueueDiscTestItem> testAttributes =
191  Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
192 
193  if (mode == QueueSizeUnit::BYTES)
194  {
195  // pktSize should be same as MeanPktSize to avoid performance gap between byte and packet
196  // mode
197  pktSize = 1000;
198  modeSize = pktSize;
199  qSize = qSize * modeSize;
200  }
201 
203  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
204  true,
205  "Verify that we can actually set the attribute MaxSize");
206 
207  Ptr<Packet> p1;
208  Ptr<Packet> p2;
209  Ptr<Packet> p3;
210  Ptr<Packet> p4;
211  Ptr<Packet> p5;
212  Ptr<Packet> p6;
213  Ptr<Packet> p7;
214  Ptr<Packet> p8;
215  p1 = Create<Packet>(pktSize);
216  p2 = Create<Packet>(pktSize);
217  p3 = Create<Packet>(pktSize);
218  p4 = Create<Packet>(pktSize);
219  p5 = Create<Packet>(pktSize);
220  p6 = Create<Packet>(pktSize);
221  p7 = Create<Packet>(pktSize);
222  p8 = Create<Packet>(pktSize);
223 
224  queue->Initialize();
225  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
226  0 * modeSize,
227  "There should be no packets in there");
228  queue->Enqueue(Create<PieQueueDiscTestItem>(p1, dest, false));
229  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
230  1 * modeSize,
231  "There should be one packet in there");
232  queue->Enqueue(Create<PieQueueDiscTestItem>(p2, dest, false));
233  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
234  2 * modeSize,
235  "There should be two packets in there");
236  queue->Enqueue(Create<PieQueueDiscTestItem>(p3, dest, false));
237  queue->Enqueue(Create<PieQueueDiscTestItem>(p4, dest, false));
238  queue->Enqueue(Create<PieQueueDiscTestItem>(p5, dest, false));
239  queue->Enqueue(Create<PieQueueDiscTestItem>(p6, dest, false));
240  queue->Enqueue(Create<PieQueueDiscTestItem>(p7, dest, false));
241  queue->Enqueue(Create<PieQueueDiscTestItem>(p8, dest, false));
242  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
243  8 * modeSize,
244  "There should be eight packets in there");
245 
246  Ptr<QueueDiscItem> item;
247 
248  item = queue->Dequeue();
249  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the first packet");
250  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
251  7 * modeSize,
252  "There should be seven packets in there");
253  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p1->GetUid(), "was this the first packet ?");
254 
255  item = queue->Dequeue();
256  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the second packet");
257  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
258  6 * modeSize,
259  "There should be six packet in there");
260  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(),
261  p2->GetUid(),
262  "Was this the second packet ?");
263 
264  item = queue->Dequeue();
265  NS_TEST_ASSERT_MSG_NE(item, nullptr, "I want to remove the third packet");
266  NS_TEST_ASSERT_MSG_EQ(queue->GetCurrentSize().GetValue(),
267  5 * modeSize,
268  "There should be five packets in there");
269  NS_TEST_ASSERT_MSG_EQ(item->GetPacket()->GetUid(), p3->GetUid(), "Was this the third packet ?");
270 
271  item = queue->Dequeue();
272  item = queue->Dequeue();
273  item = queue->Dequeue();
274  item = queue->Dequeue();
275  item = queue->Dequeue();
276 
277  item = queue->Dequeue();
278  NS_TEST_ASSERT_MSG_EQ(item, nullptr, "There are really no packets in there");
279 
280  // test 2: more data with defaults, unforced drops but no forced drops
281  queue = CreateObject<PieQueueDisc>();
282  // PieQueueDiscItem pointer for attributes
283  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
284  pktSize = 1000; // pktSize != 0 because DequeueThreshold always works in bytes
286  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
287  true,
288  "Verify that we can actually set the attribute MaxSize");
289  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Tupdate", TimeValue(Seconds(0.03))),
290  true,
291  "Verify that we can actually set the attribute Tupdate");
292  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("DequeueThreshold", UintegerValue(10000)),
293  true,
294  "Verify that we can actually set the attribute DequeueThreshold");
296  queue->SetAttributeFailSafe("QueueDelayReference", TimeValue(Seconds(0.02))),
297  true,
298  "Verify that we can actually set the attribute QueueDelayReference");
299  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxBurstAllowance", TimeValue(Seconds(0.1))),
300  true,
301  "Verify that we can actually set the attribute MaxBurstAllowance");
302  queue->Initialize();
303  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
304  DequeueWithDelay(queue, 0.012, 400);
305  Simulator::Stop(Seconds(8.0));
306  Simulator::Run();
307  QueueDisc::Stats st = queue->GetStats();
308  uint32_t test2 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
309  NS_TEST_ASSERT_MSG_NE(test2, 0, "There should be some unforced drops");
310  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
311  0,
312  "There should be zero forced drops");
313 
314  // test 3: same as test 2, but with higher QueueDelayReference
315  queue = CreateObject<PieQueueDisc>();
316  // PieQueueDiscItem pointer for attributes
317  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
319  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
320  true,
321  "Verify that we can actually set the attribute MaxSize");
322  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Tupdate", TimeValue(Seconds(0.03))),
323  true,
324  "Verify that we can actually set the attribute Tupdate");
325  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("DequeueThreshold", UintegerValue(10000)),
326  true,
327  "Verify that we can actually set the attribute DequeueThreshold");
329  queue->SetAttributeFailSafe("QueueDelayReference", TimeValue(Seconds(0.08))),
330  true,
331  "Verify that we can actually set the attribute QueueDelayReference");
332  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxBurstAllowance", TimeValue(Seconds(0.1))),
333  true,
334  "Verify that we can actually set the attribute MaxBurstAllowance");
335  queue->Initialize();
336  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
337  DequeueWithDelay(queue, 0.012, 400);
338  Simulator::Stop(Seconds(8.0));
339  Simulator::Run();
340  st = queue->GetStats();
341  uint32_t test3 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
342  NS_TEST_ASSERT_MSG_LT(test3, test2, "Test 3 should have less unforced drops than test 2");
343  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
344  0,
345  "There should be zero forced drops");
346 
347  // test 4: same as test 2, but with reduced dequeue rate
348  queue = CreateObject<PieQueueDisc>();
349  // PieQueueDiscItem pointer for attributes
350  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
352  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
353  true,
354  "Verify that we can actually set the attribute MaxSize");
355  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Tupdate", TimeValue(Seconds(0.03))),
356  true,
357  "Verify that we can actually set the attribute Tupdate");
358  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("DequeueThreshold", UintegerValue(10000)),
359  true,
360  "Verify that we can actually set the attribute DequeueThreshold");
362  queue->SetAttributeFailSafe("QueueDelayReference", TimeValue(Seconds(0.02))),
363  true,
364  "Verify that we can actually set the attribute QueueDelayReference");
365  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxBurstAllowance", TimeValue(Seconds(0.1))),
366  true,
367  "Verify that we can actually set the attribute MaxBurstAllowance");
368  queue->Initialize();
369  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
370  DequeueWithDelay(queue, 0.015, 400); // delay between two successive dequeue events is increased
371  Simulator::Stop(Seconds(8.0));
372  Simulator::Run();
373  st = queue->GetStats();
374  uint32_t test4 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
375  NS_TEST_ASSERT_MSG_GT(test4, test2, "Test 4 should have more unforced drops than test 2");
376  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
377  0,
378  "There should be zero forced drops");
379 
380  // test 5: same dequeue rate as test 4, but with higher Tupdate
381  queue = CreateObject<PieQueueDisc>();
382  // PieQueueDiscItem pointer for attributes
383  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
385  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
386  true,
387  "Verify that we can actually set the attribute MaxSize");
388  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("Tupdate", TimeValue(Seconds(0.09))),
389  true,
390  "Verify that we can actually set the attribute Tupdate");
391  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("DequeueThreshold", UintegerValue(10000)),
392  true,
393  "Verify that we can actually set the attribute DequeueThreshold");
395  queue->SetAttributeFailSafe("QueueDelayReference", TimeValue(Seconds(0.02))),
396  true,
397  "Verify that we can actually set the attribute QueueDelayReference");
398  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxBurstAllowance", TimeValue(Seconds(0.1))),
399  true,
400  "Verify that we can actually set the attribute MaxBurstAllowance");
401  queue->Initialize();
402  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
403  DequeueWithDelay(queue, 0.015, 400);
404  Simulator::Stop(Seconds(8.0));
405  Simulator::Run();
406  st = queue->GetStats();
407  uint32_t test5 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
408  NS_TEST_ASSERT_MSG_LT(test5, test4, "Test 5 should have less unforced drops than test 4");
409  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
410  0,
411  "There should be zero forced drops");
412 
413  // test 6: same as test 2, but with UseDequeueRateEstimator enabled
414  queue = CreateObject<PieQueueDisc>();
415  // PieQueueDiscItem pointer for attributes
416  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
418  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
419  true,
420  "Verify that we can actually set the attribute MaxSize");
422  queue->SetAttributeFailSafe("UseDequeueRateEstimator", BooleanValue(true)),
423  true,
424  "Verify that we can actually set the attribute UseTimestamp");
425  queue->Initialize();
426  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
427  DequeueWithDelay(queue, 0.014, 400);
428  Simulator::Stop(Seconds(8.0));
429  Simulator::Run();
430  st = queue->GetStats();
431  uint32_t test6 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
432  NS_TEST_ASSERT_MSG_NE(test6, 0, "There should be some unforced drops");
433  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
434  0,
435  "There should be zero forced drops");
436 
437  // test 7: test with CapDropAdjustment disabled
438  queue = CreateObject<PieQueueDisc>();
439  // PieQueueDiscItem pointer for attributes
440  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
442  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
443  true,
444  "Verify that we can actually set the attribute MaxSize");
445  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseCapDropAdjustment", BooleanValue(false)),
446  true,
447  "Verify that we can actually set the attribute UseCapDropAdjustment");
448  queue->Initialize();
449  testAttributes->m_checkProb = true;
450  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
451  DequeueWithDelay(queue, 0.014, 400);
452  Simulator::Stop(Seconds(8.0));
453  Simulator::Run();
454  st = queue->GetStats();
455  uint32_t test7 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
456  NS_TEST_ASSERT_MSG_NE(test7, 0, "There should be some unforced drops");
457  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
458  0,
459  "There should be zero forced drops");
460  NS_TEST_ASSERT_MSG_GT(testAttributes->m_maxDropProbDiff,
461  0.02,
462  "Maximum increase in drop probability should be greater than 0.02");
463 
464  // test 8: test with CapDropAdjustment enabled
465  queue = CreateObject<PieQueueDisc>();
466  // PieQueueDiscItem pointer for attributes
467  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
469  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
470  true,
471  "Verify that we can actually set the attribute MaxSize");
472  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseCapDropAdjustment", BooleanValue(true)),
473  true,
474  "Verify that we can actually set the attribute UseCapDropAdjustment");
475  queue->Initialize();
476  testAttributes->m_checkProb = true;
477  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
478  DequeueWithDelay(queue, 0.014, 400);
479  Simulator::Stop(Seconds(8.0));
480  Simulator::Run();
481  st = queue->GetStats();
482  uint32_t test8 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
483  NS_TEST_ASSERT_MSG_NE(test8, 0, "There should be some unforced drops");
484  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
485  0,
486  "There should be zero forced drops");
488  testAttributes->m_maxDropProbDiff,
489  0.0200000000000001,
490  "Maximum increase in drop probability should be less than or equal to 0.02");
491 
492  // test 9: PIE queue disc is ECN enabled, but packets are not ECN capable
493  queue = CreateObject<PieQueueDisc>();
494  // PieQueueDiscItem pointer for attributes
495  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
497  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
498  true,
499  "Verify that we can actually set the attribute MaxSize");
500  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
501  true,
502  "Verify that we can actually set the attribute UseEcn");
503  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MarkEcnThreshold", DoubleValue(0.3)),
504  true,
505  "Verify that we can actually set the attribute MarkEcnThreshold");
506  queue->Initialize();
507  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
508  DequeueWithDelay(queue, 0.014, 400);
509  Simulator::Stop(Seconds(8.0));
510  Simulator::Run();
511  st = queue->GetStats();
512  uint32_t test9 = st.GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK);
513  NS_TEST_ASSERT_MSG_EQ(test9, 0, "There should be zero unforced marks");
514  NS_TEST_ASSERT_MSG_NE(st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
515  0,
516  "There should be some unforced drops");
517  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
518  0,
519  "There should be zero forced drops");
520 
521  // test 10: Packets are ECN capable, but PIE queue disc is not ECN enabled
522  queue = CreateObject<PieQueueDisc>();
523  // PieQueueDiscItem pointer for attributes
524  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
526  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
527  true,
528  "Verify that we can actually set the attribute MaxSize");
529  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(false)),
530  true,
531  "Verify that we can actually set the attribute UseEcn");
532  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MarkEcnThreshold", DoubleValue(0.3)),
533  true,
534  "Verify that we can actually set the attribute MarkEcnThreshold");
535  queue->Initialize();
536  testAttributes->m_ecnCapable = true;
537  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
538  DequeueWithDelay(queue, 0.014, 400);
539  Simulator::Stop(Seconds(8.0));
540  Simulator::Run();
541  st = queue->GetStats();
542  uint32_t test10 = st.GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK);
543  NS_TEST_ASSERT_MSG_EQ(test10, 0, "There should be zero unforced marks");
544  NS_TEST_ASSERT_MSG_NE(st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
545  0,
546  "There should be some unforced drops");
547  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
548  0,
549  "There should be zero forced drops");
550 
551  // test 11: Packets and PIE queue disc both are ECN capable
552  queue = CreateObject<PieQueueDisc>();
553  // PieQueueDiscItem pointer for attributes
554  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
556  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
557  true,
558  "Verify that we can actually set the attribute MaxSize");
559  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseEcn", BooleanValue(true)),
560  true,
561  "Verify that we can actually set the attribute UseEcn");
562  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MarkEcnThreshold", DoubleValue(0.3)),
563  true,
564  "Verify that we can actually set the attribute MarkEcnThreshold");
565  queue->Initialize();
566  testAttributes->m_ecnCapable = true;
567  testAttributes->m_checkProb = true;
568  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
569  DequeueWithDelay(queue, 0.014, 400);
570  Simulator::Stop(Seconds(8.0));
571  Simulator::Run();
572  st = queue->GetStats();
573  uint32_t test11 = st.GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK);
574  NS_TEST_ASSERT_MSG_NE(test11, 0, "There should be some unforced marks");
575  // There are unforced drops because the value of m_maxDropProb goes beyond 0.3 in this test.
576  // PIE drops the packets even when they are ECN capable if drop probability is more than 30%.
577  NS_TEST_ASSERT_MSG_NE(st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
578  0,
579  "There should be some unforced drops");
580  // Confirm that m_maxDropProb goes above 0.3 in this test
581  NS_TEST_ASSERT_MSG_GT(testAttributes->m_maxDropProb,
582  0.3,
583  "Maximum Drop probability should be greater than 0.3");
584  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
585  0,
586  "There should be zero forced drops");
587 
588  // test 12: test with derandomization enabled
589  queue = CreateObject<PieQueueDisc>();
590  // PieQueueDiscItem pointer for attributes
591  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
593  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
594  true,
595  "Verify that we can actually set the attribute MaxSize");
596  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseDerandomization", BooleanValue(true)),
597  true,
598  "Verify that we can actually set the attribute UseDerandomization");
599  queue->Initialize();
600  testAttributes->m_checkAccuProb = true;
601  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
602  DequeueWithDelay(queue, 0.014, 400);
603  Simulator::Stop(Seconds(8.0));
604  Simulator::Run();
605  st = queue->GetStats();
606  uint32_t test12 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
607  NS_TEST_ASSERT_MSG_NE(test12, 0, "There should be some unforced drops");
608  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
609  0,
610  "There should be zero forced drops");
611  NS_TEST_ASSERT_MSG_EQ(testAttributes->m_accuProbError,
612  0.0,
613  "There should not be any error in setting accuProb");
614 
615  // test 13: same as test 11 but with accumulated drop probability set below the low threshold
616  queue = CreateObject<PieQueueDisc>();
617  // PieQueueDiscItem pointer for attributes
618  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
620  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
621  true,
622  "Verify that we can actually set the attribute MaxSize");
623  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseDerandomization", BooleanValue(true)),
624  true,
625  "Verify that we can actually set the attribute UseDerandomization");
626  queue->Initialize();
627  testAttributes->m_constAccuProb = true;
628  // Final value of accumulated drop probability to drop packet will be maximum 0.84 while
629  // threshold to drop packet is 0.85
630  testAttributes->m_setAccuProb = -0.16;
631  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
632  DequeueWithDelay(queue, 0.014, 400);
633  Simulator::Stop(Seconds(8.0));
634  Simulator::Run();
635  st = queue->GetStats();
636  uint32_t test13 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
637  NS_TEST_ASSERT_MSG_EQ(test13, 0, "There should be zero unforced drops");
638  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
639  0,
640  "There should be zero forced drops");
641 
642  // test 14: same as test 12 but with accumulated drop probability set above the high threshold
643  queue = CreateObject<PieQueueDisc>();
644  // PieQueueDiscItem pointer for attributes
645  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
647  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
648  true,
649  "Verify that we can actually set the attribute MaxSize");
650  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxBurstAllowance", TimeValue(Seconds(0.0))),
651  true,
652  "Verify that we can actually set the attribute MaxBurstAllowance");
653  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("UseDerandomization", BooleanValue(true)),
654  true,
655  "Verify that we can actually set the attribute UseDerandomization");
656  queue->Initialize();
657  testAttributes->m_constAccuProb = true;
658  testAttributes->m_checkMaxAccuProb = true;
659  // Final value of accumulated drop probability to drop packet will be minimum 8.6 while
660  // threshold to drop packet is 8.5
661  testAttributes->m_setAccuProb = 8.6;
662  EnqueueWithDelay(queue, pktSize, 400, testAttributes);
663  DequeueWithDelay(queue, 0.014, 400);
664  Simulator::Stop(Seconds(8.0));
665  Simulator::Run();
666  st = queue->GetStats();
667  uint32_t test14 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
669  test14,
670  testAttributes->m_expectedDrops,
671  "The number of unforced drops should be equal to number of expected unforced drops");
672  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(PieQueueDisc::FORCED_DROP),
673  0,
674  "There should be zero forced drops");
675 
676  // test 15: tests Active/Inactive feature, ActiveThreshold set to a high value so PIE never
677  // starts and there should not be any drops
678  queue = CreateObject<PieQueueDisc>();
679  // PieQueueDiscItem pointer for attributes
680  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
681  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize)));
682  queue->SetAttributeFailSafe("ActiveThreshold", TimeValue(Seconds(1)));
683  queue->Initialize();
684 
685  EnqueueWithDelay(queue, pktSize, 100, testAttributes);
686  DequeueWithDelay(queue, 0.02, 100);
687  Simulator::Stop(Seconds(8.0));
688  Simulator::Run();
689  st = queue->GetStats();
690  uint32_t test15 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
691  NS_TEST_ASSERT_MSG_EQ(test15, 0, "There should not be any drops.");
692  NS_TEST_ASSERT_MSG_EQ(st.GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK),
693  0,
694  "There should be zero marks");
695 
696  // test 16: tests Active/Inactive feature, ActiveThreshold set to a low value so PIE starts
697  // early and some packets should be dropped.
698  queue = CreateObject<PieQueueDisc>();
699  // PieQueueDiscItem pointer for attributes
700  testAttributes = Create<PieQueueDiscTestItem>(Create<Packet>(pktSize), dest, false);
701  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize)));
702  queue->SetAttributeFailSafe("ActiveThreshold", TimeValue(Seconds(0.001)));
703  queue->Initialize();
704 
705  EnqueueWithDelay(queue, pktSize, 100, testAttributes);
706  DequeueWithDelay(queue, 0.02, 100);
707  Simulator::Stop(Seconds(8.0));
708  Simulator::Run();
709  st = queue->GetStats();
710  uint32_t test16 = st.GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP);
711  NS_TEST_ASSERT_MSG_NE(test16, 0, "There should be some drops.");
712  NS_TEST_ASSERT_MSG_EQ(st.GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK),
713  0,
714  "There should be zero marks");
715 }
716 
717 void
719  uint32_t size,
720  uint32_t nPkt,
721  Ptr<PieQueueDiscTestItem> testAttributes)
722 {
723  Address dest;
724  for (uint32_t i = 0; i < nPkt; i++)
725  {
726  if (testAttributes->m_constAccuProb)
727  {
728  queue->m_accuProb = testAttributes->m_setAccuProb;
729  if (testAttributes->m_checkMaxAccuProb)
730  {
731  CheckMaxAccuProb(queue, testAttributes);
732  }
733  }
734  queue->Enqueue(
735  Create<PieQueueDiscTestItem>(Create<Packet>(size), dest, testAttributes->m_ecnCapable));
736  if (testAttributes->m_checkProb)
737  {
738  CheckDropProb(queue, testAttributes);
739  }
740  if (testAttributes->m_checkAccuProb)
741  {
742  CheckAccuProb(queue, testAttributes);
743  }
744  }
745 }
746 
747 void
749  Ptr<PieQueueDiscTestItem> testAttributes)
750 {
751  double dropProb = queue->m_dropProb;
752  if (testAttributes->m_maxDropProb < dropProb)
753  {
754  testAttributes->m_maxDropProb = dropProb;
755  }
756  if (testAttributes->m_prevDropProb > 0.1)
757  {
758  double currentDiff = dropProb - testAttributes->m_prevDropProb;
759  if (testAttributes->m_maxDropProbDiff < currentDiff)
760  {
761  testAttributes->m_maxDropProbDiff = currentDiff;
762  }
763  }
764  testAttributes->m_prevDropProb = dropProb;
765 }
766 
767 void
769  Ptr<PieQueueDiscTestItem> testAttributes)
770 {
771  double dropProb = queue->m_dropProb;
772  double accuProb = queue->m_accuProb;
773  if (accuProb != 0)
774  {
775  double expectedAccuProb = testAttributes->m_prevAccuProb + dropProb;
776  testAttributes->m_accuProbError = accuProb - expectedAccuProb;
777  }
778  testAttributes->m_prevAccuProb = accuProb;
779 }
780 
781 void
783  Ptr<PieQueueDiscTestItem> testAttributes)
784 {
785  queue->m_dropProb = 0.001;
786  QueueSize queueSize = queue->GetCurrentSize();
787  if ((queueSize.GetUnit() == QueueSizeUnit::PACKETS && queueSize.GetValue() > 2) ||
788  (queueSize.GetUnit() == QueueSizeUnit::BYTES && queueSize.GetValue() > 2000))
789  {
790  testAttributes->m_expectedDrops = testAttributes->m_expectedDrops + 1;
791  }
792 }
793 
794 void
796  uint32_t size,
797  uint32_t nPkt,
798  Ptr<PieQueueDiscTestItem> testAttributes)
799 {
800  Address dest;
801  double delay = 0.01; // enqueue packets with delay
802  for (uint32_t i = 0; i < nPkt; i++)
803  {
804  Simulator::Schedule(Time(Seconds((i + 1) * delay)),
806  this,
807  queue,
808  size,
809  1,
810  testAttributes);
811  }
812 }
813 
814 void
816 {
817  for (uint32_t i = 0; i < nPkt; i++)
818  {
819  Ptr<QueueDiscItem> item = queue->Dequeue();
820  }
821 }
822 
823 void
825 {
826  for (uint32_t i = 0; i < nPkt; i++)
827  {
828  Simulator::Schedule(Time(Seconds((i + 1) * delay)),
830  this,
831  queue,
832  1);
833  }
834 }
835 
836 void
838 {
841  Simulator::Destroy();
842 }
843 
849 static class PieQueueDiscTestSuite : public TestSuite
850 {
851  public:
853  : TestSuite("pie-queue-disc", UNIT)
854  {
855  AddTestCase(new PieQueueDiscTestCase(), TestCase::QUICK);
856  }
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:101
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
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:301
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
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:1326
PieQueueDiscTestSuite g_pieQueueTestSuite
the test suite
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:839
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
std::ofstream queueSize
uint32_t pktSize
packet size used for the simulation (in bytes)