diff --git a/.gitignore b/.gitignore index 1ac66b75573..b99d3aea026 100644 --- a/.gitignore +++ b/.gitignore @@ -35,5 +35,8 @@ TAGS build-dir/ build/ +aqm-eval-output/ +aqm-eval-output1/ /.cproject /.project +aqm-eval-output-1/ diff --git a/README b/README index b139b327757..4d041b06f91 100644 --- a/README +++ b/README @@ -1,4 +1,3 @@ - The Network Simulator, Version 3 -------------------------------- diff --git a/README.md b/README.md new file mode 100644 index 00000000000..94f75e3a703 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# Extend implementation of AQM Evaluation Suite in ns-3 + +## Course Code: CS738 + +## Assignment: #GP3 + +### Overview +AQM Evaluation Suite for ns-3 has been designed and developed at NITK based on the recommendations provided in RFC 7928. This implementation needs to be extended to add +more features that are crucial for evaluating AQM algorithms. + +Our Assignment is to enable ECN for RED, ARED, Feng Adaptive RED and NLRED. + +### References +● RFC 7928 (Link: https://tools.ietf.org/html/rfc7928) + +● AQM Evaluation Suite for ns-3 (Link: https://aqm-eval-suite.github.io/) diff --git a/scratch/scratch-simulator.cc b/scratch/scratch-simulator.cc index aa7cc6fa44d..d4c3a8715bb 100644 --- a/scratch/scratch-simulator.cc +++ b/scratch/scratch-simulator.cc @@ -15,7 +15,6 @@ */ #include "ns3/core-module.h" - using namespace ns3; NS_LOG_COMPONENT_DEFINE ("ScratchSimulator"); @@ -25,6 +24,10 @@ main (int argc, char *argv[]) { NS_LOG_UNCOND ("Scratch Simulator"); + +for(int i=0; i<5; i++) + NS_LOG_UNCOND ("Scratch Simulator"); + Simulator::Run (); Simulator::Destroy (); } diff --git a/src/aqm-eval-suite/doc/aqm-eval-suite.rst b/src/aqm-eval-suite/doc/aqm-eval-suite.rst new file mode 100644 index 00000000000..e0db8494cf9 --- /dev/null +++ b/src/aqm-eval-suite/doc/aqm-eval-suite.rst @@ -0,0 +1,178 @@ +AQM Evaluation Suite +-------------------- + +.. include:: replace.txt +.. highlight:: cpp + +.. heading hierarchy: + ------------- Chapter + ************* Section (#.#) + ============= Subsection (#.#.#) + ############# Paragraph (no number) + + +The AQM Evaluation Suite is an automated framework for comparing the performance of +ns-3 queue disciplines based on the scenarios mentioned in RFC 7928. It includes +simulation setup, topology creation, traffic generation, program execution, results +collection and their graphical representation. + + +Introducing the AQM Evaluation Suite +************************************ + +AQM Evaluation Suite automates the cycle of simulation setup to results collection +in ns-3. It closely follows the recommendations provided in RFC 7928 to setup the +simulation scenarios and collects results in the suggested formats. A user can +choose to either run an individual scenario from the set of scenarios provided in +the suite, or run all scenarios at once. Results for each scenario are systematically +stored in text and graphical formats. + +The following provides more details about the architecture of the suite, users +interaction with the suite, its scope and limitations, and steps to extend the +suite for evaluating new AQM algorithms. + +Architecture of AQM Evaluation Suite +************************************ + +The suite is implemented in ``src/aqm-eval-suite`` directory. + +Model +===== + +``src/aqm-eval-suite/model`` contains an implementation of the following three +primary classes: + +* class :cpp:class:`EvaluationTopology`: This class has three major functionalities: + + * Creating the topology: It sets up a point-to-point dumbbell topology by using + :cpp:class:`PointToPointDumbbellHelper`: with required number of nodes, and + configures the data rate and for all the links. It also installs the desired queue + discipline on the router node. + + * Installing application on nodes: it provides an API for configuration of + applications. This API takes the application parameters such as data rate, + packet size, transport protocol, initial congestion window in case of TCP, + maximum bandwidth and one way delay of the channels. + + * Getting the metrics of interest from the experiment: It uses the traces + sources provided by different classes of ns-3 for the calculation of metrics. + The metrics recommended in the RFC are queue-delay, goodput, throughput and + number of drops. + +* class :cpp:class:`EvalApp`: This class is based on :cpp:class:`OnOffApplication`: + and is used for generating TCP and UDP traffic in the suite. The native class + :cpp:class:`OnOffApplication`: in ns-3 creates sockets at the start time of an + application. Thus, to configure different values for parameters like initial + congestion window in TCP is non-trivial, since they cannot be configured before + the socket is created and after the application starts. To overcome this, + :cpp:class:`EvalApp`: is implemented on the same principles as that of the + :cpp:class:`OnOffApplication`: in which a socket is created and the application + is started only after its parameters are configured. + +* class :cpp:class:`EvalTimestampTag`: This is a subclass of :cpp:class:`Tag`: and + has been developed to fetch the queue delay information from :cpp:class:`QueueDisc`:. + When a packet is enqueued by the QueueDisc, this tag is added with a timestamp + (as the enqueue time) and when the packet is dequeued, the queue delay is computed + as the difference between the dequeue time and the enqueue time. + +Helper +====== + +``src/aqm-eval-suite/helper`` contains an implementation of the following class: + +* class :cpp:class:`ScenarioImpl`: This class implements the following two methods: + + * ``ScenarioImpl::CreateScenario ()``: This is a virtual function implemented by + each scenario according to the topology and traffic profiles mentioned in the RFC. + + * ``ScenarioImpl::RunSimulation ()``: This method takes the scenario created by + each subclass and runs them with all the queue disciplines available in ns-3. + +Utils +===== + +``src/aqm-eval-suite/utils`` directory provides four Python scripts that take +performance metrics computed in the suite as input, and generate a graph with +Queuing Delay as the X-axis against Goodput as the Y-axis. The graph depicts an +ellipse which is plotted as per the guidelines mentioned in the RFC and [Remy]. +The co-variance between the queuing delay and goodput is determined by the +orientation of the ellipse, and helps to analyze the effect of traffic load on +Goodput and Queuing Delay. + +Examples +======== + +``src/aqm-eval-suite/examples`` directory provides a set of programs, each +corresponding to a specific scenario listed in RFC 7928. Each program can be +run individually. Alternatively, `aqm-eval-suite-runner.cc` allows the user +to run all scenarios at once. + +User interaction with the suite +******************************* + +Users can learn about the list of scenarios available in the suite from +``src/aqm-eval/examples`` directory. The programs can be run in a usual way. +For example, ``aggressive-transport-sender.cc`` is equivalent to the scenario +described in Section 5.2 of the RFC. Assuming examples have been enabled +during configure, the following commands would run ``aggressive-transport-sender.cc`` + +:: + + $ ./waf --run "aqm-eval-suite-runner --number=5.2" + +or + +:: + + $ ./waf --run "aqm-eval-suite-runner --name=AggressiveTransportSender" + +To run all scenarios at once, the following command could be used: + +:: + + $ ./waf --run "aqm-eval-suite-runner --name=All" + +Simulating additional AQM algorithms using this suite +***************************************************** + +* By default, the suite evaluates AQM algorithms implemented in |ns3|. To + simulate additional AQM algorithms, such as the ones designed by the user, + the ``addAQM`` method of ``ScenarioImpl`` can be used in the scenarios + available in ``src/aqm-eval-suite/examples``. For example, to add a new AQM + of typeId ``ns3::ExampleQueueDisc`` in ``aggressive-transport-sender.cc``, + ``CreateScenario`` method can be modified as shown in the code below: + +.. code-block:: c++ + + EvaluationTopology + AggressiveTransportSender::CreateScenario (std::string aqm) + { + . + . + addAQM ("ns3::ExampleQueueDisc"); + EvaluationTopology et ("AggressiveTransportSender", nflow, pointToPoint, aqm, 1460); + . + . + } + +Scope and limitations of the suite +********************************** + +* All scenarios described in Section 5, 6 and 8 of RFC 7928 are supported. + +* Scenarios listed in Section 7 and 9 are not yet supported. + +* Multi-AQM scenarios are not yet supported. + +Packages Required for Processing Metrics and Graphing +***************************************************** + +Following are the packages required for the suite and their installation instruction in Ubuntu + +* python-pip: apt-get install python-pip + +* python numpy: pip install numpy + +* gnuplot: apt-get install gnuplot-qt + +* imagemagick (optional package for ns-3): apt-get install imagemagick diff --git a/src/aqm-eval-suite/examples/LBE-transport-sender.cc b/src/aqm-eval-suite/examples/LBE-transport-sender.cc new file mode 100644 index 00000000000..d934b8e660a --- /dev/null +++ b/src/aqm-eval-suite/examples/LBE-transport-sender.cc @@ -0,0 +1,97 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Section 5.1.2 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-5.1). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("LbeTransportSender"); + +class LbeTransportSender : public ScenarioImpl +{ +public: + LbeTransportSender (); + ~LbeTransportSender (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); +}; + +LbeTransportSender::LbeTransportSender () +{ +} + +LbeTransportSender::~LbeTransportSender () +{ +} + +EvaluationTopology +LbeTransportSender::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 2; + + EvaluationTopology et ("LbeTransportSender", nflow, pointToPoint, aqm, 698, isBql); + ApplicationContainer ac1 = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpLedbat", 0, DataRate ("10Mb/s"), 3); + + ApplicationContainer ac2 = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ac1.Start (Seconds (0)); + ac1.Stop (Seconds (300)); + + ac2.Start (Seconds (0)); + ac2.Stop (Seconds (300)); + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + LbeTransportSender sce; + sce.ConfigureQueueDisc (45, 750, "1Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/aggressive-transport-sender.cc b/src/aqm-eval-suite/examples/aggressive-transport-sender.cc new file mode 100644 index 00000000000..279b51a1fce --- /dev/null +++ b/src/aqm-eval-suite/examples/aggressive-transport-sender.cc @@ -0,0 +1,95 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Section 5.2 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-5.2). + * + * Note: BIC TCP is used as an aggressive sender due to unavailability + * of CUBIC TCP module in ns-3. + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +class AggressiveTransportSender : public ScenarioImpl +{ +public: + AggressiveTransportSender (); + ~AggressiveTransportSender (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); +}; +std::string AggressiveTcpVariant = "ns3::TcpBic"; + +AggressiveTransportSender::AggressiveTransportSender () +{ +} + +AggressiveTransportSender::~AggressiveTransportSender () +{ +} + +EvaluationTopology +AggressiveTransportSender::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 1; + + EvaluationTopology et ("AggressiveTransportSender", nflow, pointToPoint, aqm, 698, isBql); + ApplicationContainer ac = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + AggressiveTcpVariant, 0, DataRate ("10Mb/s"), 3); + + ac.Start (Seconds (0)); + ac.Stop (Seconds (300)); + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string TcpVariant = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("TcpVariant", "Aggressive TCP variant", TcpVariant); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + if ((TcpVariant == "ns3::TcpYeah") || (TcpVariant == "ns3::TcpBic") || (TcpVariant == "ns3::TcpHighSpeed") || (TcpVariant == "ns3::TcpIllinois") || (TcpVariant == "ns3::TcpScalable") || (TcpVariant == "ns3::TcpHtcp")) + { + AggressiveTcpVariant = TcpVariant; + } + AggressiveTransportSender sce; + sce.ConfigureQueueDisc (45, 750, "1Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/aqm-eval-suite-runner.cc b/src/aqm-eval-suite/examples/aqm-eval-suite-runner.cc new file mode 100644 index 00000000000..5a65f795052 --- /dev/null +++ b/src/aqm-eval-suite/examples/aqm-eval-suite-runner.cc @@ -0,0 +1,233 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +#include +#include +#include +#include +#include +#include +#include "ns3/core-module.h" +#include + +using namespace ns3; + +std::vector AQM = { +"Red", +"PfifoFast", +"CoDel", +"Pie", +"AdaptiveRed", +"FengAdaptiveRed", +"NonLinearRed" +}; +std::string queueDisc = "QueueDisc"; +uint32_t nAQM = 7; +std::string AggressiveTcp = ""; +std::string QueueDiscMode = "QUEUE_DISC_MODE_PACKETS"; +std::string isBql = "false"; + +void RemoveAqm (std::string aqm) +{ + AQM.erase (std::remove (AQM.begin (), AQM.end (), aqm), AQM.end ()); + nAQM--; +} + +void RunOneScenario (std::string scenarioName) +{ + mkdir ((std::string ("aqm-eval-output/") + scenarioName).c_str (), 0700); + mkdir ((std::string ("aqm-eval-output/") + scenarioName + (std::string ("/data"))).c_str (), 0700); + mkdir ((std::string ("aqm-eval-output/") + scenarioName + (std::string ("/graph"))).c_str (), 0700); + std::string commandToRun; + if (AggressiveTcp != "" && scenarioName == "AggressiveTransportSender") + { + commandToRun = std::string ("./waf --run \"") + scenarioName + std::string (" --TcpVariant=ns3::") + AggressiveTcp + std::string (" --QueueDiscMode=") + QueueDiscMode + std::string (" --isBql=") + isBql + std::string ("\""); + } + else + { + commandToRun = std::string ("./waf --run \"") + scenarioName + std::string (" --QueueDiscMode=") + QueueDiscMode + std::string (" --isBql=") + isBql + std::string ("\""); + } + system (commandToRun.c_str ()); + std::ofstream outfile; + outfile.open ((std::string ("aqm-eval-output/") + scenarioName + std::string ("/data/plot-shell")).c_str (), std::ios::out | std::ios::trunc); + outfile << "set terminal png size 600, 350\n"; + outfile << "set size .9, 1\n"; + outfile << "set output \"aqm-eval-output/" << scenarioName.c_str () << "/graph/qdel-goodput.png\"\n set xlabel \"Queue Delay (ms)\" font \"Verdana\"\nset ylabel \"Goodput (Mbps)\" font \"Verdana\"\n"; + outfile << "set xrange[] reverse\nset grid\nshow grid\n"; + outfile.close (); + + std::string gnuPlot = "plot "; + + for (uint32_t i = 0; i < nAQM; i++) + { + std::string proQdelThr = std::string ("python src/aqm-eval-suite/utils/generate-ellipseinput.py ") + scenarioName + " " + AQM[i] + queueDisc; + std::string proEllipse = std::string ("python src/aqm-eval-suite/utils/ellipsemaker ") + scenarioName + " " + AQM[i] + queueDisc + " " + std::to_string (i + 1); + std::string plotGoodput = std::string ("python src/aqm-eval-suite/utils/goodput_process.py ") + scenarioName + " " + AQM[i] + queueDisc; + std::string plotDelay = std::string ("python src/aqm-eval-suite/utils/delay_process.py ") + scenarioName + " " + AQM[i] + queueDisc; + system (proQdelThr.c_str ()); + system (proEllipse.c_str ()); + system (plotGoodput.c_str ()); + system (plotDelay.c_str ()); + std::string graphName = std::string ("\"aqm-eval-output/") + scenarioName + std::string ("/data/") + AQM[i] + queueDisc + std::string ("-ellipse.dat\" notitle with lines"); + if (i != nAQM - 1) + { + gnuPlot = gnuPlot + graphName + std::string (","); + } + else + { + gnuPlot = gnuPlot + graphName; + } + } + outfile.open ((std::string ("aqm-eval-output/") + scenarioName + std::string ("/data/plot-shell")).c_str (), std::ios::out | std::ios::app); + outfile << gnuPlot.c_str (); + outfile.close (); + + system ((std::string ("gnuplot aqm-eval-output/") + scenarioName + std::string ("/data/plot-shell")).c_str ()); + system ((std::string ("convert aqm-eval-output/") + scenarioName + std::string ("/graph/qdel-goodput.png aqm-eval-output/") + scenarioName + std::string ("/graph/qdel-goodput.eps")).c_str ()); +} + +void RunRttFairness (std::string scenarioName) +{ + std::string orig = scenarioName; + + for (uint32_t i = 1; i <= 15; i++) + { + char sce[20]; + sprintf (sce, "%d", i); + scenarioName = orig + std::string (sce); + mkdir ((std::string ("aqm-eval-output/") + scenarioName).c_str (), 0700); + mkdir ((std::string ("aqm-eval-output/") + scenarioName + std::string ("/data")).c_str (), 0700); + mkdir ((std::string ("aqm-eval-output/") + scenarioName + std::string ("/graph")).c_str (), 0700); + } + std::string commandToRun = std::string ("./waf --run \"")+ orig + std::string (" --QueueDiscMode=") + QueueDiscMode + std::string (" --isBql=") + isBql + std::string ("\""); + system (commandToRun.c_str ()); + for (uint32_t i = 1; i <=15; i++) + { + char sce[20]; + sprintf (sce, "%d", i); + scenarioName = orig + std::string (sce); + std::ofstream outfile; + outfile.open ((std::string ("aqm-eval-output/") + scenarioName + std::string ("/data/plot-shell")).c_str (), std::ios::out | std::ios::trunc); + outfile << "set terminal png size 600, 350\n"; + outfile << "set size .9, 1\n"; + outfile << "set output \"aqm-eval-output/" << scenarioName.c_str () << "/graph/qdel-goodput.png\"\n set xlabel \"Queue Delay (ms)\" font \"Verdana\"\nset ylabel \"Goodput (Mbps)\" font \"Verdana\"\n"; + outfile << "set xrange[] reverse\nset grid\nshow grid\n"; + outfile.close (); + + std::string gnuPlot = "plot "; + + for (uint32_t i = 0; i < nAQM; i++) + { + std::string proQdelThr = std::string ("python src/aqm-eval-suite/utils/generate-ellipseinput.py ") + scenarioName + " " + AQM[i] + queueDisc; + std::string proEllipse = std::string ("python src/aqm-eval-suite/utils/ellipsemaker ") + scenarioName + " " + AQM[i] + queueDisc + " " + std::to_string (i + 1); + std::string plotGoodput = std::string ("python src/aqm-eval-suite/utils/goodput_process.py ") + scenarioName + " " + AQM[i] + queueDisc; + std::string plotDelay = std::string ("python src/aqm-eval-suite/utils/delay_process.py ") + scenarioName + " " + AQM[i] + queueDisc; + std::string plotDrop = std::string ("python src/aqm-eval-suite/utils/drop_process.py ") + scenarioName + " " + AQM[i] + queueDisc; + system (proQdelThr.c_str ()); + system (proEllipse.c_str ()); + system (plotGoodput.c_str ()); + system (plotDelay.c_str ()); + system (plotDrop.c_str ()); + std::string graphName = std::string ("\"aqm-eval-output/") + scenarioName + std::string ("/data/") + AQM[i] + queueDisc + std::string ("-ellipse.dat\" notitle with lines"); + if (i != nAQM - 1) + { + gnuPlot = gnuPlot + graphName + std::string (","); + } + else + { + gnuPlot = gnuPlot + graphName; + } + } + + outfile.open ((std::string ("aqm-eval-output/") + scenarioName + std::string ("/data/plot-shell")).c_str (), std::ios::out | std::ios::app); + outfile << gnuPlot.c_str (); + outfile.close (); + + system ((std::string ("gnuplot aqm-eval-output/") + scenarioName + std::string ("/data/plot-shell")).c_str ()); + system ((std::string ("convert aqm-eval-output/") + scenarioName + std::string ("/graph/qdel-goodput.png aqm-eval-output/") + scenarioName + std::string ("/graph/qdel-goodput.eps")).c_str ()); + } +} + +int main (int argc, char *argv[]) +{ + mkdir ("aqm-eval-output", 0700); + std::map ScenarioNumberMapping; + ScenarioNumberMapping["4.5"] = "RttFairnessWithEcn"; + ScenarioNumberMapping["5.1.1"] = "TCPFriendlySameInitCwnd"; + ScenarioNumberMapping["5.1.2"] = "TCPFriendlyDifferentInitCwnd"; + ScenarioNumberMapping["5.2"] = "AggressiveTransportSender"; + ScenarioNumberMapping["5.3.1"] = "UnresponsiveTransport"; + ScenarioNumberMapping["5.3.2"] = "UnresponsiveWithFriendly"; + ScenarioNumberMapping["5.4"] = "LbeTransportSender"; + ScenarioNumberMapping["6"] = "RttFairness"; + ScenarioNumberMapping["8.2.2"] = "MildCongestion"; + ScenarioNumberMapping["8.2.3"] = "MediumCongestion"; + ScenarioNumberMapping["8.2.4"] = "HeavyCongestion"; + ScenarioNumberMapping["8.2.5"] = "VaryingCongestion"; + ScenarioNumberMapping["8.2.6.1"] = "VaryingBandwidthUno"; + ScenarioNumberMapping["8.2.6.2"] = "VaryingBandwidthDuo"; + + std::string scenarioName = ""; + std::string scenarioNumber = ""; + + CommandLine cmd; + cmd.AddValue ("number", "Scenario number from RFC", scenarioNumber); + cmd.AddValue ("name", "Name of the scenario (eg: TCPFriendlySameInitCwnd)", scenarioName); + cmd.AddValue ("AggressiveTcp", "Variant of the Aggressive TCP", AggressiveTcp); + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + + cmd.Parse (argc, argv); + + if (scenarioName == "" && scenarioNumber == "") + { + std::cout << "No value given"; + exit (-1); + } + + if (scenarioName == "") + { + scenarioName = ScenarioNumberMapping[scenarioNumber]; + } + + if (scenarioName != "All" && scenarioName != "RttFairness" && scenarioName != "RttFairnessWithEcn") + { + RunOneScenario (scenarioName); + } + else if (scenarioName != "All" && (scenarioName == "RttFairness" || scenarioName == "RttFairnessWithEcn")) + { + RunRttFairness (scenarioName); + } + else + { + RunRttFairness ("RttFairness"); + RunRttFairness ("RttFairnessWithEcn"); + for (std::map::iterator it = ScenarioNumberMapping.begin (); it != ScenarioNumberMapping.end (); ++it) + { + if (it->second != "RttFairness" && it->second != "RttFairnessWithEcn") + { + RunOneScenario (it->second); + } + } + } +} + diff --git a/src/aqm-eval-suite/examples/heavy-congestion.cc b/src/aqm-eval-suite/examples/heavy-congestion.cc new file mode 100644 index 00000000000..e72e5c86734 --- /dev/null +++ b/src/aqm-eval-suite/examples/heavy-congestion.cc @@ -0,0 +1,91 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Section 8.2.4 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-8.2.4). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("HeavyCongestion"); + +class HeavyCongestion : public ScenarioImpl +{ +public: + HeavyCongestion (); + ~HeavyCongestion (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); +}; + +HeavyCongestion::HeavyCongestion () +{ +} + +HeavyCongestion::~HeavyCongestion () +{ +} + +EvaluationTopology +HeavyCongestion::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 0.114 * 62; + + EvaluationTopology et ("HeavyCongestion", nflow, pointToPoint, aqm, 698, isBql); + for (uint32_t i = 0; i < nflow; i++) + { + ApplicationContainer ac = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ac.Start (Seconds ((i * nflow) / nflow)); + ac.Stop (Seconds (300 + (i * nflow) / nflow)); + } + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + HeavyCongestion sce; + sce.ConfigureQueueDisc (45, 750, "1Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/medium-congestion.cc b/src/aqm-eval-suite/examples/medium-congestion.cc new file mode 100644 index 00000000000..0b2aba9b303 --- /dev/null +++ b/src/aqm-eval-suite/examples/medium-congestion.cc @@ -0,0 +1,91 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Section 8.2.3 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-8.2.3). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("MediumCongestion"); + +class MediumCongestion : public ScenarioImpl +{ +public: + MediumCongestion (); + ~MediumCongestion (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); +}; + +MediumCongestion::MediumCongestion () +{ +} + +MediumCongestion::~MediumCongestion () +{ +} + +EvaluationTopology +MediumCongestion::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 0.081 * 62; + + EvaluationTopology et ("MediumCongestion", nflow, pointToPoint, aqm, 698, isBql); + for (uint32_t i = 0; i < nflow; i++) + { + ApplicationContainer ac = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ac.Start (Seconds ((i * nflow) / nflow)); + ac.Stop (Seconds (300 + (i * nflow) / nflow)); + } + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + MediumCongestion sce; + sce.ConfigureQueueDisc (45, 750, "1Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/mild-congestion.cc b/src/aqm-eval-suite/examples/mild-congestion.cc new file mode 100644 index 00000000000..566f8b2080d --- /dev/null +++ b/src/aqm-eval-suite/examples/mild-congestion.cc @@ -0,0 +1,91 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Section 8.2.2 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-8.2.2). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("MildCongestion"); + +class MildCongestion : public ScenarioImpl +{ +public: + MildCongestion (); + ~MildCongestion (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); +}; + +MildCongestion::MildCongestion () +{ +} + +MildCongestion::~MildCongestion () +{ +} + +EvaluationTopology +MildCongestion::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("45ms")); + uint32_t nflow = 0.036 * 62; + + EvaluationTopology et ("MildCongestion", nflow, pointToPoint, aqm, 698, isBql); + for (uint32_t i = 0; i < nflow; i++) + { + ApplicationContainer ac = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ac.Start (Seconds ((i * nflow) / nflow)); + ac.Stop (Seconds (300 + (i * nflow) / nflow)); + } + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + MildCongestion sce; + sce.ConfigureQueueDisc (45, 750, "1Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/rtt-fairness-with-ecn.cc b/src/aqm-eval-suite/examples/rtt-fairness-with-ecn.cc new file mode 100644 index 00000000000..5b2e485aadf --- /dev/null +++ b/src/aqm-eval-suite/examples/rtt-fairness-with-ecn.cc @@ -0,0 +1,132 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2018 NITK Surathkal + * + * 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: Ajumal P A + * Ananthakrishnan S + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Section 4.5 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-4.5). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" +#include "vector" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("RttFairnessWithEcn"); + +class RttFairnessWithEcn : public ScenarioImpl +{ +public: + RttFairnessWithEcn (uint32_t run); + ~RttFairnessWithEcn (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); + +private: + uint32_t m_run; + std::vector delay; +}; + +RttFairnessWithEcn::RttFairnessWithEcn (uint32_t run) +{ + m_run = run; + delay = {5, 8, 10, 16, 20, 30, 40, 60, 80, 100, 150, 200, 300, 400, 500}; +} + +RttFairnessWithEcn::~RttFairnessWithEcn () +{ +} + +EvaluationTopology +RttFairnessWithEcn::CreateScenario (std::string aqm, bool isBql) +{ + double bottleneck; + double reqDelayConstRtt; + double reqDelay; + char OWD[20]; + char scenario[20]; + char OWDConst[20]; + char bottleneckStr[20]; + if (delay[m_run] < 100) + { + bottleneck = delay[m_run] * 0.8 / 2; + reqDelay = delay[m_run] * 0.2 / 4; + reqDelayConstRtt = (50 - bottleneck) / 2; + } + else + { + bottleneck = 40; + reqDelay = (delay[m_run] - 80) / 4; + reqDelayConstRtt = 5; + } + + sprintf (OWD, "%fms", reqDelay); + sprintf (OWDConst, "%fms", reqDelayConstRtt); + sprintf (scenario, "%d", m_run + 1); + sprintf (bottleneckStr, "%fms", bottleneck); + std::string scenarioName = std::string ("RttFairnessWithEcn") + std::string (scenario); + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue (bottleneckStr)); + uint32_t nflow = 2; + + EvaluationTopology et (scenarioName, nflow, pointToPoint, aqm, 698, isBql); + ApplicationContainer ac1 = et.CreateFlow (StringValue (OWDConst), + StringValue (OWDConst), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ApplicationContainer ac2 = et.CreateFlow (StringValue (OWD), + StringValue (OWD), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ac1.Start (Seconds (0)); + ac1.Stop (Seconds (600)); + + ac2.Start (Seconds (0.5)); + ac2.Stop (Seconds (600.5)); + return et; +} + +int +main (int argc, char *argv[]) +{ + bool ecn = true; + std::string QueueDiscMode = ""; + std::string isBql = ""; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + for (uint32_t i = 0; i < 15; i++) + { + RttFairnessWithEcn rf (i); + rf.ConfigureQueueDisc (45, 750, "1Mbps", "2ms", QueueDiscMode,ecn); + rf.RunSimulation (Seconds (610), isBql == "true"); + } +} diff --git a/src/aqm-eval-suite/examples/rtt-fairness.cc b/src/aqm-eval-suite/examples/rtt-fairness.cc new file mode 100644 index 00000000000..83b5f6738c4 --- /dev/null +++ b/src/aqm-eval-suite/examples/rtt-fairness.cc @@ -0,0 +1,132 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Section 6.2 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-6.2). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" +#include "vector" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("RttFairness"); + +class RttFairness : public ScenarioImpl +{ +public: + RttFairness (uint32_t run); + ~RttFairness (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); + +private: + uint32_t m_run; + std::vector delay; +}; + +RttFairness::RttFairness (uint32_t run) +{ + m_run = run; + delay = {5, 8, 10, 16, 20, 30, 40, 60, 80, 100, 150, 200, 300, 400, 500}; +} + +RttFairness::~RttFairness () +{ +} + +EvaluationTopology +RttFairness::CreateScenario (std::string aqm, bool isBql) +{ + double bottleneck; + double reqDelayConstRtt; + double reqDelay; + char OWD[20]; + char scenario[20]; + char OWDConst[20]; + char bottleneckStr[20]; + if (delay[m_run] < 100) + { + bottleneck = delay[m_run] * 0.8 / 2; + reqDelay = delay[m_run] * 0.2 / 4; + reqDelayConstRtt = (50 - bottleneck) / 2; + } + else + { + bottleneck = 40; + reqDelay = (delay[m_run] - 80) / 4; + reqDelayConstRtt = 5; + } + + sprintf (OWD, "%fms", reqDelay); + sprintf (OWDConst, "%fms", reqDelayConstRtt); + sprintf (scenario, "%d", m_run + 1); + sprintf (bottleneckStr, "%fms", bottleneck); + std::string scenarioName = std::string ("RttFairness") + std::string (scenario); + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue (bottleneckStr)); + uint32_t nflow = 2; + + EvaluationTopology et (scenarioName, nflow, pointToPoint, aqm, 698, isBql); + ApplicationContainer ac1 = et.CreateFlow (StringValue (OWDConst), + StringValue (OWDConst), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ApplicationContainer ac2 = et.CreateFlow (StringValue (OWD), + StringValue (OWD), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ac1.Start (Seconds (0)); + ac1.Stop (Seconds (600)); + + ac2.Start (Seconds (0.5)); + ac2.Stop (Seconds (600.5)); + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + for (uint32_t i = 0; i < 15; i++) + { + RttFairness rf (i); + rf.ConfigureQueueDisc (45, 750, "1Mbps", "2ms", QueueDiscMode,ecn); + rf.RunSimulation (Seconds (610), isBql == "true"); + } +} diff --git a/src/aqm-eval-suite/examples/single-unresponsive-transport.cc b/src/aqm-eval-suite/examples/single-unresponsive-transport.cc new file mode 100644 index 00000000000..d6b0eccc85c --- /dev/null +++ b/src/aqm-eval-suite/examples/single-unresponsive-transport.cc @@ -0,0 +1,88 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the first scenario described in Section 5.3 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-5.3). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("SingleUnresponsiveTransportSender"); + +class UnresponsiveTransport : public ScenarioImpl +{ +public: + UnresponsiveTransport (); + ~UnresponsiveTransport (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); +}; + +UnresponsiveTransport::UnresponsiveTransport () +{ +} + +UnresponsiveTransport::~UnresponsiveTransport () +{ +} + +EvaluationTopology +UnresponsiveTransport::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 1; + + EvaluationTopology et ("UnresponsiveTransport", nflow, pointToPoint, aqm, 698, isBql); + ApplicationContainer ac = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "udp", 0, DataRate ("10Mb/s")); + + ac.Start (Seconds (0)); + ac.Stop (Seconds (300)); + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + UnresponsiveTransport sce; + sce.ConfigureQueueDisc (45, 750, "1Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/tcp-friendly-different-initcwnd.cc b/src/aqm-eval-suite/examples/tcp-friendly-different-initcwnd.cc new file mode 100644 index 00000000000..79fe2b0b2fb --- /dev/null +++ b/src/aqm-eval-suite/examples/tcp-friendly-different-initcwnd.cc @@ -0,0 +1,97 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Section 5.1.2 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-5.1). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("TcpFriendlyDifferentInitCwnd"); + +class TCPFriendlyDifferentInitCwnd : public ScenarioImpl +{ +public: + TCPFriendlyDifferentInitCwnd (); + ~TCPFriendlyDifferentInitCwnd (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); +}; + +TCPFriendlyDifferentInitCwnd::TCPFriendlyDifferentInitCwnd () +{ +} + +TCPFriendlyDifferentInitCwnd::~TCPFriendlyDifferentInitCwnd () +{ +} + +EvaluationTopology +TCPFriendlyDifferentInitCwnd::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 2; + + EvaluationTopology et ("TCPFriendlyDifferentInitCwnd", nflow, pointToPoint, aqm, 698, isBql); + ApplicationContainer ac1 = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ApplicationContainer ac2 = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 100, DataRate ("10Mb/s"), 10); + + ac1.Start (Seconds (0)); + ac1.Stop (Seconds (300)); + + ac2.Start (Seconds (0.5)); + ac2.Stop (Seconds (300)); + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + TCPFriendlyDifferentInitCwnd sce; + sce.ConfigureQueueDisc (45, 750, "1Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/tcp-friendly-same-initcwnd.cc b/src/aqm-eval-suite/examples/tcp-friendly-same-initcwnd.cc new file mode 100644 index 00000000000..dca620fb7d6 --- /dev/null +++ b/src/aqm-eval-suite/examples/tcp-friendly-same-initcwnd.cc @@ -0,0 +1,87 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Section 5.1.1 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-5.1). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("TcpFriendlySameInitCwnd"); + +class TCPFriendlySameInitCwnd : public ScenarioImpl +{ +public: + TCPFriendlySameInitCwnd (); + ~TCPFriendlySameInitCwnd (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); +}; + +TCPFriendlySameInitCwnd::TCPFriendlySameInitCwnd () +{ +} + +TCPFriendlySameInitCwnd::~TCPFriendlySameInitCwnd () +{ +} + +EvaluationTopology +TCPFriendlySameInitCwnd::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 1; + EvaluationTopology et ("TCPFriendlySameInitCwnd", nflow, pointToPoint, aqm, 698, isBql); + ApplicationContainer ac = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ac.Start (Seconds (0)); + ac.Stop (Seconds (300)); + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + TCPFriendlySameInitCwnd sce; + sce.ConfigureQueueDisc (45, 750, "1Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/unresponsive-with-friendly-transport.cc b/src/aqm-eval-suite/examples/unresponsive-with-friendly-transport.cc new file mode 100644 index 00000000000..5d4786611f0 --- /dev/null +++ b/src/aqm-eval-suite/examples/unresponsive-with-friendly-transport.cc @@ -0,0 +1,97 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the second scenario described in Section 5.3 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-5.3). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("UnresponsiveWithFriendlyTransportSender"); + +class UnresponsiveWithFriendly : public ScenarioImpl +{ +public: + UnresponsiveWithFriendly (); + ~UnresponsiveWithFriendly (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); +}; + +UnresponsiveWithFriendly::UnresponsiveWithFriendly () +{ +} + +UnresponsiveWithFriendly::~UnresponsiveWithFriendly () +{ +} + +EvaluationTopology +UnresponsiveWithFriendly::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 2; + + EvaluationTopology et ("UnresponsiveWithFriendly", nflow, pointToPoint, aqm, 698, isBql); + ApplicationContainer ac1 = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ac1.Start (Seconds (0)); + ac1.Stop (Seconds (300)); + + ApplicationContainer ac2 = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "udp", 0, DataRate ("0.8Mb/s")); + + ac2.Start (Seconds (0)); + ac2.Stop (Seconds (300)); + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + UnresponsiveWithFriendly sce; + sce.ConfigureQueueDisc (45, 750, "1Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/vary-available-capacity-duo.cc b/src/aqm-eval-suite/examples/vary-available-capacity-duo.cc new file mode 100644 index 00000000000..7fc0f60fd83 --- /dev/null +++ b/src/aqm-eval-suite/examples/vary-available-capacity-duo.cc @@ -0,0 +1,126 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Experiment 1 of + * Section 8.2.6 of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-8.2.6). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("VaryAvailableCapacityDuo"); + +class VaryingBandwidthDuo : public ScenarioImpl +{ +public: + VaryingBandwidthDuo (); + ~VaryingBandwidthDuo (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); + +private: + void ChangeDataRate (); + bool m_state; +}; + +VaryingBandwidthDuo::VaryingBandwidthDuo () +{ + m_state = true; +} + +VaryingBandwidthDuo::~VaryingBandwidthDuo () +{ +} + +void +VaryingBandwidthDuo::ChangeDataRate () +{ + if (m_state) + { + Config::Set ("/NodeList/0/DeviceList/0/DataRate", StringValue ("10Mbps")); + Config::Set ("/NodeList/1/DeviceList/0/DataRate", StringValue ("10Mbps")); + m_state = false; + } + else + { + Config::Set ("/NodeList/0/DeviceList/0/DataRate", StringValue ("100Mbps")); + Config::Set ("/NodeList/1/DeviceList/0/DataRate", StringValue ("100Mbps")); + m_state = true; + } +} + +EvaluationTopology +VaryingBandwidthDuo::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("100Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 2; + + EvaluationTopology et ("VaryingBandwidthDuo", nflow, pointToPoint, aqm, 698, isBql); + ApplicationContainer ac1 = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("500Mbps"), + StringValue ("500Mbps"), + "ns3::TcpNewReno", 0, DataRate ("500Mb/s"), 3); + + + ApplicationContainer ac2 = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("500Mbps"), + StringValue ("500Mbps"), + "ns3::TcpNewReno", 0, DataRate ("500Mb/s"), 3); + + ac1.Start (Seconds (0)); + ac1.Stop (Seconds (300)); + + ac2.Start (Seconds (0)); + ac2.Stop (Seconds (300)); + + for (double i = 0.1; i < 300; i += 0.1) + { + Simulator::Schedule (Seconds (i), &VaryingBandwidthDuo::ChangeDataRate, this); + } + + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + VaryingBandwidthDuo sce; + sce.ConfigureQueueDisc (500, 750, "100Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/vary-available-capacity-uno.cc b/src/aqm-eval-suite/examples/vary-available-capacity-uno.cc new file mode 100644 index 00000000000..68d4896227b --- /dev/null +++ b/src/aqm-eval-suite/examples/vary-available-capacity-uno.cc @@ -0,0 +1,125 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Experiment 1 of + * Section 8.2.6 of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-8.2.6). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("VaryAvailableCapacityUno"); + +class VaryingBandwidthUno : public ScenarioImpl +{ +public: + VaryingBandwidthUno (); + ~VaryingBandwidthUno (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); + +private: + void ChangeDataRate (); + bool m_state; +}; + +VaryingBandwidthUno::VaryingBandwidthUno () +{ + m_state = true; +} + +VaryingBandwidthUno::~VaryingBandwidthUno () +{ +} + +void +VaryingBandwidthUno::ChangeDataRate () +{ + if (m_state) + { + Config::Set ("/NodeList/0/DeviceList/0/DataRate", StringValue ("10Mbps")); + Config::Set ("/NodeList/1/DeviceList/0/DataRate", StringValue ("10Mbps")); + m_state = false; + } + else + { + Config::Set ("/NodeList/0/DeviceList/0/DataRate", StringValue ("100Mbps")); + Config::Set ("/NodeList/1/DeviceList/0/DataRate", StringValue ("100Mbps")); + m_state = true; + } +} + +EvaluationTopology +VaryingBandwidthUno::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("100Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 2; + + EvaluationTopology et ("VaryingBandwidthUno", nflow, pointToPoint, aqm, 698, isBql); + ApplicationContainer ac1 = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("500Mbps"), + StringValue ("500Mbps"), + "ns3::TcpNewReno", 0, DataRate ("500Mb/s"), 3); + + + ApplicationContainer ac2 = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("500Mbps"), + StringValue ("500Mbps"), + "ns3::TcpNewReno", 0, DataRate ("500Mb/s"), 3); + + ac1.Start (Seconds (0)); + ac1.Stop (Seconds (300)); + + ac2.Start (Seconds (0)); + ac2.Stop (Seconds (300)); + + for (double i = 20; i < 300; i += 20) + { + Simulator::Schedule (Seconds (i), &VaryingBandwidthUno::ChangeDataRate, this); + } + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + VaryingBandwidthUno sce; + sce.ConfigureQueueDisc (500, 750, "100Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/vary-congestion-level.cc b/src/aqm-eval-suite/examples/vary-congestion-level.cc new file mode 100644 index 00000000000..d46c8920659 --- /dev/null +++ b/src/aqm-eval-suite/examples/vary-congestion-level.cc @@ -0,0 +1,126 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +/* + * This example is equivalent to the scenario described in Section 8.2.5 + * of RFC 7928 (https://tools.ietf.org/html/rfc7928#section-8.2.5). + */ + +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/aqm-eval-suite-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("VaryCongestionLevel"); + +class VaryingCongestion : public ScenarioImpl +{ +public: + VaryingCongestion (); + ~VaryingCongestion (); + +protected: + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql); + +private: + void PauseApp (EvaluationTopology et, uint32_t flow) + { + et.Pause (flow); + } + + void restartApp (EvaluationTopology et, uint32_t flow) + { + et.Restart (flow); + } +}; + +VaryingCongestion::VaryingCongestion () +{ +} + +VaryingCongestion::~VaryingCongestion () +{ +} + +EvaluationTopology +VaryingCongestion::CreateScenario (std::string aqm, bool isBql) +{ + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("48ms")); + uint32_t nflow = 0.114 * 62; + + EvaluationTopology et ("VaryingCongestion", nflow, pointToPoint, aqm, 698, isBql); + for (uint32_t i = 0; i < nflow; i++) + { + ApplicationContainer ac = et.CreateFlow (StringValue ("1ms"), + StringValue ("1ms"), + StringValue ("10Mbps"), + StringValue ("10Mbps"), + "ns3::TcpNewReno", 0, DataRate ("10Mb/s"), 3); + + ac.Start (Seconds (0)); + ac.Stop (Seconds (300)); + if (i > 0.036 * 62 && i < 0.081 * 62) + { + Simulator::Schedule (Seconds (40), &VaryingCongestion::PauseApp, this, et, i); + Simulator::Schedule (Seconds (60), &VaryingCongestion::restartApp, this, et, i); + Simulator::Schedule (Seconds (100), &VaryingCongestion::PauseApp, this, et, i); + Simulator::Schedule (Seconds (120), &VaryingCongestion::restartApp, this, et, i); + Simulator::Schedule (Seconds (160), &VaryingCongestion::PauseApp, this, et, i); + Simulator::Schedule (Seconds (180), &VaryingCongestion::restartApp, this, et, i); + Simulator::Schedule (Seconds (220), &VaryingCongestion::PauseApp, this, et, i); + Simulator::Schedule (Seconds (240), &VaryingCongestion::restartApp, this, et, i); + Simulator::Schedule (Seconds (280), &VaryingCongestion::PauseApp, this, et, i); + } + else if (i > 0.036 * 62 && i < 0.114 * 62) + { + Simulator::Schedule (Seconds (20), &VaryingCongestion::PauseApp, this, et, i); + Simulator::Schedule (Seconds (60), &VaryingCongestion::restartApp, this, et, i); + Simulator::Schedule (Seconds (80), &VaryingCongestion::PauseApp, this, et, i); + Simulator::Schedule (Seconds (120), &VaryingCongestion::restartApp, this, et, i); + Simulator::Schedule (Seconds (140), &VaryingCongestion::PauseApp, this, et, i); + Simulator::Schedule (Seconds (180), &VaryingCongestion::restartApp, this, et, i); + Simulator::Schedule (Seconds (200), &VaryingCongestion::PauseApp, this, et, i); + Simulator::Schedule (Seconds (240), &VaryingCongestion::restartApp, this, et, i); + Simulator::Schedule (Seconds (260), &VaryingCongestion::PauseApp, this, et, i); + } + } + return et; +} + +int +main (int argc, char *argv[]) +{ + std::string QueueDiscMode = ""; + std::string isBql = ""; + bool ecn = false; + CommandLine cmd; + cmd.AddValue ("QueueDiscMode", "Determines the unit for QueueLimit", QueueDiscMode); + cmd.AddValue ("isBql", "Enables/Disables Byte Queue Limits", isBql); + cmd.Parse (argc, argv); + + VaryingCongestion sce; + sce.ConfigureQueueDisc (45, 750, "1Mbps", "48ms", QueueDiscMode,ecn); + sce.RunSimulation (Seconds (310), isBql == "true"); +} diff --git a/src/aqm-eval-suite/examples/wscript b/src/aqm-eval-suite/examples/wscript new file mode 100644 index 00000000000..2b028ef047a --- /dev/null +++ b/src/aqm-eval-suite/examples/wscript @@ -0,0 +1,50 @@ +# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + + + obj = bld.create_ns3_program('TCPFriendlySameInitCwnd', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'tcp-friendly-same-initcwnd.cc' + + obj = bld.create_ns3_program('TCPFriendlyDifferentInitCwnd', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'tcp-friendly-different-initcwnd.cc' + + obj = bld.create_ns3_program('AggressiveTransportSender', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'aggressive-transport-sender.cc' + + obj = bld.create_ns3_program('HeavyCongestion', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'heavy-congestion.cc' + + obj = bld.create_ns3_program('MediumCongestion', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'medium-congestion.cc' + + obj = bld.create_ns3_program('MildCongestion', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'mild-congestion.cc' + + obj = bld.create_ns3_program('RttFairness', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'rtt-fairness.cc' + + obj = bld.create_ns3_program('RttFairnessWithEcn', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'rtt-fairness-with-ecn.cc' + + obj = bld.create_ns3_program('UnresponsiveTransport', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'single-unresponsive-transport.cc' + + obj = bld.create_ns3_program('UnresponsiveWithFriendly', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'unresponsive-with-friendly-transport.cc' + + obj = bld.create_ns3_program('VaryingCongestion', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'vary-congestion-level.cc' + + obj = bld.create_ns3_program('VaryingBandwidthUno', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'vary-available-capacity-uno.cc' + + obj = bld.create_ns3_program('VaryingBandwidthDuo', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'vary-available-capacity-duo.cc' + + obj = bld.create_ns3_program('LbeTransportSender', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'LBE-transport-sender.cc' + + obj = bld.create_ns3_program('aqm-eval-suite-runner', ['aqm-eval-suite','core', 'internet', 'point-to-point', 'applications', 'point-to-point-layout']) + obj.source = 'aqm-eval-suite-runner.cc' + diff --git a/src/aqm-eval-suite/helper/aqm-eval-suite-helper.cc b/src/aqm-eval-suite/helper/aqm-eval-suite-helper.cc new file mode 100644 index 00000000000..14c11c84661 --- /dev/null +++ b/src/aqm-eval-suite/helper/aqm-eval-suite-helper.cc @@ -0,0 +1,111 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +#include "aqm-eval-suite-helper.h" + +namespace ns3 { + +ScenarioImpl::ScenarioImpl () +{ + m_AQM = { + "ns3::RedQueueDisc", + "ns3::PfifoFastQueueDisc", + "ns3::AdaptiveRedQueueDisc", + "ns3::FengAdaptiveRedQueueDisc", + "ns3::NonLinearRedQueueDisc", + "ns3::CoDelQueueDisc", + "ns3::PieQueueDisc" + }; + m_nAQM = 7; +} + +ScenarioImpl::~ScenarioImpl () +{ +} + +void +ScenarioImpl::addAQM (std::string aqm) +{ + m_AQM.push_back (aqm); + m_nAQM++; +} + +void +ScenarioImpl::DestroyTrace (EvaluationTopology et) +{ + et.DestroyConnection (); +} + +void +ScenarioImpl::ConfigureQueueDisc (uint32_t limit, uint32_t pktsize, std::string linkbw, std::string linkdel, std::string mode, bool ecn) +{ + Config::SetDefault ("ns3::PfifoFastQueueDisc::MaxSize", StringValue (std::to_string (limit) + "p")); + + Config::SetDefault ("ns3::RedQueueDisc::MeanPktSize", UintegerValue (pktsize)); + Config::SetDefault ("ns3::RedQueueDisc::LinkBandwidth", StringValue (linkbw)); + Config::SetDefault ("ns3::RedQueueDisc::LinkDelay", StringValue (linkdel)); + + if (ecn) + { + Config::SetDefault ("ns3::RedQueueDisc::UseEcn", BooleanValue (ecn)); + + Config::SetDefault ("ns3::TcpSocketBase::EcnMode", StringValue ("ClassicEcn")); + } + + Config::SetDefault ("ns3::CoDelQueueDisc::MaxSize", StringValue (std::to_string (limit) + "p")); + Config::SetDefault ("ns3::CoDelQueueDisc::MinBytes", UintegerValue (pktsize)); + + Config::SetDefault ("ns3::PieQueueDisc::MeanPktSize", UintegerValue (pktsize)); + + if (mode == "QUEUE_DISC_MODE_PACKETS") + { + Config::SetDefault ("ns3::RedQueueDisc::MaxSize", StringValue (std::to_string (limit) + "p")); + Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (5)); + Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (15)); + + Config::SetDefault ("ns3::PieQueueDisc::MaxSize", StringValue (std::to_string (limit) + "p")); + } + else + { + Config::SetDefault ("ns3::RedQueueDisc::MaxSize",StringValue (std::to_string (limit * pktsize) + "B")); + Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (5 * pktsize)); + Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (15 * pktsize)); + + Config::SetDefault ("ns3::PieQueueDisc::MaxSize", StringValue (std::to_string (limit * pktsize) + "B")); + } +} + +void +ScenarioImpl::RunSimulation (Time simtime, bool isBql) +{ + for (uint32_t i = 0; i < m_nAQM; i++) + { + EvaluationTopology et = CreateScenario (m_AQM[i], isBql); + Simulator::Schedule (simtime, &ScenarioImpl::DestroyTrace, this, et); + Simulator::Stop (simtime); + Simulator::Run (); + Simulator::Destroy (); + } +} + +} //namespace ns3 + diff --git a/src/aqm-eval-suite/helper/aqm-eval-suite-helper.h b/src/aqm-eval-suite/helper/aqm-eval-suite-helper.h new file mode 100644 index 00000000000..19ac88d2795 --- /dev/null +++ b/src/aqm-eval-suite/helper/aqm-eval-suite-helper.h @@ -0,0 +1,99 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +#ifndef AQM_EVAL_SUITE_HELPER_H +#define AQM_EVAL_SUITE_HELPER_H + +#include "ns3/eval-topology.h" + +namespace ns3 { + +/** + * \brief An abstract class for scenario implementation + * + * This class contains the definition of methods commonly used in all + * scenarios, and virtual declaration of scenario-specific methods. + */ +class ScenarioImpl +{ +public: + /** + * \brief Constructor + */ + ScenarioImpl (); + + /** + * \brief Destructor + */ + virtual ~ScenarioImpl (); + + /** + * \brief Run simulation for the specified duration + * + * \param simtime The simulation time + * \param isBql Enable/Disable Byte Queue Limits + */ + void RunSimulation (Time simtime, bool isBql); + + /** + * \brief Adds the AQM to m_AQM list + * + * \param aqm TypeID of the AQM algorithm + */ + void addAQM (std::string aqm); + + /** + * \brief Helper to disconnect trace sources + * + * \param et The EvaluationTopology for which trace sources are disconnected + */ + void DestroyTrace (EvaluationTopology et); + + /** + * \brief Configure the queue discipline + * + * \param limit Maximum capacity of the queue discipline + * \param pktsize Packet size + * \param linkbw Bottleneck link bandwidth + * \param linkdel Bottleneck link delay + * \param mode Mode of operation for QueueDisc + * \param ecn ECN marking + */ + virtual void ConfigureQueueDisc (uint32_t limit, uint32_t pktsize, std::string linkbw, std::string linkdel, std::string mode, bool ecn); + +protected: + /** + * \brief Create simulation scenario + * + * \param aqm TypeID of the AQM algorithm + */ + virtual EvaluationTopology CreateScenario (std::string aqm, bool isBql) = 0; + +private: + std::vector m_AQM; //!< List of AQM algorithms + uint32_t m_nAQM; //!< Number of AQM algorithms +}; + +} + +#endif /* AQM_EVAL_SUITE_HELPER_H */ + diff --git a/src/aqm-eval-suite/model/eval-app.cc b/src/aqm-eval-suite/model/eval-app.cc new file mode 100644 index 00000000000..265bb1d7f73 --- /dev/null +++ b/src/aqm-eval-suite/model/eval-app.cc @@ -0,0 +1,238 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +#include "ns3/log.h" +#include "ns3/core-module.h" +#include "ns3/address.h" +#include "ns3/node.h" +#include "ns3/nstime.h" +#include "ns3/socket.h" +#include "ns3/simulator.h" +#include "ns3/socket-factory.h" +#include "ns3/packet.h" +#include "ns3/uinteger.h" +#include "ns3/trace-source-accessor.h" +#include "ns3/tcp-socket-factory.h" +#include "eval-app.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("EvalApp"); + +NS_OBJECT_ENSURE_REGISTERED (EvalApp); + +EvalApp::EvalApp () + : m_socket (0), + m_peer (), + m_connected (false), + m_residualBits (0), + m_lastStartTime (Seconds (0)), + m_maxBytes (0), + m_totBytes (0) +{ + m_onTime = CreateObject (); + m_onTime->SetAttribute ("Constant", DoubleValue (1)); + m_offTime = CreateObject (); + m_offTime->SetAttribute ("Constant", DoubleValue (0)); + m_flowStop = Time::Min (); + m_flowStart = Time::Min (); +} + +EvalApp::~EvalApp () +{ + m_socket = 0; +} + +void +EvalApp::Setup (Ptr socket, Address address, uint32_t packetSize, uint64_t maxByte, uint64_t stream, DataRate rate) +{ + m_socket = socket; + m_peer = address; + m_pktSize = packetSize; + m_maxBytes = maxByte; + m_onTime->SetStream (stream); + m_offTime->SetStream (stream + 1); + m_cbrRate = rate; +} + +void +EvalApp::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + + m_socket = 0; + // chain up + Application::DoDispose (); +} + +// Called at time specified by Start +void EvalApp::StartApplication () +{ + NS_LOG_FUNCTION (this); + + m_socket->Bind (); + m_socket->Connect (m_peer); + m_socket->SetAllowBroadcast (true); + m_socket->ShutdownRecv (); + + if (m_flowStart == Time::Min ()) + { + m_flowStart = Simulator::Now (); + } + + m_socket->SetConnectCallback ( + MakeCallback (&EvalApp::ConnectionSucceeded, this), + MakeCallback (&EvalApp::ConnectionFailed, this)); + + m_cbrRateFailSafe = m_cbrRate; + + // Ensure no pending event + CancelEvents (); + + ScheduleStartEvent (); +} + +// Called at time specified by Stop +void EvalApp::StopApplication () +{ + NS_LOG_FUNCTION (this); + + CancelEvents (); + if (m_socket != 0) + { + if (m_flowStop == Time::Min ()) + { + m_flowStop = Simulator::Now (); + } + m_socket->Close (); + } + else + { + NS_LOG_WARN ("EvalApp found null socket to close in StopApplication"); + } +} + +Time EvalApp::GetFlowCompletionTime () +{ + return m_flowStop - m_flowStart; +} + +void EvalApp::CancelEvents () +{ + NS_LOG_FUNCTION (this); + + if (m_sendEvent.IsRunning () && m_cbrRateFailSafe == m_cbrRate ) + { + // Cancel the pending send packet event + // Calculate residual bits since last packet sent + Time delta (Simulator::Now () - m_lastStartTime); + int64x64_t bits = delta.To (Time::S) * m_cbrRate.GetBitRate (); + m_residualBits += bits.GetHigh (); + } + m_cbrRateFailSafe = m_cbrRate; + Simulator::Cancel (m_sendEvent); + Simulator::Cancel (m_startStopEvent); +} + +void EvalApp::StartSending () +{ + NS_LOG_FUNCTION (this); + m_lastStartTime = Simulator::Now (); + + // Schedule the send packet event + ScheduleNextTx (); + ScheduleStopEvent (); +} + +void EvalApp::StopSending () +{ + NS_LOG_FUNCTION (this); + CancelEvents (); + + ScheduleStartEvent (); +} + +void EvalApp::ScheduleNextTx () +{ + NS_LOG_FUNCTION (this); + + if (m_maxBytes == 0 || m_totBytes < m_maxBytes) + { + uint32_t bits = m_pktSize * 8 - m_residualBits; + NS_LOG_LOGIC ("bits = " << bits); + Time nextTime (Seconds (bits / + static_cast (m_cbrRate.GetBitRate ()))); + NS_LOG_LOGIC ("nextTime = " << nextTime); + m_sendEvent = Simulator::Schedule (nextTime, + &EvalApp::SendPacket, this); + } + else + { + // All done, cancel any pending events + StopApplication (); + } +} + +void EvalApp::ScheduleStartEvent () +{ + NS_LOG_FUNCTION (this); + + // Schedules the event to start sending data (switch to the "On" state) + Time offInterval = Seconds (m_offTime->GetValue ()); + NS_LOG_LOGIC ("start at " << offInterval); + m_startStopEvent = Simulator::Schedule (offInterval, &EvalApp::StartSending, this); +} + +void EvalApp::ScheduleStopEvent () +{ + NS_LOG_FUNCTION (this); + + // Schedules the event to stop sending data (switch to "Off" state) + Time onInterval = Seconds (m_onTime->GetValue ()); + NS_LOG_LOGIC ("stop at " << onInterval); + m_startStopEvent = Simulator::Schedule (onInterval, &EvalApp::StopSending, this); +} + +void EvalApp::SendPacket () +{ + NS_LOG_FUNCTION (this); + + Ptr packet = Create (m_pktSize); + m_socket->Send (packet); + m_totBytes += m_pktSize; + m_lastStartTime = Simulator::Now (); + m_residualBits = 0; + ScheduleNextTx (); +} + +void EvalApp::ConnectionSucceeded (Ptr socket) +{ + NS_LOG_FUNCTION (this << socket); + m_connected = true; +} + +void EvalApp::ConnectionFailed (Ptr socket) +{ + NS_LOG_FUNCTION (this << socket); +} + +} //namespace ns3 diff --git a/src/aqm-eval-suite/model/eval-app.h b/src/aqm-eval-suite/model/eval-app.h new file mode 100644 index 00000000000..22359adacde --- /dev/null +++ b/src/aqm-eval-suite/model/eval-app.h @@ -0,0 +1,163 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +#ifndef EVAL_APPLICATION_H +#define EVAL_APPLICATION_H + +#include "ns3/address.h" +#include "ns3/application.h" +#include "ns3/event-id.h" +#include "ns3/ptr.h" +#include "ns3/traced-callback.h" +#include "ns3/data-rate.h" +#include "ns3/random-variable-stream.h" + +namespace ns3 { + +/** + * \brief Generates traffic in the suite + * + * This class generates TCP and UDP traffic in the suite. It has been + * designed to overcome the challenges faced while configuring attributes + * of TCP sockets, such as the initial congestion window. + */ + class EvalApp : public Application + { + public: + /** + * \brief Constructor + */ + EvalApp (); + + /** + * \brief Destructor + */ + virtual ~EvalApp (); + + /** + * \brief Configures the application + * + * \param socket The socket to be used by the application + * \param address Remote address + * \param packetSize The size of payload + * \param maxByte The maximum amount of data to be sent by the application + * \param stream The stream used by RNG + * \param rate The rate at which application sends data + */ + void Setup (Ptr socket, Address address, uint32_t packetSize, uint64_t maxByte, uint64_t stream, DataRate rate); + + /** + * \brief Get the flow completion time + * + * \return The flow completion time + */ + Time GetFlowCompletionTime (); + + friend class EvaluationTopology; + +protected: + virtual void DoDispose (void); + +private: + /** + * \brief Starts the application + */ + virtual void StartApplication (void); + + /** + * \brief Stops the application + */ + virtual void StopApplication (void); + + /** + * \brief Cancel all pending events + */ + void CancelEvents (); + + /** + * \brief Start an On period + */ + + void StartSending (); + + /** + * \brief Start an Off period + */ + void StopSending (); + + /** + * \brief Send a packet + */ + void SendPacket (); + + Ptr m_socket; //!< Associated socket + Address m_peer; //!< Peer address + bool m_connected; //!< True if connected + Ptr m_onTime; //!< rng for On Time + Ptr m_offTime; //!< rng for Off Time + DataRate m_cbrRate; //!< Rate that data is generated + DataRate m_cbrRateFailSafe; //!< Rate that data is generated (check copy) + uint32_t m_pktSize; //!< Size of packets + uint32_t m_residualBits; //!< Number of generated, but not sent, bits + Time m_lastStartTime; //!< Time last packet sent + uint64_t m_maxBytes; //!< Limit total number of bytes sent + uint64_t m_totBytes; //!< Total bytes sent so far + EventId m_startStopEvent; //!< Event id for next start or stop event + EventId m_sendEvent; //!< Event id of pending "send packet" event + +private: + Time m_flowStart; //!< Flow start time + Time m_flowStop; //!< Flow stop time + + /** + * \brief Schedule the next packet transmission + */ + void ScheduleNextTx (); + + /** + * \brief Schedule the next On period start + */ + void ScheduleStartEvent (); + + /** + * \brief Schedule the next Off period start + */ + void ScheduleStopEvent (); + + /** + * \brief Handle a Connection Succeed event + * + * \param socket The connected socket + */ + void ConnectionSucceeded (Ptr socket); + + /** + * \brief Handle a Connection Failed event + * + * \param socket The not connected socket + */ + void ConnectionFailed (Ptr socket); +}; + +} + +#endif /* EVAL_APPLICATION_H */ diff --git a/src/aqm-eval-suite/model/eval-topology.cc b/src/aqm-eval-suite/model/eval-topology.cc new file mode 100644 index 00000000000..3e10a1e5852 --- /dev/null +++ b/src/aqm-eval-suite/model/eval-topology.cc @@ -0,0 +1,323 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +#include "eval-topology.h" +#include "eval-ts.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("EvaluationTopology"); + +NS_OBJECT_ENSURE_REGISTERED (EvaluationTopology); + +TypeId +EvaluationTopology::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::EvaluationTopology") + .SetGroupName ("AqmEvaluationSuite") + ; + return tid; +} + +EvaluationTopology::EvaluationTopology (std::string ScenarioName, uint32_t numFlows, + PointToPointHelper p2pHelper, std::string queueDisc, uint32_t pktSize, bool isBql) + : m_dumbbell (numFlows, p2pHelper, numFlows, p2pHelper, p2pHelper) +{ + m_numFlows = numFlows; + m_flowsAdded = 0; + m_packetSize = pktSize; + bool m_isBql = isBql; + + InternetStackHelper stack; + m_dumbbell.InstallStack (stack); + + TrafficControlHelper tch; + m_dumbbell.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0"), + Ipv4AddressHelper ("10.10.1.0", "255.255.255.0"), + Ipv4AddressHelper ("10.100.1.0", "255.255.255.0")); + tch.Uninstall (m_dumbbell.GetLeft ()->GetDevice (0)); + + if (m_isBql) + { + tch.SetQueueLimits ("ns3::DynamicQueueLimits"); + } + + m_currentAQM = queueDisc; + if (queueDisc == "ns3::AdaptiveRedQueueDisc" || queueDisc == "ns3::FengAdaptiveRedQueueDisc" || queueDisc == "ns3::NonLinearRedQueueDisc") + { + queueDisc = "ns3::RedQueueDisc"; + tch.SetRootQueueDisc (queueDisc.c_str ()); + m_queue = tch.Install (m_dumbbell.GetLeft ()->GetDevice (0)).Get (0); + if (m_currentAQM == "ns3::AdaptiveRedQueueDisc") + { + m_queue->SetAttribute ("ARED", BooleanValue (true)); + } + else if (m_currentAQM == "ns3::FengAdaptiveRedQueueDisc") + { + m_queue->SetAttribute ("FengAdaptive", BooleanValue (true)); + } + else if (m_currentAQM == "ns3::NonLinearRedQueueDisc") + { + m_queue->SetAttribute ("NLRED", BooleanValue (true)); + } + } + else + { + tch.SetRootQueueDisc (queueDisc.c_str ()); + m_queue = tch.Install (m_dumbbell.GetLeft ()->GetDevice (0)).Get (0); + } + + if (queueDisc == "ns3::RedQueueDisc") + { + StaticCast (m_queue)->AssignStreams (0); + } + else if (queueDisc == "ns3::PieQueueDisc") + { + StaticCast (m_queue)->AssignStreams (0); + } + m_queue->TraceConnectWithoutContext ("Enqueue", MakeCallback (&EvaluationTopology::PacketEnqueue, this)); + m_queue->TraceConnectWithoutContext ("Dequeue", MakeCallback (&EvaluationTopology::PacketDequeue, this)); + m_queue->TraceConnectWithoutContext ("Drop", MakeCallback (&EvaluationTopology::PacketDrop, this)); + + Ipv4GlobalRoutingHelper::PopulateRoutingTables (); + m_QDrecord = 0; + m_numQDrecord = 0; + m_lastQDrecord = Time::Min (); + m_currentAQM.replace (m_currentAQM.begin (), m_currentAQM.begin () + 5, "/"); + AsciiTraceHelper asciiQD; + std::string default_directory = "aqm-eval-output/"; + std::string data = "/data"; + m_QDfile = asciiQD.CreateFileStream (std::string (default_directory + ScenarioName + data + m_currentAQM + "-qdel.dat").c_str ()); + m_TPrecord = 0; + m_lastTPrecord = Time::Min (); + AsciiTraceHelper asciiTP; + m_TPfile = asciiTP.CreateFileStream (std::string (default_directory + ScenarioName + data + m_currentAQM + "-throughput.dat").c_str ()); + AsciiTraceHelper asciiGP; + m_GPfile = asciiGP.CreateFileStream (std::string (default_directory + ScenarioName + data + m_currentAQM + "-goodput.dat").c_str ()); + AsciiTraceHelper asciiMD; + m_metaData = asciiMD.CreateFileStream (std::string (default_directory + ScenarioName + data + m_currentAQM + "-metadata.dat").c_str ()); + AsciiTraceHelper asciiDT; + m_dropTime = asciiDT.CreateFileStream (std::string (default_directory + ScenarioName + data + m_currentAQM + "-drop.dat").c_str ()); + AsciiTraceHelper asciiET; + m_enqueueTime = asciiET.CreateFileStream (std::string (default_directory + ScenarioName + data + m_currentAQM + "-enqueue.dat").c_str ()); +} + +EvaluationTopology::~EvaluationTopology (void) +{ +} + +void +EvaluationTopology::DestroyConnection () +{ + m_queue->TraceDisconnectWithoutContext ("Enqueue", MakeCallback (&EvaluationTopology::PacketEnqueue, this)); + m_queue->TraceDisconnectWithoutContext ("Dequeue", MakeCallback (&EvaluationTopology::PacketDequeue, this)); + m_queue->TraceDisconnectWithoutContext ("Drop", MakeCallback (&EvaluationTopology::PacketDrop, this)); + + for (uint32_t i = 0; i < m_sinks.size (); i++) + { + m_sinks[i]->TraceDisconnectWithoutContext ("Rx", MakeCallback (&EvaluationTopology::PayloadSize, this)); + } + for (uint32_t i = 0; i < m_sources.size (); i++) + { + *m_metaData->GetStream () << "The flow completion time of flow " << (i + 1) + << " = " + << (m_sources[i]->GetFlowCompletionTime ()).GetSeconds () + << "\n"; + } +} + +void +EvaluationTopology::PacketEnqueue (Ptr item) +{ + Ptr p = item->GetPacket (); + EvalTimestampTag tag; + p->AddPacketTag (tag); + Ptr iqdi = Ptr (dynamic_cast (PeekPointer (item))); + *m_enqueueTime->GetStream () << (iqdi->GetHeader ()).GetDestination () + << " " + << Simulator::Now ().GetSeconds () + << "\n"; +} + +void +EvaluationTopology::PacketDequeue (Ptr item) +{ + Ptr p = item->GetPacket (); + EvalTimestampTag tag; + p->RemovePacketTag (tag); + Time delta = Simulator::Now () - tag.GetTxTime (); + if (m_lastQDrecord == Time::Min () || Simulator::Now () - m_lastQDrecord > MilliSeconds (10)) + { + m_lastQDrecord = Simulator::Now (); + if (m_numQDrecord > 0) + { + *m_QDfile->GetStream () << Simulator::Now ().GetSeconds () + << " " + << (m_QDrecord * 1.0) / (m_numQDrecord * 1.0) + << "\n"; + } + m_QDrecord = 0; + m_numQDrecord = 0; + } + m_numQDrecord++; + m_QDrecord += delta.GetMilliSeconds (); +} + +void +EvaluationTopology::PacketDrop (Ptr item) +{ + Ptr iqdi = Ptr (dynamic_cast (PeekPointer (item))); + *m_dropTime->GetStream () << (iqdi->GetHeader ()).GetDestination () + << " " + << Simulator::Now ().GetSeconds () + << "\n"; +} + +void +EvaluationTopology::PayloadSize (Ptr packet, const Address & address) +{ + *m_GPfile->GetStream () << address + << " " + << Simulator::Now ().GetSeconds () + << " " + << packet->GetSize () + << "\n"; + if (m_lastTPrecord == Time::Min () || Simulator::Now () - m_lastTPrecord > MilliSeconds (10)) + { + if (m_TPrecord > 0) + { + *m_TPfile->GetStream () << Simulator::Now ().GetSeconds () + << " " + << (m_TPrecord * 1.0) / (Simulator::Now () - m_lastTPrecord).GetSeconds () + << "\n"; + } + m_lastTPrecord = Simulator::Now (); + m_TPrecord = 0; + } + m_TPrecord += packet->GetSize (); +} + +ApplicationContainer +EvaluationTopology::CreateFlow (StringValue senderDelay, StringValue receiverDelay, + StringValue senderBW, StringValue receiverBW, + std::string transport_prot, uint64_t maxPacket, + DataRate rate, uint32_t initCwnd) +{ + NS_ASSERT_MSG (m_flowsAdded < m_numFlows, "Trying to create more flows than permitted"); + m_flowsAdded++; + + char tempstr[20]; + + sprintf (tempstr, "%d", m_flowsAdded); + std::string sdelayAddress = std::string ("/ChannelList/") + tempstr + std::string ("/Delay"); + std::string rrBWAddress = std::string ("/NodeList/1/DeviceList/") + tempstr + std::string ("/DataRate"); + std::string srBWAddress = std::string ("/NodeList/0/DeviceList/") + tempstr + std::string ("/DataRate"); + + sprintf (tempstr, "%d", m_flowsAdded + 1); + std::string slBWAddress = std::string ("/NodeList/") + tempstr + std::string ("/DeviceList/0/DataRate"); + std::string socketTypeAddress = std::string ("/NodeList/") + tempstr + std::string ("/$ns3::TcpL4Protocol/SocketType"); + + sprintf (tempstr, "%d", m_numFlows + m_flowsAdded); + std::string rdelayAddress = std::string ("/ChannelList/") + tempstr + std::string ("/Delay"); + + sprintf (tempstr, "%d", m_numFlows + m_flowsAdded + 1); + std::string rlBWAddress = std::string ("/NodeList/") + tempstr + std::string ("/DeviceList/0/DataRate"); + + Config::Set (sdelayAddress.c_str (), senderDelay); + Config::Set (rdelayAddress.c_str (), receiverDelay); + Config::Set (slBWAddress.c_str (), senderBW); + Config::Set (srBWAddress.c_str (), senderBW); + Config::Set (rlBWAddress.c_str (), receiverBW); + Config::Set (rrBWAddress.c_str (), receiverBW); + + if (transport_prot == "udp") + { + uint32_t port = 50000; + AddressValue remoteAddress (InetSocketAddress (m_dumbbell.GetRightIpv4Address (m_flowsAdded - 1), port)); + ApplicationContainer sourceAndSinkApp; + PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (m_dumbbell.GetRightIpv4Address (m_flowsAdded - 1), port)); + sinkHelper.SetAttribute ("Protocol", TypeIdValue (UdpSocketFactory::GetTypeId ())); + + Ptr ns3UdpSocket = Socket::CreateSocket (m_dumbbell.GetLeft (m_flowsAdded - 1), UdpSocketFactory::GetTypeId ()); + + Ptr app = CreateObject (); + app->Setup (ns3UdpSocket, remoteAddress.Get (), m_packetSize, maxPacket * m_packetSize, m_flowsAdded * 2, rate); + m_dumbbell.GetLeft (m_flowsAdded - 1)->AddApplication (app); + + sourceAndSinkApp.Add (app); + sourceAndSinkApp.Add (sinkHelper.Install (m_dumbbell.GetRight (m_flowsAdded - 1))); + Ptr appSink = sourceAndSinkApp.Get (1); + Ptr psink = Ptr (dynamic_cast (PeekPointer (appSink))); + psink->TraceConnectWithoutContext ("Rx", MakeCallback (&EvaluationTopology::PayloadSize, this)); + return sourceAndSinkApp; + } + else if (transport_prot.compare ("ns3::TcpWestwood") == 0) + { + // the default protocol type in ns3::TcpWestwood is WESTWOOD + Config::Set (socketTypeAddress.c_str (), TypeIdValue (TcpWestwood::GetTypeId ())); + Config::Set ("ns3::TcpWestwood::FilterType", EnumValue (TcpWestwood::TUSTIN)); + } + else if (transport_prot.compare ("ns3::TcpWestwoodPlus") == 0) + { + Config::Set (socketTypeAddress.c_str (), TypeIdValue (TcpWestwood::GetTypeId ())); + Config::Set ("ns3::TcpWestwood::ProtocolType", EnumValue (TcpWestwood::WESTWOODPLUS)); + Config::Set ("ns3::TcpWestwood::FilterType", EnumValue (TcpWestwood::TUSTIN)); + } + else + { + Config::Set (socketTypeAddress.c_str (), TypeIdValue (TypeId::LookupByName (transport_prot))); + } + + uint32_t port = 50000; + AddressValue remoteAddress (InetSocketAddress (m_dumbbell.GetRightIpv4Address (m_flowsAdded - 1), port)); + ApplicationContainer sourceAndSinkApp; + PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (m_dumbbell.GetRightIpv4Address (m_flowsAdded - 1), port)); + sinkHelper.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ())); + + Ptr ns3TcpSocket = Socket::CreateSocket (m_dumbbell.GetLeft (m_flowsAdded - 1), TcpSocketFactory::GetTypeId ()); + ns3TcpSocket->SetAttribute ("InitialCwnd", UintegerValue (initCwnd)); + ns3TcpSocket->SetAttribute ("SegmentSize", UintegerValue (m_packetSize)); + + if (transport_prot.compare ("ns3::TcpNewReno") == 0) + { + ns3TcpSocket->SetAttribute ("Sack", BooleanValue (true)); + } + else + { + ns3TcpSocket->SetAttribute ("Sack", BooleanValue (false)); + } + + Ptr app = CreateObject (); + app->Setup (ns3TcpSocket, remoteAddress.Get (), m_packetSize, maxPacket * m_packetSize, m_flowsAdded * 2, rate); + m_dumbbell.GetLeft (m_flowsAdded - 1)->AddApplication (app); + + sourceAndSinkApp.Add (app); + sourceAndSinkApp.Add (sinkHelper.Install (m_dumbbell.GetRight (m_flowsAdded - 1))); + Ptr appSink = sourceAndSinkApp.Get (1); + Ptr psink = Ptr (dynamic_cast (PeekPointer (appSink))); + psink->TraceConnectWithoutContext ("Rx", MakeCallback (&EvaluationTopology::PayloadSize, this)); + m_sinks.push_back (psink); + m_sources.push_back (app); + return sourceAndSinkApp; +} + +} //namespace ns3 diff --git a/src/aqm-eval-suite/model/eval-topology.h b/src/aqm-eval-suite/model/eval-topology.h new file mode 100644 index 00000000000..119315d5efe --- /dev/null +++ b/src/aqm-eval-suite/model/eval-topology.h @@ -0,0 +1,183 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +#ifndef EVAL_TOPOLOGY_H +#define EVAL_TOPOLOGY_H + +#include +#include +#include +#include +#include +#include "ns3/log.h" +#include "ns3/simulator.h" +#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/point-to-point-layout-module.h" +#include "ns3/traffic-control-module.h" +#include "ns3/assert.h" +#include "ns3/data-rate.h" +#include "eval-app.h" + +namespace ns3 { + +/** + * \brief Configures the topology and traffic in the suite + * + * This class sets up a point-to-point dumbbell topology, installs the + * applications on nodes and fetches the performance metrics of interest + */ +class EvaluationTopology +{ + +public: + /** + * \brief Get the type ID + * + * \return the object TypeId + */ + static TypeId GetTypeId (void); + + /** + * \brief Constructor + * + * \param ScenarioName The name of the scenario + * \param numFlows The number of flows + * \param p2pHelper The configured point-to-point channel + * \param queueDisc TypeID of the AQM algorithm + * \param pktSize The size of payload + */ + EvaluationTopology (std::string ScenarioName, + uint32_t numFlows, + PointToPointHelper p2pHelper, + std::string queueDisc, + uint32_t pktSize = 512, + bool isBql = false); + + /** + * \brief Destructor + */ + ~EvaluationTopology (); + + /** + * \brief Creates a single flow + * + * \param senderDelay Link delay from sender to left router + * \param receiverDelay Link delay from receiver to right router + * \param senderBW Link bandwidth from sender to left router + * \param receiverBW Link bandwidth from receiver to right router + * \param transport_prot The transport protocol + * \param maxPacket The maximum number of packets + * \param rate The rate of sending data + * \param initCwnd The initial congestion window for TCP + */ + ApplicationContainer CreateFlow (StringValue senderDelay, + StringValue receiverDelay, + StringValue senderBW, + StringValue receiverBW, + std::string transport_prot, + uint64_t maxPacket, + DataRate rate, + uint32_t initCwnd = 3); + + /** + * \brief Disconnects the trace sources + */ + void DestroyConnection (); + + /** + * \brief Stops the flow temporarily + * + * \param flow The flow id + */ + void Pause (uint32_t flow) + { + m_sources[flow]->CancelEvents (); + } + + /** + * \brief Restarts the paused flow + * + * \param flow The flow id + */ + void Restart (uint32_t flow) + { + m_sources[flow]->ScheduleStartEvent (); + } + +private: + /** + * \brief Adds a timestamp to the enqueued queue item + * + * \param item The queue item enqueued + */ + void PacketEnqueue (Ptr item); + + /** + * \brief Removes a timestamp from the queue item being dequeued + * + * \param item The queue item being dequeued + */ + void PacketDequeue (Ptr item); + + /** + * \brief Logs the drop time of the queue item + * + * \param item The queue item being dropped + */ + void PacketDrop (Ptr item); + + /** + * \brief Calculates goodput and logs the size of data received at application + * + * \param packet The packet received at application + * \param address The address of sender + */ + void PayloadSize (Ptr packet, const Address & address); + + std::string m_currentAQM; //!< AQM being currently simulated + uint32_t m_numFlows; //!< The total number of flows + uint32_t m_flowsAdded; //!< The number of flows added till now in the simulation + PointToPointDumbbellHelper m_dumbbell; //!< Point to point dumbbell helper object + Ptr m_queue; //!< The queue discipline installed on the bottleneck link + uint32_t m_packetSize; //!< The size of payload + uint64_t m_QDrecord; //!< The sum of queue delays observed in 10ms + uint64_t m_numQDrecord; //!< The number of samples obtained in 10ms + Time m_lastQDrecord; //!< Last time the average queue delay was calculated + Ptr m_QDfile; //!< File to store queue delay values + uint64_t m_TPrecord; //!< The total amount of data received in 10ms + Time m_lastTPrecord; //!< Last time the average goodput was calculated + Ptr m_TPfile; //!< File to store goodput values + std::vector < Ptr < PacketSink >> m_sinks; //!< List of packet sinks + Ptr m_GPfile; //!< File to store per flow statistics + std::vector < Ptr < EvalApp >> m_sources; //!< List of application sources + Ptr m_metaData; //!< File to store flow completion times + Ptr m_dropTime; //!< File to store packet drop times + Ptr m_enqueueTime; //!< File to store packet enqueue times +}; + +} + +#endif /* EVAL_TOPOLOGY_H */ diff --git a/src/aqm-eval-suite/model/eval-ts.cc b/src/aqm-eval-suite/model/eval-ts.cc new file mode 100644 index 00000000000..338a8262816 --- /dev/null +++ b/src/aqm-eval-suite/model/eval-ts.cc @@ -0,0 +1,83 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +#include "eval-ts.h" + +namespace ns3 { + +EvalTimestampTag::EvalTimestampTag () + : m_creationTime (Simulator::Now ().GetTimeStep ()) +{ +} + +TypeId +EvalTimestampTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::EvalTimestampTag") + .SetParent () + .AddConstructor () + .AddAttribute ("CreationTime", + "The time at which the timestamp was created", + StringValue ("0.0s"), + MakeTimeAccessor (&EvalTimestampTag::GetTxTime), + MakeTimeChecker ()) + ; + return tid; +} + +TypeId +EvalTimestampTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +EvalTimestampTag::GetSerializedSize (void) const +{ + return 8; +} + +void +EvalTimestampTag::Serialize (TagBuffer i) const +{ + i.WriteU64 (m_creationTime); +} + +void +EvalTimestampTag::Deserialize (TagBuffer i) +{ + m_creationTime = i.ReadU64 (); +} + +void +EvalTimestampTag::Print (std::ostream &os) const +{ + os << "CreationTime=" << m_creationTime; +} + +Time +EvalTimestampTag::GetTxTime (void) const +{ + return TimeStep (m_creationTime); +} + +} //namespace ns3 diff --git a/src/aqm-eval-suite/model/eval-ts.h b/src/aqm-eval-suite/model/eval-ts.h new file mode 100644 index 00000000000..91f347bd187 --- /dev/null +++ b/src/aqm-eval-suite/model/eval-ts.h @@ -0,0 +1,72 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 NITK Surathkal + * + * 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: Ankit Deepak + * Shravya K. S. + * Mohit P. Tahiliani + */ + +#ifndef EVAL_TS_H +#define EVAL_TS_H + +#include +#include +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/internet-module.h" + +namespace ns3 { + +/** + * \brief A packet tag to get the enqueue and dequeue timestamp for each packet + */ +class EvalTimestampTag : public Tag +{ +public: + /** + * \brief Constructor + */ + EvalTimestampTag (); + + /** + * \brief Get the type ID + * \return the object TypeId + */ + static TypeId GetTypeId (void); + + + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + virtual void Print (std::ostream &os) const; + + /** + * \brief Gets the Tag creation time + * \return the time object stored in the tag + */ + Time GetTxTime (void) const; + +private: + uint64_t m_creationTime; //!< Tag creation time +}; + +} + +#endif /* EVAL_TS_H */ diff --git a/src/aqm-eval-suite/utils/delay_process.py b/src/aqm-eval-suite/utils/delay_process.py new file mode 100644 index 00000000000..683813bf42e --- /dev/null +++ b/src/aqm-eval-suite/utils/delay_process.py @@ -0,0 +1,30 @@ +import sys +import os + +scenario_name = sys.argv[1] +queuedisc_name = sys.argv[2] +file_name = 'aqm-eval-output/'+scenario_name+"/data/"+queuedisc_name+'-qdel.dat' +File = open (file_name ,"r") +lines_read = File.readlines () +lines_read.sort () +File.close () + +gnufile = 'aqm-eval-output/'+scenario_name+"/data/"+queuedisc_name+'-gnu-delay' +gnu = open(gnufile, "w") + +gnu.write("set terminal png\n") +gnu.write("set output \"aqm-eval-output/"+scenario_name+"/graph/"+queuedisc_name+"-delay.png\"\n set xlabel \"Time (Seconds)\" font \"Verdana,12\"\nset ylabel \"Delay (ms)\" font \"Verdana,12\"\nset grid\nshow grid\nset key font \"Verdana,12\"\nset yrange [0:]\n") + + +if "RttFairness" in scenario_name: + gnu.write("set xrange [:600]\n") +else: + gnu.write("set xrange [:300]\n") + +gnu.write("plot \""+file_name+"\" using 1:2 with lines title \""+queuedisc_name+"\"") + +gnu.close() +os.system("gnuplot "+gnufile) + + + diff --git a/src/aqm-eval-suite/utils/drop_process.py b/src/aqm-eval-suite/utils/drop_process.py new file mode 100644 index 00000000000..2af496a3570 --- /dev/null +++ b/src/aqm-eval-suite/utils/drop_process.py @@ -0,0 +1,79 @@ +import sys +import os +import numpy as np + +scenario_name = sys.argv[1] +queuedisc_name = sys.argv[2] +file_name = 'aqm-eval-output/'+scenario_name+"/data/"+queuedisc_name+'-drop.dat' +new_file_name = 'aqm-eval-output/'+scenario_name+"/data/new-"+queuedisc_name+'-drop.dat' +File = open (file_name ,"r") +lines_read = File.readlines () +lines_read.sort () +File.close () +i=0 +data=[] +inst_data=[] +bucket = [] +for file_iterator in lines_read: + if i == len(lines_read)-1: + break + i+=1 + if file_iterator.split(' ')[0] == lines_read[i].split(' ')[0]: + temp_string = float(file_iterator.split(' ')[1]) + data.append(temp_string) + else: + data.sort () + data_iterator=1 + + while data_iterator < len(data): + inst_data.append(data[data_iterator]-data[data_iterator-1]) + data_iterator+=1 + hist, bin_edges = np.histogram(inst_data, normed=True, bins=10000, density=True) + dx = bin_edges[1] - bin_edges[0] + Function_uno = np.cumsum(hist)*dx + Function_duo = [[0,0], [bin_edges[0], 0]] + for k in range(len(Function_uno)): + Function_duo.append([bin_edges[k+1], Function_uno[k]]) + bucket.append(Function_duo) + data=[] + +data.sort () +data_iterator = 1 +while data_iterator < len(data): + inst_data.append(data[data_iterator]-data[data_iterator-1]) + data_iterator+=1 +hist, bin_edges = np.histogram(inst_data, normed=True, bins=10000, density=True) +dx = bin_edges[1] - bin_edges[0] +Function_uno = np.cumsum(hist)*dx +Function_duo = [[0,0], [bin_edges[0], 0]] +for k in range(len(Function_uno)): + Function_duo.append([bin_edges[k+1], Function_uno[k]]) +bucket.append(Function_duo) +data=[] + +gnufile = 'aqm-eval-output/'+scenario_name+"/data/"+queuedisc_name+'-gnu-drop' +gnu = open(gnufile, "w") + +gnu.write("set terminal png size 1260, 800\n") +gnu.write("set output \"aqm-eval-output/"+scenario_name+"/graph/"+queuedisc_name+"-drop.png\"\n set xlabel \"Time difference between two drops\"\nset ylabel \"CDF\"\nset grid\nshow grid\n") + + +wfile = open (new_file_name ,"w") + +flow = 1 +for x in bucket: + wfile.write("\n\n#\"flow"+str(flow)+"\"\n") + flow+=1 + for y in x: + wfile.write (str(y[0])+" "+str(y[1])+"\n") +wfile.close() + +for data_iterator in range(len(bucket)): + if data_iterator == 0: + gnu.write("plot \""+new_file_name+"\" i "+str(data_iterator)+" using 1:2 with lines smooth csplines title \"Flow "+str(data_iterator+1)+"\"") + else: + gnu.write(", \""+new_file_name+"\" i "+str(data_iterator)+" using 1:2 with lines smooth csplines title \"Flow "+str(data_iterator+1)+"\"") + +gnu.close() +os.system("gnuplot "+gnufile) + diff --git a/src/aqm-eval-suite/utils/ellipsemaker b/src/aqm-eval-suite/utils/ellipsemaker new file mode 100644 index 00000000000..cdb364fa9fe --- /dev/null +++ b/src/aqm-eval-suite/utils/ellipsemaker @@ -0,0 +1,86 @@ +#!/usr/bin/python + +import sys; +import numpy as np + +samples = [] + +scenario_name = sys.argv[1] +queuedisc_name = sys.argv[2] +queuedisc_index = sys.argv[3] + +input_file = open("aqm-eval-output/"+scenario_name+"/data/"+queuedisc_name+"-result.dat", "r") +lines = input_file.readlines() + +output_file_name = "aqm-eval-output/"+scenario_name+"/data/"+queuedisc_name+"-ellipse.dat" +output_file = open(output_file_name, "w") + +qdisc_label = {'PfifoFast': 'DropTail', 'CoDel': 'CoDel', 'Pie': 'PIE', 'Red': 'RED', 'AdaptiveRed': 'ARED', 'FengAdaptiveRed': 'FRED', 'NonLinearRed':'NLRED'} + +for line in lines: + fields = line.split( ' ' ) + delay, throughput = (float(fields[ 0 ]))/1000.0, (float(fields[ 1 ]))/(1024.0*128.0) + samples.append( [ delay, throughput ] ) + +samples = np.matrix( samples ) + +# taken from https://github.com/joferkington/oost_paper_code/blob/master/error_ellipse.py + +def get_ellipse(points, nstd=1): + def eigsorted(cov): + vals, vecs = np.linalg.eigh(cov) + order = vals.argsort()[::-1] + return vals[order], vecs[:,order] + + cov = np.cov(points, rowvar=False) + vals, vecs = eigsorted(cov) + theta = np.degrees(np.arctan2(*vecs[:,0][::-1])) + # Width and height are "full" widths, not radius +# width, height = 2 * nstd * np.sqrt(vals) + width = nstd[0,0] * np.sqrt(vals[0]) + height = nstd[0,1] * np.sqrt(vals[1]) + return [ width, height, theta ] + +def get_ellipse_coords(a=0.0, b=0.0, x=0.0, y=0.0, angle=0.0, k=2): + """ Draws an ellipse using (360*k + 1) discrete points; based on pseudo code + given at http://en.wikipedia.org/wiki/Ellipse + k = 1 means 361 points (degree by degree) + a = major axis distance, + b = minor axis distance, + x = offset along the x-axis + y = offset along the y-axis + angle = clockwise rotation [in degrees] of the ellipse; + * angle=0 : the ellipse is aligned with the positive x-axis + * angle=30 : rotated 30 degrees clockwise from positive x-axis + """ + pts = np.zeros((360*k+1, 2)) + + beta = -angle * np.pi/180.0 + sin_beta = np.sin(beta) + cos_beta = np.cos(beta) + alpha = np.radians(np.r_[0.:360.:1j*(360*k+1)]) + sin_alpha = np.sin(alpha) + cos_alpha = np.cos(alpha) + pts[:, 0] = x + (a * cos_alpha * cos_beta - b * sin_alpha * sin_beta) + pts[:, 1] = y + (a * cos_alpha * sin_beta + b * sin_alpha * cos_beta) + + return pts + +means = np.mean( samples, axis=0 ) +center_x = means[ 0, 0 ] +center_y = means[ 0, 1 ] +width, height, theta = get_ellipse( samples, np.std( samples, axis=0 )) + +#print center_x, center_y +#print width, height, theta + +for i in get_ellipse_coords(width, height, center_x, center_y, -theta, 10 ): + output_file.write(str(i[ 0 ]*1000.0)+' '+str(i[ 1 ])+'\n') + +output_file.close() +input_file.close() + +gnu_file = open("aqm-eval-output/"+scenario_name+"/data/plot-shell", "a") +gnu_file.write ("set label \"\" at "+str(center_x*1000.0)+","+str(center_y)+" point lt "+queuedisc_index+" pt "+queuedisc_index+" center font \"Verdana\" tc lt "+queuedisc_index+" offset 1.5,0.4\n") +gnu_file.write ("set label \""+qdisc_label[queuedisc_name[:-9]]+"\" at graph "+str(1.03)+","+str(0.96 - (0.06 * (float(queuedisc_index) - 1)))+" point lt "+queuedisc_index+" pt "+queuedisc_index+" font \"Verdana,12\" tc lt "+queuedisc_index+" offset 0.7, -0.2\n") +gnu_file.close() diff --git a/src/aqm-eval-suite/utils/generate-ellipseinput.py b/src/aqm-eval-suite/utils/generate-ellipseinput.py new file mode 100644 index 00000000000..e14541dddb5 --- /dev/null +++ b/src/aqm-eval-suite/utils/generate-ellipseinput.py @@ -0,0 +1,65 @@ +import sys + +scenario_name = sys.argv[1] +queuedisc_name = sys.argv[2] +read_qdelay_file = open("aqm-eval-output/"+scenario_name+"/data/"+queuedisc_name+"-qdel.dat", "r") +read_throughput_file = open("aqm-eval-output/"+scenario_name+"/data/"+queuedisc_name+"-throughput.dat", "r") +write_file = open("aqm-eval-output/"+scenario_name+"/data/"+queuedisc_name+"-result.dat", "w") +qdelay_lines = read_qdelay_file.readlines() +throughput_lines = read_throughput_file.readlines() +last_time_interval = 0.0 +qdelay_ans = 0.0 +qdelay_count = 0 +throughput_index = 0 +throughput_val = 0 +throughput_count = 0 +for l in qdelay_lines: + s = l.split(' ') + qdelay_time = float(s[0]) + qdelay_val = float(s[1]) + curr_time_interval = ((int)(qdelay_time*10))/10.0 + if last_time_interval == curr_time_interval: + qdelay_ans += qdelay_val + qdelay_count += 1 + else: + if not qdelay_count == 0: + qdelay_ans /= qdelay_count + while throughput_index0: + inst_data.append([a[0], (goodput_val*1.0/a[0])]) + last_recorded = a[0] + if goodput_count>0: + inst_data.append([a[0], (goodput_val*1.0/a[0])]) + data = [] + File.append(inst_data) + inst_data = [] + +data.sort() +goodput_val = 0 +goodput_count = 0 +last_recorded = 0 +for a in data: + if a[0] - last_recorded < 0.1: + goodput_val += a[1] + goodput_count+=1 + else: + last_recorded = a[0] + if goodput_count>0: + inst_data.append([float("{0:.2f}".format(a[0])), (goodput_val*1.0/a[0])]) +last_recorded = a[0] +if goodput_count>0: + inst_data.append([float("{0:.2f}".format(a[0])), (goodput_val*1.0/a[0])]) +File.append(inst_data) + +st = "" + +gnufile = 'aqm-eval-output/'+scenario_name+"/data/"+queuedisc_name+'-gnu-goodput' +gnu = open(gnufile, "w") + +gnu.write("set terminal png\n") +gnu.write("set output \"aqm-eval-output/"+scenario_name+"/graph/"+queuedisc_name+"-goodput.png\"\n set xlabel \"Time (Seconds)\" font \"Verdana,12\"\nset ylabel \"Goodput (Mbps)\" font \"Verdana,12\"\nset grid\nshow grid\nset key font \"Verdana,12\"\n") + + +wfile = open (new_file_name ,"w") + +flow = 1 +for x in File: + wfile.write("\n\n#\"flow"+str(flow)+"\"\n") + flow+=1 + for y in x: + wfile.write (str(y[0])+" "+str(y[1]/(1024*128))+"\n") +wfile.close() + +if "RttFairness" in scenario_name: + for j in range(len(File)): + if j == 0: + gnu.write("plot \""+new_file_name+"\" i "+str(j)+" using 1:2 with lines smooth csplines title \"Fixed Rtt Flow\"") + else: + gnu.write(", \""+new_file_name+"\" i "+str(j)+" using 1:2 with lines smooth csplines title \"Variable Rtt Flow\"") +else: + for j in range(len(File)): + if j == 0: + gnu.write("plot \""+new_file_name+"\" i "+str(j)+" using 1:2 with lines smooth csplines title \"Flow "+str(j+1)+"\"") + else: + gnu.write(", \""+new_file_name+"\" i "+str(j)+" using 1:2 with lines smooth csplines title \"Flow "+str(j+1)+"\"") + +gnu.close() +os.system("gnuplot "+gnufile) + + + diff --git a/src/aqm-eval-suite/wscript b/src/aqm-eval-suite/wscript new file mode 100644 index 00000000000..19553015b20 --- /dev/null +++ b/src/aqm-eval-suite/wscript @@ -0,0 +1,31 @@ +# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +# def options(opt): +# pass + +# def configure(conf): +# conf.check_nonfatal(header_name='stdint.h', define_name='HAVE_STDINT_H') + +def build(bld): + module = bld.create_ns3_module('aqm-eval-suite', ['core', 'network', 'internet']) + module.source = [ + 'model/eval-topology.cc', + 'model/eval-app.cc', + 'model/eval-ts.cc', + 'helper/aqm-eval-suite-helper.cc', + ] + + headers = bld(features='ns3header') + headers.module = 'aqm-eval-suite' + headers.source = [ + 'model/eval-topology.h', + 'model/eval-app.h', + 'model/eval-ts.h', + 'helper/aqm-eval-suite-helper.h', + ] + + if bld.env.ENABLE_EXAMPLES: + bld.recurse('examples') + + # bld.ns3_python_bindings() + diff --git a/src/traffic-control/examples/red-tests.cc b/src/traffic-control/examples/red-tests.cc index 45bcc8e8990..bb69ea95046 100644 --- a/src/traffic-control/examples/red-tests.cc +++ b/src/traffic-control/examples/red-tests.cc @@ -119,7 +119,7 @@ BuildAppsTest (uint32_t test) clientHelper1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); clientHelper1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); clientHelper1.SetAttribute - ("DataRate", DataRateValue (DataRate ("10Mb/s"))); + ("DataRate", DataRateValue (DataRate ("100Mb/s"))); clientHelper1.SetAttribute ("PacketSize", UintegerValue (1000)); @@ -324,7 +324,7 @@ main (int argc, char *argv[]) Config::SetDefault ("ns3::RedQueueDisc::QW", DoubleValue (0.002)); Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (5)); Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (15)); - + if (redTest == 3) // test like 1, but with bad params { Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (10)); diff --git a/tests.txt b/tests.txt new file mode 100644 index 00000000000..dad525f6d36 --- /dev/null +++ b/tests.txt @@ -0,0 +1,7 @@ +./waf --run "aqm-eval-suite-runner --name=All" +./waf --run "aqm-eval-suite-runner --number=4.5" + +./waf --run red-tests + +graphs +TcpSocketBase