A Discrete-Event Network Simulator
API
queue-discs-benchmark.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2015 Universita' degli Studi di Napoli Federico II
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Pasquale Imputato <p.imputato@gmail.com>
19  * Stefano Avallone <stefano.avallone@unina.it>
20  */
21 
22 // This example serves as a benchmark for all the queue discs (with BQL enabled or not)
23 //
24 // Network topology
25 //
26 // 192.168.1.0 192.168.2.0
27 // n1 ------------------------------------ n2 ----------------------------------- n3
28 // point-to-point (access link) point-to-point (bottleneck link)
29 // 100 Mbps, 0.1 ms bandwidth [10 Mbps], delay [5 ms]
30 // qdiscs PfifoFast with capacity qdiscs queueDiscType in {PfifoFast, ARED, CoDel, FqCoDel, PIE} [PfifoFast]
31 // of 1000 packets with capacity of queueDiscSize packets [1000]
32 // netdevices queues with size of 100 packets netdevices queues with size of netdevicesQueueSize packets [100]
33 // without BQL bql BQL [false]
34 // *** fixed configuration ***
35 //
36 // Two TCP flows are generated: one from n1 to n3 and the other from n3 to n1.
37 // Additionally, n1 pings n3, so that the RTT can be measured.
38 //
39 // The output will consist of a number of ping Rtt such as:
40 //
41 // /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
42 // /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
43 // /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=110 ms
44 // /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
45 // /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
46 // /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=112 ms
47 // /NodeList/0/ApplicationList/2/$ns3::V4Ping/Rtt=111 ms
48 //
49 // The files output will consist of a trace file with bytes in queue and of a trace file for limits
50 // (when BQL is enabled) both for bottleneck NetDevice on n2, two files with upload and download
51 // goodput for flows configuration and a file with flow monitor stats.
52 //
53 // If you use an AQM as queue disc on the bottleneck netdevices, you can observe that the ping Rtt
54 // decrease. A further decrease can be observed when you enable BQL.
55 
56 #include "ns3/core-module.h"
57 #include "ns3/network-module.h"
58 #include "ns3/internet-module.h"
59 #include "ns3/point-to-point-module.h"
60 #include "ns3/applications-module.h"
61 #include "ns3/internet-apps-module.h"
62 #include "ns3/traffic-control-module.h"
63 #include "ns3/flow-monitor-module.h"
64 
65 using namespace ns3;
66 
67 NS_LOG_COMPONENT_DEFINE ("BenchmarkQueueDiscs");
68 
69 void
70 LimitsTrace (Ptr<OutputStreamWrapper> stream, uint32_t oldVal, uint32_t newVal)
71 {
72  *stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
73 }
74 
75 void
76 BytesInQueueTrace (Ptr<OutputStreamWrapper> stream, uint32_t oldVal, uint32_t newVal)
77 {
78  *stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
79 }
80 
81 static void
82 GoodputSampling (std::string fileName, ApplicationContainer app, Ptr<OutputStreamWrapper> stream, float period)
83 {
84  Simulator::Schedule (Seconds (period), &GoodputSampling, fileName, app, stream, period);
85  double goodput;
86  uint64_t totalPackets = DynamicCast<PacketSink> (app.Get (0))->GetTotalRx ();
87  goodput = totalPackets * 8 / (Simulator::Now ().GetSeconds () * 1024); // Kbit/s
88  *stream->GetStream () << Simulator::Now ().GetSeconds () << " " << goodput << std::endl;
89 }
90 
91 static void PingRtt (std::string context, Time rtt)
92 {
93  std::cout << context << "=" << rtt.GetMilliSeconds () << " ms" << std::endl;
94 }
95 
96 int main (int argc, char *argv[])
97 {
98  std::string bandwidth = "10Mbps";
99  std::string delay = "5ms";
100  std::string queueDiscType = "PfifoFast";
101  uint32_t queueDiscSize = 1000;
102  uint32_t netdevicesQueueSize = 50;
103  bool bql = false;
104 
105  std::string flowsDatarate = "20Mbps";
106  uint32_t flowsPacketsSize = 1000;
107 
108  float startTime = 0.1f; // in s
109  float simDuration = 60;
110  float samplingPeriod = 1;
111 
112  CommandLine cmd (__FILE__);
113  cmd.AddValue ("bandwidth", "Bottleneck bandwidth", bandwidth);
114  cmd.AddValue ("delay", "Bottleneck delay", delay);
115  cmd.AddValue ("queueDiscType", "Bottleneck queue disc type in {PfifoFast, ARED, CoDel, FqCoDel, PIE, prio}", queueDiscType);
116  cmd.AddValue ("queueDiscSize", "Bottleneck queue disc size in packets", queueDiscSize);
117  cmd.AddValue ("netdevicesQueueSize", "Bottleneck netdevices queue size in packets", netdevicesQueueSize);
118  cmd.AddValue ("bql", "Enable byte queue limits on bottleneck netdevices", bql);
119  cmd.AddValue ("flowsDatarate", "Upload and download flows datarate", flowsDatarate);
120  cmd.AddValue ("flowsPacketsSize", "Upload and download flows packets sizes", flowsPacketsSize);
121  cmd.AddValue ("startTime", "Simulation start time", startTime);
122  cmd.AddValue ("simDuration", "Simulation duration in seconds", simDuration);
123  cmd.AddValue ("samplingPeriod", "Goodput sampling period in seconds", samplingPeriod);
124  cmd.Parse (argc, argv);
125 
126  float stopTime = startTime + simDuration;
127 
128  // Create nodes
129  NodeContainer n1, n2, n3;
130  n1.Create (1);
131  n2.Create (1);
132  n3.Create (1);
133 
134  // Create and configure access link and bottleneck link
135  PointToPointHelper accessLink;
136  accessLink.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
137  accessLink.SetChannelAttribute ("Delay", StringValue ("0.1ms"));
138  accessLink.SetQueue ("ns3::DropTailQueue", "MaxSize", StringValue ("100p"));
139 
140  PointToPointHelper bottleneckLink;
141  bottleneckLink.SetDeviceAttribute ("DataRate", StringValue (bandwidth));
142  bottleneckLink.SetChannelAttribute ("Delay", StringValue (delay));
143  bottleneckLink.SetQueue ("ns3::DropTailQueue", "MaxSize", StringValue (std::to_string (netdevicesQueueSize) + "p"));
144 
146  stack.InstallAll ();
147 
148  // Access link traffic control configuration
149  TrafficControlHelper tchPfifoFastAccess;
150  tchPfifoFastAccess.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "MaxSize", StringValue ("1000p"));
151 
152  // Bottleneck link traffic control configuration
153  TrafficControlHelper tchBottleneck;
154 
155  if (queueDiscType.compare ("PfifoFast") == 0)
156  {
157  tchBottleneck.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "MaxSize",
158  QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, queueDiscSize)));
159  }
160  else if (queueDiscType.compare ("ARED") == 0)
161  {
162  tchBottleneck.SetRootQueueDisc ("ns3::RedQueueDisc");
163  Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
164  Config::SetDefault ("ns3::RedQueueDisc::MaxSize",
165  QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, queueDiscSize)));
166  }
167  else if (queueDiscType.compare ("CoDel") == 0)
168  {
169  tchBottleneck.SetRootQueueDisc ("ns3::CoDelQueueDisc");
170  Config::SetDefault ("ns3::CoDelQueueDisc::MaxSize",
171  QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, queueDiscSize)));
172  }
173  else if (queueDiscType.compare ("FqCoDel") == 0)
174  {
175  tchBottleneck.SetRootQueueDisc ("ns3::FqCoDelQueueDisc");
176  Config::SetDefault ("ns3::FqCoDelQueueDisc::MaxSize",
177  QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, queueDiscSize)));
178  }
179  else if (queueDiscType.compare ("PIE") == 0)
180  {
181  tchBottleneck.SetRootQueueDisc ("ns3::PieQueueDisc");
182  Config::SetDefault ("ns3::PieQueueDisc::MaxSize",
183  QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, queueDiscSize)));
184  }
185  else if (queueDiscType.compare ("prio") == 0)
186  {
187  uint16_t handle = tchBottleneck.SetRootQueueDisc ("ns3::PrioQueueDisc", "Priomap",
188  StringValue ("0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1"));
189  TrafficControlHelper::ClassIdList cid = tchBottleneck.AddQueueDiscClasses (handle, 2, "ns3::QueueDiscClass");
190  tchBottleneck.AddChildQueueDisc (handle, cid[0], "ns3::FifoQueueDisc");
191  tchBottleneck.AddChildQueueDisc (handle, cid[1], "ns3::RedQueueDisc");
192  }
193  else
194  {
195  NS_ABORT_MSG ("--queueDiscType not valid");
196  }
197 
198  if (bql)
199  {
200  tchBottleneck.SetQueueLimits ("ns3::DynamicQueueLimits");
201  }
202 
203  NetDeviceContainer devicesAccessLink = accessLink.Install (n1.Get (0), n2.Get (0));
204  tchPfifoFastAccess.Install (devicesAccessLink);
206  address.SetBase ("192.168.0.0", "255.255.255.0");
207  address.NewNetwork ();
208  Ipv4InterfaceContainer interfacesAccess = address.Assign (devicesAccessLink);
209 
210  NetDeviceContainer devicesBottleneckLink = bottleneckLink.Install (n2.Get (0), n3.Get (0));
211  QueueDiscContainer qdiscs;
212  qdiscs = tchBottleneck.Install (devicesBottleneckLink);
213 
214  address.NewNetwork ();
215  Ipv4InterfaceContainer interfacesBottleneck = address.Assign (devicesBottleneckLink);
216 
217  Ptr<NetDeviceQueueInterface> interface = devicesBottleneckLink.Get (0)->GetObject<NetDeviceQueueInterface> ();
218  Ptr<NetDeviceQueue> queueInterface = interface->GetTxQueue (0);
219  Ptr<DynamicQueueLimits> queueLimits = StaticCast<DynamicQueueLimits> (queueInterface->GetQueueLimits ());
220 
221  AsciiTraceHelper ascii;
222  if (bql)
223  {
224  queueDiscType = queueDiscType + "-bql";
225  Ptr<OutputStreamWrapper> streamLimits = ascii.CreateFileStream (queueDiscType + "-limits.txt");
226  queueLimits->TraceConnectWithoutContext ("Limit",MakeBoundCallback (&LimitsTrace, streamLimits));
227  }
228  Ptr<Queue<Packet> > queue = StaticCast<PointToPointNetDevice> (devicesBottleneckLink.Get (0))->GetQueue ();
229  Ptr<OutputStreamWrapper> streamBytesInQueue = ascii.CreateFileStream (queueDiscType + "-bytesInQueue.txt");
230  queue->TraceConnectWithoutContext ("BytesInQueue",MakeBoundCallback (&BytesInQueueTrace, streamBytesInQueue));
231 
232  Ipv4InterfaceContainer n1Interface;
233  n1Interface.Add (interfacesAccess.Get (0));
234 
235  Ipv4InterfaceContainer n3Interface;
236  n3Interface.Add (interfacesBottleneck.Get (1));
237 
239 
240  Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (flowsPacketsSize));
241 
242  // Flows configuration
243  // Bidirectional TCP streams with ping like flent tcp_bidirectional test.
244  uint16_t port = 7;
245  ApplicationContainer uploadApp, downloadApp, sourceApps;
246  // Configure and install upload flow
248  PacketSinkHelper sinkHelperUp ("ns3::TcpSocketFactory", addUp);
249  sinkHelperUp.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
250  uploadApp.Add (sinkHelperUp.Install (n3));
251 
252  InetSocketAddress socketAddressUp = InetSocketAddress (n3Interface.GetAddress (0), port);
253  OnOffHelper onOffHelperUp ("ns3::TcpSocketFactory", Address ());
254  onOffHelperUp.SetAttribute ("Remote", AddressValue (socketAddressUp));
255  onOffHelperUp.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
256  onOffHelperUp.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
257  onOffHelperUp.SetAttribute ("PacketSize", UintegerValue (flowsPacketsSize));
258  onOffHelperUp.SetAttribute ("DataRate", StringValue (flowsDatarate));
259  sourceApps.Add (onOffHelperUp.Install (n1));
260 
261  port = 8;
262  // Configure and install download flow
264  PacketSinkHelper sinkHelperDown ("ns3::TcpSocketFactory", addDown);
265  sinkHelperDown.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
266  downloadApp.Add (sinkHelperDown.Install (n1));
267 
268  InetSocketAddress socketAddressDown = InetSocketAddress (n1Interface.GetAddress (0), port);
269  OnOffHelper onOffHelperDown ("ns3::TcpSocketFactory", Address ());
270  onOffHelperDown.SetAttribute ("Remote", AddressValue (socketAddressDown));
271  onOffHelperDown.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
272  onOffHelperDown.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
273  onOffHelperDown.SetAttribute ("PacketSize", UintegerValue (flowsPacketsSize));
274  onOffHelperDown.SetAttribute ("DataRate", StringValue (flowsDatarate));
275  sourceApps.Add (onOffHelperDown.Install (n3));
276 
277  // Configure and install ping
278  V4PingHelper ping = V4PingHelper (n3Interface.GetAddress (0));
279  ping.Install (n1);
280 
281  Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt", MakeCallback (&PingRtt));
282 
283  uploadApp.Start (Seconds (0));
284  uploadApp.Stop (Seconds (stopTime));
285  downloadApp.Start (Seconds (0));
286  downloadApp.Stop (Seconds (stopTime));
287 
288  sourceApps.Start (Seconds (0 + 0.1));
289  sourceApps.Stop (Seconds (stopTime - 0.1));
290 
291  Ptr<OutputStreamWrapper> uploadGoodputStream = ascii.CreateFileStream (queueDiscType + "-upGoodput.txt");
292  Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, queueDiscType + "-upGoodput.txt", uploadApp,
293  uploadGoodputStream, samplingPeriod);
294  Ptr<OutputStreamWrapper> downloadGoodputStream = ascii.CreateFileStream (queueDiscType + "-downGoodput.txt");
295  Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, queueDiscType + "-downGoodput.txt", downloadApp,
296  downloadGoodputStream, samplingPeriod);
297 
298  // Flow monitor
299  Ptr<FlowMonitor> flowMonitor;
300  FlowMonitorHelper flowHelper;
301  flowMonitor = flowHelper.InstallAll();
302 
304  Simulator::Run ();
305 
306  flowMonitor->SerializeToXmlFile(queueDiscType + "-flowMonitor.xml", true, true);
307 
309  return 0;
310 }
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Address.
Definition: address.h:278
holds a vector of ns3::Application pointers.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
void Start(Time start)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter.
void Add(ApplicationContainer other)
Append the contents of another ApplicationContainer to the end of this container.
void Stop(Time stop)
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
Manage ASCII trace files for device models.
Definition: trace-helper.h:163
Ptr< OutputStreamWrapper > CreateFileStream(std::string filename, std::ios::openmode filemode=std::ios::out)
Create and initialize an output stream object we'll use to write the traced bits.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Parse command-line arguments.
Definition: command-line.h:229
Helper to enable IP flow monitoring on a set of Nodes.
Ptr< FlowMonitor > InstallAll()
Enable flow monitoring on all nodes.
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
static Ipv4Address GetAny(void)
static void PopulateRoutingTables(void)
Build a routing database and initialize the routing tables of the nodes in the simulation.
holds a vector of std::pair of Ptr<Ipv4> and interface index.
std::pair< Ptr< Ipv4 >, uint32_t > Get(uint32_t i) const
Get the std::pair of an Ptr<Ipv4> and interface stored at the location specified by the index.
void Add(const Ipv4InterfaceContainer &other)
Concatenate the entries in the other container with ours.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
Network device transmission queue interface.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
A helper to make it easier to instantiate an ns3::OnOffApplication on a set of nodes.
Definition: on-off-helper.h:43
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
Build a set of PointToPointNetDevice objects.
void SetDeviceAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each NetDevice created by the helper.
void SetQueue(std::string type, std::string n1="", const AttributeValue &v1=EmptyAttributeValue(), std::string n2="", const AttributeValue &v2=EmptyAttributeValue(), std::string n3="", const AttributeValue &v3=EmptyAttributeValue(), std::string n4="", const AttributeValue &v4=EmptyAttributeValue())
Each point to point net device must have a queue to pass packets through.
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
NetDeviceContainer Install(NodeContainer c)
Holds a vector of ns3::QueueDisc pointers.
Class for representing queue sizes.
Definition: queue-size.h:95
AttributeValue implementation for QueueSize.
Definition: queue-size.h:221
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Hold variables of type string.
Definition: string.h:41
static TypeId GetTypeId(void)
Get the type ID.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:383
Build a set of QueueDisc objects.
QueueDiscContainer Install(NetDeviceContainer c)
uint16_t SetRootQueueDisc(const std::string &type, Args &&... args)
Helper function used to set a root queue disc of the given type and with the given attributes.
void SetQueueLimits(std::string type, Args &&... args)
Helper function used to add a queue limits object to the transmission queues of the devices.
std::vector< uint16_t > ClassIdList
Container type for Class IDs.
ClassIdList AddQueueDiscClasses(uint16_t handle, uint16_t count, const std::string &type, Args &&... args)
Helper function used to add the given number of queue disc classes (of the given type and with the gi...
uint16_t AddChildQueueDisc(uint16_t handle, uint16_t classId, const std::string &type, Args &&... args)
Helper function used to attach a child queue disc (of the given type and with the given attributes) t...
AttributeValue implementation for TypeId.
Definition: type-id.h:595
Hold an unsigned integer type.
Definition: uinteger.h:44
Create a IPv4 ping application and associate it to a node.
Definition: v4ping-helper.h:38
ApplicationContainer Install(NodeContainer nodes) const
Install a Ping application on each Node in the provided NodeContainer.
uint16_t port
Definition: dsdv-manet.cc:45
Time stopTime
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:920
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1709
@ PACKETS
Use number of packets for queue size.
Definition: queue-size.h:44
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
address
Definition: first.py:44
stack
Definition: first.py:41
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25255
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
cmd
Definition: second.py:35
void BytesInQueueTrace(Ptr< OutputStreamWrapper > stream, uint32_t oldVal, uint32_t newVal)
static void PingRtt(std::string context, Time rtt)
void LimitsTrace(Ptr< OutputStreamWrapper > stream, uint32_t oldVal, uint32_t newVal)
static void GoodputSampling(std::string fileName, ApplicationContainer app, Ptr< OutputStreamWrapper > stream, float period)
double startTime