A Discrete-Event Network Simulator
API
pie-queue-disc-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2016 NITK Surathkal
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Shravya Ks <shravya.ks0@gmail.com>
19  * Smriti Murali <m.smriti.95@gmail.com>
20  * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
21  *
22  */
23 
24 #include "ns3/test.h"
25 #include "ns3/pie-queue-disc.h"
26 #include "ns3/packet.h"
27 #include "ns3/uinteger.h"
28 #include "ns3/string.h"
29 #include "ns3/double.h"
30 #include "ns3/log.h"
31 #include "ns3/simulator.h"
32 
33 using namespace ns3;
34 
42 {
43 public:
51  PieQueueDiscTestItem (Ptr<Packet> p, const Address & addr, uint16_t protocol);
52  virtual ~PieQueueDiscTestItem ();
53  virtual void AddHeader (void);
54  virtual bool Mark (void);
55 
56 private:
68  PieQueueDiscTestItem &operator = (const PieQueueDiscTestItem &);
69 };
70 
72  : QueueDiscItem (p, addr, protocol)
73 {
74 }
75 
77 {
78 }
79 
80 void
82 {
83 }
84 
85 bool
87 {
88  return false;
89 }
90 
98 {
99 public:
101  virtual void DoRun (void);
102 private:
109  void Enqueue (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt);
116  void EnqueueWithDelay (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt);
122  void Dequeue (Ptr<PieQueueDisc> queue, uint32_t nPkt);
129  void DequeueWithDelay (Ptr<PieQueueDisc> queue, double delay, uint32_t nPkt);
134  void RunPieTest (StringValue mode);
135 };
136 
138  : TestCase ("Sanity check on the pie queue disc implementation")
139 {
140 }
141 
142 void
144 {
145  uint32_t pktSize = 0;
146 
147  // 1 for packets; pktSize for bytes
148  uint32_t modeSize = 1;
149 
150  uint32_t qSize = 300;
151  Ptr<PieQueueDisc> queue = CreateObject<PieQueueDisc> ();
152 
153 
154  // test 1: simple enqueue/dequeue with defaults, no drops
155  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
156  "Verify that we can actually set the attribute Mode");
157 
158  Address dest;
159 
160  if (queue->GetMode () == PieQueueDisc::QUEUE_DISC_MODE_BYTES)
161  {
162  // pktSize should be same as MeanPktSize to avoid performance gap between byte and packet mode
163  pktSize = 1000;
164  modeSize = pktSize;
165  qSize = qSize * modeSize;
166  }
167 
168  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
169  "Verify that we can actually set the attribute QueueLimit");
170 
171  Ptr<Packet> p1, p2, p3, p4, p5, p6, p7, p8;
172  p1 = Create<Packet> (pktSize);
173  p2 = Create<Packet> (pktSize);
174  p3 = Create<Packet> (pktSize);
175  p4 = Create<Packet> (pktSize);
176  p5 = Create<Packet> (pktSize);
177  p6 = Create<Packet> (pktSize);
178  p7 = Create<Packet> (pktSize);
179  p8 = Create<Packet> (pktSize);
180 
181  queue->Initialize ();
182  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 0 * modeSize, "There should be no packets in there");
183  queue->Enqueue (Create<PieQueueDiscTestItem> (p1, dest, 0));
184  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 1 * modeSize, "There should be one packet in there");
185  queue->Enqueue (Create<PieQueueDiscTestItem> (p2, dest, 0));
186  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 2 * modeSize, "There should be two packets in there");
187  queue->Enqueue (Create<PieQueueDiscTestItem> (p3, dest, 0));
188  queue->Enqueue (Create<PieQueueDiscTestItem> (p4, dest, 0));
189  queue->Enqueue (Create<PieQueueDiscTestItem> (p5, dest, 0));
190  queue->Enqueue (Create<PieQueueDiscTestItem> (p6, dest, 0));
191  queue->Enqueue (Create<PieQueueDiscTestItem> (p7, dest, 0));
192  queue->Enqueue (Create<PieQueueDiscTestItem> (p8, dest, 0));
193  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 8 * modeSize, "There should be eight packets in there");
194 
195  Ptr<QueueDiscItem> item;
196 
197  item = queue->Dequeue ();
198  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the first packet");
199  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 7 * modeSize, "There should be seven packets in there");
200  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p1->GetUid (), "was this the first packet ?");
201 
202  item = queue->Dequeue ();
203  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the second packet");
204  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 6 * modeSize, "There should be six packet in there");
205  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p2->GetUid (), "Was this the second packet ?");
206 
207  item = queue->Dequeue ();
208  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the third packet");
209  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 5 * modeSize, "There should be five packets in there");
210  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p3->GetUid (), "Was this the third packet ?");
211 
212  item = queue->Dequeue ();
213  item = queue->Dequeue ();
214  item = queue->Dequeue ();
215  item = queue->Dequeue ();
216  item = queue->Dequeue ();
217 
218  item = queue->Dequeue ();
219  NS_TEST_EXPECT_MSG_EQ ((item == 0), true, "There are really no packets in there");
220 
221 
222  // test 2: more data with defaults, unforced drops but no forced drops
223  queue = CreateObject<PieQueueDisc> ();
224  pktSize = 1000; // pktSize != 0 because DequeueThreshold always works in bytes
225  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
226  "Verify that we can actually set the attribute Mode");
227  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
228  "Verify that we can actually set the attribute QueueLimit");
229  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true,
230  "Verify that we can actually set the attribute A");
231  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true,
232  "Verify that we can actually set the attribute B");
233  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true,
234  "Verify that we can actually set the attribute Tupdate");
235  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true,
236  "Verify that we can actually set the attribute Supdate");
237  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
238  "Verify that we can actually set the attribute DequeueThreshold");
239  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true,
240  "Verify that we can actually set the attribute QueueDelayReference");
241  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
242  "Verify that we can actually set the attribute MaxBurstAllowance");
243  queue->Initialize ();
244  EnqueueWithDelay (queue, pktSize, 400);
245  DequeueWithDelay (queue, 0.012, 400);
246  Simulator::Stop (Seconds (8.0));
247  Simulator::Run ();
248  QueueDisc::Stats st = queue->GetStats ();
249  uint32_t test2 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
250  NS_TEST_EXPECT_MSG_NE (test2, 0, "There should be some unforced drops");
251  NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
252 
253 
254  // test 3: same as test 2, but with higher QueueDelayReference
255  queue = CreateObject<PieQueueDisc> ();
256  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
257  "Verify that we can actually set the attribute Mode");
258  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
259  "Verify that we can actually set the attribute QueueLimit");
260  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true,
261  "Verify that we can actually set the attribute A");
262  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true,
263  "Verify that we can actually set the attribute B");
264  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true,
265  "Verify that we can actually set the attribute Tupdate");
266  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true,
267  "Verify that we can actually set the attribute Supdate");
268  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
269  "Verify that we can actually set the attribute DequeueThreshold");
270  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.08))), true,
271  "Verify that we can actually set the attribute QueueDelayReference");
272  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
273  "Verify that we can actually set the attribute MaxBurstAllowance");
274  queue->Initialize ();
275  EnqueueWithDelay (queue, pktSize, 400);
276  DequeueWithDelay (queue, 0.012, 400);
277  Simulator::Stop (Seconds (8.0));
278  Simulator::Run ();
279  st = queue->GetStats ();
280  uint32_t test3 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
281  NS_TEST_EXPECT_MSG_LT (test3, test2, "Test 3 should have less unforced drops than test 2");
282  NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
283 
284 
285  // test 4: same as test 2, but with reduced dequeue rate
286  queue = CreateObject<PieQueueDisc> ();
287  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
288  "Verify that we can actually set the attribute Mode");
289  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
290  "Verify that we can actually set the attribute QueueLimit");
291  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true,
292  "Verify that we can actually set the attribute A");
293  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true,
294  "Verify that we can actually set the attribute B");
295  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true,
296  "Verify that we can actually set the attribute Tupdate");
297  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true,
298  "Verify that we can actually set the attribute Supdate");
299  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
300  "Verify that we can actually set the attribute DequeueThreshold");
301  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true,
302  "Verify that we can actually set the attribute QueueDelayReference");
303  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
304  "Verify that we can actually set the attribute MaxBurstAllowance");
305  queue->Initialize ();
306  EnqueueWithDelay (queue, pktSize, 400);
307  DequeueWithDelay (queue, 0.015, 400); // delay between two successive dequeue events is increased
308  Simulator::Stop (Seconds (8.0));
309  Simulator::Run ();
310  st = queue->GetStats ();
311  uint32_t test4 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
312  NS_TEST_EXPECT_MSG_GT (test4, test2, "Test 4 should have more unforced drops than test 2");
313  NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
314 
315 
316  // test 5: same dequeue rate as test 4, but with higher Tupdate
317  queue = CreateObject<PieQueueDisc> ();
318  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
319  "Verify that we can actually set the attribute Mode");
320  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
321  "Verify that we can actually set the attribute QueueLimit");
322  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true,
323  "Verify that we can actually set the attribute A");
324  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true,
325  "Verify that we can actually set the attribute B");
326  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.09))), true,
327  "Verify that we can actually set the attribute Tupdate");
328  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true,
329  "Verify that we can actually set the attribute Supdate");
330  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true,
331  "Verify that we can actually set the attribute DequeueThreshold");
332  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true,
333  "Verify that we can actually set the attribute QueueDelayReference");
334  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
335  "Verify that we can actually set the attribute MaxBurstAllowance");
336  queue->Initialize ();
337  EnqueueWithDelay (queue, pktSize, 400);
338  DequeueWithDelay (queue, 0.015, 400);
339  Simulator::Stop (Seconds (8.0));
340  Simulator::Run ();
341  st = queue->GetStats ();
342  uint32_t test5 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
343  NS_TEST_EXPECT_MSG_LT (test5, test4, "Test 5 should have less unforced drops than test 4");
344  NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
345 }
346 
347 void
348 PieQueueDiscTestCase::Enqueue (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt)
349 {
350  Address dest;
351  for (uint32_t i = 0; i < nPkt; i++)
352  {
353  queue->Enqueue (Create<PieQueueDiscTestItem> (Create<Packet> (size), dest, 0));
354  }
355 }
356 
357 void
358 PieQueueDiscTestCase::EnqueueWithDelay (Ptr<PieQueueDisc> queue, uint32_t size, uint32_t nPkt)
359 {
360  Address dest;
361  double delay = 0.01; // enqueue packets with delay
362  for (uint32_t i = 0; i < nPkt; i++)
363  {
364  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &PieQueueDiscTestCase::Enqueue, this, queue, size, 1);
365  }
366 }
367 
368 void
370 {
371  for (uint32_t i = 0; i < nPkt; i++)
372  {
373  Ptr<QueueDiscItem> item = queue->Dequeue ();
374  }
375 }
376 
377 void
378 PieQueueDiscTestCase::DequeueWithDelay (Ptr<PieQueueDisc> queue, double delay, uint32_t nPkt)
379 {
380  for (uint32_t i = 0; i < nPkt; i++)
381  {
382  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &PieQueueDiscTestCase::Dequeue, this, queue, 1);
383  }
384 }
385 
386 void
388 {
389  RunPieTest (StringValue ("QUEUE_DISC_MODE_PACKETS"));
390  RunPieTest (StringValue ("QUEUE_DISC_MODE_BYTES"));
391  Simulator::Destroy ();
392 }
393 
400 static class PieQueueDiscTestSuite : public TestSuite
401 {
402 public:
404  : TestSuite ("pie-queue-disc", UNIT)
405  {
406  AddTestCase (new PieQueueDiscTestCase (), TestCase::QUICK);
407  }
QueueDiscMode GetMode(void)
Get the operating mode of this queue disc.
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:155
Pie Queue Disc Test Case.
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification...
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
Definition: queue-disc.cc:730
Hold variables of type string.
Definition: string.h:41
void RunPieTest(StringValue mode)
Run test function.
A suite of tests to run.
Definition: test.h:1342
void Dequeue(Ptr< PieQueueDisc > queue, uint32_t nPkt)
Dequeue function.
#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:285
bool SetAttributeFailSafe(std::string name, const AttributeValue &value)
Set a single attribute without raising errors.
Definition: object-base.cc:205
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:148
encapsulates test code
Definition: test.h:1155
This test suite implements a Unit Test.
Definition: test.h:1352
a polymophic address class
Definition: address.h:90
virtual void DoRun(void)
Implementation to actually run this TestCase.
AttributeValue implementation for Time.
Definition: nstime.h:1055
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
Hold an unsigned integer type.
Definition: uinteger.h:44
virtual void AddHeader(void)
Add the header to the packet.
const Stats & GetStats(void)
Retrieve all the collected statistics.
Definition: queue-disc.cc:411
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
Definition: queue-disc.cc:113
Ptr< QueueDiscItem > Dequeue(void)
Request the queue discipline to extract a packet.
Definition: queue-disc.cc:765
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t GetQueueSize(void)
Get the current value of the queue in bytes or packets.
#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:739
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report if not.
Definition: test.h:1090
void EnqueueWithDelay(Ptr< PieQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue with delay function.
Pie Queue Disc Test Item.
PieQueueDiscTestSuite g_pieQueueTestSuite
the test suite
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:993
#define NS_TEST_EXPECT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report if not.
Definition: test.h:903
Pie Queue Disc Test Suite.
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)
Enqueue function.
This class can be used to hold variables of floating point type such as 'double' or 'float'...
Definition: double.h:41
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183