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/packet.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 
34 /**
35  * \ingroup traffic-control-test
36  * \ingroup tests
37  *
38  * \brief Red Queue Disc Test Item
39  */
40 class RedQueueDiscTestItem : public QueueDiscItem {
41 public:
42   /**
43    * Constructor
44    *
45    * \param p packet
46    * \param addr address
47    * \param ecnCapable ECN capable flag
48    */
49   RedQueueDiscTestItem (Ptr<Packet> p, const Address & addr, bool ecnCapable);
50   virtual ~RedQueueDiscTestItem ();
51   virtual void AddHeader (void);
52   virtual bool Mark(void);
53 
54 private:
55   RedQueueDiscTestItem ();
56   /**
57    * \brief Copy constructor
58    * Disable default implementation to avoid misuse
59    */
60   RedQueueDiscTestItem (const RedQueueDiscTestItem &);
61   /**
62    * \brief Assignment operator
63    * \return this object
64    * Disable default implementation to avoid misuse
65    */
66   RedQueueDiscTestItem &operator = (const RedQueueDiscTestItem &);
67   bool m_ecnCapablePacket; ///< ECN capable packet?
68 };
69 
RedQueueDiscTestItem(Ptr<Packet> p,const Address & addr,bool ecnCapable)70 RedQueueDiscTestItem::RedQueueDiscTestItem (Ptr<Packet> p, const Address & addr, bool ecnCapable)
71   : QueueDiscItem (p, addr, 0),
72     m_ecnCapablePacket (ecnCapable)
73 {
74 }
75 
~RedQueueDiscTestItem()76 RedQueueDiscTestItem::~RedQueueDiscTestItem ()
77 {
78 }
79 
80 void
AddHeader(void)81 RedQueueDiscTestItem::AddHeader (void)
82 {
83 }
84 
85 bool
Mark(void)86 RedQueueDiscTestItem::Mark (void)
87 {
88   if (m_ecnCapablePacket)
89     {
90       return true;
91     }
92   return false;
93 }
94 
95 /**
96  * \ingroup traffic-control-test
97  * \ingroup tests
98  *
99  * \brief Red Queue Disc Test Case
100  */
101 class RedQueueDiscTestCase : public TestCase
102 {
103 public:
104   RedQueueDiscTestCase ();
105   virtual void DoRun (void);
106 private:
107   /**
108    * Enqueue function
109    * \param queue the queue disc
110    * \param size the size
111    * \param nPkt the number of packets
112    * \param ecnCapable ECN capable flag
113    */
114   void Enqueue (Ptr<RedQueueDisc> queue, uint32_t size, uint32_t nPkt, bool ecnCapable);
115   /**
116    * Run RED test function
117    * \param mode the mode
118    */
119   void RunRedTest (QueueSizeUnit mode);
120 };
121 
RedQueueDiscTestCase()122 RedQueueDiscTestCase::RedQueueDiscTestCase ()
123   : TestCase ("Sanity check on the red queue implementation")
124 {
125 }
126 
127 void
RunRedTest(QueueSizeUnit mode)128 RedQueueDiscTestCase::RunRedTest (QueueSizeUnit mode)
129 {
130   uint32_t pktSize = 0;
131   // 1 for packets; pktSize for bytes
132   uint32_t modeSize = 1;
133   double minTh = 2;
134   double maxTh = 5;
135   uint32_t qSize = 8;
136   Ptr<RedQueueDisc> queue = CreateObject<RedQueueDisc> ();
137 
138   // test 1: simple enqueue/dequeue with no drops
139   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
140                          "Verify that we can actually set the attribute MinTh");
141   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
142                          "Verify that we can actually set the attribute MaxTh");
143   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
144                          true, "Verify that we can actually set the attribute MaxSize");
145   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
146                          "Verify that we can actually set the attribute QW");
147 
148   Address dest;
149 
150   if (mode == QueueSizeUnit::BYTES)
151     {
152       // pktSize should be same as MeanPktSize to avoid performance gap between byte and packet mode
153       pktSize = 500;
154       modeSize = pktSize;
155       queue->SetTh (minTh * modeSize, maxTh * modeSize);
156       queue->SetMaxSize (QueueSize (mode, qSize * modeSize));
157     }
158 
159   Ptr<Packet> p1, p2, p3, p4, p5, p6, p7, p8;
160   p1 = Create<Packet> (pktSize);
161   p2 = Create<Packet> (pktSize);
162   p3 = Create<Packet> (pktSize);
163   p4 = Create<Packet> (pktSize);
164   p5 = Create<Packet> (pktSize);
165   p6 = Create<Packet> (pktSize);
166   p7 = Create<Packet> (pktSize);
167   p8 = Create<Packet> (pktSize);
168 
169   queue->Initialize ();
170   NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 0 * modeSize, "There should be no packets in there");
171   queue->Enqueue (Create<RedQueueDiscTestItem> (p1, dest, false));
172   NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 1 * modeSize, "There should be one packet in there");
173   queue->Enqueue (Create<RedQueueDiscTestItem> (p2, dest, false));
174   NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 2 * modeSize, "There should be two packets in there");
175   queue->Enqueue (Create<RedQueueDiscTestItem> (p3, dest, false));
176   queue->Enqueue (Create<RedQueueDiscTestItem> (p4, dest, false));
177   queue->Enqueue (Create<RedQueueDiscTestItem> (p5, dest, false));
178   queue->Enqueue (Create<RedQueueDiscTestItem> (p6, dest, false));
179   queue->Enqueue (Create<RedQueueDiscTestItem> (p7, dest, false));
180   queue->Enqueue (Create<RedQueueDiscTestItem> (p8, dest, false));
181   NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 8 * modeSize, "There should be eight packets in there");
182 
183   Ptr<QueueDiscItem> item;
184 
185   item = queue->Dequeue ();
186   NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the first packet");
187   NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 7 * modeSize, "There should be seven packets in there");
188   NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p1->GetUid (), "was this the first packet ?");
189 
190   item = queue->Dequeue ();
191   NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the second packet");
192   NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 6 * modeSize, "There should be six packet in there");
193   NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p2->GetUid (), "Was this the second packet ?");
194 
195   item = queue->Dequeue ();
196   NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the third packet");
197   NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 5 * modeSize, "There should be five packets in there");
198   NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p3->GetUid (), "Was this the third packet ?");
199 
200   item = queue->Dequeue ();
201   item = queue->Dequeue ();
202   item = queue->Dequeue ();
203   item = queue->Dequeue ();
204   item = queue->Dequeue ();
205 
206   item = queue->Dequeue ();
207   NS_TEST_EXPECT_MSG_EQ ((item == 0), true, "There are really no packets in there");
208 
209 
210   // test 2: more data, but with no drops
211   queue = CreateObject<RedQueueDisc> ();
212   minTh = 70 * modeSize;
213   maxTh = 150 * modeSize;
214   qSize = 300 * modeSize;
215   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
216                          "Verify that we can actually set the attribute MinTh");
217   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
218                          "Verify that we can actually set the attribute MaxTh");
219   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
220                          true, "Verify that we can actually set the attribute MaxSize");
221   queue->Initialize ();
222   Enqueue (queue, pktSize, 300, false);
223   QueueDisc::Stats st = queue->GetStats ();
224   NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
225                          "There should be zero unforced drops");
226   NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP), 0,
227                          "There should be zero forced dropps");
228   NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP), 0,
229                          "There should be zero drops due to queue limit");
230 
231   // save number of drops from tests
232   struct d {
233     uint32_t test3;
234     uint32_t test4;
235     uint32_t test5;
236     uint32_t test6;
237     uint32_t test7;
238     uint32_t test11;
239     uint32_t test12;
240     uint32_t test13;
241   } drop;
242 
243 
244   // test 3: more data, now drops due QW change
245   queue = CreateObject<RedQueueDisc> ();
246   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
247                          "Verify that we can actually set the attribute MinTh");
248   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
249                          "Verify that we can actually set the attribute MaxTh");
250   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
251                          true, "Verify that we can actually set the attribute MaxSize");
252   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
253                          "Verify that we can actually set the attribute QW");
254   queue->Initialize ();
255   Enqueue (queue, pktSize, 300, false);
256   st = queue->GetStats ();
257   drop.test3 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP)
258                + st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP)
259                + st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP);
260   NS_TEST_EXPECT_MSG_NE (drop.test3, 0, "There should be some dropped packets");
261 
262 
263   // test 4: reduced maxTh, this causes more drops
264   maxTh = 100 * modeSize;
265   queue = CreateObject<RedQueueDisc> ();
266   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
267                          "Verify that we can actually set the attribute MinTh");
268   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
269                          "Verify that we can actually set the attribute MaxTh");
270   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
271                          true, "Verify that we can actually set the attribute MaxSize");
272   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
273                          "Verify that we can actually set the attribute QW");
274   queue->Initialize ();
275   Enqueue (queue, pktSize, 300, false);
276   st = queue->GetStats ();
277   drop.test4 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP)
278                + st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP)
279                + st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP);
280   NS_TEST_EXPECT_MSG_GT (drop.test4, drop.test3, "Test 4 should have more drops than test 3");
281 
282 
283   // test 5: change drop probability to a high value (LInterm)
284   maxTh = 150 * modeSize;
285   queue = CreateObject<RedQueueDisc> ();
286   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
287                          "Verify that we can actually set the attribute MinTh");
288   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
289                          "Verify that we can actually set the attribute MaxTh");
290   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
291                          true, "Verify that we can actually set the attribute MaxSize");
292   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
293                          "Verify that we can actually set the attribute QW");
294   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (5)), true,
295                          "Verify that we can actually set the attribute LInterm");
296   queue->Initialize ();
297   Enqueue (queue, pktSize, 300, false);
298   st = queue->GetStats ();
299   drop.test5 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP)
300                + st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP)
301                + st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP);
302   NS_TEST_EXPECT_MSG_GT (drop.test5, drop.test3, "Test 5 should have more drops than test 3");
303 
304 
305   // test 6: disable Gentle param
306   queue = CreateObject<RedQueueDisc> ();
307   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
308                          "Verify that we can actually set the attribute MinTh");
309   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
310                          "Verify that we can actually set the attribute MaxTh");
311   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
312                          true, "Verify that we can actually set the attribute MaxSize");
313   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
314                          "Verify that we can actually set the attribute QW");
315   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (false)), true,
316                          "Verify that we can actually set the attribute Gentle");
317   queue->Initialize ();
318   Enqueue (queue, pktSize, 300, false);
319   st = queue->GetStats ();
320   drop.test6 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP)
321                + st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP)
322                + st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP);
323   NS_TEST_EXPECT_MSG_GT (drop.test6, drop.test3, "Test 6 should have more drops than test 3");
324 
325 
326   // test 7: disable Wait param
327   queue = CreateObject<RedQueueDisc> ();
328   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
329                          "Verify that we can actually set the attribute MinTh");
330   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
331                          "Verify that we can actually set the attribute MaxTh");
332   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
333                          true, "Verify that we can actually set the attribute MaxSize");
334   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
335                          "Verify that we can actually set the attribute QW");
336   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Wait", BooleanValue (false)), true,
337                          "Verify that we can actually set the attribute Wait");
338   queue->Initialize ();
339   Enqueue (queue, pktSize, 300, false);
340   st = queue->GetStats ();
341   drop.test7 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP)
342                + st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP)
343                + st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP);
344   NS_TEST_EXPECT_MSG_GT (drop.test7, drop.test3, "Test 7 should have more drops than test 3");
345 
346 
347   // test 8: RED queue disc is ECN enabled, but packets are not ECN capable
348   queue = CreateObject<RedQueueDisc> ();
349   minTh = 30 * modeSize;
350   maxTh = 90 * modeSize;
351   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
352                          "Verify that we can actually set the attribute MinTh");
353   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
354                          "Verify that we can actually set the attribute MaxTh");
355   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
356                          true, "Verify that we can actually set the attribute MaxSize");
357   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
358                          "Verify that we can actually set the attribute QW");
359   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (2)), true,
360                          "Verify that we can actually set the attribute LInterm");
361   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (true)), true,
362                          "Verify that we can actually set the attribute Gentle");
363   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)), true,
364                          "Verify that we can actually set the attribute UseECN");
365   queue->Initialize ();
366   Enqueue (queue, pktSize, 300, false);
367   st = queue->GetStats ();
368   // Packets are not ECN capable, so there should be only unforced drops, no unforced marks
369   NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
370                          "There should be some unforced drops");
371   NS_TEST_EXPECT_MSG_EQ (st.GetNMarkedPackets (RedQueueDisc::UNFORCED_MARK), 0,
372                          "There should be no unforced marks");
373 
374 
375   // test 9: Packets are ECN capable, but RED queue disc is not ECN enabled
376   queue = CreateObject<RedQueueDisc> ();
377   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
378                          "Verify that we can actually set the attribute MinTh");
379   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
380                          "Verify that we can actually set the attribute MaxTh");
381   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
382                          true, "Verify that we can actually set the attribute MaxSize");
383   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
384                          "Verify that we can actually set the attribute QW");
385   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (2)), true,
386                          "Verify that we can actually set the attribute LInterm");
387   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (true)), true,
388                          "Verify that we can actually set the attribute Gentle");
389   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (false)), true,
390                          "Verify that we can actually set the attribute UseECN");
391   queue->Initialize ();
392   Enqueue (queue, pktSize, 300, true);
393   st = queue->GetStats ();
394   // RED queue disc is not ECN enabled, so there should be only unforced drops, no unforced marks
395   NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
396                          "There should be some unforced drops");
397   NS_TEST_EXPECT_MSG_EQ (st.GetNMarkedPackets (RedQueueDisc::UNFORCED_MARK), 0,
398                          "There should be no unforced marks");
399 
400 
401   // test 10: Packets are ECN capable and RED queue disc is ECN enabled
402   queue = CreateObject<RedQueueDisc> ();
403   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
404                          "Verify that we can actually set the attribute MinTh");
405   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
406                          "Verify that we can actually set the attribute MaxTh");
407   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
408                          true, "Verify that we can actually set the attribute MaxSize");
409   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
410                          "Verify that we can actually set the attribute QW");
411   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (2)), true,
412                          "Verify that we can actually set the attribute LInterm");
413   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (true)), true,
414                          "Verify that we can actually set the attribute Gentle");
415   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("UseEcn", BooleanValue (true)), true,
416                          "Verify that we can actually set the attribute UseECN");
417   queue->Initialize ();
418   Enqueue (queue, pktSize, 300, true);
419   st = queue->GetStats ();
420   // Packets are ECN capable, RED queue disc is ECN enabled; there should be only unforced marks, no unforced drops
421   NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
422                          "There should be no unforced drops");
423   NS_TEST_EXPECT_MSG_NE (st.GetNMarkedPackets (RedQueueDisc::UNFORCED_MARK), 0,
424                          "There should be some unforced marks");
425 
426 
427   // test 11: RED with default parameter settings, linear drop probability and fixed m_curMaxP
428   queue = CreateObject<RedQueueDisc> ();
429   minTh = 30 * modeSize;
430   maxTh = 90 * modeSize;
431   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
432                          "Verify that we can actually set the attribute MinTh");
433   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
434                          "Verify that we can actually set the attribute MaxTh");
435   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
436                          true, "Verify that we can actually set the attribute MaxSize");
437   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
438                          "Verify that we can actually set the attribute QW");
439   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (2)), true,
440                          "Verify that we can actually set the attribute LInterm");
441   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (true)), true,
442                          "Verify that we can actually set the attribute Gentle");
443   queue->Initialize ();
444   Enqueue (queue, pktSize, 300, false);
445   st = queue->GetStats ();
446   drop.test11 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP);
447   NS_TEST_EXPECT_MSG_NE (drop.test11, 0, "There should some dropped packets due to probability mark");
448 
449 
450   // test 12: Feng's Adaptive RED with default parameter settings and varying m_curMaxP
451   queue = CreateObject<RedQueueDisc> ();
452   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
453                          "Verify that we can actually set the attribute MinTh");
454   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
455                          "Verify that we can actually set the attribute MaxTh");
456   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
457                          true, "Verify that we can actually set the attribute MaxSize");
458   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
459                          "Verify that we can actually set the attribute QW");
460   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (2)), true,
461                          "Verify that we can actually set the attribute LInterm");
462   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (true)), true,
463                          "Verify that we can actually set the attribute Gentle");
464   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("FengAdaptive", BooleanValue (true)), true,
465                          "Verify that we can actually set the attribute FengAdaptive");
466   queue->Initialize ();
467   Enqueue (queue, pktSize, 300, false);
468   st = queue->GetStats ();
469   drop.test12 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP);
470   NS_TEST_EXPECT_MSG_LT (drop.test12, drop.test11, "Test 12 should have less drops due to probability mark than test 11");
471 
472 
473   // test 13: RED with Nonlinear drop probability
474   queue = CreateObject<RedQueueDisc> ();
475   minTh = 30 * modeSize;
476   maxTh = 90 * modeSize;
477   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
478                          "Verify that we can actually set the attribute MinTh");
479   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
480                          "Verify that we can actually set the attribute MaxTh");
481   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
482                          true, "Verify that we can actually set the attribute MaxSize");
483   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
484                          "Verify that we can actually set the attribute QW");
485   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (2)), true,
486                          "Verify that we can actually set the attribute LInterm");
487   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (true)), true,
488                          "Verify that we can actually set the attribute Gentle");
489   NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("NLRED", BooleanValue (true)), true,
490                          "Verify that we can actually set the attribute NLRED");
491   queue->Initialize ();
492   Enqueue (queue, pktSize, 300, false);
493   st = queue->GetStats ();
494   drop.test13 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP);
495   NS_TEST_EXPECT_MSG_LT (drop.test13, drop.test11, "Test 13 should have less drops due to probability mark than test 11");
496 
497 }
498 
499 void
Enqueue(Ptr<RedQueueDisc> queue,uint32_t size,uint32_t nPkt,bool ecnCapable)500 RedQueueDiscTestCase::Enqueue (Ptr<RedQueueDisc> queue, uint32_t size, uint32_t nPkt, bool ecnCapable)
501 {
502   Address dest;
503   for (uint32_t i = 0; i < nPkt; i++)
504     {
505       queue->Enqueue (Create<RedQueueDiscTestItem> (Create<Packet> (size), dest, ecnCapable));
506     }
507 }
508 
509 void
DoRun(void)510 RedQueueDiscTestCase::DoRun (void)
511 {
512   RunRedTest (QueueSizeUnit::PACKETS);
513   RunRedTest (QueueSizeUnit::BYTES);
514   Simulator::Destroy ();
515 
516 }
517 
518 /**
519  * \ingroup traffic-control-test
520  * \ingroup tests
521  *
522  * \brief Red Queue Disc Test Suite
523  */
524 static class RedQueueDiscTestSuite : public TestSuite
525 {
526 public:
RedQueueDiscTestSuite()527   RedQueueDiscTestSuite ()
528     : TestSuite ("red-queue-disc", UNIT)
529   {
530     AddTestCase (new RedQueueDiscTestCase (), TestCase::QUICK);
531   }
532 } g_redQueueTestSuite; ///< the test suite
533