A Discrete-Event Network Simulator
API
queue-discs-benchmark.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 Universita' degli Studi di Napoli Federico II
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Authors: Pasquale Imputato <p.imputato@gmail.com>
18 * Stefano Avallone <stefano.avallone@unina.it>
19 */
20
21// This example serves as a benchmark for all the queue discs (with BQL enabled or not)
22//
23// Network topology
24//
25// 192.168.1.0 192.168.2.0
26// n1 ------------------------------------ n2 ----------------------------------- n3
27// point-to-point (access link) point-to-point (bottleneck link)
28// 100 Mbps, 0.1 ms bandwidth [10 Mbps], delay [5 ms]
29// qdiscs PfifoFast with capacity qdiscs queueDiscType in {PfifoFast, ARED, CoDel,
30// FqCoDel, PIE} [PfifoFast] of 1000 packets with capacity of
31// queueDiscSize packets [1000] netdevices queues with size of 100 packets netdevices queues with
32// size of netdevicesQueueSize packets [100] without BQL bql BQL
33// [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/applications-module.h"
57#include "ns3/core-module.h"
58#include "ns3/flow-monitor-module.h"
59#include "ns3/internet-apps-module.h"
60#include "ns3/internet-module.h"
61#include "ns3/network-module.h"
62#include "ns3/point-to-point-module.h"
63#include "ns3/traffic-control-module.h"
64
65using namespace ns3;
66
67NS_LOG_COMPONENT_DEFINE("BenchmarkQueueDiscs");
68
76void
78{
79 *stream->GetStream() << Simulator::Now().GetSeconds() << " " << newVal << std::endl;
80}
81
89void
91{
92 *stream->GetStream() << Simulator::Now().GetSeconds() << " " << newVal << std::endl;
93}
94
102static void
104{
105 Simulator::Schedule(Seconds(period), &GoodputSampling, app, stream, period);
106 double goodput;
107 uint64_t totalPackets = DynamicCast<PacketSink>(app.Get(0))->GetTotalRx();
108 goodput = totalPackets * 8 / (Simulator::Now().GetSeconds() * 1024); // Kbit/s
109 *stream->GetStream() << Simulator::Now().GetSeconds() << " " << goodput << std::endl;
110}
111
118static void
119PingRtt(std::string context, Time rtt)
120{
121 std::cout << context << "=" << rtt.GetMilliSeconds() << " ms" << std::endl;
122}
123
124int
125main(int argc, char* argv[])
126{
127 std::string bandwidth = "10Mbps";
128 std::string delay = "5ms";
129 std::string queueDiscType = "PfifoFast";
130 uint32_t queueDiscSize = 1000;
131 uint32_t netdevicesQueueSize = 50;
132 bool bql = false;
133
134 std::string flowsDatarate = "20Mbps";
135 uint32_t flowsPacketsSize = 1000;
136
137 float startTime = 0.1F; // in s
138 float simDuration = 60;
139 float samplingPeriod = 1;
140
141 CommandLine cmd(__FILE__);
142 cmd.AddValue("bandwidth", "Bottleneck bandwidth", bandwidth);
143 cmd.AddValue("delay", "Bottleneck delay", delay);
144 cmd.AddValue("queueDiscType",
145 "Bottleneck queue disc type in {PfifoFast, ARED, CoDel, FqCoDel, PIE, prio}",
146 queueDiscType);
147 cmd.AddValue("queueDiscSize", "Bottleneck queue disc size in packets", queueDiscSize);
148 cmd.AddValue("netdevicesQueueSize",
149 "Bottleneck netdevices queue size in packets",
150 netdevicesQueueSize);
151 cmd.AddValue("bql", "Enable byte queue limits on bottleneck netdevices", bql);
152 cmd.AddValue("flowsDatarate", "Upload and download flows datarate", flowsDatarate);
153 cmd.AddValue("flowsPacketsSize", "Upload and download flows packets sizes", flowsPacketsSize);
154 cmd.AddValue("startTime", "Simulation start time", startTime);
155 cmd.AddValue("simDuration", "Simulation duration in seconds", simDuration);
156 cmd.AddValue("samplingPeriod", "Goodput sampling period in seconds", samplingPeriod);
157 cmd.Parse(argc, argv);
158
159 float stopTime = startTime + simDuration;
160
161 // Create nodes
162 NodeContainer n1;
163 NodeContainer n2;
164 NodeContainer n3;
165 n1.Create(1);
166 n2.Create(1);
167 n3.Create(1);
168
169 // Create and configure access link and bottleneck link
170 PointToPointHelper accessLink;
171 accessLink.SetDeviceAttribute("DataRate", StringValue("100Mbps"));
172 accessLink.SetChannelAttribute("Delay", StringValue("0.1ms"));
173 accessLink.SetQueue("ns3::DropTailQueue", "MaxSize", StringValue("100p"));
174
175 PointToPointHelper bottleneckLink;
176 bottleneckLink.SetDeviceAttribute("DataRate", StringValue(bandwidth));
177 bottleneckLink.SetChannelAttribute("Delay", StringValue(delay));
178 bottleneckLink.SetQueue("ns3::DropTailQueue",
179 "MaxSize",
180 StringValue(std::to_string(netdevicesQueueSize) + "p"));
181
183 stack.InstallAll();
184
185 // Access link traffic control configuration
186 TrafficControlHelper tchPfifoFastAccess;
187 tchPfifoFastAccess.SetRootQueueDisc("ns3::PfifoFastQueueDisc", "MaxSize", StringValue("1000p"));
188
189 // Bottleneck link traffic control configuration
190 TrafficControlHelper tchBottleneck;
191
192 if (queueDiscType == "PfifoFast")
193 {
194 tchBottleneck.SetRootQueueDisc(
195 "ns3::PfifoFastQueueDisc",
196 "MaxSize",
198 }
199 else if (queueDiscType == "ARED")
200 {
201 tchBottleneck.SetRootQueueDisc("ns3::RedQueueDisc");
202 Config::SetDefault("ns3::RedQueueDisc::ARED", BooleanValue(true));
203 Config::SetDefault("ns3::RedQueueDisc::MaxSize",
205 }
206 else if (queueDiscType == "CoDel")
207 {
208 tchBottleneck.SetRootQueueDisc("ns3::CoDelQueueDisc");
209 Config::SetDefault("ns3::CoDelQueueDisc::MaxSize",
211 }
212 else if (queueDiscType == "FqCoDel")
213 {
214 tchBottleneck.SetRootQueueDisc("ns3::FqCoDelQueueDisc");
215 Config::SetDefault("ns3::FqCoDelQueueDisc::MaxSize",
217 }
218 else if (queueDiscType == "PIE")
219 {
220 tchBottleneck.SetRootQueueDisc("ns3::PieQueueDisc");
221 Config::SetDefault("ns3::PieQueueDisc::MaxSize",
223 }
224 else if (queueDiscType == "prio")
225 {
226 uint16_t handle =
227 tchBottleneck.SetRootQueueDisc("ns3::PrioQueueDisc",
228 "Priomap",
229 StringValue("0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1"));
231 tchBottleneck.AddQueueDiscClasses(handle, 2, "ns3::QueueDiscClass");
232 tchBottleneck.AddChildQueueDisc(handle, cid[0], "ns3::FifoQueueDisc");
233 tchBottleneck.AddChildQueueDisc(handle, cid[1], "ns3::RedQueueDisc");
234 }
235 else
236 {
237 NS_ABORT_MSG("--queueDiscType not valid");
238 }
239
240 if (bql)
241 {
242 tchBottleneck.SetQueueLimits("ns3::DynamicQueueLimits");
243 }
244
245 NetDeviceContainer devicesAccessLink = accessLink.Install(n1.Get(0), n2.Get(0));
246 tchPfifoFastAccess.Install(devicesAccessLink);
248 address.SetBase("192.168.0.0", "255.255.255.0");
249 address.NewNetwork();
250 Ipv4InterfaceContainer interfacesAccess = address.Assign(devicesAccessLink);
251
252 NetDeviceContainer devicesBottleneckLink = bottleneckLink.Install(n2.Get(0), n3.Get(0));
253 QueueDiscContainer qdiscs;
254 qdiscs = tchBottleneck.Install(devicesBottleneckLink);
255
256 address.NewNetwork();
257 Ipv4InterfaceContainer interfacesBottleneck = address.Assign(devicesBottleneckLink);
258
260 devicesBottleneckLink.Get(0)->GetObject<NetDeviceQueueInterface>();
261 Ptr<NetDeviceQueue> queueInterface = interface->GetTxQueue(0);
262 Ptr<DynamicQueueLimits> queueLimits =
263 StaticCast<DynamicQueueLimits>(queueInterface->GetQueueLimits());
264
265 AsciiTraceHelper ascii;
266 if (bql)
267 {
268 queueDiscType = queueDiscType + "-bql";
269 Ptr<OutputStreamWrapper> streamLimits =
270 ascii.CreateFileStream(queueDiscType + "-limits.txt");
271 queueLimits->TraceConnectWithoutContext("Limit",
272 MakeBoundCallback(&LimitsTrace, streamLimits));
273 }
274 Ptr<Queue<Packet>> queue =
275 StaticCast<PointToPointNetDevice>(devicesBottleneckLink.Get(0))->GetQueue();
276 Ptr<OutputStreamWrapper> streamBytesInQueue =
277 ascii.CreateFileStream(queueDiscType + "-bytesInQueue.txt");
278 queue->TraceConnectWithoutContext("BytesInQueue",
279 MakeBoundCallback(&BytesInQueueTrace, streamBytesInQueue));
280
281 Ipv4InterfaceContainer n1Interface;
282 n1Interface.Add(interfacesAccess.Get(0));
283
284 Ipv4InterfaceContainer n3Interface;
285 n3Interface.Add(interfacesBottleneck.Get(1));
286
287 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
288
289 Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(flowsPacketsSize));
290
291 // Flows configuration
292 // Bidirectional TCP streams with ping like flent tcp_bidirectional test.
293 uint16_t port = 7;
294 ApplicationContainer uploadApp;
295 ApplicationContainer downloadApp;
296 ApplicationContainer sourceApps;
297 // Configure and install upload flow
298 Address addUp(InetSocketAddress(Ipv4Address::GetAny(), port));
299 PacketSinkHelper sinkHelperUp("ns3::TcpSocketFactory", addUp);
300 sinkHelperUp.SetAttribute("Protocol", TypeIdValue(TcpSocketFactory::GetTypeId()));
301 uploadApp.Add(sinkHelperUp.Install(n3));
302
303 InetSocketAddress socketAddressUp = InetSocketAddress(n3Interface.GetAddress(0), port);
304 OnOffHelper onOffHelperUp("ns3::TcpSocketFactory", Address());
305 onOffHelperUp.SetAttribute("Remote", AddressValue(socketAddressUp));
306 onOffHelperUp.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
307 onOffHelperUp.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
308 onOffHelperUp.SetAttribute("PacketSize", UintegerValue(flowsPacketsSize));
309 onOffHelperUp.SetAttribute("DataRate", StringValue(flowsDatarate));
310 sourceApps.Add(onOffHelperUp.Install(n1));
311
312 port = 8;
313 // Configure and install download flow
314 Address addDown(InetSocketAddress(Ipv4Address::GetAny(), port));
315 PacketSinkHelper sinkHelperDown("ns3::TcpSocketFactory", addDown);
316 sinkHelperDown.SetAttribute("Protocol", TypeIdValue(TcpSocketFactory::GetTypeId()));
317 downloadApp.Add(sinkHelperDown.Install(n1));
318
319 InetSocketAddress socketAddressDown = InetSocketAddress(n1Interface.GetAddress(0), port);
320 OnOffHelper onOffHelperDown("ns3::TcpSocketFactory", Address());
321 onOffHelperDown.SetAttribute("Remote", AddressValue(socketAddressDown));
322 onOffHelperDown.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
323 onOffHelperDown.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
324 onOffHelperDown.SetAttribute("PacketSize", UintegerValue(flowsPacketsSize));
325 onOffHelperDown.SetAttribute("DataRate", StringValue(flowsDatarate));
326 sourceApps.Add(onOffHelperDown.Install(n3));
327
328 // Configure and install ping
329 V4PingHelper ping = V4PingHelper(n3Interface.GetAddress(0));
330 ping.Install(n1);
331
332 Config::Connect("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt", MakeCallback(&PingRtt));
333
334 uploadApp.Start(Seconds(0));
335 uploadApp.Stop(Seconds(stopTime));
336 downloadApp.Start(Seconds(0));
337 downloadApp.Stop(Seconds(stopTime));
338
339 sourceApps.Start(Seconds(0 + 0.1));
340 sourceApps.Stop(Seconds(stopTime - 0.1));
341
342 Ptr<OutputStreamWrapper> uploadGoodputStream =
343 ascii.CreateFileStream(queueDiscType + "-upGoodput.txt");
344 Simulator::Schedule(Seconds(samplingPeriod),
346 uploadApp,
347 uploadGoodputStream,
348 samplingPeriod);
349 Ptr<OutputStreamWrapper> downloadGoodputStream =
350 ascii.CreateFileStream(queueDiscType + "-downGoodput.txt");
351 Simulator::Schedule(Seconds(samplingPeriod),
353 downloadApp,
354 downloadGoodputStream,
355 samplingPeriod);
356
357 // Flow monitor
358 Ptr<FlowMonitor> flowMonitor;
359 FlowMonitorHelper flowHelper;
360 flowMonitor = flowHelper.InstallAll();
361
362 Simulator::Stop(Seconds(stopTime));
363 Simulator::Run();
364
365 flowMonitor->SerializeToXmlFile(queueDiscType + "-flowMonitor.xml", true, true);
366
367 Simulator::Destroy();
368 return 0;
369}
a polymophic address class
Definition: address.h:92
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:173
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:232
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:44
std::ostream * GetStream()
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 SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
void SetQueue(std::string type, Ts &&... args)
Each point to point net device must have a queue to pass packets through.
NetDeviceContainer Install(NodeContainer c)
Holds a vector of ns3::QueueDisc pointers.
Class for representing queue sizes.
Definition: queue-size.h:96
AttributeValue implementation for QueueSize.
Hold variables of type string.
Definition: string.h:42
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:407
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:402
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:600
Hold an unsigned integer type.
Definition: uinteger.h:45
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:891
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:975
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:752
@ PACKETS
Use number of packets for queue size.
Definition: queue-size.h:45
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
address
Definition: first.py:40
stack
Definition: first.py:37
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:691
cmd
Definition: second.py:33
void BytesInQueueTrace(Ptr< OutputStreamWrapper > stream, uint32_t oldVal, uint32_t newVal)
Print the bytes in the queue.
static void PingRtt(std::string context, Time rtt)
Print the ping RTT.
static void GoodputSampling(ApplicationContainer app, Ptr< OutputStreamWrapper > stream, float period)
Sample and print the queue goodput.
void LimitsTrace(Ptr< OutputStreamWrapper > stream, uint32_t oldVal, uint32_t newVal)
Print the queue limitis.