A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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::Ping/Rtt=111 ms
42// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=111 ms
43// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=110 ms
44// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=111 ms
45// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=111 ms
46// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=112 ms
47// /NodeList/0/ApplicationList/2/$ns3::Ping/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
69/**
70 * Print the queue limits.
71 *
72 * \param stream The output stream.
73 * \param oldVal Old value.
74 * \param newVal New value.
75 */
76void
78{
79 *stream->GetStream() << Simulator::Now().GetSeconds() << " " << newVal << std::endl;
80}
81
82/**
83 * Print the bytes in the queue.
84 *
85 * \param stream The output stream.
86 * \param oldVal Old value.
87 * \param newVal New value.
88 */
89void
91{
92 *stream->GetStream() << Simulator::Now().GetSeconds() << " " << newVal << std::endl;
93}
94
95/**
96 * Sample and print the queue goodput.
97 *
98 * \param app The Tx app.
99 * \param stream The output stream.
100 * \param period The sampling period.
101 */
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
112/**
113 * Print the ping RTT.
114 *
115 * \param context The context.
116 * \param rtt The RTT.
117 */
118static void
119PingRtt(std::string context, uint16_t, 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",
197 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
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",
204 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
205 }
206 else if (queueDiscType == "CoDel")
207 {
208 tchBottleneck.SetRootQueueDisc("ns3::CoDelQueueDisc");
209 Config::SetDefault("ns3::CoDelQueueDisc::MaxSize",
210 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
211 }
212 else if (queueDiscType == "FqCoDel")
213 {
214 tchBottleneck.SetRootQueueDisc("ns3::FqCoDelQueueDisc");
215 Config::SetDefault("ns3::FqCoDelQueueDisc::MaxSize",
216 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
217 }
218 else if (queueDiscType == "PIE")
219 {
220 tchBottleneck.SetRootQueueDisc("ns3::PieQueueDisc");
221 Config::SetDefault("ns3::PieQueueDisc::MaxSize",
222 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
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
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
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
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 PingHelper ping(n3Interface.GetAddress(0));
330 ping.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::QUIET));
331 ping.Install(n1);
332
333 Config::Connect("/NodeList/*/ApplicationList/*/$ns3::Ping/Rtt", MakeCallback(&PingRtt));
334
335 uploadApp.Start(Seconds(0));
336 uploadApp.Stop(Seconds(stopTime));
337 downloadApp.Start(Seconds(0));
338 downloadApp.Stop(Seconds(stopTime));
339
340 sourceApps.Start(Seconds(0 + 0.1));
341 sourceApps.Stop(Seconds(stopTime - 0.1));
342
343 Ptr<OutputStreamWrapper> uploadGoodputStream =
344 ascii.CreateFileStream(queueDiscType + "-upGoodput.txt");
345 Simulator::Schedule(Seconds(samplingPeriod),
347 uploadApp,
348 uploadGoodputStream,
349 samplingPeriod);
350 Ptr<OutputStreamWrapper> downloadGoodputStream =
351 ascii.CreateFileStream(queueDiscType + "-downGoodput.txt");
352 Simulator::Schedule(Seconds(samplingPeriod),
354 downloadApp,
355 downloadGoodputStream,
356 samplingPeriod);
357
358 // Flow monitor
359 Ptr<FlowMonitor> flowMonitor;
360 FlowMonitorHelper flowHelper;
361 flowMonitor = flowHelper.InstallAll();
362
363 accessLink.EnablePcapAll("queue");
364
367
368 flowMonitor->SerializeToXmlFile(queueDiscType + "-flowMonitor.xml", true, true);
369
371 return 0;
372}
a polymophic address class
Definition: address.h:101
AttributeValue implementation for Address.
Definition: address.h:286
holds a vector of ns3::Application pointers.
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
void Stop(Time stop) const
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
void Add(ApplicationContainer other)
Append the contents of another ApplicationContainer to the end of this container.
Manage ASCII trace files for device models.
Definition: trace-helper.h:174
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
Hold variables of type enum.
Definition: enum.h:62
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()
static void PopulateRoutingTables()
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:37
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
void EnablePcapAll(std::string prefix, bool promiscuous=false)
Enable pcap output on each device (which is of the appropriate type) in the set of all nodes created ...
Create a ping application and associate it to a node.
Definition: ping-helper.h:42
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)
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Holds a vector of ns3::QueueDisc pointers.
Class for representing queue sizes.
Definition: queue-size.h:96
AttributeValue implementation for QueueSize.
Definition: queue-size.h:221
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static void Run()
Run the simulation.
Definition: simulator.cc:178
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
Hold variables of type string.
Definition: string.h:56
static TypeId GetTypeId()
Get the type ID.
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:408
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
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:598
Hold an unsigned integer type.
Definition: uinteger.h:45
uint16_t port
Definition: dsdv-manet.cc:44
Time stopTime
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:894
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:978
#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:765
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
ns address
Definition: first.py:47
ns stack
Definition: first.py:44
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:704
ns cmd
Definition: second.py:40
void BytesInQueueTrace(Ptr< OutputStreamWrapper > stream, uint32_t oldVal, uint32_t newVal)
Print the bytes in the queue.
static void PingRtt(std::string context, uint16_t, 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 limits.