A Discrete-Event Network Simulator
API
red-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 © 2011 Marcos Talau
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  * Author: Marcos Talau (talau@users.sourceforge.net)
19  * Modified by: Pasquale Imputato <p.imputato@gmail.com>
20  *
21  */
22 
23 #include "ns3/test.h"
24 #include "ns3/red-queue-disc.h"
25 #include "ns3/drop-tail-queue.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/string.h"
28 #include "ns3/double.h"
29 #include "ns3/log.h"
30 #include "ns3/simulator.h"
31 
32 using namespace ns3;
33 
35 public:
36  RedQueueDiscTestItem (Ptr<Packet> p, const Address & addr, uint16_t protocol);
37  virtual ~RedQueueDiscTestItem ();
38  virtual void AddHeader (void);
39 
40 private:
43  RedQueueDiscTestItem &operator = (const RedQueueDiscTestItem &);
44 };
45 
47  : QueueDiscItem (p, addr, protocol)
48 {
49 }
50 
52 {
53 }
54 
55 void
57 {
58 }
59 
61 {
62 public:
64  virtual void DoRun (void);
65 private:
66  void Enqueue (Ptr<RedQueueDisc> queue, uint32_t size, uint32_t nPkt);
67  void RunRedTest (StringValue mode);
68 };
69 
71  : TestCase ("Sanity check on the red queue implementation")
72 {
73 }
74 
75 void
77 {
78  uint32_t pktSize = 0;
79  // 1 for packets; pktSize for bytes
80  uint32_t modeSize = 1;
81  double minTh = 2;
82  double maxTh = 5;
83  uint32_t qSize = 8;
84  Ptr<RedQueueDisc> queue = CreateObject<RedQueueDisc> ();
85 
86  // test 1: simple enqueue/dequeue with no drops
87  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
88  "Verify that we can actually set the attribute Mode");
89  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
90  "Verify that we can actually set the attribute MinTh");
91  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
92  "Verify that we can actually set the attribute MaxTh");
93  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
94  "Verify that we can actually set the attribute QueueLimit");
95  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
96  "Verify that we can actually set the attribute QW");
97 
98  Address dest;
99 
100  if (queue->GetMode () == Queue::QUEUE_MODE_BYTES)
101  {
102  pktSize = 1000;
103  modeSize = pktSize;
104  queue->SetTh (minTh * modeSize, maxTh * modeSize);
105  queue->SetQueueLimit (qSize * modeSize);
106  }
107 
108  Ptr<Packet> p1, p2, p3, p4, p5, p6, p7, p8;
109  p1 = Create<Packet> (pktSize);
110  p2 = Create<Packet> (pktSize);
111  p3 = Create<Packet> (pktSize);
112  p4 = Create<Packet> (pktSize);
113  p5 = Create<Packet> (pktSize);
114  p6 = Create<Packet> (pktSize);
115  p7 = Create<Packet> (pktSize);
116  p8 = Create<Packet> (pktSize);
117 
118  queue->Initialize ();
119  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 0 * modeSize, "There should be no packets in there");
120  queue->Enqueue (Create<RedQueueDiscTestItem> (p1, dest, 0));
121  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 1 * modeSize, "There should be one packet in there");
122  queue->Enqueue (Create<RedQueueDiscTestItem> (p2, dest, 0));
123  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 2 * modeSize, "There should be two packets in there");
124  queue->Enqueue (Create<RedQueueDiscTestItem> (p3, dest, 0));
125  queue->Enqueue (Create<RedQueueDiscTestItem> (p4, dest, 0));
126  queue->Enqueue (Create<RedQueueDiscTestItem> (p5, dest, 0));
127  queue->Enqueue (Create<RedQueueDiscTestItem> (p6, dest, 0));
128  queue->Enqueue (Create<RedQueueDiscTestItem> (p7, dest, 0));
129  queue->Enqueue (Create<RedQueueDiscTestItem> (p8, dest, 0));
130  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 8 * modeSize, "There should be eight packets in there");
131 
132  Ptr<QueueDiscItem> item;
133 
134  item = queue->Dequeue ();
135  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the first packet");
136  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 7 * modeSize, "There should be seven packets in there");
137  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p1->GetUid (), "was this the first packet ?");
138 
139  item = queue->Dequeue ();
140  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the second packet");
141  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 6 * modeSize, "There should be six packet in there");
142  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p2->GetUid (), "Was this the second packet ?");
143 
144  item = queue->Dequeue ();
145  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the third packet");
146  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 5 * modeSize, "There should be five packets in there");
147  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p3->GetUid (), "Was this the third packet ?");
148 
149  item = queue->Dequeue ();
150  item = queue->Dequeue ();
151  item = queue->Dequeue ();
152  item = queue->Dequeue ();
153  item = queue->Dequeue ();
154 
155  item = queue->Dequeue ();
156  NS_TEST_EXPECT_MSG_EQ ((item == 0), true, "There are really no packets in there");
157 
158 
159  // test 2: more data, but with no drops
160  queue = CreateObject<RedQueueDisc> ();
161  minTh = 70 * modeSize;
162  maxTh = 150 * modeSize;
163  qSize = 300 * modeSize;
164  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
165  "Verify that we can actually set the attribute Mode");
166  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
167  "Verify that we can actually set the attribute MinTh");
168  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
169  "Verify that we can actually set the attribute MaxTh");
170  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
171  "Verify that we can actually set the attribute QueueLimit");
172  queue->Initialize ();
173  Enqueue (queue, pktSize, 300);
174  RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queue)->GetStats ();
175  NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should zero dropped packets due probability mark");
176  NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should zero dropped packets due hardmark mark");
177  NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should zero dropped packets due queue full");
178 
179  // save number of drops from tests
180  struct d {
181  uint32_t test3;
182  uint32_t test4;
183  uint32_t test5;
184  uint32_t test6;
185  uint32_t test7;
186  } drop;
187 
188 
189  // test 3: more data, now drops due QW change
190  queue = CreateObject<RedQueueDisc> ();
191  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
192  "Verify that we can actually set the attribute Mode");
193  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
194  "Verify that we can actually set the attribute MinTh");
195  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
196  "Verify that we can actually set the attribute MaxTh");
197  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
198  "Verify that we can actually set the attribute QueueLimit");
199  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
200  "Verify that we can actually set the attribute QW");
201  queue->Initialize ();
202  Enqueue (queue, pktSize, 300);
203  st = StaticCast<RedQueueDisc> (queue)->GetStats ();
204  drop.test3 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
205  NS_TEST_EXPECT_MSG_NE (drop.test3, 0, "There should be some dropped packets");
206 
207 
208  // test 4: reduced maxTh, this causes more drops
209  maxTh = 100 * modeSize;
210  queue = CreateObject<RedQueueDisc> ();
211  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
212  "Verify that we can actually set the attribute Mode");
213  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
214  "Verify that we can actually set the attribute MinTh");
215  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
216  "Verify that we can actually set the attribute MaxTh");
217  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
218  "Verify that we can actually set the attribute QueueLimit");
219  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
220  "Verify that we can actually set the attribute QW");
221  queue->Initialize ();
222  Enqueue (queue, pktSize, 300);
223  st = StaticCast<RedQueueDisc> (queue)->GetStats ();
224  drop.test4 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
225  NS_TEST_EXPECT_MSG_GT (drop.test4, drop.test3, "Test 4 should have more drops than test 3");
226 
227 
228  // test 5: change drop probability to a high value (LInterm)
229  maxTh = 150 * modeSize;
230  queue = CreateObject<RedQueueDisc> ();
231  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
232  "Verify that we can actually set the attribute Mode");
233  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
234  "Verify that we can actually set the attribute MinTh");
235  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
236  "Verify that we can actually set the attribute MaxTh");
237  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
238  "Verify that we can actually set the attribute QueueLimit");
239  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
240  "Verify that we can actually set the attribute QW");
241  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (5)), true,
242  "Verify that we can actually set the attribute LInterm");
243  queue->Initialize ();
244  Enqueue (queue, pktSize, 300);
245  st = StaticCast<RedQueueDisc> (queue)->GetStats ();
246  drop.test5 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
247  NS_TEST_EXPECT_MSG_GT (drop.test5, drop.test3, "Test 5 should have more drops than test 3");
248 
249 
250  // test 6: disable Gentle param
251  queue = CreateObject<RedQueueDisc> ();
252  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
253  "Verify that we can actually set the attribute Mode");
254  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
255  "Verify that we can actually set the attribute MinTh");
256  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
257  "Verify that we can actually set the attribute MaxTh");
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 ("QW", DoubleValue (0.020)), true,
261  "Verify that we can actually set the attribute QW");
262  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (false)), true,
263  "Verify that we can actually set the attribute Gentle");
264  queue->Initialize ();
265  Enqueue (queue, pktSize, 300);
266  st = StaticCast<RedQueueDisc> (queue)->GetStats ();
267  drop.test6 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
268  NS_TEST_EXPECT_MSG_GT (drop.test6, drop.test3, "Test 6 should have more drops than test 3");
269 
270 
271  // test 7: disable Wait param
272  queue = CreateObject<RedQueueDisc> ();
273  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
274  "Verify that we can actually set the attribute Mode");
275  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
276  "Verify that we can actually set the attribute MinTh");
277  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
278  "Verify that we can actually set the attribute MaxTh");
279  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
280  "Verify that we can actually set the attribute QueueLimit");
281  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
282  "Verify that we can actually set the attribute QW");
283  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Wait", BooleanValue (false)), true,
284  "Verify that we can actually set the attribute Wait");
285  queue->Initialize ();
286  Enqueue (queue, pktSize, 300);
287  st = StaticCast<RedQueueDisc> (queue)->GetStats ();
288  drop.test7 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
289  NS_TEST_EXPECT_MSG_GT (drop.test7, drop.test3, "Test 7 should have more drops than test 3");
290 }
291 
292 void
293 RedQueueDiscTestCase::Enqueue (Ptr<RedQueueDisc> queue, uint32_t size, uint32_t nPkt)
294 {
295  Address dest;
296  for (uint32_t i = 0; i < nPkt; i++)
297  {
298  queue->Enqueue (Create<RedQueueDiscTestItem> (Create<Packet> (size), dest, 0));
299  }
300 }
301 
302 void
304 {
305  RunRedTest (StringValue ("QUEUE_MODE_PACKETS"));
306  RunRedTest (StringValue ("QUEUE_MODE_BYTES"));
307  Simulator::Destroy ();
308 
309 }
310 
311 static class RedQueueDiscTestSuite : public TestSuite
312 {
313 public:
315  : TestSuite ("red-queue-disc", UNIT)
316  {
317  AddTestCase (new RedQueueDiscTestCase (), TestCase::QUICK);
318  }
uint32_t GetQueueSize(void)
Get the current value of the queue in bytes or packets.
AttributeValue implementation for Boolean.
Definition: boolean.h:34
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
Definition: queue-disc.cc:451
Hold variables of type string.
Definition: string.h:41
void SetTh(double minTh, double maxTh)
Set the thresh limits of RED.
virtual void AddHeader(void)
Add the header to the packet.
A suite of tests to run.
Definition: test.h:1333
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:368
#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:278
bool SetAttributeFailSafe(std::string name, const AttributeValue &value)
Set a single attribute without raising errors.
Definition: object-base.cc:211
RedQueueDiscTestSuite g_redQueueTestSuite
void Enqueue(Ptr< RedQueueDisc > queue, uint32_t size, uint32_t nPkt)
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-disc.h:43
encapsulates test code
Definition: test.h:1147
This test suite implements a Unit Test.
Definition: test.h:1343
a polymophic address class
Definition: address.h:90
void SetQueueLimit(uint32_t lim)
Set the limit of the queue.
uint32_t forcedDrop
Forced drops, qavg > max threshold.
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:298
Hold an unsigned integer type.
Definition: uinteger.h:44
uint32_t qLimDrop
Drops due to queue limits.
Ptr< QueueDiscItem > Dequeue(void)
Request the queue discipline to extract a packet.
Definition: queue-disc.cc:467
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Queue::QueueMode GetMode(void)
Get the encapsulation mode of this queue.
#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:732
#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:1083
void RunRedTest(StringValue mode)
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
virtual void DoRun(void)
Implementation to actually run this TestCase.
uint32_t unforcedDrop
Early probability drops.