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
65using namespace ns3;
66
67NS_LOG_COMPONENT_DEFINE ("BenchmarkQueueDiscs");
68
69void
71{
72 *stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
73}
74
75void
77{
78 *stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
79}
80
81static void
82GoodputSampling (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
91static void PingRtt (std::string context, Time rtt)
92{
93 std::cout << context << "=" << rtt.GetMilliSeconds () << " ms" << std::endl;
94}
95
96int 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",
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",
166 }
167 else if (queueDiscType.compare ("CoDel") == 0)
168 {
169 tchBottleneck.SetRootQueueDisc ("ns3::CoDelQueueDisc");
170 Config::SetDefault ("ns3::CoDelQueueDisc::MaxSize",
172 }
173 else if (queueDiscType.compare ("FqCoDel") == 0)
174 {
175 tchBottleneck.SetRootQueueDisc ("ns3::FqCoDelQueueDisc");
176 Config::SetDefault ("ns3::FqCoDelQueueDisc::MaxSize",
178 }
179 else if (queueDiscType.compare ("PIE") == 0)
180 {
181 tchBottleneck.SetRootQueueDisc ("ns3::PieQueueDisc");
182 Config::SetDefault ("ns3::PieQueueDisc::MaxSize",
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
238 Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
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
247 Address addUp (InetSocketAddress (Ipv4Address::GetAny (), port));
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
263 Address addDown (InetSocketAddress (Ipv4Address::GetAny (), port));
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
303 Simulator::Stop (Seconds (stopTime));
304 Simulator::Run ();
305
306 flowMonitor->SerializeToXmlFile(queueDiscType + "-flowMonitor.xml", true, true);
307
308 Simulator::Destroy ();
309 return 0;
310}
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Address.
holds a vector of ns3::Application pointers.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
void Start(Time start)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter.
void 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.
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.
Hold variables of type string.
Definition: string.h:41
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 Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
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
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)