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