A Discrete-Event Network Simulator
API
fq-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 Universita' degli Studi di Napoli Federico II
4  * Copyright (c) 2020 NITK Surathkal (modified for FQ-PIE)
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Authors: Pasquale Imputato <p.imputato@gmail.com>
20  * Stefano Avallone <stefano.avallone@unina.it>
21  * Modified for FQ-PIE by: Bhaskar Kataria <bhaskar.k7920@gmail.com>
22  * Tom Henderson <tomhend@u.washington.edu>
23  * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
24  * Vivek Jain <jain.vivek.anand@gmail.com>
25  * Ankit Deepak <adadeepak8@gmail.com>
26  *
27  */
28 
29 #include "ns3/test.h"
30 #include "ns3/simulator.h"
31 #include "ns3/fq-pie-queue-disc.h"
32 #include "ns3/pie-queue-disc.h"
33 #include "ns3/ipv4-header.h"
34 #include "ns3/ipv4-packet-filter.h"
35 #include "ns3/ipv4-queue-disc-item.h"
36 #include "ns3/ipv4-address.h"
37 #include "ns3/ipv6-header.h"
38 #include "ns3/ipv6-packet-filter.h"
39 #include "ns3/ipv6-queue-disc-item.h"
40 #include "ns3/tcp-header.h"
41 #include "ns3/udp-header.h"
42 #include "ns3/string.h"
43 #include "ns3/pointer.h"
44 
45 using namespace ns3;
46 
48 static int32_t g_hash;
49 
56 {
57 public:
62  static TypeId GetTypeId (void);
63 
65  virtual ~Ipv4FqPieTestPacketFilter ();
66 
67 private:
73  virtual int32_t DoClassify (Ptr<QueueDiscItem> item) const;
74 
80  virtual bool CheckProtocol (Ptr<QueueDiscItem> item) const;
81 };
82 
83 TypeId
85 {
86  static TypeId tid = TypeId ("ns3::Ipv4FqPieTestPacketFilter")
88  .SetGroupName ("Internet")
89  .AddConstructor<Ipv4FqPieTestPacketFilter> ()
90  ;
91  return tid;
92 }
93 
95 {}
96 
98 {}
99 
100 int32_t
102 {
103  return g_hash;
104 }
105 
106 bool
108 {
109  return true;
110 }
111 
118 {
119 public:
121  virtual ~FqPieQueueDiscNoSuitableFilter ();
122 
123 private:
124  virtual void DoRun (void);
125 };
126 
128  : TestCase ("Test packets that are not classified by any filter")
129 {}
130 
132 {}
133 
134 void
136 {
137  // Packets that cannot be classified by the available filters should be dropped
138  Ptr<FqPieQueueDisc> queueDisc = CreateObjectWithAttributes<FqPieQueueDisc> ("MaxSize", StringValue ("4p"));
139  Ptr<Ipv4FqPieTestPacketFilter> filter = CreateObject<Ipv4FqPieTestPacketFilter> ();
140  queueDisc->AddPacketFilter (filter);
141 
142  g_hash = -1;
143  queueDisc->SetQuantum (1500);
144  queueDisc->Initialize ();
145 
146  Ptr<Packet> p;
147  p = Create<Packet> ();
149  Ipv6Header ipv6Header;
150  Address dest;
151  item = Create<Ipv6QueueDiscItem> (p, dest, 0, ipv6Header);
152  queueDisc->Enqueue (item);
153  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetNQueueDiscClasses (), 0, "no flow queue should have been created");
154 
155  p = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello, world"), 12);
156  item = Create<Ipv6QueueDiscItem> (p, dest, 0, ipv6Header);
157  queueDisc->Enqueue (item);
158  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetNQueueDiscClasses (), 0, "no flow queue should have been created");
159 
160  Simulator::Destroy ();
161 }
162 
169 {
170 public:
173 
174 private:
175  virtual void DoRun (void);
181  void AddPacket (Ptr<FqPieQueueDisc> queue, Ipv4Header hdr);
182 };
183 
185  : TestCase ("Test IP flows separation and packet limit")
186 {}
187 
189 {}
190 
191 void
193 {
194  Ptr<Packet> p = Create<Packet> (100);
195  Address dest;
196  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, hdr);
197  queue->Enqueue (item);
198 }
199 
200 void
202 {
203  Ptr<FqPieQueueDisc> queueDisc = CreateObjectWithAttributes<FqPieQueueDisc> ("MaxSize", StringValue ("4p"));
204 
205  queueDisc->SetQuantum (1500);
206  queueDisc->Initialize ();
207 
208  Ipv4Header hdr;
209  hdr.SetPayloadSize (100);
210  hdr.SetSource (Ipv4Address ("10.10.1.1"));
211  hdr.SetDestination (Ipv4Address ("10.10.1.2"));
212  hdr.SetProtocol (7);
213 
214  // Add three packets from the first flow
215  AddPacket (queueDisc, hdr);
216  AddPacket (queueDisc, hdr);
217  AddPacket (queueDisc, hdr);
218  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 3, "unexpected number of packets in the queue disc");
219  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the flow queue");
220 
221  // Add two packets from the second flow
222  hdr.SetDestination (Ipv4Address ("10.10.1.7"));
223  // Add the first packet
224  AddPacket (queueDisc, hdr);
225  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 4, "unexpected number of packets in the queue disc");
226  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the flow queue");
227  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the flow queue");
228  // Add the second packet that causes two packets to be dropped from the fat flow (max backlog = 300, threshold = 150)
229  AddPacket (queueDisc, hdr);
230  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 3, "unexpected number of packets in the queue disc");
231  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the flow queue");
232  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the flow queue");
233 
234  Simulator::Destroy ();
235 }
236 
243 {
244 public:
246  virtual ~FqPieQueueDiscDeficit ();
247 
248 private:
249  virtual void DoRun (void);
255  void AddPacket (Ptr<FqPieQueueDisc> queue, Ipv4Header hdr);
256 };
257 
259  : TestCase ("Test credits and flows status")
260 {}
261 
263 {}
264 
265 void
267 {
268  Ptr<Packet> p = Create<Packet> (100);
269  Address dest;
270  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, hdr);
271  queue->Enqueue (item);
272 }
273 
274 void
276 {
277  Ptr<FqPieQueueDisc> queueDisc = CreateObject<FqPieQueueDisc> ();
278 
279  queueDisc->SetQuantum (90);
280  queueDisc->Initialize ();
281 
282  Ipv4Header hdr;
283  hdr.SetPayloadSize (100);
284  hdr.SetSource (Ipv4Address ("10.10.1.1"));
285  hdr.SetDestination (Ipv4Address ("10.10.1.2"));
286  hdr.SetProtocol (7);
287 
288  // Add a packet from the first flow
289  AddPacket (queueDisc, hdr);
290  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 1, "unexpected number of packets in the queue disc");
291  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the first flow queue");
292  Ptr<FqPieFlow> flow1 = StaticCast<FqPieFlow> (queueDisc->GetQueueDiscClass (0));
293  NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), static_cast<int32_t> (queueDisc->GetQuantum ()), "the deficit of the first flow must equal the quantum");
294  NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqPieFlow::NEW_FLOW, "the first flow must be in the list of new queues");
295  // Dequeue a packet
296  queueDisc->Dequeue ();
297  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 0, "unexpected number of packets in the queue disc");
298  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 0, "unexpected number of packets in the first flow queue");
299  // the deficit for the first flow becomes 90 - (100+20) = -30
300  NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), -30, "unexpected deficit for the first flow");
301 
302  // Add two packets from the first flow
303  AddPacket (queueDisc, hdr);
304  AddPacket (queueDisc, hdr);
305  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 2, "unexpected number of packets in the queue disc");
306  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the first flow queue");
307  NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqPieFlow::NEW_FLOW, "the first flow must still be in the list of new queues");
308 
309  // Add two packets from the second flow
310  hdr.SetDestination (Ipv4Address ("10.10.1.10"));
311  AddPacket (queueDisc, hdr);
312  AddPacket (queueDisc, hdr);
313  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 4, "unexpected number of packets in the queue disc");
314  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the first flow queue");
315  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the second flow queue");
316  Ptr<FqPieFlow> flow2 = StaticCast<FqPieFlow> (queueDisc->GetQueueDiscClass (1));
317  NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), static_cast<int32_t> (queueDisc->GetQuantum ()), "the deficit of the second flow must equal the quantum");
318  NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqPieFlow::NEW_FLOW, "the second flow must be in the list of new queues");
319 
320  // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
321  queueDisc->Dequeue ();
322  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 3, "unexpected number of packets in the queue disc");
323  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the first flow queue");
324  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
325  // the first flow got a quantum of deficit (-30+90=60) and has been moved to the end of the list of old queues
326  NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), 60, "unexpected deficit for the first flow");
327  NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqPieFlow::OLD_FLOW, "the first flow must be in the list of old queues");
328  // the second flow has a negative deficit (-30) and is still in the list of new queues
329  NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), -30, "unexpected deficit for the second flow");
330  NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqPieFlow::NEW_FLOW, "the second flow must be in the list of new queues");
331 
332  // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
333  queueDisc->Dequeue ();
334  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 2, "unexpected number of packets in the queue disc");
335  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the first flow queue");
336  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
337  // the first flow has a negative deficit (60-(100+20)= -60) and stays in the list of old queues
338  NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), -60, "unexpected deficit for the first flow");
339  NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqPieFlow::OLD_FLOW, "the first flow must be in the list of old queues");
340  // the second flow got a quantum of deficit (-30+90=60) and has been moved to the end of the list of old queues
341  NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), 60, "unexpected deficit for the second flow");
342  NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqPieFlow::OLD_FLOW, "the second flow must be in the list of new queues");
343 
344  // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
345  queueDisc->Dequeue ();
346  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 1, "unexpected number of packets in the queue disc");
347  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the first flow queue");
348  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 0, "unexpected number of packets in the second flow queue");
349  // the first flow got a quantum of deficit (-60+90=30) and has been moved to the end of the list of old queues
350  NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), 30, "unexpected deficit for the first flow");
351  NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqPieFlow::OLD_FLOW, "the first flow must be in the list of old queues");
352  // the second flow has a negative deficit (60-(100+20)= -60)
353  NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), -60, "unexpected deficit for the second flow");
354  NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqPieFlow::OLD_FLOW, "the second flow must be in the list of new queues");
355 
356  // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
357  queueDisc->Dequeue ();
358  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 0, "unexpected number of packets in the queue disc");
359  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 0, "unexpected number of packets in the first flow queue");
360  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 0, "unexpected number of packets in the second flow queue");
361  // the first flow has a negative deficit (30-(100+20)= -90)
362  NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), -90, "unexpected deficit for the first flow");
363  NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqPieFlow::OLD_FLOW, "the first flow must be in the list of old queues");
364  // the second flow got a quantum of deficit (-60+90=30) and has been moved to the end of the list of old queues
365  NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), 30, "unexpected deficit for the second flow");
366  NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqPieFlow::OLD_FLOW, "the second flow must be in the list of new queues");
367 
368  // Dequeue a packet
369  queueDisc->Dequeue ();
370  // the first flow is at the head of the list of old queues but has a negative deficit, thus it gets a quantun
371  // of deficit (-90+90=0) and is moved to the end of the list of old queues. Then, the second flow (which has a
372  // positive deficit) is selected, but the second flow is empty and thus it is set to inactive. The first flow is
373  // reconsidered, but it has a null deficit, hence it gets another quantum of deficit (0+90=90). Then, the first
374  // flow is reconsidered again, now it has a positive deficit and hence it is selected. But, it is empty and
375  // therefore is set to inactive, too.
376  NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), 90, "unexpected deficit for the first flow");
377  NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqPieFlow::INACTIVE, "the first flow must be inactive");
378  NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), 30, "unexpected deficit for the second flow");
379  NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqPieFlow::INACTIVE, "the second flow must be inactive");
380 
381  Simulator::Destroy ();
382 }
383 
390 {
391 public:
394 
395 private:
396  virtual void DoRun (void);
403  void AddPacket (Ptr<FqPieQueueDisc> queue, Ipv4Header ipHdr, TcpHeader tcpHdr);
404 };
405 
407  : TestCase ("Test TCP flows separation")
408 {}
409 
411 {}
412 
413 void
415 {
416  Ptr<Packet> p = Create<Packet> (100);
417  p->AddHeader (tcpHdr);
418  Address dest;
419  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, ipHdr);
420  queue->Enqueue (item);
421 }
422 
423 void
425 {
426  Ptr<FqPieQueueDisc> queueDisc = CreateObjectWithAttributes<FqPieQueueDisc> ("MaxSize", StringValue ("10p"));
427 
428  queueDisc->SetQuantum (1500);
429  queueDisc->Initialize ();
430 
431  Ipv4Header hdr;
432  hdr.SetPayloadSize (100);
433  hdr.SetSource (Ipv4Address ("10.10.1.1"));
434  hdr.SetDestination (Ipv4Address ("10.10.1.2"));
435  hdr.SetProtocol (6);
436 
437  TcpHeader tcpHdr;
438  tcpHdr.SetSourcePort (7);
439  tcpHdr.SetDestinationPort (27);
440 
441  // Add three packets from the first flow
442  AddPacket (queueDisc, hdr, tcpHdr);
443  AddPacket (queueDisc, hdr, tcpHdr);
444  AddPacket (queueDisc, hdr, tcpHdr);
445  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 3, "unexpected number of packets in the queue disc");
446  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
447 
448  // Add a packet from the second flow
449  tcpHdr.SetSourcePort (8);
450  AddPacket (queueDisc, hdr, tcpHdr);
451  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 4, "unexpected number of packets in the queue disc");
452  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
453  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
454 
455  // Add a packet from the third flow
456  tcpHdr.SetDestinationPort (28);
457  AddPacket (queueDisc, hdr, tcpHdr);
458  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 5, "unexpected number of packets in the queue disc");
459  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
460  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
461  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the third flow queue");
462 
463  // Add two packets from the fourth flow
464  tcpHdr.SetSourcePort (7);
465  AddPacket (queueDisc, hdr, tcpHdr);
466  AddPacket (queueDisc, hdr, tcpHdr);
467  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 7, "unexpected number of packets in the queue disc");
468  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
469  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
470  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the third flow queue");
471  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (3)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the third flow queue");
472 
473  Simulator::Destroy ();
474 }
475 
482 {
483 public:
486 
487 private:
488  virtual void DoRun (void);
495  void AddPacket (Ptr<FqPieQueueDisc> queue, Ipv4Header ipHdr, UdpHeader udpHdr);
496 };
497 
499  : TestCase ("Test UDP flows separation")
500 {}
501 
503 {}
504 
505 void
507 {
508  Ptr<Packet> p = Create<Packet> (100);
509  p->AddHeader (udpHdr);
510  Address dest;
511  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, ipHdr);
512  queue->Enqueue (item);
513 }
514 
515 void
517 {
518  Ptr<FqPieQueueDisc> queueDisc = CreateObjectWithAttributes<FqPieQueueDisc> ("MaxSize", StringValue ("10p"));
519 
520  queueDisc->SetQuantum (1500);
521  queueDisc->Initialize ();
522 
523  Ipv4Header hdr;
524  hdr.SetPayloadSize (100);
525  hdr.SetSource (Ipv4Address ("10.10.1.1"));
526  hdr.SetDestination (Ipv4Address ("10.10.1.2"));
527  hdr.SetProtocol (17);
528 
529  UdpHeader udpHdr;
530  udpHdr.SetSourcePort (7);
531  udpHdr.SetDestinationPort (27);
532 
533  // Add three packets from the first flow
534  AddPacket (queueDisc, hdr, udpHdr);
535  AddPacket (queueDisc, hdr, udpHdr);
536  AddPacket (queueDisc, hdr, udpHdr);
537  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 3, "unexpected number of packets in the queue disc");
538  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
539 
540  // Add a packet from the second flow
541  udpHdr.SetSourcePort (8);
542  AddPacket (queueDisc, hdr, udpHdr);
543  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 4, "unexpected number of packets in the queue disc");
544  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
545  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
546 
547  // Add a packet from the third flow
548  udpHdr.SetDestinationPort (28);
549  AddPacket (queueDisc, hdr, udpHdr);
550  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 5, "unexpected number of packets in the queue disc");
551  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
552  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
553  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the third flow queue");
554 
555  // Add two packets from the fourth flow
556  udpHdr.SetSourcePort (7);
557  AddPacket (queueDisc, hdr, udpHdr);
558  AddPacket (queueDisc, hdr, udpHdr);
559  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 7, "unexpected number of packets in the queue disc");
560  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
561  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
562  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the third flow queue");
563  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (3)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the third flow queue");
564 
565  Simulator::Destroy ();
566 }
567 
568 
596 {
597 public:
600 
601 private:
602  virtual void DoRun (void);
608  void AddPacket (Ptr<FqPieQueueDisc> queue, Ipv4Header hdr);
609 };
610 
612  : TestCase ("Test credits and flows status")
613 {}
614 
616 {}
617 
618 void
620 {
621  Ptr<Packet> p = Create<Packet> (100);
622  Address dest;
623  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, hdr);
624  queue->Enqueue (item);
625 }
626 
627 void
629 {
630  Ptr<FqPieQueueDisc> queueDisc = CreateObjectWithAttributes<FqPieQueueDisc> ("EnableSetAssociativeHash", BooleanValue (true));
631  queueDisc->SetQuantum (90);
632  queueDisc->Initialize ();
633 
634  Ptr<Ipv4FqPieTestPacketFilter> filter = CreateObject<Ipv4FqPieTestPacketFilter> ();
635  queueDisc->AddPacketFilter (filter);
636 
637  Ipv4Header hdr;
638  hdr.SetPayloadSize (100);
639  hdr.SetSource (Ipv4Address ("10.10.1.1"));
640  hdr.SetDestination (Ipv4Address ("10.10.1.2"));
641  hdr.SetProtocol (7);
642 
643  g_hash = 0;
644  AddPacket (queueDisc, hdr);
645  g_hash = 1;
646  AddPacket (queueDisc, hdr);
647  AddPacket (queueDisc, hdr);
648  g_hash = 2;
649  AddPacket (queueDisc, hdr);
650  g_hash = 3;
651  AddPacket (queueDisc, hdr);
652  g_hash = 4;
653  AddPacket (queueDisc, hdr);
654  AddPacket (queueDisc, hdr);
655  g_hash = 5;
656  AddPacket (queueDisc, hdr);
657  g_hash = 6;
658  AddPacket (queueDisc, hdr);
659  g_hash = 7;
660  AddPacket (queueDisc, hdr);
661  g_hash = 1024;
662  AddPacket (queueDisc, hdr);
663 
664  NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 11,
665  "unexpected number of packets in the queue disc");
666  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 2,
667  "unexpected number of packets in the first flow queue of set one");
668  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 2,
669  "unexpected number of packets in the second flow queue of set one");
670  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetNPackets (), 1,
671  "unexpected number of packets in the third flow queue of set one");
672  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (3)->GetQueueDisc ()->GetNPackets (), 1,
673  "unexpected number of packets in the fourth flow queue of set one");
674  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (4)->GetQueueDisc ()->GetNPackets (), 2,
675  "unexpected number of packets in the fifth flow queue of set one");
676  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (5)->GetQueueDisc ()->GetNPackets (), 1,
677  "unexpected number of packets in the sixth flow queue of set one");
678  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (6)->GetQueueDisc ()->GetNPackets (), 1,
679  "unexpected number of packets in the seventh flow queue of set one");
680  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (7)->GetQueueDisc ()->GetNPackets (), 1,
681  "unexpected number of packets in the eighth flow queue of set one");
682  g_hash = 1025;
683  AddPacket (queueDisc, hdr);
684  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3,
685  "unexpected number of packets in the first flow of set one");
686  g_hash = 10;
687  AddPacket (queueDisc, hdr);
688  NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (8)->GetQueueDisc ()->GetNPackets (), 1,
689  "unexpected number of packets in the first flow of set two");
690  Simulator::Destroy ();
691 }
692 
693 
710 {
711 public:
713  virtual ~FqPieQueueDiscL4sMode ();
714 
715 private:
716  virtual void DoRun (void);
723  void AddPacket (Ptr<FqPieQueueDisc> queue, Ipv4Header hdr, uint32_t nPkt);
731  void AddPacketWithDelay (Ptr<FqPieQueueDisc> queue,Ipv4Header hdr, double delay, uint32_t nPkt);
737  void Dequeue (Ptr<FqPieQueueDisc> queue, uint32_t nPkt);
744  void DequeueWithDelay (Ptr<FqPieQueueDisc> queue, double delay, uint32_t nPkt);
745 };
746 
748  : TestCase ("Test L4S mode")
749 {}
750 
752 {}
753 
754 void
756 {
757  Address dest;
758  Ptr<Packet> p = Create<Packet> (100);
759  for (uint32_t i = 0; i < nPkt; i++)
760  {
761  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, hdr);
762  queue->Enqueue (item);
763  }
764 }
765 
766 void
768 {
769  for (uint32_t i = 0; i < nPkt; i++)
770  {
771  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &FqPieQueueDiscL4sMode::AddPacket, this, queue, hdr, 1);
772  }
773 }
774 
775 void
777 {
778  for (uint32_t i = 0; i < nPkt; i++)
779  {
780  Ptr<QueueDiscItem> item = queue->Dequeue ();
781  }
782 }
783 
784 void
786 {
787  for (uint32_t i = 0; i < nPkt; i++)
788  {
789  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &FqPieQueueDiscL4sMode::Dequeue, this, queue, 1);
790  }
791 }
792 
793 void
795 {
796  // Test is divided into 2 sub test cases:
797  // 1) Without hash collisions
798  // 2) With hash collisions
799 
800  // Test case 1, Without hash collisions
801  Ptr<FqPieQueueDisc> queueDisc = CreateObjectWithAttributes<FqPieQueueDisc> ("MaxSize", StringValue ("10240p"),
802  "UseEcn", BooleanValue (true), "Perturbation", UintegerValue (0),
803  "UseL4s", BooleanValue (true), "CeThreshold", TimeValue (MilliSeconds (2)));
804 
805  queueDisc->SetQuantum (1514);
806  queueDisc->Initialize ();
807  Ipv4Header hdr;
808  hdr.SetPayloadSize (100);
809  hdr.SetSource (Ipv4Address ("10.10.1.1"));
810  hdr.SetDestination (Ipv4Address ("10.10.1.2"));
811  hdr.SetProtocol (7);
812  hdr.SetEcn (Ipv4Header::ECN_ECT1);
813 
814  // Add 70 ECT1 (ECN capable) packets from the first flow
815  // Set delay = 0.5ms
816  double delay = 0.0005;
817  Simulator::Schedule (Time (Seconds (0)), &FqPieQueueDiscL4sMode::AddPacketWithDelay, this, queueDisc, hdr, delay, 70);
818 
819  // Add 70 ECT0 (ECN capable) packets from second flow
820  hdr.SetEcn (Ipv4Header::ECN_ECT0);
821  hdr.SetDestination (Ipv4Address ("10.10.1.10"));
822  Simulator::Schedule (Time (Seconds (0)), &FqPieQueueDiscL4sMode::AddPacketWithDelay, this, queueDisc, hdr, delay, 70);
823 
824  //Dequeue 140 packets with delay 1ms
825  delay = 0.001;
826  DequeueWithDelay (queueDisc, delay, 140);
827  Simulator::Stop (Seconds (10.0));
828  Simulator::Run ();
829 
830  Ptr<PieQueueDisc> q0 = queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetObject <PieQueueDisc> ();
831  Ptr<PieQueueDisc> q1 = queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetObject <PieQueueDisc> ();
832 
833  NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (PieQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 66, "There should be 66 marked packets"
834  "4th packet is enqueued at 2ms and dequeued at 4ms hence the delay of 2ms which not greater than CE threshold"
835  "5th packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and subsequent packet also do have delay"
836  "greater than CE threshold so all the packets after 4th packet are marked");
837  NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP), 0, "Queue delay is less than max burst allowance so"
838  "There should not be any dropped packets");
839  NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK), 0, "There should not be any marked packets");
840  NS_TEST_EXPECT_MSG_EQ (q1->GetStats ().GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK), 0, "There should not be marked packets.");
841  NS_TEST_EXPECT_MSG_EQ (q1->GetStats ().GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP), 0, "There should not be any dropped packets");
842 
843  Simulator::Destroy ();
844 
845  // Test case 2, With hash collisions
846  queueDisc = CreateObjectWithAttributes<FqPieQueueDisc> ("MaxSize", StringValue ("10240p"),
847  "UseEcn", BooleanValue (true), "Perturbation", UintegerValue (0),
848  "UseL4s", BooleanValue (true), "CeThreshold", TimeValue (MilliSeconds (2)));
849 
850  queueDisc->SetQuantum (1514);
851  queueDisc->Initialize ();
852  hdr.SetPayloadSize (100);
853  hdr.SetSource (Ipv4Address ("10.10.1.1"));
854  hdr.SetDestination (Ipv4Address ("10.10.1.2"));
855  hdr.SetProtocol (7);
856  hdr.SetEcn (Ipv4Header::ECN_ECT1);
857 
858  // Add 70 ECT1 (ECN capable) packets from the first flow
859  // Set delay = 1ms
860  delay = 0.001;
861  Simulator::Schedule (Time (Seconds (0.0005)), &FqPieQueueDiscL4sMode::AddPacket, this, queueDisc, hdr, 1);
862  Simulator::Schedule (Time (Seconds (0.0005)), &FqPieQueueDiscL4sMode::AddPacketWithDelay, this, queueDisc, hdr, delay, 69);
863 
864  // Add 70 ECT0 (ECN capable) packets from first flow
865  hdr.SetEcn (Ipv4Header::ECN_ECT0);
866  Simulator::Schedule (Time (Seconds (0)), &FqPieQueueDiscL4sMode::AddPacketWithDelay, this, queueDisc, hdr, delay, 70);
867 
868  //Dequeue 140 packets with delay 1ms
869  DequeueWithDelay (queueDisc, delay, 140);
870  Simulator::Stop (Seconds (1.0));
871  Simulator::Run ();
872  q0 = queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetObject <PieQueueDisc> ();
873  q0 = queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetObject <PieQueueDisc> ();
874 
875  NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (PieQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 68, "There should be 68 marked packets"
876  "2nd ECT1 packet is enqueued at 1.5ms and dequeued at 3ms hence the delay of 1.5ms which not greater than CE threshold"
877  "3rd packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and subsequent packet also do have delay"
878  "greater than CE threshold so all the packets after 2nd packet are marked");
879  NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP), 0, "Queue delay is less than max burst allowance so"
880  "There should not be any dropped packets");
881  NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK), 0, "There should not be any marked packets");
882 
883  Simulator::Destroy ();
884 }
885 
886 
893 {
894 public:
896 };
897 
899  : TestSuite ("fq-pie-queue-disc", UNIT)
900 {
901  AddTestCase (new FqPieQueueDiscNoSuitableFilter, TestCase::QUICK);
903  AddTestCase (new FqPieQueueDiscDeficit, TestCase::QUICK);
904  AddTestCase (new FqPieQueueDiscTCPFlowsSeparation, TestCase::QUICK);
905  AddTestCase (new FqPieQueueDiscUDPFlowsSeparation, TestCase::QUICK);
906  AddTestCase (new FqPieQueueDiscSetLinearProbing, TestCase::QUICK);
907  AddTestCase (new FqPieQueueDiscL4sMode, TestCase::QUICK);
908 }
909 
This class tests the deficit per flow.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqPieQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
This class tests the IP flows separation and the packet limit.
void AddPacket(Ptr< FqPieQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
virtual void DoRun(void)
Implementation to actually run this TestCase.
This class tests L4S mode.
void AddPacketWithDelay(Ptr< FqPieQueueDisc > queue, Ipv4Header hdr, double delay, uint32_t nPkt)
Enqueue the given number of packets at different times.
void DequeueWithDelay(Ptr< FqPieQueueDisc > queue, double delay, uint32_t nPkt)
Dequeue the given number of packets at different times.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqPieQueueDisc > queue, Ipv4Header hdr, uint32_t nPkt)
Enqueue the given number of packets.
void Dequeue(Ptr< FqPieQueueDisc > queue, uint32_t nPkt)
Dequeue the given number of packets.
This class tests packets for which there is no suitable filter.
virtual void DoRun(void)
Implementation to actually run this TestCase.
This class tests linear probing, collision response, and set creation capability of set associative h...
void AddPacket(Ptr< FqPieQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
virtual void DoRun(void)
Implementation to actually run this TestCase.
This class tests the TCP flows separation.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqPieQueueDisc > queue, Ipv4Header ipHdr, TcpHeader tcpHdr)
Enqueue a packet.
FQ-PIE queue disc test suite.
This class tests the UDP flows separation.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqPieQueueDisc > queue, Ipv4Header ipHdr, UdpHeader udpHdr)
Enqueue a packet.
Simple test packet filter able to classify IPv4 packets.
virtual int32_t DoClassify(Ptr< QueueDiscItem > item) const
Classify a QueueDiscItem.
virtual bool CheckProtocol(Ptr< QueueDiscItem > item) const
Check the protocol.
static TypeId GetTypeId(void)
Get the type ID.
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
Packet header for IPv4.
Definition: ipv4-header.h:34
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:298
void SetPayloadSize(uint16_t size)
Definition: ipv4-header.cc:56
void SetEcn(EcnType ecn)
Set ECN Field.
Definition: ipv4-header.cc:97
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:278
void SetSource(Ipv4Address source)
Definition: ipv4-header.cc:285
Ipv4PacketFilter is the abstract base class for filters defined for IPv4 packets.
Packet header for IPv6.
Definition: ipv6-header.h:36
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
Implements PIE Active Queue Management discipline.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
Hold variables of type string.
Definition: string.h:41
Header for the Transmission Control Protocol.
Definition: tcp-header.h:45
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:95
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:89
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Packet header for UDP packets.
Definition: udp-header.h:40
void SetSourcePort(uint16_t port)
Definition: udp-header.cc:60
void SetDestinationPort(uint16_t port)
Definition: udp-header.cc:55
Hold an unsigned integer type.
Definition: uinteger.h:44
static FqPieQueueDiscTestSuite g_fqPieQueueDiscTestSuite
Do not forget to allocate an instance of this TestSuite.
static int32_t g_hash
Variable to assign g_hash to a new packet's flow.
@ INACTIVE
Inactive Period or unslotted CSMA-CA.
Definition: lr-wpan-mac.h:93
#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:141
#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:240
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
Every class exported by the ns3 library is enclosed in the ns3 namespace.