A Discrete-Event Network Simulator
API
fq-cobalt-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 (adapted for COBALT)
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 by: Bhaskar Kataria <bhaskar.k7920@gmail.com> (COBALT changes)
22 */
23
24#include "ns3/test.h"
25#include "ns3/simulator.h"
26#include "ns3/fq-cobalt-queue-disc.h"
27#include "ns3/cobalt-queue-disc.h"
28#include "ns3/ipv4-header.h"
29#include "ns3/ipv4-packet-filter.h"
30#include "ns3/ipv4-queue-disc-item.h"
31#include "ns3/ipv4-address.h"
32#include "ns3/ipv6-header.h"
33#include "ns3/ipv6-packet-filter.h"
34#include "ns3/ipv6-queue-disc-item.h"
35#include "ns3/tcp-header.h"
36#include "ns3/udp-header.h"
37#include "ns3/string.h"
38#include "ns3/pointer.h"
39
40using namespace ns3;
41
44
51public:
56 static TypeId GetTypeId (void);
57
60
61private:
67 virtual int32_t DoClassify (Ptr<QueueDiscItem> item) const;
68
74 virtual bool CheckProtocol (Ptr<QueueDiscItem> item) const;
75};
76
79{
80 static TypeId tid = TypeId ("ns3::Ipv4FqCobaltTestPacketFilter")
82 .SetGroupName ("Internet")
83 .AddConstructor<Ipv4FqCobaltTestPacketFilter> ()
84 ;
85 return tid;
86}
87
89{
90}
91
93{
94}
95
98{
99 return g_hash;
100}
101
102bool
104{
105 return true;
106}
107
114{
115public:
118
119private:
120 virtual void DoRun (void);
121};
122
124 : TestCase ("Test packets that are not classified by any filter")
125{
126}
127
129{
130}
131
132void
134{
135 // Packets that cannot be classified by the available filters should be dropped
136 Ptr<FqCobaltQueueDisc> queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ("MaxSize", StringValue ("4p"));
137 Ptr<Ipv4FqCobaltTestPacketFilter> filter = CreateObject<Ipv4FqCobaltTestPacketFilter> ();
138 queueDisc->AddPacketFilter (filter);
139
140 g_hash = -1;
141 queueDisc->SetQuantum (1500);
142 queueDisc->Initialize ();
143
144 Ptr<Packet> p;
145 p = Create<Packet> ();
147 Ipv6Header ipv6Header;
148 Address dest;
149 item = Create<Ipv6QueueDiscItem> (p, dest, 0, ipv6Header);
150 queueDisc->Enqueue (item);
151 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetNQueueDiscClasses (), 0, "no flow queue should have been created");
152
153 p = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello, world"), 12);
154 item = Create<Ipv6QueueDiscItem> (p, dest, 0, ipv6Header);
155 queueDisc->Enqueue (item);
156 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetNQueueDiscClasses (), 0, "no flow queue should have been created");
157
158 Simulator::Destroy ();
159}
160
167{
168public:
171
172private:
173 virtual void DoRun (void);
180};
181
183 : TestCase ("Test IP flows separation and packet limit")
184{
185}
186
188{
189}
190
191void
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
200void
202{
203 Ptr<FqCobaltQueueDisc> queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ("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{
244public:
246 virtual ~FqCobaltQueueDiscDeficit ();
247
248private:
249 virtual void DoRun (void);
256};
257
259 : TestCase ("Test credits and flows status")
260{
261}
262
264{
265}
266
267void
269{
270 Ptr<Packet> p = Create<Packet> (100);
271 Address dest;
272 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, hdr);
273 queue->Enqueue (item);
274}
275
276void
278{
279 Ptr<FqCobaltQueueDisc> queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ();
280
281 queueDisc->SetQuantum (90);
282 queueDisc->Initialize ();
283
284 Ipv4Header hdr;
285 hdr.SetPayloadSize (100);
286 hdr.SetSource (Ipv4Address ("10.10.1.1"));
287 hdr.SetDestination (Ipv4Address ("10.10.1.2"));
288 hdr.SetProtocol (7);
289
290 // Add a packet from the first flow
291 AddPacket (queueDisc, hdr);
292 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 1, "unexpected number of packets in the queue disc");
293 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the first flow queue");
294 Ptr<FqCobaltFlow> flow1 = StaticCast<FqCobaltFlow> (queueDisc->GetQueueDiscClass (0));
295 NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), static_cast<int32_t> (queueDisc->GetQuantum ()), "the deficit of the first flow must equal the quantum");
296 NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqCobaltFlow::NEW_FLOW, "the first flow must be in the list of new queues");
297 // Dequeue a packet
298 queueDisc->Dequeue ();
299 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 0, "unexpected number of packets in the queue disc");
300 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 0, "unexpected number of packets in the first flow queue");
301 // the deficit for the first flow becomes 90 - (100+20) = -30
302 NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), -30, "unexpected deficit for the first flow");
303
304 // Add two packets from the first flow
305 AddPacket (queueDisc, hdr);
306 AddPacket (queueDisc, hdr);
307 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 2, "unexpected number of packets in the queue disc");
308 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the first flow queue");
309 NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqCobaltFlow::NEW_FLOW, "the first flow must still be in the list of new queues");
310
311 // Add two packets from the second flow
312 hdr.SetDestination (Ipv4Address ("10.10.1.10"));
313 AddPacket (queueDisc, hdr);
314 AddPacket (queueDisc, hdr);
315 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 4, "unexpected number of packets in the queue disc");
316 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the first flow queue");
317 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the second flow queue");
318 Ptr<FqCobaltFlow> flow2 = StaticCast<FqCobaltFlow> (queueDisc->GetQueueDiscClass (1));
319 NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), static_cast<int32_t> (queueDisc->GetQuantum ()), "the deficit of the second flow must equal the quantum");
320 NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqCobaltFlow::NEW_FLOW, "the second flow must be in the list of new queues");
321
322 // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
323 queueDisc->Dequeue ();
324 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 3, "unexpected number of packets in the queue disc");
325 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the first flow queue");
326 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
327 // the first flow got a quantum of deficit (-30+90=60) and has been moved to the end of the list of old queues
328 NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), 60, "unexpected deficit for the first flow");
329 NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqCobaltFlow::OLD_FLOW, "the first flow must be in the list of old queues");
330 // the second flow has a negative deficit (-30) and is still in the list of new queues
331 NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), -30, "unexpected deficit for the second flow");
332 NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqCobaltFlow::NEW_FLOW, "the second flow must be in the list of new queues");
333
334 // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
335 queueDisc->Dequeue ();
336 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 2, "unexpected number of packets in the queue disc");
337 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the first flow queue");
338 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
339 // the first flow has a negative deficit (60-(100+20)= -60) and stays in the list of old queues
340 NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), -60, "unexpected deficit for the first flow");
341 NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqCobaltFlow::OLD_FLOW, "the first flow must be in the list of old queues");
342 // the second flow got a quantum of deficit (-30+90=60) and has been moved to the end of the list of old queues
343 NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), 60, "unexpected deficit for the second flow");
344 NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqCobaltFlow::OLD_FLOW, "the second flow must be in the list of new queues");
345
346 // Dequeue a packet (from the second flow, as the first flow has a negative deficit)
347 queueDisc->Dequeue ();
348 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 1, "unexpected number of packets in the queue disc");
349 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the first flow queue");
350 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 0, "unexpected number of packets in the second flow queue");
351 // the first flow got a quantum of deficit (-60+90=30) and has been moved to the end of the list of old queues
352 NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), 30, "unexpected deficit for the first flow");
353 NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqCobaltFlow::OLD_FLOW, "the first flow must be in the list of old queues");
354 // the second flow has a negative deficit (60-(100+20)= -60)
355 NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), -60, "unexpected deficit for the second flow");
356 NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqCobaltFlow::OLD_FLOW, "the second flow must be in the list of new queues");
357
358 // Dequeue a packet (from the first flow, as the second flow has a negative deficit)
359 queueDisc->Dequeue ();
360 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 0, "unexpected number of packets in the queue disc");
361 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 0, "unexpected number of packets in the first flow queue");
362 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 0, "unexpected number of packets in the second flow queue");
363 // the first flow has a negative deficit (30-(100+20)= -90)
364 NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), -90, "unexpected deficit for the first flow");
365 NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqCobaltFlow::OLD_FLOW, "the first flow must be in the list of old queues");
366 // the second flow got a quantum of deficit (-60+90=30) and has been moved to the end of the list of old queues
367 NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), 30, "unexpected deficit for the second flow");
368 NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqCobaltFlow::OLD_FLOW, "the second flow must be in the list of new queues");
369
370 // Dequeue a packet
371 queueDisc->Dequeue ();
372 // the first flow is at the head of the list of old queues but has a negative deficit, thus it gets a quantun
373 // of deficit (-90+90=0) and is moved to the end of the list of old queues. Then, the second flow (which has a
374 // positive deficit) is selected, but the second flow is empty and thus it is set to inactive. The first flow is
375 // reconsidered, but it has a null deficit, hence it gets another quantum of deficit (0+90=90). Then, the first
376 // flow is reconsidered again, now it has a positive deficit and hence it is selected. But, it is empty and
377 // therefore is set to inactive, too.
378 NS_TEST_ASSERT_MSG_EQ (flow1->GetDeficit (), 90, "unexpected deficit for the first flow");
379 NS_TEST_ASSERT_MSG_EQ (flow1->GetStatus (), FqCobaltFlow::INACTIVE, "the first flow must be inactive");
380 NS_TEST_ASSERT_MSG_EQ (flow2->GetDeficit (), 30, "unexpected deficit for the second flow");
381 NS_TEST_ASSERT_MSG_EQ (flow2->GetStatus (), FqCobaltFlow::INACTIVE, "the second flow must be inactive");
382
383 Simulator::Destroy ();
384}
385
392{
393public:
396
397private:
398 virtual void DoRun (void);
405 void AddPacket (Ptr<FqCobaltQueueDisc> queue, Ipv4Header ipHdr, TcpHeader tcpHdr);
406};
407
409 : TestCase ("Test TCP flows separation")
410{
411}
412
414{
415}
416
417void
419{
420 Ptr<Packet> p = Create<Packet> (100);
421 p->AddHeader (tcpHdr);
422 Address dest;
423 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, ipHdr);
424 queue->Enqueue (item);
425}
426
427void
429{
430 Ptr<FqCobaltQueueDisc> queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ("MaxSize", StringValue ("10p"));
431
432 queueDisc->SetQuantum (1500);
433 queueDisc->Initialize ();
434
435 Ipv4Header hdr;
436 hdr.SetPayloadSize (100);
437 hdr.SetSource (Ipv4Address ("10.10.1.1"));
438 hdr.SetDestination (Ipv4Address ("10.10.1.2"));
439 hdr.SetProtocol (6);
440
441 TcpHeader tcpHdr;
442 tcpHdr.SetSourcePort (7);
443 tcpHdr.SetDestinationPort (27);
444
445 // Add three packets from the first flow
446 AddPacket (queueDisc, hdr, tcpHdr);
447 AddPacket (queueDisc, hdr, tcpHdr);
448 AddPacket (queueDisc, hdr, tcpHdr);
449 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 3, "unexpected number of packets in the queue disc");
450 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
451
452 // Add a packet from the second flow
453 tcpHdr.SetSourcePort (8);
454 AddPacket (queueDisc, hdr, tcpHdr);
455 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 4, "unexpected number of packets in the queue disc");
456 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
457 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
458
459 // Add a packet from the third flow
460 tcpHdr.SetDestinationPort (28);
461 AddPacket (queueDisc, hdr, tcpHdr);
462 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 5, "unexpected number of packets in the queue disc");
463 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
464 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
465 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the third flow queue");
466
467 // Add two packets from the fourth flow
468 tcpHdr.SetSourcePort (7);
469 AddPacket (queueDisc, hdr, tcpHdr);
470 AddPacket (queueDisc, hdr, tcpHdr);
471 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 7, "unexpected number of packets in the queue disc");
472 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
473 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
474 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the third flow queue");
475 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (3)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the third flow queue");
476
477 Simulator::Destroy ();
478}
479
486{
487public:
490
491private:
492 virtual void DoRun (void);
499 void AddPacket (Ptr<FqCobaltQueueDisc> queue, Ipv4Header ipHdr, UdpHeader udpHdr);
500};
501
503 : TestCase ("Test UDP flows separation")
504{
505}
506
508{
509}
510
511void
513{
514 Ptr<Packet> p = Create<Packet> (100);
515 p->AddHeader (udpHdr);
516 Address dest;
517 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, ipHdr);
518 queue->Enqueue (item);
519}
520
521void
523{
524 Ptr<FqCobaltQueueDisc> queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ("MaxSize", StringValue ("10p"));
525
526 queueDisc->SetQuantum (1500);
527 queueDisc->Initialize ();
528
529 Ipv4Header hdr;
530 hdr.SetPayloadSize (100);
531 hdr.SetSource (Ipv4Address ("10.10.1.1"));
532 hdr.SetDestination (Ipv4Address ("10.10.1.2"));
533 hdr.SetProtocol (17);
534
535 UdpHeader udpHdr;
536 udpHdr.SetSourcePort (7);
537 udpHdr.SetDestinationPort (27);
538
539 // Add three packets from the first flow
540 AddPacket (queueDisc, hdr, udpHdr);
541 AddPacket (queueDisc, hdr, udpHdr);
542 AddPacket (queueDisc, hdr, udpHdr);
543 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 3, "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
546 // Add a packet from the second flow
547 udpHdr.SetSourcePort (8);
548 AddPacket (queueDisc, hdr, udpHdr);
549 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 4, "unexpected number of packets in the queue disc");
550 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
551 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
552
553 // Add a packet from the third flow
554 udpHdr.SetDestinationPort (28);
555 AddPacket (queueDisc, hdr, udpHdr);
556 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 5, "unexpected number of packets in the queue disc");
557 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
558 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
559 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the third flow queue");
560
561 // Add two packets from the fourth flow
562 udpHdr.SetSourcePort (7);
563 AddPacket (queueDisc, hdr, udpHdr);
564 AddPacket (queueDisc, hdr, udpHdr);
565 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 7, "unexpected number of packets in the queue disc");
566 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3, "unexpected number of packets in the first flow queue");
567 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the second flow queue");
568 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetNPackets (), 1, "unexpected number of packets in the third flow queue");
569 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (3)->GetQueueDisc ()->GetNPackets (), 2, "unexpected number of packets in the third flow queue");
570
571 Simulator::Destroy ();
572}
573
594{
595public:
598
599private:
600 virtual void DoRun (void);
609 void AddPacket (Ptr<FqCobaltQueueDisc> queue, Ipv4Header hdr, u_int32_t nPkt, u_int32_t nPktEnqueued, u_int32_t nQueueFlows);
615 void Dequeue (Ptr<FqCobaltQueueDisc> queue, uint32_t nPkt);
622 void DequeueWithDelay (Ptr<FqCobaltQueueDisc> queue, double delay, uint32_t nPkt);
628 void DropNextTracer (int64_t oldVal, int64_t newVal);
630};
631
633 : TestCase ("Test ECN marking")
634{
635 m_dropNextCount = 0;
636}
637
639{
640}
641
642void
643FqCobaltQueueDiscEcnMarking::AddPacket (Ptr<FqCobaltQueueDisc> queue, Ipv4Header hdr, u_int32_t nPkt, u_int32_t nPktEnqueued, u_int32_t nQueueFlows)
644{
645 Address dest;
646 Ptr<Packet> p = Create<Packet> (100);
647 for (uint32_t i = 0; i < nPkt; i++)
648 {
649 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, hdr);
650 queue->Enqueue (item);
651 }
652 NS_TEST_EXPECT_MSG_EQ (queue->GetNQueueDiscClasses (), nQueueFlows, "unexpected number of flow queues");
653 NS_TEST_EXPECT_MSG_EQ (queue->GetNPackets (), nPktEnqueued, "unexpected number of enqueued packets");
654}
655
656void
658{
659 Ptr<CobaltQueueDisc> q3 = queue->GetQueueDiscClass (3)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
660
661 // Trace DropNext after the first dequeue as m_dropNext value is set after the first dequeue
662 if (q3->GetNPackets () == 19)
663 {
664 q3->TraceConnectWithoutContext ("DropNext", MakeCallback (&FqCobaltQueueDiscEcnMarking::DropNextTracer, this));
665 }
666
667 for (uint32_t i = 0; i < nPkt; i++)
668 {
669 Ptr<QueueDiscItem> item = queue->Dequeue ();
670 }
671}
672
673void
675{
676 for (uint32_t i = 0; i < nPkt; i++)
677 {
678 Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &FqCobaltQueueDiscEcnMarking::Dequeue, this, queue, 1);
679 }
680}
681
682void
683FqCobaltQueueDiscEcnMarking::DropNextTracer ([[maybe_unused]] int64_t oldVal, [[maybe_unused]] int64_t newVal)
684{
686}
687
688void
690{
691 // Test is divided into 3 sub test cases:
692 // 1) CeThreshold disabled
693 // 2) CeThreshold enabled
694 // 3) Same as 2 but with higher queue delay
695
696 // Test case 1, CeThreshold disabled
697 Ptr<FqCobaltQueueDisc> queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ("MaxSize", StringValue ("10240p"), "UseEcn", BooleanValue (true),
698 "Perturbation", UintegerValue (0), "BlueThreshold", TimeValue (Time::Max ()));
699
700 queueDisc->SetQuantum (1514);
701 queueDisc->Initialize ();
702 Ipv4Header hdr;
703 hdr.SetPayloadSize (100);
704 hdr.SetSource (Ipv4Address ("10.10.1.1"));
705 hdr.SetDestination (Ipv4Address ("10.10.1.2"));
706 hdr.SetProtocol (7);
707 hdr.SetEcn (Ipv4Header::ECN_ECT0);
708
709 // Add 20 ECT0 (ECN capable) packets from the first flow
710 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 20, 1);
711
712 // Add 20 ECT0 (ECN capable) packets from second flow
713 hdr.SetDestination (Ipv4Address ("10.10.1.10"));
714 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 40, 2);
715
716 // Add 20 ECT0 (ECN capable) packets from third flow
717 hdr.SetDestination (Ipv4Address ("10.10.1.20"));
718 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 60, 3);
719
720 // Add 20 NotECT packets from fourth flow
721 hdr.SetDestination (Ipv4Address ("10.10.1.30"));
722 hdr.SetEcn (Ipv4Header::ECN_NotECT);
723 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 80, 4);
724
725 // Add 20 NotECT packets from fifth flow
726 hdr.SetDestination (Ipv4Address ("10.10.1.40"));
727 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 100, 5);
728
729 //Dequeue 60 packets with delay 110ms to induce packet drops and keep some remaining packets in each queue
730 DequeueWithDelay (queueDisc, 0.11, 60);
731 Simulator::Run ();
732 Simulator::Stop (Seconds (8.0));
733 Ptr<CobaltQueueDisc> q0 = queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
734 Ptr<CobaltQueueDisc> q1 = queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
735 Ptr<CobaltQueueDisc> q2 = queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
736 Ptr<CobaltQueueDisc> q3 = queueDisc->GetQueueDiscClass (3)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
737 Ptr<CobaltQueueDisc> q4 = queueDisc->GetQueueDiscClass (4)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
738
739 // As packets in flow queues are ECN capable
740 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 19, "There should be 19 marked packets."
741 "As there is no CoDel minBytes parameter so all the packets apart from the first one gets marked. As q3 and q4 have"
742 "NotEct packets and the queue delay is much higher than 5ms so the queue gets empty pretty quickly so more"
743 "packets from q0 can be dequeued.");
744 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
745 NS_TEST_EXPECT_MSG_EQ (q1->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 16, "There should be 16 marked packets"
746 "As there is no CoDel minBytes parameter so all the packets apart from the first one until no more packets are dequeued"
747 "are marked.");
748 NS_TEST_EXPECT_MSG_EQ (q1->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
749 NS_TEST_EXPECT_MSG_EQ (q2->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 12, "There should be 12 marked packets"
750 "Each packet size is 120 bytes and the quantum is 1500 bytes so in the first turn (1514/120 = 12.61) 13 packets are"
751 "dequeued and apart from the first one, all the packets are marked.");
752 NS_TEST_EXPECT_MSG_EQ (q2->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
753
754 // As packets in flow queues are not ECN capable
755 NS_TEST_EXPECT_MSG_EQ (q3->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), m_dropNextCount, "The number of drops should"
756 "be equal to the number of times m_dropNext is updated");
757 NS_TEST_EXPECT_MSG_EQ (q3->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 0, "There should not be any marked packets");
758 NS_TEST_EXPECT_MSG_EQ (q4->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), m_dropNextCount, "The number of drops should"
759 "be equal to the number of times m_dropNext is updated");
760 NS_TEST_EXPECT_MSG_EQ (q4->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 0, "There should not be any marked packets");
761
762 Simulator::Destroy ();
763
764 // Test case 2, CeThreshold set to 2ms
765 queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ("MaxSize", StringValue ("10240p"), "UseEcn", BooleanValue (true),
766 "CeThreshold", TimeValue (MilliSeconds (2)));
767 queueDisc->SetQuantum (1514);
768 queueDisc->Initialize ();
769
770 // Add 20 ECT0 (ECN capable) packets from first flow
771 hdr.SetDestination (Ipv4Address ("10.10.1.2"));
772 hdr.SetEcn (Ipv4Header::ECN_ECT0);
773 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 20, 1);
774
775 // Add 20 ECT0 (ECN capable) packets from second flow
776 hdr.SetDestination (Ipv4Address ("10.10.1.10"));
777 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 40, 2);
778
779 // Add 20 ECT0 (ECN capable) packets from third flow
780 hdr.SetDestination (Ipv4Address ("10.10.1.20"));
781 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 60, 3);
782
783 // Add 20 NotECT packets from fourth flow
784 hdr.SetDestination (Ipv4Address ("10.10.1.30"));
785 hdr.SetEcn (Ipv4Header::ECN_NotECT);
786 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 80, 4);
787
788 // Add 20 NotECT packets from fifth flow
789 hdr.SetDestination (Ipv4Address ("10.10.1.40"));
790 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 100, 5);
791
792 //Dequeue 60 packets with delay 0.1ms to induce packet drops and keep some remaining packets in each queue
793 DequeueWithDelay (queueDisc, 0.0001, 60);
794 Simulator::Run ();
795 Simulator::Stop (Seconds (8.0));
796 q0 = queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
797 q1 = queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
798 q2 = queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
799 q3 = queueDisc->GetQueueDiscClass (3)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
800 q4 = queueDisc->GetQueueDiscClass (4)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
801
802 // As packets in flow queues are ECN capable
803 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
804 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 0, "There should not be any marked packets"
805 "with quantum of 1514, 13 packets of size 120 bytes can be dequeued. sojourn time of 13th packet is 1.3ms which is"
806 "less than CE threshold");
807 NS_TEST_EXPECT_MSG_EQ (q1->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
808 NS_TEST_EXPECT_MSG_EQ (q1->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 6, "There should be 6 marked packets"
809 "with quantum of 1514, 13 packets of size 120 bytes can be dequeued. sojourn time of 8th packet is 2.1ms which is greater"
810 "than CE threshold and subsequent packet also have sojourn time more 8th packet hence remaining packet are marked.");
811 NS_TEST_EXPECT_MSG_EQ (q2->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
812 NS_TEST_EXPECT_MSG_EQ (q2->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 13, "There should be 13 marked packets"
813 "with quantum of 1514, 13 packets of size 120 bytes can be dequeued and all of them have sojourn time more than CE threshold");
814
815 // As packets in flow queues are not ECN capable
816 NS_TEST_EXPECT_MSG_EQ (q3->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 0, "There should not be any marked packets");
817 NS_TEST_EXPECT_MSG_EQ (q3->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
818 NS_TEST_EXPECT_MSG_EQ (q4->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 0, "There should not be any marked packets");
819 NS_TEST_EXPECT_MSG_EQ (q4->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 1, "There should 1 dropped packet. As the queue"
820 "delay for the first dequeue is greater than the target (5ms), Cobalt overloads the m_dropNext field as an activity timeout"
821 "and dropNext is to set to the current Time value so on the next dequeue a packet is dropped.");
822
823 Simulator::Destroy ();
824
825 // Test case 3, CeThreshold set to 2ms with higher queue delay. This test is mainly to check that the packets are not getting marked twice.
826 queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ("MaxSize", StringValue ("10240p"), "UseEcn", BooleanValue (true),
827 "CeThreshold", TimeValue (MilliSeconds (2)), "BlueThreshold", TimeValue (Time::Max()));
828 queueDisc->SetQuantum (1514);
829 queueDisc->Initialize ();
830
831 // Add 20 ECT0 (ECN capable) packets from first flow
832 hdr.SetDestination (Ipv4Address ("10.10.1.2"));
833 hdr.SetEcn (Ipv4Header::ECN_ECT0);
834 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 20, 1);
835
836 // Add 20 ECT0 (ECN capable) packets from second flow
837 hdr.SetDestination (Ipv4Address ("10.10.1.10"));
838 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 40, 2);
839
840 // Add 20 ECT0 (ECN capable) packets from third flow
841 hdr.SetDestination (Ipv4Address ("10.10.1.20"));
842 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 60, 3);
843
844 // Add 20 NotECT packets from fourth flow
845 hdr.SetDestination (Ipv4Address ("10.10.1.30"));
846 hdr.SetEcn (Ipv4Header::ECN_NotECT);
847 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 80, 4);
848
849 // Add 20 NotECT packets from fifth flow
850 hdr.SetDestination (Ipv4Address ("10.10.1.40"));
851 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscEcnMarking::AddPacket, this, queueDisc, hdr, 20, 100, 5);
852
853 // Reset m_dropNextCount value;
854 m_dropNextCount = 0;
855
856 //Dequeue 60 packets with delay 110ms to induce packet drops and keep some remaining packets in each queue
857 DequeueWithDelay (queueDisc, 0.110, 60);
858 Simulator::Run ();
859 Simulator::Stop (Seconds (8.0));
860 q0 = queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
861 q1 = queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
862 q2 = queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
863 q3 = queueDisc->GetQueueDiscClass (3)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
864 q4 = queueDisc->GetQueueDiscClass (4)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
865
866 // As packets in flow queues are ECN capable
867 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
868 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK) +
869 q0->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 20 - q0->GetNPackets (), "Number of CE threshold"
870 " exceeded marks plus Number of Target exceeded marks should be equal to total number of packets dequeued");
871 NS_TEST_EXPECT_MSG_EQ (q1->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
872 NS_TEST_EXPECT_MSG_EQ (q1->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK) +
873 q1->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 20 - q1->GetNPackets (), "Number of CE threshold"
874 " exceeded marks plus Number of Target exceeded marks should be equal to total number of packets dequeued");
875 NS_TEST_EXPECT_MSG_EQ (q2->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
876 NS_TEST_EXPECT_MSG_EQ (q2->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK) +
877 q2->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 20 - q2->GetNPackets (), "Number of CE threshold"
878 " exceeded marks plus Number of Target exceeded marks should be equal to total number of packets dequeued");
879
880 // As packets in flow queues are not ECN capable
881 NS_TEST_EXPECT_MSG_EQ (q3->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 0, "There should not be any marked packets");
882 NS_TEST_EXPECT_MSG_EQ (q3->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), m_dropNextCount, "The number of drops should"
883 "be equal to the number of times m_dropNext is updated");
884 NS_TEST_EXPECT_MSG_EQ (q4->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 0, "There should not be any marked packets");
885 NS_TEST_EXPECT_MSG_EQ (q4->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), m_dropNextCount, "The number of drops should"
886 "be equal to the number of times m_dropNext is updated");
887
888 Simulator::Destroy ();
889}
890
916{
917public:
920private:
921 virtual void DoRun (void);
928};
929
931 : TestCase ("Test credits and flows status")
932{
933}
934
936{
937}
938
939void
941{
942 Ptr<Packet> p = Create<Packet> (100);
943 Address dest;
944 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, hdr);
945 queue->Enqueue (item);
946}
947
948void
950{
951 Ptr<FqCobaltQueueDisc> queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ("EnableSetAssociativeHash", BooleanValue (true));
952 queueDisc->SetQuantum (90);
953 queueDisc->Initialize ();
954
955 Ptr<Ipv4FqCobaltTestPacketFilter> filter = CreateObject<Ipv4FqCobaltTestPacketFilter> ();
956 queueDisc->AddPacketFilter (filter);
957
958 Ipv4Header hdr;
959 hdr.SetPayloadSize (100);
960 hdr.SetSource (Ipv4Address ("10.10.1.1"));
961 hdr.SetDestination (Ipv4Address ("10.10.1.2"));
962 hdr.SetProtocol (7);
963
964 g_hash = 0;
965 AddPacket (queueDisc, hdr);
966 g_hash = 1;
967 AddPacket (queueDisc, hdr);
968 AddPacket (queueDisc, hdr);
969 g_hash = 2;
970 AddPacket (queueDisc, hdr);
971 g_hash = 3;
972 AddPacket (queueDisc, hdr);
973 g_hash = 4;
974 AddPacket (queueDisc, hdr);
975 AddPacket (queueDisc, hdr);
976 g_hash = 5;
977 AddPacket (queueDisc, hdr);
978 g_hash = 6;
979 AddPacket (queueDisc, hdr);
980 g_hash = 7;
981 AddPacket (queueDisc, hdr);
982 g_hash = 1024;
983 AddPacket (queueDisc, hdr);
984
985 NS_TEST_ASSERT_MSG_EQ (queueDisc->QueueDisc::GetNPackets (), 11,
986 "unexpected number of packets in the queue disc");
987 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 2,
988 "unexpected number of packets in the first flow queue of set one");
989 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetNPackets (), 2,
990 "unexpected number of packets in the second flow queue of set one");
991 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (2)->GetQueueDisc ()->GetNPackets (), 1,
992 "unexpected number of packets in the third flow queue of set one");
993 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (3)->GetQueueDisc ()->GetNPackets (), 1,
994 "unexpected number of packets in the fourth flow queue of set one");
995 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (4)->GetQueueDisc ()->GetNPackets (), 2,
996 "unexpected number of packets in the fifth flow queue of set one");
997 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (5)->GetQueueDisc ()->GetNPackets (), 1,
998 "unexpected number of packets in the sixth flow queue of set one");
999 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (6)->GetQueueDisc ()->GetNPackets (), 1,
1000 "unexpected number of packets in the seventh flow queue of set one");
1001 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (7)->GetQueueDisc ()->GetNPackets (), 1,
1002 "unexpected number of packets in the eighth flow queue of set one");
1003 g_hash = 1025;
1004 AddPacket (queueDisc, hdr);
1005 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), 3,
1006 "unexpected number of packets in the first flow of set one");
1007 g_hash = 10;
1008 AddPacket (queueDisc, hdr);
1009 NS_TEST_ASSERT_MSG_EQ (queueDisc->GetQueueDiscClass (8)->GetQueueDisc ()->GetNPackets (), 1,
1010 "unexpected number of packets in the first flow of set two");
1011 Simulator::Destroy ();
1012}
1013
1014
1032{
1033public:
1035 virtual ~FqCobaltQueueDiscL4sMode ();
1036
1037private:
1038 virtual void DoRun (void);
1045 void AddPacket (Ptr<FqCobaltQueueDisc> queue, Ipv4Header hdr, u_int32_t nPkt);
1053 void AddPacketWithDelay (Ptr<FqCobaltQueueDisc> queue,Ipv4Header hdr, double delay, uint32_t nPkt);
1059 void Dequeue (Ptr<FqCobaltQueueDisc> queue, uint32_t nPkt);
1066 void DequeueWithDelay (Ptr<FqCobaltQueueDisc> queue, double delay, uint32_t nPkt);
1067};
1068
1070 : TestCase ("Test L4S mode")
1071{
1072}
1073
1075{
1076}
1077
1078void
1080{
1081 Address dest;
1082 Ptr<Packet> p = Create<Packet> (100);
1083 for (uint32_t i = 0; i < nPkt; i++)
1084 {
1085 Ptr<Ipv4QueueDiscItem> item = Create<Ipv4QueueDiscItem> (p, dest, 0, hdr);
1086 queue->Enqueue (item);
1087 }
1088}
1089
1090void
1092{
1093 for (uint32_t i = 0; i < nPkt; i++)
1094 {
1095 Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &FqCobaltQueueDiscL4sMode::AddPacket, this, queue, hdr, 1);
1096 }
1097}
1098
1099void
1101{
1102 for (uint32_t i = 0; i < nPkt; i++)
1103 {
1104 Ptr<QueueDiscItem> item = queue->Dequeue ();
1105 }
1106}
1107
1108void
1110{
1111 for (uint32_t i = 0; i < nPkt; i++)
1112 {
1113 Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &FqCobaltQueueDiscL4sMode::Dequeue, this, queue, 1);
1114 }
1115}
1116
1117void
1119{
1120 // Test is divided into 2 sub test cases:
1121 // 1) Without hash collisions
1122 // 2) With hash collisions
1123
1124 // Test case 1, Without hash collisions
1125 Ptr<FqCobaltQueueDisc> queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ("MaxSize", StringValue ("10240p"), "UseEcn", BooleanValue (true),
1126 "Perturbation", UintegerValue (0), "UseL4s", BooleanValue (true),
1127 "CeThreshold", TimeValue (MilliSeconds (2)));
1128
1129 queueDisc->SetQuantum (1514);
1130 queueDisc->Initialize ();
1131 Ipv4Header hdr;
1132 hdr.SetPayloadSize (100);
1133 hdr.SetSource (Ipv4Address ("10.10.1.1"));
1134 hdr.SetDestination (Ipv4Address ("10.10.1.2"));
1135 hdr.SetProtocol (7);
1136 hdr.SetEcn (Ipv4Header::ECN_ECT1);
1137
1138 // Add 70 ECT1 (ECN capable) packets from the first flow
1139 // Set delay = 0.5ms
1140 double delay = 0.0005;
1141 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscL4sMode::AddPacketWithDelay, this, queueDisc, hdr, delay, 70);
1142
1143 // Add 70 ECT0 (ECN capable) packets from second flow
1144 hdr.SetEcn (Ipv4Header::ECN_ECT0);
1145 hdr.SetDestination (Ipv4Address ("10.10.1.10"));
1146 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscL4sMode::AddPacketWithDelay, this, queueDisc, hdr, delay, 70);
1147
1148 //Dequeue 140 packets with delay 1ms
1149 delay = 0.001;
1150 DequeueWithDelay (queueDisc, delay, 140);
1151 Simulator::Run ();
1152 Simulator::Stop (Seconds (8.0));
1153 Ptr<CobaltQueueDisc> q0 = queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
1154 Ptr<CobaltQueueDisc> q1 = queueDisc->GetQueueDiscClass (1)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
1155
1156 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 66, "There should be 66 marked packets"
1157 "4th packet is enqueued at 2ms and dequeued at 4ms hence the delay of 2ms which not greater than CE threshold"
1158 "5th packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and subsequent packet also do have delay"
1159 "greater than CE threshold so all the packets after 4th packet are marked");
1160 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
1161 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 0, "There should not be any marked packets");
1162 NS_TEST_EXPECT_MSG_EQ (q1->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 2, "There should be 2 marked packets. Packets are dequeued"
1163 "from q0 first, which leads to delay greater than 5ms for the first dequeue from q1. Because of inactivity (started with high queue delay)"
1164 "Cobalt keeps drop_next as now and the next packet is marked. With second dequeue count increases to 2, drop_next becomes now plus around"
1165 "70ms which is less than the running time(140), and as the queue delay is persistantly higher than 5ms, second packet is marked.");
1166 NS_TEST_EXPECT_MSG_EQ (q1->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
1167
1168 Simulator::Destroy ();
1169
1170 // Test case 2, With hash collisions
1171 queueDisc = CreateObjectWithAttributes<FqCobaltQueueDisc> ("MaxSize", StringValue ("10240p"), "UseEcn", BooleanValue (true),
1172 "Perturbation", UintegerValue (0), "UseL4s", BooleanValue (true),
1173 "CeThreshold", TimeValue (MilliSeconds (2)));
1174
1175 queueDisc->SetQuantum (1514);
1176 queueDisc->Initialize ();
1177 hdr.SetPayloadSize (100);
1178 hdr.SetSource (Ipv4Address ("10.10.1.1"));
1179 hdr.SetDestination (Ipv4Address ("10.10.1.2"));
1180 hdr.SetProtocol (7);
1181 hdr.SetEcn (Ipv4Header::ECN_ECT1);
1182
1183 // Add 70 ECT1 (ECN capable) packets from the first flow
1184 // Set delay = 1ms
1185 delay = 0.001;
1186 Simulator::Schedule (Time (Seconds (0.0005)), &FqCobaltQueueDiscL4sMode::AddPacket, this, queueDisc, hdr, 1);
1187 Simulator::Schedule (Time (Seconds (0.0005)), &FqCobaltQueueDiscL4sMode::AddPacketWithDelay, this, queueDisc, hdr, delay, 69);
1188
1189 // Add 70 ECT0 (ECN capable) packets from first flow
1190 hdr.SetEcn (Ipv4Header::ECN_ECT0);
1191 Simulator::Schedule (Time (Seconds (0)), &FqCobaltQueueDiscL4sMode::AddPacketWithDelay, this, queueDisc, hdr, delay, 70);
1192
1193 //Dequeue 140 packets with delay 1ms
1194 DequeueWithDelay (queueDisc, delay, 140);
1195 Simulator::Run ();
1196 Simulator::Stop (Seconds (8.0));
1197 q0 = queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
1198 q0 = queueDisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetObject <CobaltQueueDisc> ();
1199
1200 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (CobaltQueueDisc::CE_THRESHOLD_EXCEEDED_MARK), 68, "There should be 68 marked packets"
1201 "2nd ECT1 packet is enqueued at 1.5ms and dequeued at 3ms hence the delay of 1.5ms which not greater than CE threshold"
1202 "3rd packet is enqueued at 2.5ms and dequeued at 5ms hence the delay of 2.5ms and subsequent packet also do have delay"
1203 "greater than CE threshold so all the packets after 2nd packet are marked");
1204 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP), 0, "There should not be any dropped packets");
1205 NS_TEST_EXPECT_MSG_EQ (q0->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK), 1, "There should be 1 marked packets");
1206
1207 Simulator::Destroy ();
1208
1209}
1210
1217{
1218public:
1220};
1221
1223 : TestSuite ("fq-cobalt-queue-disc", UNIT)
1224{
1225 AddTestCase (new FqCobaltQueueDiscNoSuitableFilter, TestCase::QUICK);
1227 AddTestCase (new FqCobaltQueueDiscDeficit, TestCase::QUICK);
1228 AddTestCase (new FqCobaltQueueDiscTCPFlowsSeparation, TestCase::QUICK);
1229 AddTestCase (new FqCobaltQueueDiscUDPFlowsSeparation, TestCase::QUICK);
1230 AddTestCase (new FqCobaltQueueDiscEcnMarking, TestCase::QUICK);
1231 AddTestCase (new FqCobaltQueueDiscSetLinearProbing, TestCase::QUICK);
1232 AddTestCase (new FqCobaltQueueDiscL4sMode, TestCase::QUICK);
1233}
1234
#define Max(a, b)
This class tests the deficit per flow.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
virtual void DoRun(void)
Implementation to actually run this TestCase.
uint32_t m_dropNextCount
count the number of times m_dropNext is recalculated
void DequeueWithDelay(Ptr< FqCobaltQueueDisc > queue, double delay, uint32_t nPkt)
Dequeue the given number of packets at different times.
void Dequeue(Ptr< FqCobaltQueueDisc > queue, uint32_t nPkt)
Dequeue the given number of packets.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr, u_int32_t nPkt, u_int32_t nPktEnqueued, u_int32_t nQueueFlows)
Enqueue the given number of packets.
void DropNextTracer(int64_t oldVal, int64_t newVal)
Tracer for the DropNext attribute.
virtual void DoRun(void)
Implementation to actually run this TestCase.
This class tests the IP flows separation and the packet limit.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr, u_int32_t nPkt)
Enqueue the given number of packets.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void DequeueWithDelay(Ptr< FqCobaltQueueDisc > queue, double delay, uint32_t nPkt)
Dequeue the given number of packets at different times.
void Dequeue(Ptr< FqCobaltQueueDisc > queue, uint32_t nPkt)
Dequeue the given number of packets.
void AddPacketWithDelay(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr, double delay, uint32_t nPkt)
Enqueue the given number of packets at different times.
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...
virtual void DoRun(void)
Implementation to actually run this TestCase.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header hdr)
Enqueue a packet.
This class tests the TCP flows separation.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header ipHdr, TcpHeader tcpHdr)
Enqueue a packet.
virtual void DoRun(void)
Implementation to actually run this TestCase.
FQ-COBALT queue disc test suite.
This class tests the UDP flows separation.
void AddPacket(Ptr< FqCobaltQueueDisc > queue, Ipv4Header ipHdr, UdpHeader udpHdr)
Enqueue a packet.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Simple test packet filter able to classify IPv4 packets.
virtual int32_t DoClassify(Ptr< QueueDiscItem > item) const
Classify a QueueDiscItem.
static TypeId GetTypeId(void)
Get the type ID.
virtual bool CheckProtocol(Ptr< QueueDiscItem > item) const
Check the protocol.
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Cobalt packet queue disc.
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
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 FqCobaltQueueDiscTestSuite g_fqCobaltQueueDiscTestSuite
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.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648