A Discrete-Event Network Simulator
API
adaptive-red-queue-disc-test-suite.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  * Author: Mohit P. Tahiliani <tahiliani@nitk.edu.in>
18  *
19  */
20 
21 #include "ns3/double.h"
22 #include "ns3/log.h"
23 #include "ns3/packet.h"
24 #include "ns3/red-queue-disc.h"
25 #include "ns3/simulator.h"
26 #include "ns3/string.h"
27 #include "ns3/test.h"
28 #include "ns3/uinteger.h"
29 
30 using namespace ns3;
31 
44 {
45  public:
53  ~AredQueueDiscTestItem() override;
54 
55  // Delete default constructor, copy constructor and assignment operator to avoid misuse
59 
60  void AddHeader() override;
61  bool Mark() override;
62 };
63 
65  : QueueDiscItem(p, addr, 0)
66 {
67 }
68 
70 {
71 }
72 
73 void
75 {
76 }
77 
78 bool
80 {
81  return false;
82 }
83 
90 {
91  public:
93  void DoRun() override;
94 
95  private:
102  void Enqueue(Ptr<RedQueueDisc> queue, uint32_t size, uint32_t nPkt);
109  void EnqueueWithDelay(Ptr<RedQueueDisc> queue, uint32_t size, uint32_t nPkt);
114  void RunAredDiscTest(QueueSizeUnit mode);
115 };
116 
118  : TestCase("Sanity check on the functionality of Adaptive RED")
119 {
120 }
121 
122 void
124 {
125  uint32_t pktSize = 0;
126  uint32_t modeSize = 1; // 1 for packets; pktSize for bytes
127  double minTh = 70;
128  double maxTh = 150;
129  uint32_t qSize = 300;
130  Address dest;
131 
132  // test 1: Verify automatic setting of QW. [QW = 0.0 with default LinkBandwidth]
133  Ptr<RedQueueDisc> queue = CreateObject<RedQueueDisc>();
134 
135  if (mode == QueueSizeUnit::BYTES)
136  {
137  pktSize = 500;
138  modeSize = pktSize;
139  minTh = minTh * modeSize;
140  maxTh = maxTh * modeSize;
141  qSize = qSize * modeSize;
142  }
143 
144  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinTh", DoubleValue(minTh)),
145  true,
146  "Verify that we can actually set the attribute MinTh");
147  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxTh", DoubleValue(maxTh)),
148  true,
149  "Verify that we can actually set the attribute MaxTh");
151  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
152  true,
153  "Verify that we can actually set the attribute MaxSize");
154  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("QW", DoubleValue(0.0)),
155  true,
156  "Verify that we can actually set the attribute QW");
157  queue->Initialize();
158  Enqueue(queue, pktSize, 300);
159  QueueDisc::Stats st = queue->GetStats();
160  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP),
161  0,
162  "There should be zero unforced drops");
163 
164  // test 2: Verify automatic setting of QW. [QW = 0.0 with lesser LinkBandwidth]
165  queue = CreateObject<RedQueueDisc>();
166  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinTh", DoubleValue(minTh)),
167  true,
168  "Verify that we can actually set the attribute MinTh");
169  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxTh", DoubleValue(maxTh)),
170  true,
171  "Verify that we can actually set the attribute MaxTh");
173  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
174  true,
175  "Verify that we can actually set the attribute MaxSize");
176  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("QW", DoubleValue(0.0)),
177  true,
178  "Verify that we can actually set the attribute QW");
180  queue->SetAttributeFailSafe("LinkBandwidth", DataRateValue(DataRate("0.015Mbps"))),
181  true,
182  "Verify that we can actually set the attribute LinkBandwidth");
183  queue->Initialize();
184  Enqueue(queue, pktSize, 300);
185  st = queue->GetStats();
186  NS_TEST_ASSERT_MSG_NE(st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP),
187  0,
188  "There should be some unforced drops");
189 
190  // test 3: Verify automatic setting of QW. [QW = -1.0 with default LinkBandwidth]
191  queue = CreateObject<RedQueueDisc>();
192  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinTh", DoubleValue(minTh)),
193  true,
194  "Verify that we can actually set the attribute MinTh");
195  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxTh", DoubleValue(maxTh)),
196  true,
197  "Verify that we can actually set the attribute MaxTh");
199  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
200  true,
201  "Verify that we can actually set the attribute MaxSize");
202  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("QW", DoubleValue(-1.0)),
203  true,
204  "Verify that we can actually set the attribute QW");
205  queue->Initialize();
206  Enqueue(queue, pktSize, 300);
207  st = queue->GetStats();
208  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP),
209  0,
210  "There should be zero unforced drops");
211 
212  // test 4: Verify automatic setting of QW. [QW = -1.0 with lesser LinkBandwidth]
213  queue = CreateObject<RedQueueDisc>();
214  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinTh", DoubleValue(minTh)),
215  true,
216  "Verify that we can actually set the attribute MinTh");
217  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxTh", DoubleValue(maxTh)),
218  true,
219  "Verify that we can actually set the attribute MaxTh");
221  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
222  true,
223  "Verify that we can actually set the attribute MaxSize");
224  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("QW", DoubleValue(-1.0)),
225  true,
226  "Verify that we can actually set the attribute QW");
228  queue->SetAttributeFailSafe("LinkBandwidth", DataRateValue(DataRate("0.015Mbps"))),
229  true,
230  "Verify that we can actually set the attribute LinkBandwidth");
231  queue->Initialize();
232  Enqueue(queue, pktSize, 300);
233  st = queue->GetStats();
234  NS_TEST_ASSERT_MSG_NE(st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP),
235  0,
236  "There should be some unforced drops");
237 
238  // test 5: Verify automatic setting of QW. [QW = -2.0 with default LinkBandwidth]
239  queue = CreateObject<RedQueueDisc>();
240  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinTh", DoubleValue(minTh)),
241  true,
242  "Verify that we can actually set the attribute MinTh");
243  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxTh", DoubleValue(maxTh)),
244  true,
245  "Verify that we can actually set the attribute MaxTh");
247  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
248  true,
249  "Verify that we can actually set the attribute MaxSize");
250  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("QW", DoubleValue(-2.0)),
251  true,
252  "Verify that we can actually set the attribute QW");
253  queue->Initialize();
254  Enqueue(queue, pktSize, 300);
255  st = queue->GetStats();
256  uint32_t test5 = st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP);
257  NS_TEST_ASSERT_MSG_NE(test5, 0, "There should be some unforced drops");
258 
259  // test 6: Verify automatic setting of QW. [QW = -2.0 with lesser LinkBandwidth]
260  queue = CreateObject<RedQueueDisc>();
261  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinTh", DoubleValue(minTh)),
262  true,
263  "Verify that we can actually set the attribute MinTh");
264  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxTh", DoubleValue(maxTh)),
265  true,
266  "Verify that we can actually set the attribute MaxTh");
268  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
269  true,
270  "Verify that we can actually set the attribute MaxSize");
271  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("QW", DoubleValue(-2.0)),
272  true,
273  "Verify that we can actually set the attribute QW");
275  queue->SetAttributeFailSafe("LinkBandwidth", DataRateValue(DataRate("0.015Mbps"))),
276  true,
277  "Verify that we can actually set the attribute LinkBandwidth");
278  queue->Initialize();
279  Enqueue(queue, pktSize, 300);
280  st = queue->GetStats();
281  uint32_t test6 = st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP);
282  NS_TEST_ASSERT_MSG_NE(test6, test5, "Test 6 should have more unforced drops than Test 5");
283 
284  // test 7: Verify automatic setting of minTh and maxTh. [minTh = maxTh = 0.0, with default
285  // LinkBandwidth]
286  queue = CreateObject<RedQueueDisc>();
287  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinTh", DoubleValue(0.0)),
288  true,
289  "Verify that we can actually set the attribute MinTh");
290  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxTh", DoubleValue(0.0)),
291  true,
292  "Verify that we can actually set the attribute MaxTh");
294  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
295  true,
296  "Verify that we can actually set the attribute MaxSize");
297  queue->Initialize();
298  Enqueue(queue, pktSize, 300);
299  st = queue->GetStats();
300  NS_TEST_ASSERT_MSG_NE(st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP),
301  0,
302  "There should be some unforced drops");
303 
304  // test 8: Verify automatic setting of minTh and maxTh. [minTh = maxTh = 0.0, with higher
305  // LinkBandwidth]
306  queue = CreateObject<RedQueueDisc>();
307  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinTh", DoubleValue(0.0)),
308  true,
309  "Verify that we can actually set the attribute MinTh");
310  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxTh", DoubleValue(0.0)),
311  true,
312  "Verify that we can actually set the attribute MaxTh");
314  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
315  true,
316  "Verify that we can actually set the attribute MaxSize");
318  queue->SetAttributeFailSafe("LinkBandwidth", DataRateValue(DataRate("150Mbps"))),
319  true,
320  "Verify that we can actually set the attribute LinkBandwidth");
321  queue->Initialize();
322  Enqueue(queue, pktSize, 300);
323  st = queue->GetStats();
324  NS_TEST_ASSERT_MSG_EQ(st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP),
325  0,
326  "There should be zero unforced drops");
327 
328  // test 9: Default RED (automatic and adaptive settings disabled)
329  queue = CreateObject<RedQueueDisc>();
330  minTh = 5 * modeSize;
331  maxTh = 15 * modeSize;
332  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MinTh", DoubleValue(minTh)),
333  true,
334  "Verify that we can actually set the attribute MinTh");
335  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("MaxTh", DoubleValue(maxTh)),
336  true,
337  "Verify that we can actually set the attribute MaxTh");
339  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
340  true,
341  "Verify that we can actually set the attribute MaxSize");
342  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("QW", DoubleValue(0.002)),
343  true,
344  "Verify that we can actually set the attribute QW");
345  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("LInterm", DoubleValue(2)),
346  true,
347  "Verify that we can actually set the attribute LInterm");
348  queue->Initialize();
349  EnqueueWithDelay(queue, pktSize, 300);
350  Simulator::Stop(Seconds(5));
351  Simulator::Run();
352  st = queue->GetStats();
353  uint32_t test9 = st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP);
354  NS_TEST_ASSERT_MSG_NE(st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP),
355  0,
356  "There should be some unforced drops");
357 
358  // test 10: Adaptive RED (automatic and adaptive settings enabled)
359  queue = CreateObject<RedQueueDisc>();
361  queue->SetAttributeFailSafe("MaxSize", QueueSizeValue(QueueSize(mode, qSize))),
362  true,
363  "Verify that we can actually set the attribute MaxSize");
364  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("LInterm", DoubleValue(2)),
365  true,
366  "Verify that we can actually set the attribute LInterm");
367  NS_TEST_ASSERT_MSG_EQ(queue->SetAttributeFailSafe("ARED", BooleanValue(true)),
368  true,
369  "Verify that we can actually set the attribute ARED");
370  queue->Initialize();
371  EnqueueWithDelay(queue, pktSize, 300);
372  Simulator::Stop(Seconds(5));
373  Simulator::Run();
374  st = queue->GetStats();
375  uint32_t test10 = st.GetNDroppedPackets(RedQueueDisc::UNFORCED_DROP);
376  NS_TEST_ASSERT_MSG_LT(test10, test9, "Test 10 should have less unforced drops than test 9");
377 }
378 
379 void
380 AredQueueDiscTestCase::Enqueue(Ptr<RedQueueDisc> queue, uint32_t size, uint32_t nPkt)
381 {
382  Address dest;
383  for (uint32_t i = 0; i < nPkt; i++)
384  {
385  queue->Enqueue(Create<AredQueueDiscTestItem>(Create<Packet>(size), dest));
386  }
387 }
388 
389 void
390 AredQueueDiscTestCase::EnqueueWithDelay(Ptr<RedQueueDisc> queue, uint32_t size, uint32_t nPkt)
391 {
392  Address dest;
393  double delay = 0.01; // enqueue packets with delay to allow m_curMaxP to adapt
394  for (uint32_t i = 0; i < nPkt; i++)
395  {
396  Simulator::Schedule(Time(Seconds((i + 1) * delay)),
398  this,
399  queue,
400  size,
401  1);
402  }
403 }
404 
405 void
407 {
410  Simulator::Destroy();
411 }
412 
418 static class AredQueueDiscTestSuite : public TestSuite
419 {
420  public:
422  : TestSuite("adaptive-red-queue-disc", UNIT)
423  {
424  AddTestCase(new AredQueueDiscTestCase(), TestCase::QUICK);
425  }
void RunAredDiscTest(QueueSizeUnit mode)
Run ARED queue disc test function.
void Enqueue(Ptr< RedQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
void EnqueueWithDelay(Ptr< RedQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue with delay function.
void DoRun() override
Implementation to actually run this TestCase.
AredQueueDiscTestItem()=delete
void AddHeader() override
Add the header to the packet.
AredQueueDiscTestItem(const AredQueueDiscTestItem &)=delete
bool Mark() override
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification.
AredQueueDiscTestItem & operator=(const AredQueueDiscTestItem &)=delete
a polymophic address class
Definition: address.h:101
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:133
Class for representing queue sizes.
Definition: queue-size.h:96
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:327
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
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
AredQueueDiscTestSuite g_aredQueueDiscTestSuite
the test suite
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:839
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Structure that keeps the queue disc statistics.
Definition: queue-disc.h:188
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
Definition: queue-disc.cc:111
uint32_t pktSize
packet size used for the simulation (in bytes)