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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Pasquale Imputato <p.imputato@gmail.com>
7 * Stefano Avallone <stefano.avallone@unina.it>
8 */
9
10// This example serves as a benchmark for all the queue discs (with BQL enabled or not)
11//
12// Network topology
13//
14// 192.168.1.0 192.168.2.0
15// n1 ------------------------------------ n2 ----------------------------------- n3
16// point-to-point (access link) point-to-point (bottleneck link)
17// 100 Mbps, 0.1 ms bandwidth [10 Mbps], delay [5 ms]
18// qdiscs PfifoFast with capacity qdiscs queueDiscType in {PfifoFast, ARED, CoDel,
19// FqCoDel, PIE} [PfifoFast] of 1000 packets with capacity of
20// queueDiscSize packets [1000] netdevices queues with size of 100 packets netdevices queues with
21// size of netdevicesQueueSize packets [100] without BQL bql BQL
22// [false]
23// *** fixed configuration ***
24//
25// Two TCP flows are generated: one from n1 to n3 and the other from n3 to n1.
26// Additionally, n1 pings n3, so that the RTT can be measured.
27//
28// The output will consist of a number of ping Rtt such as:
29//
30// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=111 ms
31// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=111 ms
32// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=110 ms
33// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=111 ms
34// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=111 ms
35// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=112 ms
36// /NodeList/0/ApplicationList/2/$ns3::Ping/Rtt=111 ms
37//
38// The files output will consist of a trace file with bytes in queue and of a trace file for limits
39// (when BQL is enabled) both for bottleneck NetDevice on n2, two files with upload and download
40// goodput for flows configuration and a file with flow monitor stats.
41//
42// If you use an AQM as queue disc on the bottleneck netdevices, you can observe that the ping Rtt
43// decrease. A further decrease can be observed when you enable BQL.
44
45#include "ns3/applications-module.h"
46#include "ns3/core-module.h"
47#include "ns3/flow-monitor-module.h"
48#include "ns3/internet-apps-module.h"
49#include "ns3/internet-module.h"
50#include "ns3/network-module.h"
51#include "ns3/point-to-point-module.h"
52#include "ns3/traffic-control-module.h"
53
54using namespace ns3;
55
56NS_LOG_COMPONENT_DEFINE("BenchmarkQueueDiscs");
57
58/**
59 * Print the queue limits.
60 *
61 * \param stream The output stream.
62 * \param oldVal Old value.
63 * \param newVal New value.
64 */
65void
67{
68 *stream->GetStream() << Simulator::Now().GetSeconds() << " " << newVal << std::endl;
69}
70
71/**
72 * Print the bytes in the queue.
73 *
74 * \param stream The output stream.
75 * \param oldVal Old value.
76 * \param newVal New value.
77 */
78void
80{
81 *stream->GetStream() << Simulator::Now().GetSeconds() << " " << newVal << std::endl;
82}
83
84/**
85 * Sample and print the queue goodput.
86 *
87 * \param app The Tx app.
88 * \param stream The output stream.
89 * \param period The sampling period.
90 */
91static void
93{
94 Simulator::Schedule(Seconds(period), &GoodputSampling, app, stream, period);
95 double goodput;
96 uint64_t totalPackets = DynamicCast<PacketSink>(app.Get(0))->GetTotalRx();
97 goodput = totalPackets * 8 / (Simulator::Now().GetSeconds() * 1024); // Kbit/s
98 *stream->GetStream() << Simulator::Now().GetSeconds() << " " << goodput << std::endl;
99}
100
101/**
102 * Print the ping RTT.
103 *
104 * \param context The context.
105 * \param rtt The RTT.
106 */
107static void
108PingRtt(std::string context, uint16_t, Time rtt)
109{
110 std::cout << context << "=" << rtt.GetMilliSeconds() << " ms" << std::endl;
111}
112
113int
114main(int argc, char* argv[])
115{
116 std::string bandwidth = "10Mbps";
117 std::string delay = "5ms";
118 std::string queueDiscType = "PfifoFast";
119 uint32_t queueDiscSize = 1000;
120 uint32_t netdevicesQueueSize = 50;
121 bool bql = false;
122
123 std::string flowsDatarate = "20Mbps";
124 uint32_t flowsPacketsSize = 1000;
125
126 float startTime = 0.1F; // in s
127 float simDuration = 60;
128 float samplingPeriod = 1;
129
130 CommandLine cmd(__FILE__);
131 cmd.AddValue("bandwidth", "Bottleneck bandwidth", bandwidth);
132 cmd.AddValue("delay", "Bottleneck delay", delay);
133 cmd.AddValue("queueDiscType",
134 "Bottleneck queue disc type in {PfifoFast, ARED, CoDel, FqCoDel, PIE, prio}",
135 queueDiscType);
136 cmd.AddValue("queueDiscSize", "Bottleneck queue disc size in packets", queueDiscSize);
137 cmd.AddValue("netdevicesQueueSize",
138 "Bottleneck netdevices queue size in packets",
139 netdevicesQueueSize);
140 cmd.AddValue("bql", "Enable byte queue limits on bottleneck netdevices", bql);
141 cmd.AddValue("flowsDatarate", "Upload and download flows datarate", flowsDatarate);
142 cmd.AddValue("flowsPacketsSize", "Upload and download flows packets sizes", flowsPacketsSize);
143 cmd.AddValue("startTime", "Simulation start time", startTime);
144 cmd.AddValue("simDuration", "Simulation duration in seconds", simDuration);
145 cmd.AddValue("samplingPeriod", "Goodput sampling period in seconds", samplingPeriod);
146 cmd.Parse(argc, argv);
147
148 float stopTime = startTime + simDuration;
149
150 // Create nodes
151 NodeContainer n1;
152 NodeContainer n2;
153 NodeContainer n3;
154 n1.Create(1);
155 n2.Create(1);
156 n3.Create(1);
157
158 // Create and configure access link and bottleneck link
159 PointToPointHelper accessLink;
160 accessLink.SetDeviceAttribute("DataRate", StringValue("100Mbps"));
161 accessLink.SetChannelAttribute("Delay", StringValue("0.1ms"));
162 accessLink.SetQueue("ns3::DropTailQueue", "MaxSize", StringValue("100p"));
163
164 PointToPointHelper bottleneckLink;
165 bottleneckLink.SetDeviceAttribute("DataRate", StringValue(bandwidth));
166 bottleneckLink.SetChannelAttribute("Delay", StringValue(delay));
167 bottleneckLink.SetQueue("ns3::DropTailQueue",
168 "MaxSize",
169 StringValue(std::to_string(netdevicesQueueSize) + "p"));
170
172 stack.InstallAll();
173
174 // Access link traffic control configuration
175 TrafficControlHelper tchPfifoFastAccess;
176 tchPfifoFastAccess.SetRootQueueDisc("ns3::PfifoFastQueueDisc", "MaxSize", StringValue("1000p"));
177
178 // Bottleneck link traffic control configuration
179 TrafficControlHelper tchBottleneck;
180
181 if (queueDiscType == "PfifoFast")
182 {
183 tchBottleneck.SetRootQueueDisc(
184 "ns3::PfifoFastQueueDisc",
185 "MaxSize",
186 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
187 }
188 else if (queueDiscType == "ARED")
189 {
190 tchBottleneck.SetRootQueueDisc("ns3::RedQueueDisc");
191 Config::SetDefault("ns3::RedQueueDisc::ARED", BooleanValue(true));
192 Config::SetDefault("ns3::RedQueueDisc::MaxSize",
193 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
194 }
195 else if (queueDiscType == "CoDel")
196 {
197 tchBottleneck.SetRootQueueDisc("ns3::CoDelQueueDisc");
198 Config::SetDefault("ns3::CoDelQueueDisc::MaxSize",
199 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
200 }
201 else if (queueDiscType == "FqCoDel")
202 {
203 tchBottleneck.SetRootQueueDisc("ns3::FqCoDelQueueDisc");
204 Config::SetDefault("ns3::FqCoDelQueueDisc::MaxSize",
205 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
206 }
207 else if (queueDiscType == "PIE")
208 {
209 tchBottleneck.SetRootQueueDisc("ns3::PieQueueDisc");
210 Config::SetDefault("ns3::PieQueueDisc::MaxSize",
211 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
212 }
213 else if (queueDiscType == "prio")
214 {
215 uint16_t handle =
216 tchBottleneck.SetRootQueueDisc("ns3::PrioQueueDisc",
217 "Priomap",
218 StringValue("0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1"));
220 tchBottleneck.AddQueueDiscClasses(handle, 2, "ns3::QueueDiscClass");
221 tchBottleneck.AddChildQueueDisc(handle, cid[0], "ns3::FifoQueueDisc");
222 tchBottleneck.AddChildQueueDisc(handle, cid[1], "ns3::RedQueueDisc");
223 }
224 else
225 {
226 NS_ABORT_MSG("--queueDiscType not valid");
227 }
228
229 if (bql)
230 {
231 tchBottleneck.SetQueueLimits("ns3::DynamicQueueLimits");
232 }
233
234 NetDeviceContainer devicesAccessLink = accessLink.Install(n1.Get(0), n2.Get(0));
235 tchPfifoFastAccess.Install(devicesAccessLink);
237 address.SetBase("192.168.0.0", "255.255.255.0");
238 address.NewNetwork();
239 Ipv4InterfaceContainer interfacesAccess = address.Assign(devicesAccessLink);
240
241 NetDeviceContainer devicesBottleneckLink = bottleneckLink.Install(n2.Get(0), n3.Get(0));
242 QueueDiscContainer qdiscs;
243 qdiscs = tchBottleneck.Install(devicesBottleneckLink);
244
245 address.NewNetwork();
246 Ipv4InterfaceContainer interfacesBottleneck = address.Assign(devicesBottleneckLink);
247
249 devicesBottleneckLink.Get(0)->GetObject<NetDeviceQueueInterface>();
250 Ptr<NetDeviceQueue> queueInterface = interface->GetTxQueue(0);
251 Ptr<DynamicQueueLimits> queueLimits =
252 StaticCast<DynamicQueueLimits>(queueInterface->GetQueueLimits());
253
254 AsciiTraceHelper ascii;
255 if (bql)
256 {
257 queueDiscType = queueDiscType + "-bql";
258 Ptr<OutputStreamWrapper> streamLimits =
259 ascii.CreateFileStream(queueDiscType + "-limits.txt");
260 queueLimits->TraceConnectWithoutContext("Limit",
261 MakeBoundCallback(&LimitsTrace, streamLimits));
262 }
263 Ptr<Queue<Packet>> queue =
264 StaticCast<PointToPointNetDevice>(devicesBottleneckLink.Get(0))->GetQueue();
265 Ptr<OutputStreamWrapper> streamBytesInQueue =
266 ascii.CreateFileStream(queueDiscType + "-bytesInQueue.txt");
267 queue->TraceConnectWithoutContext("BytesInQueue",
268 MakeBoundCallback(&BytesInQueueTrace, streamBytesInQueue));
269
270 Ipv4InterfaceContainer n1Interface;
271 n1Interface.Add(interfacesAccess.Get(0));
272
273 Ipv4InterfaceContainer n3Interface;
274 n3Interface.Add(interfacesBottleneck.Get(1));
275
277
278 Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(flowsPacketsSize));
279
280 // Flows configuration
281 // Bidirectional TCP streams with ping like flent tcp_bidirectional test.
282 uint16_t port = 7;
283 ApplicationContainer uploadApp;
284 ApplicationContainer downloadApp;
285 ApplicationContainer sourceApps;
286 // Configure and install upload flow
288 PacketSinkHelper sinkHelperUp("ns3::TcpSocketFactory", addUp);
289 sinkHelperUp.SetAttribute("Protocol", TypeIdValue(TcpSocketFactory::GetTypeId()));
290 uploadApp.Add(sinkHelperUp.Install(n3));
291
292 InetSocketAddress socketAddressUp = InetSocketAddress(n3Interface.GetAddress(0), port);
293 OnOffHelper onOffHelperUp("ns3::TcpSocketFactory", Address());
294 onOffHelperUp.SetAttribute("Remote", AddressValue(socketAddressUp));
295 onOffHelperUp.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
296 onOffHelperUp.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
297 onOffHelperUp.SetAttribute("PacketSize", UintegerValue(flowsPacketsSize));
298 onOffHelperUp.SetAttribute("DataRate", StringValue(flowsDatarate));
299 sourceApps.Add(onOffHelperUp.Install(n1));
300
301 port = 8;
302 // Configure and install download flow
304 PacketSinkHelper sinkHelperDown("ns3::TcpSocketFactory", addDown);
305 sinkHelperDown.SetAttribute("Protocol", TypeIdValue(TcpSocketFactory::GetTypeId()));
306 downloadApp.Add(sinkHelperDown.Install(n1));
307
308 InetSocketAddress socketAddressDown = InetSocketAddress(n1Interface.GetAddress(0), port);
309 OnOffHelper onOffHelperDown("ns3::TcpSocketFactory", Address());
310 onOffHelperDown.SetAttribute("Remote", AddressValue(socketAddressDown));
311 onOffHelperDown.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
312 onOffHelperDown.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
313 onOffHelperDown.SetAttribute("PacketSize", UintegerValue(flowsPacketsSize));
314 onOffHelperDown.SetAttribute("DataRate", StringValue(flowsDatarate));
315 sourceApps.Add(onOffHelperDown.Install(n3));
316
317 // Configure and install ping
318 PingHelper ping(n3Interface.GetAddress(0));
319 ping.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::QUIET));
320 ping.Install(n1);
321
322 Config::Connect("/NodeList/*/ApplicationList/*/$ns3::Ping/Rtt", MakeCallback(&PingRtt));
323
324 uploadApp.Start(Seconds(0));
325 uploadApp.Stop(Seconds(stopTime));
326 downloadApp.Start(Seconds(0));
327 downloadApp.Stop(Seconds(stopTime));
328
329 sourceApps.Start(Seconds(0 + 0.1));
330 sourceApps.Stop(Seconds(stopTime - 0.1));
331
332 Ptr<OutputStreamWrapper> uploadGoodputStream =
333 ascii.CreateFileStream(queueDiscType + "-upGoodput.txt");
334 Simulator::Schedule(Seconds(samplingPeriod),
336 uploadApp,
337 uploadGoodputStream,
338 samplingPeriod);
339 Ptr<OutputStreamWrapper> downloadGoodputStream =
340 ascii.CreateFileStream(queueDiscType + "-downGoodput.txt");
341 Simulator::Schedule(Seconds(samplingPeriod),
343 downloadApp,
344 downloadGoodputStream,
345 samplingPeriod);
346
347 // Flow monitor
348 Ptr<FlowMonitor> flowMonitor;
349 FlowMonitorHelper flowHelper;
350 flowMonitor = flowHelper.InstallAll();
351
352 accessLink.EnablePcapAll("queue");
353
356
357 flowMonitor->SerializeToXmlFile(queueDiscType + "-flowMonitor.xml", true, true);
358
360 return 0;
361}
a polymophic address class
Definition address.h:90
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.
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.
Parse command-line arguments.
Hold variables of type enum.
Definition enum.h:52
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.
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:31
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.
Holds a vector of ns3::QueueDisc pointers.
Class for representing queue sizes.
Definition queue-size.h:85
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Hold variables of type string.
Definition string.h:45
static TypeId GetTypeId()
Get the type ID.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:397
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
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...
Hold an unsigned integer type.
Definition uinteger.h:34
uint16_t port
Definition dsdv-manet.cc:33
Time stopTime
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:883
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:967
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition callback.h:745
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
address
Definition first.py:36
stack
Definition first.py:33
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:684
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:587
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.