A Discrete-Event Network Simulator
API
fqcodel-l4s-example.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2020 NITK Surathkal
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: Bhaskar Kataria <bhaskar.k7920@gmail.com>
19 * Tom Henderson <tomhend@u.washington.edu>
20 * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
21 * Vivek Jain <jain.vivek.anand@gmail.com>
22 * Ankit Deepak <adadeepak8@gmail.com>
23 * This script is written using Tom Henderson's L4S evaluation available at https://gitlab.com/tomhend/modules/l4s-evaluation
24 */
25
26// The 9 configurations below test BIC and DCTCP under various scenarios.
27// Scenarios are numbered 1-9. By default, scenario number 0 (i.e., no
28// scenario) is configured, which means that the user is free to set
29// any of the parameters freely; if scenarios 1 through 9 are selected,
30// the scenario parameters are fixed.
31//
32// The configuration of the scenarios starts from basic TCP BIC without ECN
33// with the base RTT of 80ms and then in the next scenario, ECN is enabled,
34// and gradually, the complexity of the scenario increases and the last scenario
35// consists of 2 flows one with BIC and other with DCTCP and finally tests
36// The performance of the L4S mode of FqCoDel queue disc.
37
289#include "ns3/core-module.h"
290#include "ns3/network-module.h"
291#include "ns3/internet-module.h"
292#include "ns3/flow-monitor-helper.h"
293#include "ns3/point-to-point-module.h"
294#include "ns3/applications-module.h"
295#include "ns3/internet-apps-module.h"
296#include "ns3/traffic-control-module.h"
297
298using namespace ns3;
299
300NS_LOG_COMPONENT_DEFINE ("FqCoDelL4SExample");
301
304
309
310void
311TraceN0Cwnd (std::ofstream* ofStream, uint32_t oldCwnd, uint32_t newCwnd)
312{
313 // TCP segment size is configured below to be 1448 bytes
314 // so that we can report cwnd in units of segments
315 *ofStream << Simulator::Now ().GetSeconds () << " " << static_cast<double> (newCwnd) / 1448 << std::endl;
316}
317
318void
319TraceN1Cwnd (std::ofstream* ofStream, uint32_t oldCwnd, uint32_t newCwnd)
320{
321 // TCP segment size is configured below to be 1448 bytes
322 // so that we can report cwnd in units of segments
323 *ofStream << Simulator::Now ().GetSeconds () << " " << static_cast<double> (newCwnd) / 1448 << std::endl;
324}
325
326void
327TraceN0Rtt (std::ofstream* ofStream, Time oldRtt, Time newRtt)
328{
329 *ofStream << Simulator::Now ().GetSeconds () << " " << newRtt.GetSeconds () * 1000 << std::endl;
330}
331
332void
333TraceN1Rtt (std::ofstream* ofStream, Time oldRtt, Time newRtt)
334{
335 *ofStream << Simulator::Now ().GetSeconds () << " " << newRtt.GetSeconds () * 1000 << std::endl;
336}
337
338void
339TracePingRtt (std::ofstream* ofStream, Time rtt)
340{
341 *ofStream << Simulator::Now ().GetSeconds () << " " << rtt.GetSeconds () * 1000 << std::endl;
342}
343
344void
346{
347 g_n0BytesReceived += packet->GetSize ();
348}
349
350void
352{
353 g_n1BytesReceived += packet->GetSize ();
354}
355
356void
357TraceDrop (std::ofstream* ofStream, Ptr<const QueueDiscItem> item)
358{
359 *ofStream << Simulator::Now ().GetSeconds () << " " << std::hex << item->Hash () << std::endl;
361}
362
363void
364TraceMark (std::ofstream* ofStream, Ptr<const QueueDiscItem> item, const char* reason)
365{
366 *ofStream << Simulator::Now ().GetSeconds () << " " << std::hex << item->Hash () << std::endl;
368}
369
370void
371TraceQueueLength (std::ofstream* ofStream, DataRate linkRate, uint32_t oldVal, uint32_t newVal)
372{
373 // output in units of ms
374 *ofStream << Simulator::Now ().GetSeconds () << " " << std::fixed << static_cast<double> (newVal * 8) / (linkRate.GetBitRate () / 1000) << std::endl;
375}
376
377void
378TraceDropsFrequency (std::ofstream* ofStream, Time dropsSamplingInterval)
379{
380 *ofStream << Simulator::Now ().GetSeconds () << " " << g_dropsObserved << std::endl;
381 g_dropsObserved = 0;
382 Simulator::Schedule (dropsSamplingInterval, &TraceDropsFrequency, ofStream, dropsSamplingInterval);
383}
384
385void
386TraceMarksFrequency (std::ofstream* ofStream, Time marksSamplingInterval)
387{
388 *ofStream << Simulator::Now ().GetSeconds () << " " << g_marksObserved << std::endl;
389 g_marksObserved = 0;
390 Simulator::Schedule (marksSamplingInterval, &TraceMarksFrequency, ofStream, marksSamplingInterval);
391}
392
393void
394TraceN0Throughput (std::ofstream* ofStream, Time throughputInterval)
395{
396 *ofStream << Simulator::Now ().GetSeconds () << " " << g_n0BytesReceived * 8 / throughputInterval.GetSeconds () / 1e6 << std::endl;
398 Simulator::Schedule (throughputInterval, &TraceN0Throughput, ofStream, throughputInterval);
399}
400
401void
402TraceN1Throughput (std::ofstream* ofStream, Time throughputInterval)
403{
404 *ofStream << Simulator::Now ().GetSeconds () << " " << g_n1BytesReceived * 8 / throughputInterval.GetSeconds () / 1e6 << std::endl;
406 Simulator::Schedule (throughputInterval, &TraceN1Throughput, ofStream, throughputInterval);
407}
408
409void
410ScheduleN0TcpCwndTraceConnection (std::ofstream* ofStream)
411{
412 Config::ConnectWithoutContext ("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeBoundCallback (&TraceN0Cwnd, ofStream));
413}
414
415void
416ScheduleN0TcpRttTraceConnection (std::ofstream* ofStream)
417{
418 Config::ConnectWithoutContext ("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/RTT", MakeBoundCallback (&TraceN0Rtt, ofStream));
419}
420
421void
423{
424 Config::ConnectWithoutContext ("/NodeList/6/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&TraceN0Rx));
425}
426
427void
428ScheduleN1TcpCwndTraceConnection (std::ofstream* ofStream)
429{
430 Config::ConnectWithoutContext ("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeBoundCallback (&TraceN1Cwnd, ofStream));
431}
432
433void
434ScheduleN1TcpRttTraceConnection (std::ofstream* ofStream)
435{
436 Config::ConnectWithoutContext ("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/RTT", MakeBoundCallback (&TraceN1Rtt, ofStream));
437}
438
439void
441{
442 Config::ConnectWithoutContext ("/NodeList/7/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&TraceN1Rx));
443}
444
445static void
446PacketDequeue (std::ofstream* n0OfStream, std::ofstream* n1OfStream, Ptr<QueueDiscItem const> item)
447{
448 Ptr<Packet> p = item->GetPacket ();
450 Ipv4Address address = iqdi->GetHeader ().GetDestination ();
451 Time qDelay = Simulator::Now () - item->GetTimeStamp ();
452 if (address == "192.168.2.2")
453 {
454 *n0OfStream << Simulator::Now ().GetSeconds () << " " << qDelay.GetMicroSeconds () / 1000.0 << std::endl;
455 }
456 else if (address == "192.168.3.2")
457 {
458 *n1OfStream << Simulator::Now ().GetSeconds () << " " << qDelay.GetMicroSeconds () / 1000.0 << std::endl;
459 }
460}
461
462int
463main (int argc, char *argv[])
464{
466 // variables not configured at command line //
468 Time stopTime = Seconds (70);
469 Time baseRtt = MilliSeconds (80);
470 uint32_t pingSize = 100; // bytes
471 Time pingInterval = MilliSeconds (100);
472 Time marksSamplingInterval = MilliSeconds (100);
473 Time throughputSamplingInterval = MilliSeconds (200);
474 DataRate bottleneckRate ("100Mbps");
475
476 std::string dir = "results/FqCoDel-L4S/";
477 std::string dirToSave = "mkdir -p " + dir;
478 if (system (dirToSave.c_str ()) == -1)
479 {
480 exit (1);
481 }
482
483 std::string pingTraceFile = dir + "ping.dat";
484 std::string n0TcpRttTraceFile = dir + "n0-tcp-rtt.dat";
485 std::string n0TcpCwndTraceFile = dir + "n0-tcp-cwnd.dat";
486 std::string n0TcpThroughputTraceFile = dir + "n0-tcp-throughput.dat";
487 std::string n1TcpRttTraceFile = dir + "n1-tcp-rtt.dat";
488 std::string n1TcpCwndTraceFile = dir + "n1-tcp-cwnd.dat";
489 std::string n1TcpThroughputTraceFile = dir + "n1-tcp-throughput.dat";
490 std::string dropTraceFile = dir + "drops.dat";
491 std::string dropsFrequencyTraceFile = dir + "drops-frequency.dat";
492 std::string lengthTraceFile = dir + "length.dat";
493 std::string markTraceFile = dir + "mark.dat";
494 std::string marksFrequencyTraceFile = dir + "marks-frequency.dat";
495 std::string queueDelayN0TraceFile = dir + "queue-delay-n0.dat";
496 std::string queueDelayN1TraceFile = dir + "queue-delay-n1.dat";
497
499 // variables configured at command line //
501 bool enablePcap = false;
502 bool useCeThreshold = false;
503 Time ceThreshold = MilliSeconds (1);
504 std::string n0TcpType = "bic";
505 std::string n1TcpType = "";
506 bool enableN1Tcp = false;
507 bool useEcn = true;
508 std::string queueType = "fq";
509 std::string linkDataRate = "1Gbps";
510 uint32_t scenarioNum = 0;
511
513 // Override ns-3 defaults //
515 Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1448));
516 // Increase default buffer sizes to improve throughput over long delay paths
517 Config::SetDefault ("ns3::TcpSocket::SndBufSize",UintegerValue (8192000));
518 Config::SetDefault ("ns3::TcpSocket::RcvBufSize",UintegerValue (8192000));
519 Config::SetDefault ("ns3::TcpSocket::InitialCwnd", UintegerValue (10));
520 Config::SetDefault ("ns3::TcpL4Protocol::RecoveryType", TypeIdValue (TcpPrrRecovery::GetTypeId ()));
521
523 // command-line argument parsing //
526 cmd.AddValue ("n0TcpType", "n0 TCP type (bic, dctcp, or reno)", n0TcpType);
527 cmd.AddValue ("n1TcpType", "n1 TCP type (bic, dctcp, or reno)", n1TcpType);
528 cmd.AddValue ("scenarioNum", "Scenario number from the scenarios avalaible in the file (1-9)", scenarioNum);
529 cmd.AddValue ("bottleneckQueueType", "n2 queue type (fq or codel)", queueType);
530 cmd.AddValue ("baseRtt", "base RTT", baseRtt);
531 cmd.AddValue ("useCeThreshold", "use CE Threshold", useCeThreshold);
532 cmd.AddValue ("useEcn", "use ECN", useEcn);
533 cmd.AddValue ("ceThreshold", "CoDel CE threshold", ceThreshold);
534 cmd.AddValue ("bottleneckRate", "data rate of bottleneck", bottleneckRate);
535 cmd.AddValue ("linkRate", "data rate of edge link", linkDataRate);
536 cmd.AddValue ("stopTime", "simulation stop time", stopTime);
537 cmd.AddValue ("enablePcap", "enable Pcap", enablePcap);
538 cmd.AddValue ("pingTraceFile", "filename for ping tracing", pingTraceFile);
539 cmd.AddValue ("n0TcpRttTraceFile", "filename for n0 rtt tracing", n0TcpRttTraceFile);
540 cmd.AddValue ("n0TcpCwndTraceFile", "filename for n0 cwnd tracing", n0TcpCwndTraceFile);
541 cmd.AddValue ("n0TcpThroughputTraceFile", "filename for n0 throughput tracing", n0TcpThroughputTraceFile);
542 cmd.AddValue ("n1TcpRttTraceFile", "filename for n1 rtt tracing", n1TcpRttTraceFile);
543 cmd.AddValue ("n1TcpCwndTraceFile", "filename for n1 cwnd tracing", n1TcpCwndTraceFile);
544 cmd.AddValue ("n1TcpThroughputTraceFile", "filename for n1 throughput tracing", n1TcpThroughputTraceFile);
545 cmd.AddValue ("dropTraceFile", "filename for n2 drops tracing", dropTraceFile);
546 cmd.AddValue ("dropsFrequencyTraceFile", "filename for n2 drop frequency tracing", dropsFrequencyTraceFile);
547 cmd.AddValue ("lengthTraceFile", "filename for n2 queue length tracing", lengthTraceFile);
548 cmd.AddValue ("markTraceFile", "filename for n2 mark tracing", markTraceFile);
549 cmd.AddValue ("marksFrequencyTraceFile", "filename for n2 mark frequency tracing", marksFrequencyTraceFile);
550 cmd.AddValue ("queueDelayN0TraceFile", "filename for n0 queue delay tracing", queueDelayN0TraceFile);
551 cmd.AddValue ("queueDelayN1TraceFile", "filename for n1 queue delay tracing", queueDelayN1TraceFile);
552 cmd.Parse (argc, argv);
553 Time oneWayDelay = baseRtt / 2;
554 TypeId n0TcpTypeId;
555 TypeId n1TcpTypeId;
556 TypeId queueTypeId;
557 if (!scenarioNum)
558 {
559 if (useEcn)
560 {
561 Config::SetDefault ("ns3::TcpSocketBase::UseEcn", StringValue ("On"));
562 }
563
564 if (n0TcpType == "reno")
565 {
566 n0TcpTypeId = TcpNewReno::GetTypeId ();
567 }
568 else if (n0TcpType == "bic")
569 {
570 n0TcpTypeId = TcpBic::GetTypeId ();
571 }
572 else if (n0TcpType == "dctcp")
573 {
574 n0TcpTypeId = TcpDctcp::GetTypeId ();
575 }
576 else
577 {
578 NS_FATAL_ERROR ("Fatal error: tcp unsupported");
579 }
580
581 if (n1TcpType == "reno")
582 {
583 enableN1Tcp = true;
584 n1TcpTypeId = TcpNewReno::GetTypeId ();
585 }
586 else if (n1TcpType == "bic")
587 {
588 enableN1Tcp = true;
589 n1TcpTypeId = TcpBic::GetTypeId ();
590 }
591 else if (n1TcpType == "dctcp")
592 {
593 enableN1Tcp = true;
594 n1TcpTypeId = TypeId::LookupByName ("ns3::TcpDctcp");
595 }
596 else if (n1TcpType == "")
597 {
598 NS_LOG_DEBUG ("No N1 TCP selected");
599 }
600 else
601 {
602 NS_FATAL_ERROR ("Fatal error: tcp unsupported");
603 }
604
605 if (queueType == "fq")
606 {
607 queueTypeId = FqCoDelQueueDisc::GetTypeId ();
608 }
609 else if (queueType == "codel")
610 {
611 queueTypeId = CoDelQueueDisc::GetTypeId ();
612 }
613 else
614 {
615 NS_FATAL_ERROR ("Fatal error: queueType unsupported");
616 }
617 if (useCeThreshold)
618 {
619 Config::SetDefault ("ns3::FqCoDelQueueDisc::CeThreshold", TimeValue (ceThreshold));
620 }
621 }
622 else if (scenarioNum == 1 || scenarioNum == 2 || scenarioNum == 5 || scenarioNum == 6)
623 {
624 if (scenarioNum == 2 || scenarioNum == 6)
625 {
626 Config::SetDefault ("ns3::TcpSocketBase::UseEcn", StringValue ("On"));
627 }
628 n0TcpTypeId = TcpBic::GetTypeId ();
629 if (scenarioNum == 5 || scenarioNum == 6)
630 {
631 enableN1Tcp = true;
632 n1TcpTypeId = TcpBic::GetTypeId ();
633 }
634 queueTypeId = FqCoDelQueueDisc::GetTypeId ();
635 }
636 else if (scenarioNum == 3 || scenarioNum == 4 || scenarioNum == 7 || scenarioNum == 8 || scenarioNum == 9)
637 {
638 Config::SetDefault ("ns3::TcpSocketBase::UseEcn", StringValue ("On"));
639 n0TcpTypeId = TcpDctcp::GetTypeId ();
640 queueTypeId = FqCoDelQueueDisc::GetTypeId ();
641 oneWayDelay = MicroSeconds (500);
642 Config::SetDefault ("ns3::FqCoDelQueueDisc::CeThreshold", TimeValue (MilliSeconds (1)));
643 if (scenarioNum == 9)
644 {
645 n0TcpTypeId = TcpBic::GetTypeId ();
646 // For TCP Bic base RTT is 80 and base RTT for dctcp is set to 1 while setting delay for p2p devices
647 oneWayDelay = MilliSeconds (40);
648 }
649 if (scenarioNum == 4 || scenarioNum == 8 || scenarioNum == 9)
650 {
651 Config::SetDefault ("ns3::FqCoDelQueueDisc::UseL4s", BooleanValue (true));
652 Config::SetDefault ("ns3::TcpDctcp::UseEct0", BooleanValue (false));
653 }
654 if (scenarioNum == 7 || scenarioNum == 8 || scenarioNum == 9)
655 {
656 enableN1Tcp = true;
657 n1TcpTypeId = TcpDctcp::GetTypeId ();
658 }
659 }
660 else
661 {
662 NS_FATAL_ERROR ("Fatal error: scenario unavailble");
663 }
664
665 std::ofstream pingOfStream;
666 pingOfStream.open (pingTraceFile.c_str (), std::ofstream::out);
667 std::ofstream n0TcpRttOfStream;
668 n0TcpRttOfStream.open (n0TcpRttTraceFile.c_str (), std::ofstream::out);
669 std::ofstream n0TcpCwndOfStream;
670 n0TcpCwndOfStream.open (n0TcpCwndTraceFile.c_str (), std::ofstream::out);
671 std::ofstream n0TcpThroughputOfStream;
672 n0TcpThroughputOfStream.open (n0TcpThroughputTraceFile.c_str (), std::ofstream::out);
673 std::ofstream n1TcpRttOfStream;
674 n1TcpRttOfStream.open (n1TcpRttTraceFile.c_str (), std::ofstream::out);
675 std::ofstream n1TcpCwndOfStream;
676 n1TcpCwndOfStream.open (n1TcpCwndTraceFile.c_str (), std::ofstream::out);
677 std::ofstream n1TcpThroughputOfStream;
678 n1TcpThroughputOfStream.open (n1TcpThroughputTraceFile.c_str (), std::ofstream::out);
679
680 // Queue disc files
681 std::ofstream dropOfStream;
682 dropOfStream.open (dropTraceFile.c_str (), std::ofstream::out);
683 std::ofstream markOfStream;
684 markOfStream.open (markTraceFile.c_str (), std::ofstream::out);
685 std::ofstream dropsFrequencyOfStream;
686 dropsFrequencyOfStream.open (dropsFrequencyTraceFile.c_str (), std::ofstream::out);
687 std::ofstream marksFrequencyOfStream;
688 marksFrequencyOfStream.open (marksFrequencyTraceFile.c_str (), std::ofstream::out);
689 std::ofstream lengthOfStream;
690 lengthOfStream.open (lengthTraceFile.c_str (), std::ofstream::out);
691 std::ofstream queueDelayN0OfStream;
692 queueDelayN0OfStream.open (queueDelayN0TraceFile.c_str (), std::ofstream::out);
693 std::ofstream queueDelayN1OfStream;
694 queueDelayN1OfStream.open (queueDelayN1TraceFile.c_str (), std::ofstream::out);
695
697 // scenario setup //
699 Ptr<Node> pingServer = CreateObject<Node> ();
700 Ptr<Node> n0Server = CreateObject<Node> ();
701 Ptr<Node> n1Server = CreateObject<Node> ();
702 Ptr<Node> n2 = CreateObject<Node> ();
703 Ptr<Node> n3 = CreateObject<Node> ();
704 Ptr<Node> pingClient = CreateObject<Node> ();
705 Ptr<Node> n4Client = CreateObject<Node> ();
706 Ptr<Node> n5Client = CreateObject<Node> ();
707
708 // Device containers
709 NetDeviceContainer pingServerDevices;
710 NetDeviceContainer n0ServerDevices;
711 NetDeviceContainer n1ServerDevices;
712 NetDeviceContainer n2n3Devices;
713 NetDeviceContainer pingClientDevices;
714 NetDeviceContainer n4ClientDevices;
715 NetDeviceContainer n5ClientDevices;
716
718 p2p.SetQueue ("ns3::DropTailQueue", "MaxSize", QueueSizeValue (QueueSize ("3p")));
719 p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate (linkDataRate)));
720 // Add delay only on the server links
721 p2p.SetChannelAttribute ("Delay", TimeValue (oneWayDelay));
722 pingServerDevices = p2p.Install (n2, pingServer);
723 n0ServerDevices = p2p.Install (n2, n0Server);
724
725 // In scenario 9, base RTT of n1server (dctcp) is 1ms
726 if (scenarioNum == 9)
727 {
728 p2p.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (500)));
729 }
730 n1ServerDevices = p2p.Install (n2, n1Server);
731 p2p.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (1)));
732 n2n3Devices = p2p.Install (n2, n3);
733 pingClientDevices = p2p.Install (n3, pingClient);
734 n4ClientDevices = p2p.Install (n3, n4Client);
735 n5ClientDevices = p2p.Install (n3, n5Client);
737 p->SetAttribute ("DataRate", DataRateValue (bottleneckRate));
738
739 InternetStackHelper stackHelper;
740 stackHelper.InstallAll ();
741
742 // Set the per-node TCP type here
743 Ptr<TcpL4Protocol> proto;
744 proto = n4Client->GetObject<TcpL4Protocol> ();
745 proto->SetAttribute ("SocketType", TypeIdValue (n0TcpTypeId));
746 proto = n0Server->GetObject<TcpL4Protocol> ();
747 proto->SetAttribute ("SocketType", TypeIdValue (n0TcpTypeId));
748 if (enableN1Tcp)
749 {
750 proto = n5Client->GetObject<TcpL4Protocol> ();
751 proto->SetAttribute ("SocketType", TypeIdValue (n1TcpTypeId));
752 proto = n1Server->GetObject<TcpL4Protocol> ();
753 proto->SetAttribute ("SocketType", TypeIdValue (n1TcpTypeId));
754 }
755
756 // InternetStackHelper will install a base TrafficControLayer on the node,
757 // but the Ipv4AddressHelper below will install the default FqCoDelQueueDisc
758 // on all single device nodes. The below code overrides the configuration
759 // that is normally done by the Ipv4AddressHelper::Install() method by
760 // instead explicitly configuring the queue discs we want on each device.
762 tchFq.SetRootQueueDisc ("ns3::FqCoDelQueueDisc");
763 tchFq.SetQueueLimits ("ns3::DynamicQueueLimits", "HoldTime", StringValue ("1ms"));
764 tchFq.Install (pingServerDevices);
765 tchFq.Install (n0ServerDevices);
766 tchFq.Install (n1ServerDevices);
767 tchFq.Install (n2n3Devices.Get (1)); // n2 queue for bottleneck link
768 tchFq.Install (pingClientDevices);
769 tchFq.Install (n4ClientDevices);
770 tchFq.Install (n5ClientDevices);
772 tchN2.SetRootQueueDisc (queueTypeId.GetName ());
773 tchN2.SetQueueLimits ("ns3::DynamicQueueLimits", "HoldTime", StringValue ("1000ms"));
774 tchN2.Install (n2n3Devices.Get (0));
775
777 ipv4.SetBase ("10.1.1.0", "255.255.255.0");
778 Ipv4InterfaceContainer pingServerIfaces = ipv4.Assign (pingServerDevices);
779 ipv4.SetBase ("10.1.2.0", "255.255.255.0");
780 Ipv4InterfaceContainer n0ServerIfaces = ipv4.Assign (n0ServerDevices);
781 ipv4.SetBase ("10.1.3.0", "255.255.255.0");
782 Ipv4InterfaceContainer secondServerIfaces = ipv4.Assign (n1ServerDevices);
783 ipv4.SetBase ("172.16.1.0", "255.255.255.0");
784 Ipv4InterfaceContainer n2n3Ifaces = ipv4.Assign (n2n3Devices);
785 ipv4.SetBase ("192.168.1.0", "255.255.255.0");
786 Ipv4InterfaceContainer pingClientIfaces = ipv4.Assign (pingClientDevices);
787 ipv4.SetBase ("192.168.2.0", "255.255.255.0");
788 Ipv4InterfaceContainer n4ClientIfaces = ipv4.Assign (n4ClientDevices);
789 ipv4.SetBase ("192.168.3.0", "255.255.255.0");
790 Ipv4InterfaceContainer n5ClientIfaces = ipv4.Assign (n5ClientDevices);
791
792 Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
793
795 // application setup //
797
798 V4PingHelper pingHelper ("192.168.1.2");
799 pingHelper.SetAttribute ("Interval", TimeValue (pingInterval));
800 pingHelper.SetAttribute ("Size", UintegerValue (pingSize));
801 ApplicationContainer pingContainer = pingHelper.Install (pingServer);
802 Ptr<V4Ping> v4Ping = pingContainer.Get (0)->GetObject<V4Ping> ();
803 v4Ping->TraceConnectWithoutContext ("Rtt", MakeBoundCallback (&TracePingRtt, &pingOfStream));
804 pingContainer.Start (Seconds (1));
805 pingContainer.Stop (stopTime - Seconds (1));
806
807 BulkSendHelper tcp ("ns3::TcpSocketFactory", Address ());
808 // set to large value: e.g. 1000 Mb/s for 60 seconds = 7500000000 bytes
809 tcp.SetAttribute ("MaxBytes", UintegerValue (7500000000));
810 // Configure n4/n0 TCP client/server pair
811 uint16_t n4Port = 5000;
813 InetSocketAddress n0DestAddress (n4ClientIfaces.GetAddress (1), n4Port);
814 tcp.SetAttribute ("Remote", AddressValue (n0DestAddress));
815 n0App = tcp.Install (n0Server);
816 n0App.Start (Seconds (5));
817 n0App.Stop (stopTime - Seconds (1));
818
819 Address n4SinkAddress (InetSocketAddress (Ipv4Address::GetAny (), n4Port));
820 PacketSinkHelper n4SinkHelper ("ns3::TcpSocketFactory", n4SinkAddress);
821 ApplicationContainer n4SinkApp;
822 n4SinkApp = n4SinkHelper.Install (n4Client);
823 n4SinkApp.Start (Seconds (5));
824 n4SinkApp.Stop (stopTime - MilliSeconds (500));
825
826 // Configure second TCP client/server pair
827 if (enableN1Tcp)
828 {
829 uint16_t n5Port = 5000;
830 ApplicationContainer secondApp;
831 InetSocketAddress n1DestAddress (n5ClientIfaces.GetAddress (1), n5Port);
832 tcp.SetAttribute ("Remote", AddressValue (n1DestAddress));
833 secondApp = tcp.Install (n1Server);
834 secondApp.Start (Seconds (15));
835 secondApp.Stop (stopTime - Seconds (1));
836
837 Address n5SinkAddress (InetSocketAddress (Ipv4Address::GetAny (), n5Port));
838 PacketSinkHelper n5SinkHelper ("ns3::TcpSocketFactory", n5SinkAddress);
839 ApplicationContainer n5SinkApp;
840 n5SinkApp = n5SinkHelper.Install (n5Client);
841 n5SinkApp.Start (Seconds (15));
842 n5SinkApp.Stop (stopTime - MilliSeconds (500));
843 }
844
845 // Setup traces that can be hooked now
848 tc = n2n3Devices.Get (0)->GetNode ()->GetObject<TrafficControlLayer> ();
849 qd = tc->GetRootQueueDiscOnDevice (n2n3Devices.Get (0));
850 qd->TraceConnectWithoutContext ("Drop", MakeBoundCallback (&TraceDrop, &dropOfStream));
851 qd->TraceConnectWithoutContext ("Mark", MakeBoundCallback (&TraceMark, &markOfStream));
852 qd->TraceConnectWithoutContext ("BytesInQueue", MakeBoundCallback (&TraceQueueLength, &lengthOfStream, bottleneckRate));
853 qd->TraceConnectWithoutContext ("Dequeue", MakeBoundCallback (&PacketDequeue, &queueDelayN0OfStream, &queueDelayN1OfStream));
854
855 // Setup scheduled traces; TCP traces must be hooked after socket creation
856 Simulator::Schedule (Seconds (5) + MilliSeconds (100), &ScheduleN0TcpRttTraceConnection, &n0TcpRttOfStream);
857 Simulator::Schedule (Seconds (5) + MilliSeconds (100), &ScheduleN0TcpCwndTraceConnection, &n0TcpCwndOfStream);
858 Simulator::Schedule (Seconds (5) + MilliSeconds (100), &ScheduleN0PacketSinkConnection);
859 Simulator::Schedule (throughputSamplingInterval, &TraceN0Throughput, &n0TcpThroughputOfStream, throughputSamplingInterval);
860 // Setup scheduled traces; TCP traces must be hooked after socket creation
861 if (enableN1Tcp)
862 {
863 Simulator::Schedule (Seconds (15) + MilliSeconds (100), &ScheduleN1TcpRttTraceConnection, &n1TcpRttOfStream);
864 Simulator::Schedule (Seconds (15) + MilliSeconds (100), &ScheduleN1TcpCwndTraceConnection, &n1TcpCwndOfStream);
865 Simulator::Schedule (Seconds (15) + MilliSeconds (100), &ScheduleN1PacketSinkConnection);
866 }
867 Simulator::Schedule (throughputSamplingInterval, &TraceN1Throughput, &n1TcpThroughputOfStream, throughputSamplingInterval);
868 Simulator::Schedule (marksSamplingInterval, &TraceMarksFrequency, &marksFrequencyOfStream, marksSamplingInterval);
869 Simulator::Schedule (marksSamplingInterval, &TraceDropsFrequency, &dropsFrequencyOfStream, marksSamplingInterval);
870
871 if (enablePcap)
872 {
873 p2p.EnablePcapAll ("FqCoDel-L4S-example", false);
874 }
875
876 Simulator::Stop (stopTime);
877 Simulator::Run ();
878
879 pingOfStream.close ();
880 n0TcpCwndOfStream.close ();
881 n0TcpRttOfStream.close ();
882 n0TcpThroughputOfStream.close ();
883 n1TcpCwndOfStream.close ();
884 n1TcpRttOfStream.close ();
885 n1TcpThroughputOfStream.close ();
886 dropOfStream.close ();
887 markOfStream.close ();
888 dropsFrequencyOfStream.close ();
889 marksFrequencyOfStream.close ();
890 lengthOfStream.close ();
891 queueDelayN0OfStream.close ();
892 queueDelayN1OfStream.close ();
893}
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Address.
holds a vector of ns3::Application pointers.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
void Start(Time start)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter.
void Stop(Time stop)
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
A helper to make it easier to instantiate an ns3::BulkSendApplication on a set of nodes.
Parse command-line arguments.
Definition: command-line.h:229
Class for representing data rates.
Definition: data-rate.h:89
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:287
AttributeValue implementation for DataRate.
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
void InstallAll(void) const
Aggregate IPv4, IPv6, UDP, and TCP stacks to all nodes in the simulation.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
Ipv4QueueDiscItem is a subclass of QueueDiscItem which stores IPv4 packets.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
virtual Ptr< Node > GetNode(void) const =0
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
void EnablePcapAll(std::string prefix, bool promiscuous=false)
Enable pcap output on each device (which is of the appropriate type) in the set of all nodes created ...
Build a set of PointToPointNetDevice objects.
void SetDeviceAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each NetDevice created by the helper.
void SetQueue(std::string type, std::string n1="", const AttributeValue &v1=EmptyAttributeValue(), std::string n2="", const AttributeValue &v2=EmptyAttributeValue(), std::string n3="", const AttributeValue &v3=EmptyAttributeValue(), std::string n4="", const AttributeValue &v4=EmptyAttributeValue())
Each point to point net device must have a queue to pass packets through.
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
NetDeviceContainer Install(NodeContainer c)
A Device for a Point to Point Network Link.
Class for representing queue sizes.
Definition: queue-size.h:95
AttributeValue implementation for QueueSize.
Hold variables of type string.
Definition: string.h:41
TCP socket creation and multiplexing/demultiplexing.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:387
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
AttributeValue implementation for Time.
Definition: nstime.h:1308
Build a set of QueueDisc objects.
QueueDiscContainer Install(NetDeviceContainer c)
uint16_t SetRootQueueDisc(const std::string &type, Args &&... args)
Helper function used to set a root queue disc of the given type and with the given attributes.
void SetQueueLimits(std::string type, Args &&... args)
Helper function used to add a queue limits object to the transmission queues of the devices.
Introspection did not find any typical Config paths.
a unique identifier for an interface.
Definition: type-id.h:59
std::string GetName(void) const
Get the name.
Definition: type-id.cc:976
AttributeValue implementation for TypeId.
Definition: type-id.h:595
Hold an unsigned integer type.
Definition: uinteger.h:44
Create a IPv4 ping application and associate it to a node.
Definition: v4ping-helper.h:38
an application which sends one ICMP ECHO request, waits for a REPLYs and reports the calculated RTT.
Definition: v4ping.h:42
Time stopTime
void TraceDropsFrequency(std::ofstream *ofStream, Time dropsSamplingInterval)
void TraceN0Rx(Ptr< const Packet > packet, const Address &address)
void ScheduleN0TcpCwndTraceConnection(std::ofstream *ofStream)
void TraceMarksFrequency(std::ofstream *ofStream, Time marksSamplingInterval)
void ScheduleN1TcpRttTraceConnection(std::ofstream *ofStream)
void TraceN0Cwnd(std::ofstream *ofStream, uint32_t oldCwnd, uint32_t newCwnd)
void TraceN1Throughput(std::ofstream *ofStream, Time throughputInterval)
void ScheduleN1PacketSinkConnection(void)
void TraceMark(std::ofstream *ofStream, Ptr< const QueueDiscItem > item, const char *reason)
void TracePingRtt(std::ofstream *ofStream, Time rtt)
void ScheduleN0PacketSinkConnection(void)
void TraceN1Cwnd(std::ofstream *ofStream, uint32_t oldCwnd, uint32_t newCwnd)
uint32_t g_n1BytesReceived
double avgQueueDiscSize
void TraceDrop(std::ofstream *ofStream, Ptr< const QueueDiscItem > item)
uint32_t g_n0BytesReceived
void TraceN0Throughput(std::ofstream *ofStream, Time throughputInterval)
uint32_t g_marksObserved
void TraceN1Rtt(std::ofstream *ofStream, Time oldRtt, Time newRtt)
void ScheduleN1TcpCwndTraceConnection(std::ofstream *ofStream)
void TraceN0Rtt(std::ofstream *ofStream, Time oldRtt, Time newRtt)
uint32_t g_dropsObserved
void TraceQueueLength(std::ofstream *ofStream, DataRate linkRate, uint32_t oldVal, uint32_t newVal)
void TraceN1Rx(Ptr< const Packet > packet, const Address &address)
uint32_t checkTimes
static void PacketDequeue(std::ofstream *n0OfStream, std::ofstream *n1OfStream, Ptr< QueueDiscItem const > item)
void ScheduleN0TcpRttTraceConnection(std::ofstream *ofStream)
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:901
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1709
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
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
address
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:415
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
cmd
Definition: second.py:35
std::string dir