From 36470ffec1c7cacb88e747a7c83f49e9ec2c2df5 Mon Sep 17 00:00:00 2001
From: Pasquale Imputato
Date: Mon, 8 Aug 2016 00:21:22 +0200
Subject: [PATCH] examples: Add an example to evaluate the performance of
various queue discs
---
.../traffic-control/queue-discs-benchmark.cc | 288 ++++++++++++++++++
examples/traffic-control/wscript | 4 +
2 files changed, 292 insertions(+)
create mode 100644 examples/traffic-control/queue-discs-benchmark.cc
diff --git a/examples/traffic-control/queue-discs-benchmark.cc b/examples/traffic-control/queue-discs-benchmark.cc
new file mode 100644
index 000000000..3c9edaf42
--- /dev/null
+++ b/examples/traffic-control/queue-discs-benchmark.cc
@@ -0,0 +1,288 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 Universita' degli Studi di Napoli Federico II
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Pasquale Imputato
+ * Stefano Avallone
+ */
+
+// This example serves as a benchmark for all the queue discs (with BQL enabled or not)
+//
+// Network topology
+//
+// 192.168.1.0 192.168.2.0
+// n1 ------------------------------------ n2 ----------------------------------- n3
+// point-to-point (access link) point-to-point (bottleneck link)
+// 100 Mbps, 0.1 ms bandwidth [10 Mbps], delay [5 ms]
+// qdiscs PfifoFast with capacity qdiscs queueDiscType in {PfifoFast, ARED, CoDel} [PfifoFast]
+// of 1000 packets with capacity of queueDiscSize packets [1000]
+// netdevices queues with size of 100 packets netdevices queues with size of netdevicesQueueSize packets [100]
+// without BQL bql BQL [false]
+// *** fixed configuration ***
+//
+// The output will consist of a number of ping Rtt such as:
+//
+// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
+// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
+// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=110 ms
+// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
+// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
+// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=112 ms
+// /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
+//
+// The files output will consist of a trace file with bytes in queue and of a trace file for limits
+// (when BQL is enabled) both for bottleneck NetDevice on n2, two files with upload and download
+// goodput for flows configuration and a file with flow monitor stats.
+//
+// If you use an AQM as queue disc on the bottleneck netdevices, you can observe that the ping Rtt
+// decrease. A further decrease can be observed when you enable BQL.
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/internet-module.h"
+#include "ns3/point-to-point-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/internet-apps-module.h"
+#include "ns3/traffic-control-module.h"
+#include "ns3/flow-monitor-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("BenchmarkQueueDiscs");
+
+void
+LimitsTrace (Ptr stream, uint32_t oldVal, uint32_t newVal)
+{
+ *stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
+}
+
+void
+BytesInQueueTrace (Ptr stream, uint32_t oldVal, uint32_t newVal)
+{
+ *stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
+}
+
+static void
+GoodputSampling (std::string fileName, ApplicationContainer app, Ptr stream, float period)
+{
+ Simulator::Schedule (Seconds (period), &GoodputSampling, fileName, app, stream, period);
+ double goodput;
+ uint32_t totalPackets = DynamicCast (app.Get (0))->GetTotalRx ();
+ goodput = totalPackets * 8 / (Simulator::Now ().GetSeconds () * 1024); // Kbit/s
+ *stream->GetStream () << Simulator::Now ().GetSeconds () << " " << goodput << std::endl;
+}
+
+static void PingRtt (std::string context, Time rtt)
+{
+ std::cout << context << "=" << rtt.GetMilliSeconds () << " ms" << std::endl;
+}
+
+int main (int argc, char *argv[])
+{
+ std::string bandwidth = "10Mbps";
+ std::string delay = "5ms";
+ std::string queueDiscType = "PfifoFast";
+ uint32_t queueDiscSize = 1000;
+ uint32_t netdevicesQueueSize = 100;
+ bool bql = false;
+
+ std::string flowsDatarate = "20Mbps";
+ uint32_t flowsPacketsSize = 1000;
+
+ float startTime = 0.1; // in s
+ float simDuration = 60;
+ float samplingPeriod = 1;
+
+ CommandLine cmd;
+ cmd.AddValue ("bandwidth", "Bottleneck bandwidth", bandwidth);
+ cmd.AddValue ("delay", "Bottleneck delay", delay);
+ cmd.AddValue ("queueDiscType", "Bottleneck queue disc type in {PfifoFast, ARED, CoDel}", queueDiscType);
+ cmd.AddValue ("queueDiscSize", "Bottleneck queue disc size in packets", queueDiscSize);
+ cmd.AddValue ("netdevicesQueueSize", "Bottleneck netdevices queue size in packets", netdevicesQueueSize);
+ cmd.AddValue ("bql", "Enable byte queue limits on bottleneck netdevices", bql);
+ cmd.AddValue ("flowsDatarate", "Upload and download flows datarate", flowsDatarate);
+ cmd.AddValue ("flowsPacketsSize", "Upload and download flows packets sizes", flowsPacketsSize);
+ cmd.AddValue ("startTime", "Simulation start time", startTime);
+ cmd.AddValue ("simDuration", "Simulation duration in seconds", simDuration);
+ cmd.AddValue ("samplingPeriod", "Goodput sampling period in seconds", samplingPeriod);
+ cmd.Parse (argc, argv);
+
+ float stopTime = startTime + simDuration;
+
+ // Create nodes
+ NodeContainer n1, n2, n3;
+ n1.Create (1);
+ n2.Create (1);
+ n3.Create (1);
+
+ // Create and configure access link and bottleneck link
+ PointToPointHelper accessLink;
+ accessLink.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
+ accessLink.SetChannelAttribute ("Delay", StringValue ("0.1ms"));
+
+ PointToPointHelper bottleneckLink;
+ bottleneckLink.SetDeviceAttribute ("DataRate", StringValue (bandwidth));
+ bottleneckLink.SetChannelAttribute ("Delay", StringValue (delay));
+
+ InternetStackHelper stack;
+ stack.InstallAll ();
+
+ // Access link traffic control configuration
+ TrafficControlHelper tchPfifoFastAccess;
+ uint32_t handle = tchPfifoFastAccess.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "Limit", UintegerValue (1000));
+
+ // Bottleneck link traffic control configuration
+ TrafficControlHelper tchBottleneck;
+
+ if (queueDiscType.compare ("PfifoFast") == 0)
+ {
+ tchBottleneck.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "Limit", UintegerValue (queueDiscSize));
+ }
+ else if (queueDiscType.compare ("ARED") == 0)
+ {
+ handle = tchBottleneck.SetRootQueueDisc ("ns3::RedQueueDisc");
+ Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
+ tchBottleneck.AddInternalQueues (handle, 1, "ns3::DropTailQueue", "MaxPackets", UintegerValue (queueDiscSize));
+ }
+ else if (queueDiscType.compare ("CoDel") == 0)
+ {
+ handle = tchBottleneck.SetRootQueueDisc ("ns3::CoDelQueueDisc");
+ Config::SetDefault ("ns3::CoDelQueueDisc::Mode", EnumValue (Queue::QUEUE_MODE_PACKETS));
+ tchBottleneck.AddInternalQueues (handle, 1, "ns3::DropTailQueue", "MaxPackets", UintegerValue (queueDiscSize));
+ }
+ else
+ {
+ NS_ABORT_MSG ("--queueDiscType not valid");
+ }
+
+ if (bql)
+ {
+ tchBottleneck.SetQueueLimits ("ns3::DynamicQueueLimits");
+ }
+
+ Config::SetDefault ("ns3::Queue::Mode", StringValue ("QUEUE_MODE_PACKETS"));
+ Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (100));
+
+ NetDeviceContainer devicesAccessLink = accessLink.Install (n1.Get (0), n2.Get (0));
+ tchPfifoFastAccess.Install (devicesAccessLink);
+ Ipv4AddressHelper address;
+ address.SetBase ("192.168.0.0", "255.255.255.0");
+ address.NewNetwork ();
+ Ipv4InterfaceContainer interfacesAccess = address.Assign (devicesAccessLink);
+
+ Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (netdevicesQueueSize));
+
+ NetDeviceContainer devicesBottleneckLink = bottleneckLink.Install (n2.Get (0), n3.Get (0));
+ QueueDiscContainer qdiscs;
+ qdiscs = tchBottleneck.Install (devicesBottleneckLink);
+
+ address.NewNetwork ();
+ Ipv4InterfaceContainer interfacesBottleneck = address.Assign (devicesBottleneckLink);
+
+ Ptr interface = devicesBottleneckLink.Get (0)->GetObject ();
+ Ptr queueInterface = interface->GetTxQueue (0);
+ Ptr queueLimits = StaticCast (queueInterface->GetQueueLimits ());
+
+ AsciiTraceHelper ascii;
+ if (bql)
+ {
+ queueDiscType = queueDiscType + "-bql";
+ Ptr streamLimits = ascii.CreateFileStream (queueDiscType + "-limits.txt");
+ queueLimits->TraceConnectWithoutContext ("Limit",MakeBoundCallback (&LimitsTrace, streamLimits));
+ }
+ Ptr queue = StaticCast (devicesBottleneckLink.Get (0))->GetQueue ();
+ Ptr streamBytesInQueue = ascii.CreateFileStream (queueDiscType + "-bytesInQueue.txt");
+ queue->TraceConnectWithoutContext ("BytesInQueue",MakeBoundCallback (&BytesInQueueTrace, streamBytesInQueue));
+
+ Ipv4InterfaceContainer n1Interface;
+ n1Interface.Add (interfacesAccess.Get (0));
+
+ Ipv4InterfaceContainer n3Interface;
+ n3Interface.Add (interfacesBottleneck.Get (1));
+
+ Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+ Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (flowsPacketsSize));
+
+ // Flows configuration
+ // Bidirectional TCP streams with ping like flent tcp_bidirectional test.
+ uint16_t port = 7;
+ ApplicationContainer uploadApp, downloadApp, sourceApps;
+ // Configure and install upload flow
+ Address addUp (InetSocketAddress (Ipv4Address::GetAny (), port));
+ PacketSinkHelper sinkHelperUp ("ns3::TcpSocketFactory", addUp);
+ sinkHelperUp.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
+ uploadApp.Add (sinkHelperUp.Install (n3));
+
+ InetSocketAddress socketAddressUp = InetSocketAddress (n3Interface.GetAddress (0), port);
+ OnOffHelper onOffHelperUp ("ns3::TcpSocketFactory", Address ());
+ onOffHelperUp.SetAttribute ("Remote", AddressValue (socketAddressUp));
+ onOffHelperUp.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
+ onOffHelperUp.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
+ onOffHelperUp.SetAttribute ("PacketSize", UintegerValue (flowsPacketsSize));
+ onOffHelperUp.SetAttribute ("DataRate", StringValue (flowsDatarate));
+ sourceApps.Add (onOffHelperUp.Install (n1));
+
+ port = 8;
+ // Configure and install download flow
+ Address addDown (InetSocketAddress (Ipv4Address::GetAny (), port));
+ PacketSinkHelper sinkHelperDown ("ns3::TcpSocketFactory", addDown);
+ sinkHelperDown.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
+ downloadApp.Add (sinkHelperDown.Install (n1));
+
+ InetSocketAddress socketAddressDown = InetSocketAddress (n1Interface.GetAddress (0), port);
+ OnOffHelper onOffHelperDown ("ns3::TcpSocketFactory", Address ());
+ onOffHelperDown.SetAttribute ("Remote", AddressValue (socketAddressDown));
+ onOffHelperDown.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
+ onOffHelperDown.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
+ onOffHelperDown.SetAttribute ("PacketSize", UintegerValue (flowsPacketsSize));
+ onOffHelperDown.SetAttribute ("DataRate", StringValue (flowsDatarate));
+ sourceApps.Add (onOffHelperDown.Install (n3));
+
+ // Configure and install ping
+ V4PingHelper ping = V4PingHelper (n3Interface.GetAddress (0));
+ ping.Install (n1);
+
+ Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt", MakeCallback (&PingRtt));
+
+ uploadApp.Start (Seconds (0));
+ uploadApp.Stop (Seconds (stopTime));
+ downloadApp.Start (Seconds (0));
+ downloadApp.Stop (Seconds (stopTime));
+
+ sourceApps.Start (Seconds (0 + 0.1));
+ sourceApps.Stop (Seconds (stopTime - 0.1));
+
+ Ptr uploadGoodputStream = ascii.CreateFileStream (queueDiscType + "-upGoodput.txt");
+ Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, queueDiscType + "-upGoodput.txt", uploadApp,
+ uploadGoodputStream, samplingPeriod);
+ Ptr downloadGoodputStream = ascii.CreateFileStream (queueDiscType + "-downGoodput.txt");
+ Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, queueDiscType + "-downGoodput.txt", downloadApp,
+ downloadGoodputStream, samplingPeriod);
+
+ // Flow monitor
+ Ptr flowMonitor;
+ FlowMonitorHelper flowHelper;
+ flowMonitor = flowHelper.InstallAll();
+
+ Simulator::Stop (Seconds (stopTime));
+ Simulator::Run ();
+
+ flowMonitor->SerializeToXmlFile(queueDiscType + "-flowMonitor.xml", true, true);
+
+ Simulator::Destroy ();
+ return 0;
+}
diff --git a/examples/traffic-control/wscript b/examples/traffic-control/wscript
index 3955647f6..05a8c2a55 100644
--- a/examples/traffic-control/wscript
+++ b/examples/traffic-control/wscript
@@ -4,3 +4,7 @@ def build(bld):
obj = bld.create_ns3_program('traffic-control',
['internet', 'point-to-point', 'applications', 'traffic-control'])
obj.source = 'traffic-control.cc'
+
+ obj = bld.create_ns3_program('queue-discs-benchmark',
+ ['internet', 'point-to-point', 'applications', 'internet-apps', 'traffic-control', 'flow-monitor'])
+ obj.source = 'queue-discs-benchmark.cc'