A Discrete-Event Network Simulator
API
fq-pie-queue-disc-test-suite.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Universita' degli Studi di Napoli Federico II
3  * Copyright (c) 2020 NITK Surathkal (modified for FQ-PIE)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Pasquale Imputato <p.imputato@gmail.com>
19  * Stefano Avallone <stefano.avallone@unina.it>
20  * Modified for FQ-PIE by: Bhaskar Kataria <bhaskar.k7920@gmail.com>
21  * Tom Henderson <tomhend@u.washington.edu>
22  * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
23  * Vivek Jain <jain.vivek.anand@gmail.com>
24  * Ankit Deepak <adadeepak8@gmail.com>
25  *
26  */
27 
28 #include "ns3/fq-pie-queue-disc.h"
29 #include "ns3/ipv4-address.h"
30 #include "ns3/ipv4-header.h"
31 #include "ns3/ipv4-packet-filter.h"
32 #include "ns3/ipv4-queue-disc-item.h"
33 #include "ns3/ipv6-header.h"
34 #include "ns3/ipv6-packet-filter.h"
35 #include "ns3/ipv6-queue-disc-item.h"
36 #include "ns3/pie-queue-disc.h"
37 #include "ns3/pointer.h"
38 #include "ns3/simulator.h"
39 #include "ns3/string.h"
40 #include "ns3/tcp-header.h"
41 #include "ns3/test.h"
42 #include "ns3/udp-header.h"
43 
44 using namespace ns3;
45 
47 static int32_t g_hash;
48 
55 {
56  public:
61  static TypeId GetTypeId();
62 
64  ~Ipv4FqPieTestPacketFilter() override;
65 
66  private:
72  int32_t DoClassify(Ptr<QueueDiscItem> item) const override;
73 
79  bool CheckProtocol(Ptr<QueueDiscItem> item) const override;
80 };
81 
82 TypeId
84 {
85  static TypeId tid = TypeId("ns3::Ipv4FqPieTestPacketFilter")
87  .SetGroupName("Internet")
88  .AddConstructor<Ipv4FqPieTestPacketFilter>();
89  return tid;
90 }
91 
93 {
94 }
95 
97 {
98 }
99 
100 int32_t
102 {
103  return g_hash;
104 }
105 
106 bool
108 {
109  return true;
110 }
111 
118 {
119  public:
121  ~FqPieQueueDiscNoSuitableFilter() override;
122 
123  private:
124  void DoRun() override;
125 };
126 
128  : TestCase("Test packets that are not classified by any filter")
129 {
130 }
131 
133 {
134 }
135 
136 void
138 {
139  // Packets that cannot be classified by the available filters should be dropped
140  Ptr<FqPieQueueDisc> queueDisc =
141  CreateObjectWithAttributes<FqPieQueueDisc>("MaxSize", StringValue("4p"));
142  Ptr<Ipv4FqPieTestPacketFilter> filter = CreateObject<Ipv4FqPieTestPacketFilter>();
143  queueDisc->AddPacketFilter(filter);
144 
145  g_hash = -1;
146  queueDisc->SetQuantum(1500);
147  queueDisc->Initialize();
148 
149  Ptr<Packet> p;
150  p = Create<Packet>();
152  Ipv6Header ipv6Header;
153  Address dest;
154  item = Create<Ipv6QueueDiscItem>(p, dest, 0, ipv6Header);
155  queueDisc->Enqueue(item);
156  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetNQueueDiscClasses(),
157  0,
158  "no flow queue should have been created");
159 
160  p = Create<Packet>(reinterpret_cast<const uint8_t*>("hello, world"), 12);
161  item = Create<Ipv6QueueDiscItem>(p, dest, 0, ipv6Header);
162  queueDisc->Enqueue(item);
163  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetNQueueDiscClasses(),
164  0,
165  "no flow queue should have been created");
166 
167  Simulator::Destroy();
168 }
169 
176 {
177  public:
180 
181  private:
182  void DoRun() override;
188  void AddPacket(Ptr<FqPieQueueDisc> queue, Ipv4Header hdr);
189 };
190 
192  : TestCase("Test IP flows separation and packet limit")
193 {
194 }
195 
197 {
198 }
199 
200 void
202 {
203  Ptr<Packet> p = Create<Packet>(100);
204  Address dest;
205  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, hdr);
206  queue->Enqueue(item);
207 }
208 
209 void
211 {
212  Ptr<FqPieQueueDisc> queueDisc =
213  CreateObjectWithAttributes<FqPieQueueDisc>("MaxSize", StringValue("4p"));
214 
215  queueDisc->SetQuantum(1500);
216  queueDisc->Initialize();
217 
218  Ipv4Header hdr;
219  hdr.SetPayloadSize(100);
220  hdr.SetSource(Ipv4Address("10.10.1.1"));
221  hdr.SetDestination(Ipv4Address("10.10.1.2"));
222  hdr.SetProtocol(7);
223 
224  // Add three packets from the first flow
225  AddPacket(queueDisc, hdr);
226  AddPacket(queueDisc, hdr);
227  AddPacket(queueDisc, hdr);
228  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
229  3,
230  "unexpected number of packets in the queue disc");
231  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
232  3,
233  "unexpected number of packets in the flow queue");
234 
235  // Add two packets from the second flow
236  hdr.SetDestination(Ipv4Address("10.10.1.7"));
237  // Add the first packet
238  AddPacket(queueDisc, hdr);
239  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
240  4,
241  "unexpected number of packets in the queue disc");
242  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
243  3,
244  "unexpected number of packets in the flow queue");
245  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
246  1,
247  "unexpected number of packets in the flow queue");
248  // Add the second packet that causes two packets to be dropped from the fat flow (max backlog =
249  // 300, threshold = 150)
250  AddPacket(queueDisc, hdr);
251  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
252  3,
253  "unexpected number of packets in the queue disc");
254  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
255  1,
256  "unexpected number of packets in the flow queue");
257  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
258  2,
259  "unexpected number of packets in the flow queue");
260 
261  Simulator::Destroy();
262 }
263 
270 {
271  public:
273  ~FqPieQueueDiscDeficit() override;
274 
275  private:
276  void DoRun() override;
282  void AddPacket(Ptr<FqPieQueueDisc> queue, Ipv4Header hdr);
283 };
284 
286  : TestCase("Test credits and flows status")
287 {
288 }
289 
291 {
292 }
293 
294 void
296 {
297  Ptr<Packet> p = Create<Packet>(100);
298  Address dest;
299  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, hdr);
300  queue->Enqueue(item);
301 }
302 
303 void
305 {
306  Ptr<FqPieQueueDisc> queueDisc = CreateObject<FqPieQueueDisc>();
307 
308  queueDisc->SetQuantum(90);
309  queueDisc->Initialize();
310 
311  Ipv4Header hdr;
312  hdr.SetPayloadSize(100);
313  hdr.SetSource(Ipv4Address("10.10.1.1"));
314  hdr.SetDestination(Ipv4Address("10.10.1.2"));
315  hdr.SetProtocol(7);
316 
317  // Add a packet from the first flow
318  AddPacket(queueDisc, hdr);
319  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
320  1,
321  "unexpected number of packets in the queue disc");
322  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
323  1,
324  "unexpected number of packets in the first flow queue");
325  Ptr<FqPieFlow> flow1 = StaticCast<FqPieFlow>(queueDisc->GetQueueDiscClass(0));
326  NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(),
327  static_cast<int32_t>(queueDisc->GetQuantum()),
328  "the deficit of the first flow must equal the quantum");
329  NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
330  FqPieFlow::NEW_FLOW,
331  "the first flow must be in the list of new queues");
332  // Dequeue a packet
333  queueDisc->Dequeue();
334  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
335  0,
336  "unexpected number of packets in the queue disc");
337  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
338  0,
339  "unexpected number of packets in the first flow queue");
340  // the deficit for the first flow becomes 90 - (100+20) = -30
341  NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -30, "unexpected deficit for the first flow");
342 
343  // Add two packets from the first flow
344  AddPacket(queueDisc, hdr);
345  AddPacket(queueDisc, hdr);
346  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
347  2,
348  "unexpected number of packets in the queue disc");
349  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
350  2,
351  "unexpected number of packets in the first flow queue");
352  NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
353  FqPieFlow::NEW_FLOW,
354  "the first flow must still be in the list of new queues");
355 
356  // Add two packets from the second flow
357  hdr.SetDestination(Ipv4Address("10.10.1.10"));
358  AddPacket(queueDisc, hdr);
359  AddPacket(queueDisc, hdr);
360  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
361  4,
362  "unexpected number of packets in the queue disc");
363  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
364  2,
365  "unexpected number of packets in the first flow queue");
366  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
367  2,
368  "unexpected number of packets in the second flow queue");
369  Ptr<FqPieFlow> flow2 = StaticCast<FqPieFlow>(queueDisc->GetQueueDiscClass(1));
370  NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(),
371  static_cast<int32_t>(queueDisc->GetQuantum()),
372  "the deficit of the second flow must equal the quantum");
373  NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
374  FqPieFlow::NEW_FLOW,
375  "the second flow must be in the list of new queues");
376 
377  // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
378  queueDisc->Dequeue();
379  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
380  3,
381  "unexpected number of packets in the queue disc");
382  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
383  2,
384  "unexpected number of packets in the first flow queue");
385  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
386  1,
387  "unexpected number of packets in the second flow queue");
388  // the first flow got a quantum of deficit (-30+90=60) and has been moved to the end of the list
389  // of old queues
390  NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 60, "unexpected deficit for the first flow");
391  NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
392  FqPieFlow::OLD_FLOW,
393  "the first flow must be in the list of old queues");
394  // the second flow has a negative deficit (-30) and is still in the list of new queues
395  NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), -30, "unexpected deficit for the second flow");
396  NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
397  FqPieFlow::NEW_FLOW,
398  "the second flow must be in the list of new queues");
399 
400  // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
401  queueDisc->Dequeue();
402  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
403  2,
404  "unexpected number of packets in the queue disc");
405  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
406  1,
407  "unexpected number of packets in the first flow queue");
408  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
409  1,
410  "unexpected number of packets in the second flow queue");
411  // the first flow has a negative deficit (60-(100+20)= -60) and stays in the list of old queues
412  NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -60, "unexpected deficit for the first flow");
413  NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
414  FqPieFlow::OLD_FLOW,
415  "the first flow must be in the list of old queues");
416  // the second flow got a quantum of deficit (-30+90=60) and has been moved to the end of the
417  // list of old queues
418  NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 60, "unexpected deficit for the second flow");
419  NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
420  FqPieFlow::OLD_FLOW,
421  "the second flow must be in the list of new queues");
422 
423  // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
424  queueDisc->Dequeue();
425  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
426  1,
427  "unexpected number of packets in the queue disc");
428  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
429  1,
430  "unexpected number of packets in the first flow queue");
431  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
432  0,
433  "unexpected number of packets in the second flow queue");
434  // the first flow got a quantum of deficit (-60+90=30) and has been moved to the end of the list
435  // of old queues
436  NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 30, "unexpected deficit for the first flow");
437  NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
438  FqPieFlow::OLD_FLOW,
439  "the first flow must be in the list of old queues");
440  // the second flow has a negative deficit (60-(100+20)= -60)
441  NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), -60, "unexpected deficit for the second flow");
442  NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
443  FqPieFlow::OLD_FLOW,
444  "the second flow must be in the list of new queues");
445 
446  // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
447  queueDisc->Dequeue();
448  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
449  0,
450  "unexpected number of packets in the queue disc");
451  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
452  0,
453  "unexpected number of packets in the first flow queue");
454  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
455  0,
456  "unexpected number of packets in the second flow queue");
457  // the first flow has a negative deficit (30-(100+20)= -90)
458  NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), -90, "unexpected deficit for the first flow");
459  NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
460  FqPieFlow::OLD_FLOW,
461  "the first flow must be in the list of old queues");
462  // the second flow got a quantum of deficit (-60+90=30) and has been moved to the end of the
463  // list of old queues
464  NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 30, "unexpected deficit for the second flow");
465  NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
466  FqPieFlow::OLD_FLOW,
467  "the second flow must be in the list of new queues");
468 
469  // Dequeue a packet
470  queueDisc->Dequeue();
471  // the first flow is at the head of the list of old queues but has a negative deficit, thus it
472  // gets a quantun of deficit (-90+90=0) and is moved to the end of the list of old queues. Then,
473  // the second flow (which has a positive deficit) is selected, but the second flow is empty and
474  // thus it is set to inactive. The first flow is reconsidered, but it has a null deficit, hence
475  // it gets another quantum of deficit (0+90=90). Then, the first flow is reconsidered again, now
476  // it has a positive deficit and hence it is selected. But, it is empty and therefore is set to
477  // inactive, too.
478  NS_TEST_ASSERT_MSG_EQ(flow1->GetDeficit(), 90, "unexpected deficit for the first flow");
479  NS_TEST_ASSERT_MSG_EQ(flow1->GetStatus(),
481  "the first flow must be inactive");
482  NS_TEST_ASSERT_MSG_EQ(flow2->GetDeficit(), 30, "unexpected deficit for the second flow");
483  NS_TEST_ASSERT_MSG_EQ(flow2->GetStatus(),
485  "the second flow must be inactive");
486 
487  Simulator::Destroy();
488 }
489 
496 {
497  public:
500 
501  private:
502  void DoRun() override;
509  void AddPacket(Ptr<FqPieQueueDisc> queue, Ipv4Header ipHdr, TcpHeader tcpHdr);
510 };
511 
513  : TestCase("Test TCP flows separation")
514 {
515 }
516 
518 {
519 }
520 
521 void
523  Ipv4Header ipHdr,
524  TcpHeader tcpHdr)
525 {
526  Ptr<Packet> p = Create<Packet>(100);
527  p->AddHeader(tcpHdr);
528  Address dest;
529  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, ipHdr);
530  queue->Enqueue(item);
531 }
532 
533 void
535 {
536  Ptr<FqPieQueueDisc> queueDisc =
537  CreateObjectWithAttributes<FqPieQueueDisc>("MaxSize", StringValue("10p"));
538 
539  queueDisc->SetQuantum(1500);
540  queueDisc->Initialize();
541 
542  Ipv4Header hdr;
543  hdr.SetPayloadSize(100);
544  hdr.SetSource(Ipv4Address("10.10.1.1"));
545  hdr.SetDestination(Ipv4Address("10.10.1.2"));
546  hdr.SetProtocol(6);
547 
548  TcpHeader tcpHdr;
549  tcpHdr.SetSourcePort(7);
550  tcpHdr.SetDestinationPort(27);
551 
552  // Add three packets from the first flow
553  AddPacket(queueDisc, hdr, tcpHdr);
554  AddPacket(queueDisc, hdr, tcpHdr);
555  AddPacket(queueDisc, hdr, tcpHdr);
556  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
557  3,
558  "unexpected number of packets in the queue disc");
559  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
560  3,
561  "unexpected number of packets in the first flow queue");
562 
563  // Add a packet from the second flow
564  tcpHdr.SetSourcePort(8);
565  AddPacket(queueDisc, hdr, tcpHdr);
566  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
567  4,
568  "unexpected number of packets in the queue disc");
569  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
570  3,
571  "unexpected number of packets in the first flow queue");
572  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
573  1,
574  "unexpected number of packets in the second flow queue");
575 
576  // Add a packet from the third flow
577  tcpHdr.SetDestinationPort(28);
578  AddPacket(queueDisc, hdr, tcpHdr);
579  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
580  5,
581  "unexpected number of packets in the queue disc");
582  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
583  3,
584  "unexpected number of packets in the first flow queue");
585  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
586  1,
587  "unexpected number of packets in the second flow queue");
588  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
589  1,
590  "unexpected number of packets in the third flow queue");
591 
592  // Add two packets from the fourth flow
593  tcpHdr.SetSourcePort(7);
594  AddPacket(queueDisc, hdr, tcpHdr);
595  AddPacket(queueDisc, hdr, tcpHdr);
596  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
597  7,
598  "unexpected number of packets in the queue disc");
599  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
600  3,
601  "unexpected number of packets in the first flow queue");
602  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
603  1,
604  "unexpected number of packets in the second flow queue");
605  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
606  1,
607  "unexpected number of packets in the third flow queue");
608  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
609  2,
610  "unexpected number of packets in the third flow queue");
611 
612  Simulator::Destroy();
613 }
614 
621 {
622  public:
625 
626  private:
627  void DoRun() override;
634  void AddPacket(Ptr<FqPieQueueDisc> queue, Ipv4Header ipHdr, UdpHeader udpHdr);
635 };
636 
638  : TestCase("Test UDP flows separation")
639 {
640 }
641 
643 {
644 }
645 
646 void
648  Ipv4Header ipHdr,
649  UdpHeader udpHdr)
650 {
651  Ptr<Packet> p = Create<Packet>(100);
652  p->AddHeader(udpHdr);
653  Address dest;
654  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, ipHdr);
655  queue->Enqueue(item);
656 }
657 
658 void
660 {
661  Ptr<FqPieQueueDisc> queueDisc =
662  CreateObjectWithAttributes<FqPieQueueDisc>("MaxSize", StringValue("10p"));
663 
664  queueDisc->SetQuantum(1500);
665  queueDisc->Initialize();
666 
667  Ipv4Header hdr;
668  hdr.SetPayloadSize(100);
669  hdr.SetSource(Ipv4Address("10.10.1.1"));
670  hdr.SetDestination(Ipv4Address("10.10.1.2"));
671  hdr.SetProtocol(17);
672 
673  UdpHeader udpHdr;
674  udpHdr.SetSourcePort(7);
675  udpHdr.SetDestinationPort(27);
676 
677  // Add three packets from the first flow
678  AddPacket(queueDisc, hdr, udpHdr);
679  AddPacket(queueDisc, hdr, udpHdr);
680  AddPacket(queueDisc, hdr, udpHdr);
681  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
682  3,
683  "unexpected number of packets in the queue disc");
684  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
685  3,
686  "unexpected number of packets in the first flow queue");
687 
688  // Add a packet from the second flow
689  udpHdr.SetSourcePort(8);
690  AddPacket(queueDisc, hdr, udpHdr);
691  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
692  4,
693  "unexpected number of packets in the queue disc");
694  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
695  3,
696  "unexpected number of packets in the first flow queue");
697  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
698  1,
699  "unexpected number of packets in the second flow queue");
700 
701  // Add a packet from the third flow
702  udpHdr.SetDestinationPort(28);
703  AddPacket(queueDisc, hdr, udpHdr);
704  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
705  5,
706  "unexpected number of packets in the queue disc");
707  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
708  3,
709  "unexpected number of packets in the first flow queue");
710  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
711  1,
712  "unexpected number of packets in the second flow queue");
713  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
714  1,
715  "unexpected number of packets in the third flow queue");
716 
717  // Add two packets from the fourth flow
718  udpHdr.SetSourcePort(7);
719  AddPacket(queueDisc, hdr, udpHdr);
720  AddPacket(queueDisc, hdr, udpHdr);
721  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
722  7,
723  "unexpected number of packets in the queue disc");
724  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
725  3,
726  "unexpected number of packets in the first flow queue");
727  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
728  1,
729  "unexpected number of packets in the second flow queue");
730  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
731  1,
732  "unexpected number of packets in the third flow queue");
733  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
734  2,
735  "unexpected number of packets in the third flow queue");
736 
737  Simulator::Destroy();
738 }
739 
767 {
768  public:
771 
772  private:
773  void DoRun() override;
779  void AddPacket(Ptr<FqPieQueueDisc> queue, Ipv4Header hdr);
780 };
781 
783  : TestCase("Test credits and flows status")
784 {
785 }
786 
788 {
789 }
790 
791 void
793 {
794  Ptr<Packet> p = Create<Packet>(100);
795  Address dest;
796  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, hdr);
797  queue->Enqueue(item);
798 }
799 
800 void
802 {
803  Ptr<FqPieQueueDisc> queueDisc =
804  CreateObjectWithAttributes<FqPieQueueDisc>("EnableSetAssociativeHash", BooleanValue(true));
805  queueDisc->SetQuantum(90);
806  queueDisc->Initialize();
807 
808  Ptr<Ipv4FqPieTestPacketFilter> filter = CreateObject<Ipv4FqPieTestPacketFilter>();
809  queueDisc->AddPacketFilter(filter);
810 
811  Ipv4Header hdr;
812  hdr.SetPayloadSize(100);
813  hdr.SetSource(Ipv4Address("10.10.1.1"));
814  hdr.SetDestination(Ipv4Address("10.10.1.2"));
815  hdr.SetProtocol(7);
816 
817  g_hash = 0;
818  AddPacket(queueDisc, hdr);
819  g_hash = 1;
820  AddPacket(queueDisc, hdr);
821  AddPacket(queueDisc, hdr);
822  g_hash = 2;
823  AddPacket(queueDisc, hdr);
824  g_hash = 3;
825  AddPacket(queueDisc, hdr);
826  g_hash = 4;
827  AddPacket(queueDisc, hdr);
828  AddPacket(queueDisc, hdr);
829  g_hash = 5;
830  AddPacket(queueDisc, hdr);
831  g_hash = 6;
832  AddPacket(queueDisc, hdr);
833  g_hash = 7;
834  AddPacket(queueDisc, hdr);
835  g_hash = 1024;
836  AddPacket(queueDisc, hdr);
837 
838  NS_TEST_ASSERT_MSG_EQ(queueDisc->QueueDisc::GetNPackets(),
839  11,
840  "unexpected number of packets in the queue disc");
841  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
842  2,
843  "unexpected number of packets in the first flow queue of set one");
844  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetNPackets(),
845  2,
846  "unexpected number of packets in the second flow queue of set one");
847  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(2)->GetQueueDisc()->GetNPackets(),
848  1,
849  "unexpected number of packets in the third flow queue of set one");
850  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(3)->GetQueueDisc()->GetNPackets(),
851  1,
852  "unexpected number of packets in the fourth flow queue of set one");
853  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(4)->GetQueueDisc()->GetNPackets(),
854  2,
855  "unexpected number of packets in the fifth flow queue of set one");
856  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(5)->GetQueueDisc()->GetNPackets(),
857  1,
858  "unexpected number of packets in the sixth flow queue of set one");
859  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(6)->GetQueueDisc()->GetNPackets(),
860  1,
861  "unexpected number of packets in the seventh flow queue of set one");
862  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(7)->GetQueueDisc()->GetNPackets(),
863  1,
864  "unexpected number of packets in the eighth flow queue of set one");
865  g_hash = 1025;
866  AddPacket(queueDisc, hdr);
867  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
868  3,
869  "unexpected number of packets in the first flow of set one");
870  g_hash = 10;
871  AddPacket(queueDisc, hdr);
872  NS_TEST_ASSERT_MSG_EQ(queueDisc->GetQueueDiscClass(8)->GetQueueDisc()->GetNPackets(),
873  1,
874  "unexpected number of packets in the first flow of set two");
875  Simulator::Destroy();
876 }
877 
893 {
894  public:
896  ~FqPieQueueDiscL4sMode() override;
897 
898  private:
899  void DoRun() override;
906  void AddPacket(Ptr<FqPieQueueDisc> queue, Ipv4Header hdr, uint32_t nPkt);
914  void AddPacketWithDelay(Ptr<FqPieQueueDisc> queue, Ipv4Header hdr, double delay, uint32_t nPkt);
920  void Dequeue(Ptr<FqPieQueueDisc> queue, uint32_t nPkt);
927  void DequeueWithDelay(Ptr<FqPieQueueDisc> queue, double delay, uint32_t nPkt);
928 };
929 
931  : TestCase("Test L4S mode")
932 {
933 }
934 
936 {
937 }
938 
939 void
941 {
942  Address dest;
943  Ptr<Packet> p = Create<Packet>(100);
944  for (uint32_t i = 0; i < nPkt; i++)
945  {
946  Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem>(p, dest, 0, hdr);
947  queue->Enqueue(item);
948  }
949 }
950 
951 void
953  Ipv4Header hdr,
954  double delay,
955  uint32_t nPkt)
956 {
957  for (uint32_t i = 0; i < nPkt; i++)
958  {
959  Simulator::Schedule(Time(Seconds((i + 1) * delay)),
961  this,
962  queue,
963  hdr,
964  1);
965  }
966 }
967 
968 void
970 {
971  for (uint32_t i = 0; i < nPkt; i++)
972  {
973  Ptr<QueueDiscItem> item = queue->Dequeue();
974  }
975 }
976 
977 void
979 {
980  for (uint32_t i = 0; i < nPkt; i++)
981  {
982  Simulator::Schedule(Time(Seconds((i + 1) * delay)),
984  this,
985  queue,
986  1);
987  }
988 }
989 
990 void
992 {
993  // Test is divided into 2 sub test cases:
994  // 1) Without hash collisions
995  // 2) With hash collisions
996 
997  // Test case 1, Without hash collisions
998  Ptr<FqPieQueueDisc> queueDisc =
999  CreateObjectWithAttributes<FqPieQueueDisc>("MaxSize",
1000  StringValue("10240p"),
1001  "UseEcn",
1002  BooleanValue(true),
1003  "Perturbation",
1004  UintegerValue(0),
1005  "UseL4s",
1006  BooleanValue(true),
1007  "CeThreshold",
1008  TimeValue(MilliSeconds(2)));
1009 
1010  queueDisc->SetQuantum(1514);
1011  queueDisc->Initialize();
1012  Ipv4Header hdr;
1013  hdr.SetPayloadSize(100);
1014  hdr.SetSource(Ipv4Address("10.10.1.1"));
1015  hdr.SetDestination(Ipv4Address("10.10.1.2"));
1016  hdr.SetProtocol(7);
1017  hdr.SetEcn(Ipv4Header::ECN_ECT1);
1018 
1019  // Add 70 ECT1 (ECN capable) packets from the first flow
1020  // Set delay = 0.5ms
1021  double delay = 0.0005;
1022  Simulator::Schedule(Time(Seconds(0)),
1024  this,
1025  queueDisc,
1026  hdr,
1027  delay,
1028  70);
1029 
1030  // Add 70 ECT0 (ECN capable) packets from second flow
1031  hdr.SetEcn(Ipv4Header::ECN_ECT0);
1032  hdr.SetDestination(Ipv4Address("10.10.1.10"));
1033  Simulator::Schedule(Time(Seconds(0)),
1035  this,
1036  queueDisc,
1037  hdr,
1038  delay,
1039  70);
1040 
1041  // Dequeue 140 packets with delay 1ms
1042  delay = 0.001;
1043  DequeueWithDelay(queueDisc, delay, 140);
1044  Simulator::Stop(Seconds(10.0));
1045  Simulator::Run();
1046 
1047  Ptr<PieQueueDisc> q0 =
1048  queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<PieQueueDisc>();
1049  Ptr<PieQueueDisc> q1 =
1050  queueDisc->GetQueueDiscClass(1)->GetQueueDisc()->GetObject<PieQueueDisc>();
1051 
1053  q0->GetStats().GetNMarkedPackets(PieQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1054  66,
1055  "There should be 66 marked packets"
1056  "4th packet is enqueued at 2ms and dequeued at 4ms hence the delay of 2ms which not "
1057  "greater than CE threshold"
1058  "5th packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and "
1059  "subsequent packet also do have delay"
1060  "greater than CE threshold so all the packets after 4th packet are marked");
1061  NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
1062  0,
1063  "Queue delay is less than max burst allowance so"
1064  "There should not be any dropped packets");
1065  NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK),
1066  0,
1067  "There should not be any marked packets");
1068  NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK),
1069  0,
1070  "There should not be marked packets.");
1071  NS_TEST_EXPECT_MSG_EQ(q1->GetStats().GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
1072  0,
1073  "There should not be any dropped packets");
1074 
1075  Simulator::Destroy();
1076 
1077  // Test case 2, With hash collisions
1078  queueDisc = CreateObjectWithAttributes<FqPieQueueDisc>("MaxSize",
1079  StringValue("10240p"),
1080  "UseEcn",
1081  BooleanValue(true),
1082  "Perturbation",
1083  UintegerValue(0),
1084  "UseL4s",
1085  BooleanValue(true),
1086  "CeThreshold",
1087  TimeValue(MilliSeconds(2)));
1088 
1089  queueDisc->SetQuantum(1514);
1090  queueDisc->Initialize();
1091  hdr.SetPayloadSize(100);
1092  hdr.SetSource(Ipv4Address("10.10.1.1"));
1093  hdr.SetDestination(Ipv4Address("10.10.1.2"));
1094  hdr.SetProtocol(7);
1095  hdr.SetEcn(Ipv4Header::ECN_ECT1);
1096 
1097  // Add 70 ECT1 (ECN capable) packets from the first flow
1098  // Set delay = 1ms
1099  delay = 0.001;
1100  Simulator::Schedule(Time(Seconds(0.0005)),
1102  this,
1103  queueDisc,
1104  hdr,
1105  1);
1106  Simulator::Schedule(Time(Seconds(0.0005)),
1108  this,
1109  queueDisc,
1110  hdr,
1111  delay,
1112  69);
1113 
1114  // Add 70 ECT0 (ECN capable) packets from first flow
1115  hdr.SetEcn(Ipv4Header::ECN_ECT0);
1116  Simulator::Schedule(Time(Seconds(0)),
1118  this,
1119  queueDisc,
1120  hdr,
1121  delay,
1122  70);
1123 
1124  // Dequeue 140 packets with delay 1ms
1125  DequeueWithDelay(queueDisc, delay, 140);
1126  Simulator::Stop(Seconds(1.0));
1127  Simulator::Run();
1128  q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<PieQueueDisc>();
1129  q0 = queueDisc->GetQueueDiscClass(0)->GetQueueDisc()->GetObject<PieQueueDisc>();
1130 
1132  q0->GetStats().GetNMarkedPackets(PieQueueDisc::CE_THRESHOLD_EXCEEDED_MARK),
1133  68,
1134  "There should be 68 marked packets"
1135  "2nd ECT1 packet is enqueued at 1.5ms and dequeued at 3ms hence the delay of 1.5ms which "
1136  "not greater than CE threshold"
1137  "3rd packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and "
1138  "subsequent packet also do have delay"
1139  "greater than CE threshold so all the packets after 2nd packet are marked");
1140  NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNDroppedPackets(PieQueueDisc::UNFORCED_DROP),
1141  0,
1142  "Queue delay is less than max burst allowance so"
1143  "There should not be any dropped packets");
1144  NS_TEST_EXPECT_MSG_EQ(q0->GetStats().GetNMarkedPackets(PieQueueDisc::UNFORCED_MARK),
1145  0,
1146  "There should not be any marked packets");
1147 
1148  Simulator::Destroy();
1149 }
1150 
1157 {
1158  public:
1160 };
1161 
1163  : TestSuite("fq-pie-queue-disc", UNIT)
1164 {
1165  AddTestCase(new FqPieQueueDiscNoSuitableFilter, TestCase::QUICK);
1167  AddTestCase(new FqPieQueueDiscDeficit, TestCase::QUICK);
1168  AddTestCase(new FqPieQueueDiscTCPFlowsSeparation, TestCase::QUICK);
1169  AddTestCase(new FqPieQueueDiscUDPFlowsSeparation, TestCase::QUICK);
1170  AddTestCase(new FqPieQueueDiscSetLinearProbing, TestCase::QUICK);
1171  AddTestCase(new FqPieQueueDiscL4sMode, TestCase::QUICK);
1172 }
1173 
This class tests the deficit per flow.
void DoRun() override
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.
void DoRun() override
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 DoRun() override
Implementation to actually run this TestCase.
void DequeueWithDelay(Ptr< FqPieQueueDisc > queue, double delay, uint32_t nPkt)
Dequeue the given number of packets at different times.
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.
void DoRun() override
Implementation to actually run this TestCase.
This class tests linear probing, collision response, and set creation capability of set associative h...
void DoRun() override
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqPieQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
This class tests the TCP flows separation.
void DoRun() override
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.
void DoRun() override
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.
static TypeId GetTypeId()
Get the type ID.
bool CheckProtocol(Ptr< QueueDiscItem > item) const override
Check the protocol.
int32_t DoClassify(Ptr< QueueDiscItem > item) const override
Classify a QueueDiscItem.
a polymophic address class
Definition: address.h:101
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
Packet header for IPv4.
Definition: ipv4-header.h:34
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:309
void SetPayloadSize(uint16_t size)
Definition: ipv4-header.cc:57
void SetEcn(EcnType ecn)
Set ECN Field.
Definition: ipv4-header.cc:100
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:288
void SetSource(Ipv4Address source)
Definition: ipv4-header.cc:295
Ipv4PacketFilter is the abstract base class for filters defined for IPv4 packets.
Packet header for IPv6.
Definition: ipv6-header.h:35
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
Implements PIE Active Queue Management discipline.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Hold variables of type string.
Definition: string.h:56
Header for the Transmission Control Protocol.
Definition: tcp-header.h:47
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:70
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:64
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
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Packet header for UDP packets.
Definition: udp-header.h:41
void SetSourcePort(uint16_t port)
Definition: udp-header.cc:42
void SetDestinationPort(uint16_t port)
Definition: udp-header.cc:36
Hold an unsigned integer type.
Definition: uinteger.h:45
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:104
#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_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:251
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
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.