A Discrete-Event Network Simulator
API
cobalt-queue-disc-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2019 NITK Surathkal
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Ported to ns-3 by: Vignesh Kannan <vignesh2496@gmail.com>
19  * Harsh Lara <harshapplefan@gmail.com>
20  * Jendaipou Palmei <jendaipoupalmei@gmail.com>
21  * Shefali Gupta <shefaligups11@gmail.com>
22  * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
23  */
24 
25 #include "ns3/test.h"
26 #include "ns3/cobalt-queue-disc.h"
27 #include "ns3/packet.h"
28 #include "ns3/uinteger.h"
29 #include "ns3/string.h"
30 #include "ns3/double.h"
31 #include "ns3/log.h"
32 #include "ns3/simulator.h"
33 
34 using namespace ns3;
42 {
43 public:
52  CobaltQueueDiscTestItem (Ptr<Packet> p, const Address & addr,uint16_t protocol, bool ecnCapable);
53  virtual ~CobaltQueueDiscTestItem ();
54  virtual void AddHeader (void);
55  virtual bool Mark (void);
56 
57 private:
71 };
72 
73 CobaltQueueDiscTestItem::CobaltQueueDiscTestItem (Ptr<Packet> p, const Address & addr,uint16_t protocol, bool ecnCapable)
74  : QueueDiscItem (p, addr, ecnCapable),
75  m_ecnCapablePacket (ecnCapable)
76 {
77 }
78 
80 {
81 }
82 
83 void
85 {
86 }
87 
88 bool
90 {
92  {
93  return true;
94  }
95  return false;
96 }
97 
105 {
106 public:
113  virtual void DoRun (void);
114 
123 private:
125 };
126 
128  : TestCase ("Basic enqueue and dequeue operations, and attribute setting" + std::to_string (mode))
129 {
130  m_mode = mode;
131 }
132 
133 void
135 {
136  Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
137 
138  uint32_t pktSize = 1000;
139  uint32_t modeSize = 0;
140 
141  Address dest;
142 
143  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Interval", StringValue ("50ms")), true,
144  "Verify that we can actually set the attribute Interval");
145  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Target", StringValue ("4ms")), true,
146  "Verify that we can actually set the attribute Target");
147  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
148  "Disable Blue enhancement");
149 
151  {
152  modeSize = pktSize;
153  }
154  else if (m_mode == QueueSizeUnit::PACKETS)
155  {
156  modeSize = 1;
157  }
158  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 1500))),
159  true, "Verify that we can actually set the attribute MaxSize");
160  queue->Initialize ();
161 
162  Ptr<Packet> p1, p2, p3, p4, p5, p6;
163  p1 = Create<Packet> (pktSize);
164  p2 = Create<Packet> (pktSize);
165  p3 = Create<Packet> (pktSize);
166  p4 = Create<Packet> (pktSize);
167  p5 = Create<Packet> (pktSize);
168  p6 = Create<Packet> (pktSize);
169 
170  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 0 * modeSize, "There should be no packets in queue");
171  queue->Enqueue (Create<CobaltQueueDiscTestItem> (p1, dest,0, false));
172  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 1 * modeSize, "There should be one packet in queue");
173  queue->Enqueue (Create<CobaltQueueDiscTestItem> (p2, dest,0, false));
174  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 2 * modeSize, "There should be two packets in queue");
175  queue->Enqueue (Create<CobaltQueueDiscTestItem> (p3, dest,0, false));
176  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 3 * modeSize, "There should be three packets in queue");
177  queue->Enqueue (Create<CobaltQueueDiscTestItem> (p4, dest,0, false));
178  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 4 * modeSize, "There should be four packets in queue");
179  queue->Enqueue (Create<CobaltQueueDiscTestItem> (p5, dest,0, false));
180  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 5 * modeSize, "There should be five packets in queue");
181  queue->Enqueue (Create<CobaltQueueDiscTestItem> (p6, dest,0, false));
182  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 6 * modeSize, "There should be six packets in queue");
183 
184  NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::OVERLIMIT_DROP), 0, "There should be no packets being dropped due to full queue");
185 
186  Ptr<QueueDiscItem> item;
187 
188  item = queue->Dequeue ();
189  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the first packet");
190  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 5 * modeSize, "There should be five packets in queue");
191  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p1->GetUid (), "was this the first packet ?");
192 
193  item = queue->Dequeue ();
194  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the second packet");
195  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 4 * modeSize, "There should be four packets in queue");
196  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p2->GetUid (), "Was this the second packet ?");
197 
198  item = queue->Dequeue ();
199  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the third packet");
200  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 3 * modeSize, "There should be three packets in queue");
201  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p3->GetUid (), "Was this the third packet ?");
202 
203  item = queue->Dequeue ();
204  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the forth packet");
205  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 2 * modeSize, "There should be two packets in queue");
206  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p4->GetUid (), "Was this the fourth packet ?");
207 
208  item = queue->Dequeue ();
209  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the fifth packet");
210  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 1 * modeSize, "There should be one packet in queue");
211  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p5->GetUid (), "Was this the fifth packet ?");
212 
213  item = queue->Dequeue ();
214  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the last packet");
215  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 0 * modeSize, "There should be zero packet in queue");
216  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p6->GetUid (), "Was this the sixth packet ?");
217 
218  item = queue->Dequeue ();
219  NS_TEST_EXPECT_MSG_EQ ((item == 0), true, "There are really no packets in queue");
220 
221  NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should be no packet drops according to Cobalt algorithm");
222 }
223 
231 {
232 public:
234  virtual void DoRun (void);
241  void Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt);
246  void RunDropTest (QueueSizeUnit mode);
247 
248  void EnqueueWithDelay (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt);
249 
250 };
251 
253  : TestCase ("Drop tests verification for both packets and bytes mode")
254 {
255 }
256 
257 void
259 
260 {
261  uint32_t pktSize = 1500;
262  uint32_t modeSize = 0;
263  Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
264 
265  if (mode == QueueSizeUnit::BYTES)
266  {
267  modeSize = pktSize;
268  }
269  else if (mode == QueueSizeUnit::PACKETS)
270  {
271  modeSize = 1;
272  }
273 
274  queue = CreateObject<CobaltQueueDisc> ();
275  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, modeSize * 100))),
276  true, "Verify that we can actually set the attribute MaxSize");
277  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
278  "Disable Blue enhancement");
279  queue->Initialize ();
280 
281  if (mode == QueueSizeUnit::BYTES)
282  {
283  EnqueueWithDelay (queue, pktSize, 200);
284  }
285  else
286  {
287  EnqueueWithDelay (queue, 1, 200);
288  }
289 
290  Simulator::Stop (Seconds (8.0));
291  Simulator::Run ();
292 
293  QueueDisc::Stats st = queue->GetStats ();
294 
295 // The Pdrop value should increase, from it's default value of zero
296  NS_TEST_EXPECT_MSG_NE (queue->GetPdrop (), 0, "Pdrop should be non-zero");
297  NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (CobaltQueueDisc::OVERLIMIT_DROP), 0, "Drops due to queue overflow should be non-zero");
298 }
299 
300 void
302 {
303  Address dest;
304  double delay = 0.01; // enqueue packets with delay
305  for (uint32_t i = 0; i < nPkt; i++)
306  {
307  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &CobaltQueueDiscDropTest::Enqueue, this, queue, size, 1);
308  }
309 }
310 
311 void
312 CobaltQueueDiscDropTest::Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt)
313 {
314  Address dest;
315  for (uint32_t i = 0; i < nPkt; i++)
316  {
317  queue->Enqueue (Create<CobaltQueueDiscTestItem> (Create<Packet> (size), dest, 0, true));
318  }
319 }
320 
321 void
323 {
326  Simulator::Destroy ();
327 }
328 
336 {
337 public:
344  virtual void DoRun (void);
345 
346 private:
354  void Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt, bool ecnCapable);
361  void Dequeue (Ptr<CobaltQueueDisc> queue, uint32_t modeSize, uint32_t testCase);
367  void DropNextTracer (int64_t oldVal, int64_t newVal);
369  uint32_t m_dropNextCount;
372 };
373 
375  : TestCase ("Basic mark operations")
376 {
377  m_mode = mode;
378  m_dropNextCount = 0;
379 }
380 
381 void
382 CobaltQueueDiscMarkTest::DropNextTracer (int64_t oldVal, int64_t newVal)
383 {
384  NS_UNUSED (oldVal);
385  NS_UNUSED (newVal);
386  m_dropNextCount++;
387 }
388 
389 void
391 {
392  // Test is divided into 3 sub test cases:
393  // 1) Packets are not ECN capable.
394  // 2) Packets are ECN capable.
395  // 3) Some packets are ECN capable.
396 
397  // Test case 1
398  Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
399  uint32_t pktSize = 1000;
400  uint32_t modeSize = 0;
403 
405  {
406  modeSize = pktSize;
407  }
408  else if (m_mode == QueueSizeUnit::PACKETS)
409  {
410  modeSize = 1;
411  }
412 
413  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 500))),
414  true, "Verify that we can actually set the attribute MaxSize");
415  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (false)),
416  true, "Verify that we can actually set the attribute UseEcn");
417  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
418  "Disable Blue enhancement");
419  queue->Initialize ();
420 
421  // Not-ECT traffic to induce packet drop
422  Enqueue (queue, pktSize, 20, false);
423  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 20 * modeSize, "There should be 20 packets in queue.");
424 
425  // Although the first dequeue occurs with a sojourn time above target
426  // there should not be any dropped packets in this interval
427  Time waitUntilFirstDequeue = 2 * queue->GetTarget ();
428  Simulator::Schedule (waitUntilFirstDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 1);
429 
430  // This dequeue should cause a packet to be dropped
431  Time waitUntilSecondDequeue = waitUntilFirstDequeue + 2 * queue->GetInterval ();
432  Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 1);
433 
434  Simulator::Run ();
435  Simulator::Destroy ();
436 
437  // Test case 2, queue with ECN capable traffic for marking of packets instead of dropping
438  queue = CreateObject<CobaltQueueDisc> ();
439  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 500))),
440  true, "Verify that we can actually set the attribute MaxSize");
441  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)),
442  true, "Verify that we can actually set the attribute UseEcn");
443  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
444  "Disable Blue enhancement");
445  queue->Initialize ();
446 
447  // ECN capable traffic
448  Enqueue (queue, pktSize, 20, true);
449  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 20 * modeSize, "There should be 20 packets in queue.");
450 
451  // Although the first dequeue occurs with a sojourn time above target
452  // there should not be any marked packets in this interval
453  Simulator::Schedule (waitUntilFirstDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
454 
455  // This dequeue should cause a packet to be marked
456  Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
457 
458  // This dequeue should cause a packet to be marked as dropnext is equal to current time
459  Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
460 
461  // In dropping phase and it's time for next packet to be marked
462  // the dequeue should cause additional packet to be marked
463  Simulator::Schedule (waitUntilSecondDequeue * 2, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
464 
465  Simulator::Run ();
466  Simulator::Destroy ();
467 
468  // Test case 3, some packets are ECN capable
469  queue = CreateObject<CobaltQueueDisc> ();
470  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 500))),
471  true, "Verify that we can actually set the attribute MaxSize");
472  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)),
473  true, "Verify that we can actually set the attribute UseEcn");
474  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
475  "Disable Blue enhancement");
476  queue->Initialize ();
477 
478  // First 3 packets in the queue are ecnCapable
479  Enqueue (queue, pktSize, 3, true);
480  // Rest of the packet are not ecnCapable
481  Enqueue (queue, pktSize, 17, false);
482  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 20 * modeSize, "There should be 20 packets in queue.");
483 
484  // Although the first dequeue occurs with a sojourn time above target
485  // there should not be any marked packets in this interval
486  Simulator::Schedule (waitUntilFirstDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
487 
488  // This dequeue should cause a packet to be marked
489  Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
490 
491  // This dequeue should cause a packet to be marked as dropnext is equal to current time
492  Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
493 
494  // In dropping phase and it's time for next packet to be dropped as packets are not ECN capable
495  // the dequeue should cause packet to be dropped
496  Simulator::Schedule (waitUntilSecondDequeue * 2, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
497 
498  Simulator::Run ();
499  Simulator::Destroy ();
500 }
501 
502 void
503 CobaltQueueDiscMarkTest::Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt, bool ecnCapable)
504 {
505  Address dest;
506  for (uint32_t i = 0; i < nPkt; i++)
507  {
508  queue->Enqueue (Create<CobaltQueueDiscTestItem> (Create<Packet> (size), dest, 0, ecnCapable));
509  }
510 }
511 
512 void
513 CobaltQueueDiscMarkTest::Dequeue (Ptr<CobaltQueueDisc> queue, uint32_t modeSize, uint32_t testCase)
514 {
515  uint32_t initialMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
516  uint32_t initialQSize = queue->GetCurrentSize ().GetValue ();
517  uint32_t initialDropNext = queue->GetDropNext ();
518  Time currentTime = Simulator::Now ();
519  uint32_t currentDropCount = 0;
520  uint32_t currentMarkCount = 0;
521 
522  if (initialMarkCount > 0 && currentTime.GetNanoSeconds () > initialDropNext && testCase == 3)
523  {
525  }
526 
527  if (initialQSize != 0)
528  {
529  Ptr<QueueDiscItem> item = queue->Dequeue ();
530  if (testCase == 1)
531  {
532  currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
533  if (currentDropCount != 0)
534  {
535  nPacketsBeforeFirstDrop = initialQSize;
536  }
537  }
538  if (testCase == 2)
539  {
540  if (initialMarkCount == 0 && currentTime > queue->GetTarget ())
541  {
542  if (currentTime < queue->GetInterval ())
543  {
544  currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
545  currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
546  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "There should be 1 packet dequeued.");
547  NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
548  NS_TEST_ASSERT_MSG_EQ (currentMarkCount, 0, "We are not in dropping state."
549  "Sojourn time has just gone above target from below."
550  "Hence, there should be no marked packets");
551  }
552  else if (currentTime >= queue->GetInterval ())
553  {
554  nPacketsBeforeFirstMark = initialQSize;
555  currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
556  currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
557  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize,
558  "Sojourn time has been above target for at least interval."
559  "We enter the dropping state and perform initial packet marking"
560  "So there should be only 1 more packet dequeued.");
561  NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
562  NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 1, "There should be 1 marked packet");
563  }
564  }
565  else if (initialMarkCount > 0)
566  {
567  if (currentTime.GetNanoSeconds () <= initialDropNext)
568  {
569  currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
570  currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
571  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "We are in dropping state."
572  "Sojourn is still above target."
573  "There should be only 1 more packet dequeued");
574  NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
575  NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 2, "There should be 2 marked packet as."
576  "current dropnext is equal to current time.");
577  }
578  else if (currentTime.GetNanoSeconds () > initialDropNext)
579  {
580  currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
581  currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
582  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "We are in dropping state."
583  "It's time for packet to be marked"
584  "So there should be only 1 more packet dequeued");
585  NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
586  NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 3, "There should be 3 marked packet");
587  NS_TEST_EXPECT_MSG_EQ (nPacketsBeforeFirstDrop, nPacketsBeforeFirstMark, "Number of packets in the queue before drop should be equal"
588  "to number of packets in the queue before first mark as the behavior until packet N should be the same.");
589  }
590  }
591  }
592  else if (testCase == 3)
593  {
594  if (initialMarkCount == 0 && currentTime > queue->GetTarget ())
595  {
596  if (currentTime < queue->GetInterval ())
597  {
598  currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
599  currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
600  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "There should be 1 packet dequeued.");
601  NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
602  NS_TEST_ASSERT_MSG_EQ (currentMarkCount, 0, "We are not in dropping state."
603  "Sojourn time has just gone above target from below."
604  "Hence, there should be no marked packets");
605  }
606  else if (currentTime >= queue->GetInterval ())
607  {
608  currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
609  currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
610  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize,
611  "Sojourn time has been above target for at least interval."
612  "We enter the dropping state and perform initial packet marking"
613  "So there should be only 1 more packet dequeued.");
614  NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
615  NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 1, "There should be 1 marked packet");
616  }
617  }
618  else if (initialMarkCount > 0)
619  {
620  if (currentTime.GetNanoSeconds () <= initialDropNext)
621  {
622  currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
623  currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
624  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "We are in dropping state."
625  "Sojourn is still above target."
626  "So there should be only 1 more packet dequeued");
627  NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
628  NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 2, "There should be 2 marked packet"
629  "as dropnext is equal to current time");
630  }
631  else if (currentTime.GetNanoSeconds () > initialDropNext)
632  {
633  currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
634  currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
635  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - (m_dropNextCount + 1) * modeSize, "We are in dropping state."
636  "It's time for packet to be dropped as packets are not ecnCapable"
637  "The number of packets dequeued equals to the number of times m_dropNext is updated plus initial dequeue");
638  NS_TEST_EXPECT_MSG_EQ (currentDropCount, m_dropNextCount, "The number of drops equals to the number of times m_dropNext is updated");
639  NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 2, "There should still be only 2 marked packet");
640  }
641  }
642  }
643  }
644 }
645 
653 {
654 public:
657 
658 private:
659  virtual void DoRun (void);
666  void Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt);
674  void EnqueueWithDelay (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt, Time delay);
680  void Dequeue (Ptr<CobaltQueueDisc> queue, uint32_t modeSize);
688  void DequeueWithDelay (Ptr<CobaltQueueDisc> queue, uint32_t modeSize, uint32_t nPkt, Time delay);
690 };
691 
693  : TestCase ("Test CE Threshold marking")
694 {
695  m_mode = mode;
696 }
697 
699 {
700 }
701 
702 void
704 {
705  Address dest;
706  for (uint32_t i = 0; i < nPkt; i++)
707  {
708  queue->Enqueue (Create<CobaltQueueDiscTestItem> (Create<Packet> (size), dest, 0, true));
709  }
710 }
711 
712 void
714 {
715  for (uint32_t i = 0; i < nPkt; i++)
716  {
717  Simulator::Schedule (Time (Seconds ((i + 1) * delay.GetSeconds ())), &CobaltQueueDiscCeThresholdTest::Enqueue, this, queue, size, 1);
718  }
719 }
720 
721 void
723 {
724  Ptr<QueueDiscItem> item = queue->Dequeue ();
725 
726  if (Simulator::Now () > MilliSeconds (11) && Simulator::Now () < MilliSeconds (28))
727  {
728  NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 1, "There should be only 1 packet"
729  "mark, the delay between the enqueueing of the packets decreased after the"
730  "1st mark (packet enqueued at 11ms) and increased for the packet enqueued after 20.6ms."
731  "Queue delay remains below or equal to 1ms for the packet enqueued before 28ms");
732  }
733  if (Simulator::Now () > MilliSeconds (31) )
734  {
735  NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 3, "There should be 3 packet"
736  "marks, the delay between the enqueueing of the packets decreased after 1st mark"
737  "(packet enqueued at 11ms) and increased for the packet enqueued after 20.6ms."
738  "Queue delay remains below 1ms for the packets enqueued before 28ms and increases"
739  "for the packets enqueued after 28ms.");
740  }
741 }
742 
743 void
744 CobaltQueueDiscCeThresholdTest::DequeueWithDelay (Ptr<CobaltQueueDisc> queue, uint32_t modeSize, uint32_t nPkt, Time delay)
745 {
746  for (uint32_t i = 0; i < nPkt; i++)
747  {
748  Simulator::Schedule (Time (Seconds ((i + 1) * delay.GetSeconds ())), &CobaltQueueDiscCeThresholdTest::Dequeue, this, queue, modeSize);
749  }
750 }
751 
752 void
754 {
755  Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
756  uint32_t pktSize = 1000;
757  uint32_t modeSize = 0;
758 
760  {
761  modeSize = pktSize;
762  }
763  else if (m_mode == QueueSizeUnit::PACKETS)
764  {
765  modeSize = 1;
766  }
767 
768  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)),
769  true, "Verify that we can actually set the attribute UseEcn");
770  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("CeThreshold", TimeValue (MilliSeconds (1))),
771  true, "Verify that we can actually set the attribute UseEcn");
772  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
773  "Disable Blue enhancement");
774  queue->Initialize ();
775 
776  // Enqueue 11 packets every 1ms
777  EnqueueWithDelay (queue, pktSize, 11, MilliSeconds (1));
778 
779  // With every dequeue, queue delay increases by 0.1ms as packet enqueues every 1ms while dequeues at 1.1ms
780  // so at 11th dequeue, the dequeued packet should be marked.
781  Time dequeueInterval = MicroSeconds (1100);
782  DequeueWithDelay (queue, modeSize, 11, dequeueInterval);
783 
784  // First mark occured for the packet enqueued at 11ms, ideally TCP would decrease sending rate
785  // which can be simulated by increasing interval between subsequent enqueues, so packets are now enqueued with a delay 1.2ms.
786  Time waitUntilFirstMark = MilliSeconds(11);
787  Simulator::Schedule (waitUntilFirstMark, &CobaltQueueDiscCeThresholdTest::EnqueueWithDelay, this, queue, pktSize, 9, MicroSeconds (1200));
788 
789  // Keep dequeueing with the same delay
790  Simulator::Schedule (waitUntilFirstMark, &CobaltQueueDiscCeThresholdTest::DequeueWithDelay, this, queue, modeSize, 9, dequeueInterval);
791 
792  // Queue delay becomes 0.2ms for the packet enqueued at 20.6ms, time to decrease interval between subsequent enqueues,
793  // as ideally TCP would again start increasing sending rate
794  Time waitUntilDecreasingEnqueueDelay = waitUntilFirstMark + MilliSeconds(9);
795  Simulator::Schedule (waitUntilDecreasingEnqueueDelay, &CobaltQueueDiscCeThresholdTest::EnqueueWithDelay, this, queue, pktSize, 10, MilliSeconds (1));
796 
797  // Keep dequeueing with the same delay
798  Simulator::Schedule (waitUntilFirstMark, &CobaltQueueDiscCeThresholdTest::DequeueWithDelay, this, queue, modeSize, 10, dequeueInterval);
799 
800  Simulator::Run ();
801  Simulator::Destroy ();
802 }
803 
804 
818 {
819 public:
822 
823 private:
824  virtual void DoRun (void);
831  void Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt);
836  void Dequeue (Ptr<CobaltQueueDisc> queue);
843  void DequeueWithDelay (Ptr<CobaltQueueDisc> queue, uint32_t nPkt, Time delay);
845 };
846 
848  : TestCase ("Enhanced Blue tests verification for both packets and bytes mode")
849 {
850  m_mode = mode;
851 }
852 
854 {
855 }
856 
857 void
859 
860 {
861  uint32_t pktSize = 1500;
862  uint32_t modeSize = 0;
863  Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
864 
866  {
867  modeSize = pktSize;
868  }
869  else if (m_mode == QueueSizeUnit::PACKETS)
870  {
871  modeSize = 1;
872  }
873  queue->Initialize ();
874  queue->AssignStreams (1);
875  Enqueue (queue, modeSize, 200);
876  DequeueWithDelay (queue, 100, MilliSeconds (10));
877 
878  Simulator::Stop (Seconds (8.0));
879  Simulator::Run ();
880 
881  QueueDisc::Stats st = queue->GetStats ();
882 
883  // The Pdrop value should increase, from it's default value of zero
884  NS_TEST_EXPECT_MSG_EQ (queue->GetPdrop (), 0.234375, "Pdrop should be increased by 1/256 for every packet whose sojourn time is above 400ms."
885  " From the 41st dequeue until the last one, sojourn time is above 400ms, so 60 packets have sojourn time above 400ms"
886  "hence Pdrop should be increased 60*(1/256) which is 0.234375");
887  NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 49, "There should a fixed number of drops (49 here)");
888  Simulator::Destroy ();
889 
890 
891  queue = CreateObject<CobaltQueueDisc> ();
892  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)),
893  true, "Verify that we can actually set the attribute UseEcn");
894  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("BlueThreshold", TimeValue (Time::Max ())), true,
895  "Disable Blue enhancement");
896  queue->Initialize ();
897  Enqueue (queue, modeSize, 200);
898  DequeueWithDelay (queue, 100, MilliSeconds (10));
899 
900  Simulator::Stop (Seconds (8.0));
901  Simulator::Run ();
902 
903  st = queue->GetStats ();
904 
905  NS_TEST_EXPECT_MSG_EQ (queue->GetPdrop (), 0, "Pdrop should be zero");
906  NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not any dropped packets");
907  Simulator::Destroy ();
908 }
909 
910 void
912 {
913  Address dest;
914  for (uint32_t i = 0; i < nPkt; i++)
915  {
916  queue->Enqueue (Create<CobaltQueueDiscTestItem> (Create<Packet> (size), dest, 0, true));
917  }
918 }
919 
920 void
922 {
923  Ptr<QueueDiscItem> item = queue->Dequeue ();
924 }
925 
926 void
928 {
929  for (uint32_t i = 0; i < nPkt; i++)
930  {
931  Simulator::Schedule (Time (Seconds ((i + 1) * delay.GetSeconds ())), &CobaltQueueDiscEnhancedBlueTest::Dequeue, this, queue);
932  }
933 }
934 
935 
936 static class CobaltQueueDiscTestSuite : public TestSuite
937 {
938 public:
940  : TestSuite ("cobalt-queue-disc", UNIT)
941  {
942  // Test 1: simple enqueue/dequeue with no drops
943  AddTestCase (new CobaltQueueDiscBasicEnqueueDequeue (PACKETS), TestCase::QUICK);
944  AddTestCase (new CobaltQueueDiscBasicEnqueueDequeue (BYTES), TestCase::QUICK);
945  // Test 2: Drop test
946  AddTestCase (new CobaltQueueDiscDropTest (), TestCase::QUICK);
947  // Test 3: Mark test
948  AddTestCase (new CobaltQueueDiscMarkTest (PACKETS), TestCase::QUICK);
949  AddTestCase (new CobaltQueueDiscMarkTest (BYTES), TestCase::QUICK);
950  // Test 4: CE threshold marking test
951  AddTestCase (new CobaltQueueDiscCeThresholdTest (PACKETS), TestCase::QUICK);
952  AddTestCase (new CobaltQueueDiscCeThresholdTest (BYTES), TestCase::QUICK);
953  // Test 4: Blue enhancement test
954  AddTestCase (new CobaltQueueDiscEnhancedBlueTest (PACKETS), TestCase::QUICK);
955  AddTestCase (new CobaltQueueDiscEnhancedBlueTest (BYTES), TestCase::QUICK);
956  }
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:185
void Dequeue(Ptr< CobaltQueueDisc > queue)
Dequeue function.
uint64_t GetUid(void) const
Returns the packet&#39;s Uid.
Definition: packet.cc:390
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
AttributeValue implementation for Boolean.
Definition: boolean.h:36
Class for representing queue sizes.
Definition: queue-size.h:94
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
Definition: queue-disc.cc:861
Hold variables of type string.
Definition: string.h:41
uint32_t GetValue() const
Get the underlying value.
Definition: queue-size.cc:175
QueueSizeUnit
Enumeration of the operating modes of queues.
Definition: queue-size.h:42
QueueSize GetCurrentSize(void)
Get the current size of the queue disc in bytes, if operating in bytes mode, or packets, otherwise.
Definition: queue-disc.cc:523
A suite of tests to run.
Definition: test.h:1343
void Enqueue(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
void EnqueueWithDelay(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt)
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:283
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
bool SetAttributeFailSafe(std::string name, const AttributeValue &value)
Set a single attribute without raising errors.
Definition: object-base.cc:205
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:148
void Enqueue(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
encapsulates test code
Definition: test.h:1153
STL namespace.
uint32_t nPacketsBeforeFirstDrop
Number of packets in the queue before first drop.
Test 1: simple enqueue/dequeue with no drops.
virtual void DoRun(void)
Implementation to actually run this TestCase.
CobaltQueueDiscBasicEnqueueDequeue(QueueSizeUnit mode)
Constructor.
a polymophic address class
Definition: address.h:90
Cobalt Queue Disc Test Item.
virtual void AddHeader(void)
Add the header to the packet.
virtual void DoRun(void)
Implementation to actually run this TestCase.
AttributeValue implementation for Time.
Definition: nstime.h:1353
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
Definition: queue-disc.cc:110
Use number of packets for queue size.
Definition: queue-size.h:44
#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:166
QueueSizeUnit m_mode
Queue test size function.
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification...
#define Max(a, b)
const Stats & GetStats(void)
Retrieve all the collected statistics.
Definition: queue-disc.cc:421
void EnqueueWithDelay(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt, Time delay)
Enqueue with delay function.
Test 5: Cobalt Queue Disc Enhanced Blue Test Item This test checks that the Blue Enhancement is worki...
void DropNextTracer(int64_t oldVal, int64_t newVal)
Drop next tracer function.
Ptr< QueueDiscItem > Dequeue(void)
Extract from the queue disc the packet that has been dequeued by calling Peek, if any...
Definition: queue-disc.cc:896
Time GetTarget(void) const
Get the target queue delay.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:293
double GetPdrop() const
Get the drop probability of Blue.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t nPacketsBeforeFirstMark
Number of packets in the queue before first mark.
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:392
Test 3: Cobalt Queue Disc ECN marking Test Item.
int64_t GetDropNext(void) const
Get the time for next packet drop while in the dropping state.
Test 2: Cobalt Queue Disc Drop Test Item.
uint32_t GetNMarkedPackets(std::string reason) const
Get the number of packets marked for the given reason.
Definition: queue-disc.cc:152
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
Definition: test.h:737
void Dequeue(Ptr< CobaltQueueDisc > queue, uint32_t modeSize)
Dequeue function.
bool m_ecnCapablePacket
ECN capable packet?
virtual void DoRun(void)
Implementation to actually run this TestCase.
CobaltQueueDiscTestSuite g_cobaltQueueTestSuite
the test suite
Time GetInterval(void) const
Get the interval.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Test 4: Cobalt Queue Disc CE Threshold marking Test Item.
uint32_t m_dropNextCount
count the number of times m_dropNext is recalculated
CobaltQueueDiscMarkTest(QueueSizeUnit mode)
Constructor.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1305
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
void RunDropTest(QueueSizeUnit mode)
Run Cobalt test function.
This test suite implements a Unit Test.
Definition: test.h:1353
virtual void DoRun(void)
Implementation to actually run this TestCase.
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:86
Use number of bytes for queue size.
Definition: queue-size.h:45
void Enqueue(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt, bool ecnCapable)
Enqueue function.
void Dequeue(Ptr< CobaltQueueDisc > queue, uint32_t modeSize, uint32_t testCase)
Dequeue function.
void DequeueWithDelay(Ptr< CobaltQueueDisc > queue, uint32_t nPkt, Time delay)
Dequeue with delay function.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183
void DequeueWithDelay(Ptr< CobaltQueueDisc > queue, uint32_t modeSize, uint32_t nPkt, Time delay)
Dequeue with delay function.
void Enqueue(Ptr< CobaltQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.