Skip to content

Commit e9d4691

Browse files
committed
examples: Add benchmark queue discs example
1 parent 53fc5ed commit e9d4691

File tree

2 files changed

+322
-0
lines changed

2 files changed

+322
-0
lines changed
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
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 benchmark test 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 bottleneckBandwidth [10 Mbps], bottleneckDelay [5 ms]
30+
// qdiscs PfifoFast with capacity qdiscs bottleneckQueueDiscType in {PfifoFast, ARED, CoDel} [PfifoFast]
31+
// of 1000 packets with capacity of bottleneckQueueDiscSize packets [1000]
32+
// NetDevices queues with size of 100 packets NetDevices queues with size of bottleneckNetdevicesQueueSize packets [100]
33+
// without BQL bottleneckBql BQL [false]
34+
// *** fixed configuration ***
35+
//
36+
// The output will consist of a number of ping Rtt such as:
37+
//
38+
// /NodeList/0/ApplicationList/8/$ns3::V4Ping/Rtt=10 ms
39+
// /NodeList/0/ApplicationList/8/$ns3::V4Ping/Rtt=111 ms
40+
// /NodeList/0/ApplicationList/8/$ns3::V4Ping/Rtt=109 ms
41+
// /NodeList/0/ApplicationList/8/$ns3::V4Ping/Rtt=109 ms
42+
// /NodeList/0/ApplicationList/8/$ns3::V4Ping/Rtt=111 ms
43+
// /NodeList/0/ApplicationList/8/$ns3::V4Ping/Rtt=107 ms
44+
// /NodeList/0/ApplicationList/8/$ns3::V4Ping/Rtt=111 ms
45+
//
46+
// The file output will consist of a trace file with bytes in queue and of a trace file for limits
47+
// (when BQL is enabled) both for bottleneck NetDevice on n2, two files with upload an download
48+
// goodput for RRUL-like flows configuration, and a file with flow monitor stats.
49+
//
50+
// If you decrease the size of the bottleneckNetdevicesQueueSize from 100 to 50, one can
51+
// observe that the ping Rtt decreases. A further decrease can be observed when enable bottleneckBql
52+
// (regardless of the bottleneckNetdevicesQueueSize).
53+
// Also, you can evaluate the effect combined of the variation of bottleneckQueueDiscType and of
54+
// the bottleneckNetdevicesQueueSize (with or without 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 n3App, Ptr<OutputStreamWrapper> goodputStream, float samplingPeriod)
83+
{
84+
Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, fileName, n3App, goodputStream, samplingPeriod);
85+
double goodput[4];
86+
for (int i = 0; i < 4; i++)
87+
{
88+
uint32_t totalPackets = DynamicCast<PacketSink> (n3App.Get (i))->GetTotalRx ();
89+
goodput[i] = totalPackets * 8 / (Simulator::Now ().GetSeconds () * 1024); // Kbit/s
90+
}
91+
*goodputStream->GetStream () << Simulator::Now ().GetSeconds () << " " << goodput[0] << " " << goodput[1] << " "
92+
<< goodput[2] << " " << goodput[3] << std::endl;
93+
}
94+
95+
static void PingRtt (std::string context, Time rtt)
96+
{
97+
std::cout << context << "=" << rtt.GetMilliSeconds () << " ms" << std::endl;
98+
}
99+
100+
int main (int argc, char *argv[])
101+
{
102+
std::string bottleneckBandwidth = "10Mbps";
103+
std::string bottleneckDelay = "5ms";
104+
std::string bottleneckQueueDiscType = "PfifoFast";
105+
uint32_t bottleneckQueueDiscSize = 1000;
106+
uint32_t bottleneckNetdevicesQueueSize = 100;
107+
bool bottleneckBql = false;
108+
float startTime = 0.1; // in s
109+
float simDuration = 60;
110+
float samplingPeriod = 1;
111+
112+
// RRUL-like flows configuration with 4 upload + 4 download flows
113+
std::string rates[4];
114+
rates[0] = "4Mbps";
115+
rates[1] = "2Mbps";
116+
rates[2] = "4Mbps";
117+
rates[3] = "2Mbps";
118+
uint32_t sizes[4];
119+
sizes[0] = 1460;
120+
sizes[1] = 1460;
121+
sizes[2] = 1460;
122+
sizes[3] = 1460;
123+
uint8_t priorities[4];
124+
priorities[0] = 0x00; // Best effort
125+
priorities[1] = 0x28; // CS5
126+
priorities[2] = 0x2E; // EF
127+
priorities[3] = 0x0A; // Bulk
128+
129+
CommandLine cmd;
130+
cmd.AddValue ("bottleneckBandwidth", "Bottleneck bandwidth", bottleneckBandwidth);
131+
cmd.AddValue ("bottleneckDelay", "Bottleneck delay", bottleneckDelay);
132+
cmd.AddValue ("bottleneckQueueDiscType", "Queue disc type: PfifoFast, ARED, CoDel", bottleneckQueueDiscType);
133+
cmd.AddValue ("bottleneckQueueDiscSize", "Queue disc size in packets", bottleneckQueueDiscSize);
134+
cmd.AddValue ("bottleneckNetdevicesQueueSize", "Queue size in packets", bottleneckNetdevicesQueueSize);
135+
cmd.AddValue ("bottleneckBql", "Enable byte queue limits on bottleneck netdevices", bottleneckBql);
136+
cmd.AddValue ("startTime", "Simulation start time", startTime);
137+
cmd.AddValue ("simDuration", "Simulation duration in seconds", simDuration);
138+
cmd.Parse (argc, argv);
139+
140+
float stopTime = startTime + simDuration;
141+
142+
// Create nodes
143+
NodeContainer n1, n2, n3;
144+
n1.Create (1);
145+
n2.Create (1);
146+
n3.Create (1);
147+
148+
// Create and configure access link and bottleneck link
149+
PointToPointHelper accessLink;
150+
accessLink.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
151+
accessLink.SetChannelAttribute ("Delay", StringValue ("0.1ms"));
152+
153+
PointToPointHelper bottleneckLink;
154+
bottleneckLink.SetDeviceAttribute ("DataRate", StringValue (bottleneckBandwidth));
155+
bottleneckLink.SetChannelAttribute ("Delay", StringValue (bottleneckDelay));
156+
157+
InternetStackHelper stack;
158+
stack.InstallAll ();
159+
160+
// Access link traffic control configuration
161+
TrafficControlHelper tchPfifoFastAccess;
162+
uint32_t handle = tchPfifoFastAccess.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "Limit", UintegerValue (1000));
163+
164+
// Bottleneck link traffic control configuration
165+
TrafficControlHelper tchPfifoFastBottleneck;
166+
handle = tchPfifoFastBottleneck.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "Limit", UintegerValue (bottleneckQueueDiscSize));
167+
168+
TrafficControlHelper tchRed;
169+
handle = tchRed.SetRootQueueDisc ("ns3::RedQueueDisc");
170+
Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
171+
tchRed.AddInternalQueues (handle, 1, "ns3::DropTailQueue", "MaxPackets", UintegerValue (bottleneckQueueDiscSize));
172+
173+
TrafficControlHelper tchCoDel;
174+
handle = tchCoDel.SetRootQueueDisc ("ns3::CoDelQueueDisc");
175+
Config::SetDefault ("ns3::CoDelQueueDisc::Mode", EnumValue (Queue::QUEUE_MODE_PACKETS));
176+
tchCoDel.AddInternalQueues (handle, 1, "ns3::DropTailQueue", "MaxPackets", UintegerValue (bottleneckQueueDiscSize));
177+
178+
if (bottleneckBql)
179+
{
180+
tchPfifoFastBottleneck.SetQueueLimits ("ns3::DynamicQueueLimits");
181+
tchRed.SetQueueLimits ("ns3::DynamicQueueLimits");
182+
tchCoDel.SetQueueLimits ("ns3::DynamicQueueLimits");
183+
}
184+
185+
Config::SetDefault ("ns3::Queue::Mode", StringValue ("QUEUE_MODE_PACKETS"));
186+
Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (100));
187+
188+
NetDeviceContainer devicesAccessLink = accessLink.Install (n1.Get (0), n2.Get (0));
189+
tchPfifoFastAccess.Install (devicesAccessLink);
190+
Ipv4AddressHelper address;
191+
address.SetBase ("192.168.0.0", "255.255.255.0");
192+
address.NewNetwork ();
193+
Ipv4InterfaceContainer interfacesAccess = address.Assign (devicesAccessLink);
194+
195+
Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (bottleneckNetdevicesQueueSize));
196+
197+
NetDeviceContainer devicesBottleneckLink = bottleneckLink.Install (n2.Get (0), n3.Get (0));
198+
QueueDiscContainer qdiscs;
199+
if (bottleneckQueueDiscType.compare ("PfifoFast") == 0)
200+
{
201+
qdiscs = tchPfifoFastBottleneck.Install (devicesBottleneckLink);
202+
}
203+
else if (bottleneckQueueDiscType.compare ("ARED") == 0)
204+
{
205+
qdiscs = tchRed.Install (devicesBottleneckLink);
206+
}
207+
else if (bottleneckQueueDiscType.compare ("CoDel") == 0)
208+
{
209+
qdiscs = tchCoDel.Install (devicesBottleneckLink);
210+
}
211+
else
212+
{
213+
NS_ABORT_MSG ("--bottleneckQueueDiscType not valid");
214+
}
215+
address.NewNetwork ();
216+
Ipv4InterfaceContainer interfacesBottleneck = address.Assign (devicesBottleneckLink);
217+
218+
Ptr<NetDeviceQueueInterface> interface = devicesBottleneckLink.Get (0)->GetObject<NetDeviceQueueInterface> ();
219+
Ptr<NetDeviceQueue> queueInterface = interface->GetTxQueue (0);
220+
Ptr<DynamicQueueLimits> queueLimits = StaticCast<DynamicQueueLimits> (queueInterface->GetQueueLimits ());
221+
222+
AsciiTraceHelper ascii;
223+
if (bottleneckBql)
224+
{
225+
bottleneckQueueDiscType = bottleneckQueueDiscType + "-bql";
226+
Ptr<OutputStreamWrapper> streamLimits = ascii.CreateFileStream (bottleneckQueueDiscType + "-limits.txt");
227+
queueLimits->TraceConnectWithoutContext ("Limit",MakeBoundCallback (&LimitsTrace, streamLimits));
228+
}
229+
Ptr<Queue> queue = StaticCast<PointToPointNetDevice> (devicesBottleneckLink.Get (0))->GetQueue ();
230+
Ptr<OutputStreamWrapper> streamBytesInQueue = ascii.CreateFileStream (bottleneckQueueDiscType + "-bytesInQueue.txt");
231+
queue->TraceConnectWithoutContext ("BytesInQueue",MakeBoundCallback (&BytesInQueueTrace, streamBytesInQueue));
232+
233+
Ipv4InterfaceContainer n1Interface;
234+
n1Interface.Add (interfacesAccess.Get (0));
235+
236+
Ipv4InterfaceContainer n3Interface;
237+
n3Interface.Add (interfacesBottleneck.Get (1));
238+
239+
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
240+
241+
uint32_t segmentSize = std::max (std::max (std::max (sizes[0], sizes[1]), sizes[2]), sizes[3]);
242+
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (segmentSize));
243+
244+
uint16_t port = 7;
245+
ApplicationContainer uploadApps, downloadApps, sourceApps;
246+
// Configure and install upload flows
247+
for (int i = 0; i < 4; i++)
248+
{
249+
Address add (InetSocketAddress (Ipv4Address::GetAny (), port + i));
250+
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", add);
251+
sinkHelper.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
252+
uploadApps.Add (sinkHelper.Install (n3));
253+
254+
InetSocketAddress socketAddress = InetSocketAddress (n3Interface.GetAddress (0), port + i);
255+
socketAddress.SetTos (priorities [i]);
256+
OnOffHelper onOffHelper ("ns3::TcpSocketFactory", Address ());
257+
onOffHelper.SetAttribute ("Remote", AddressValue (socketAddress));
258+
onOffHelper.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
259+
onOffHelper.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
260+
onOffHelper.SetAttribute ("PacketSize", UintegerValue (sizes [i]));
261+
onOffHelper.SetAttribute ("DataRate", StringValue (rates [i]));
262+
sourceApps.Add (onOffHelper.Install (n1));
263+
}
264+
265+
port = 11;
266+
// Configure and install download flows
267+
for (int i = 0; i < 4; i++)
268+
{
269+
Address add (InetSocketAddress (Ipv4Address::GetAny (), port + i));
270+
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", add);
271+
sinkHelper.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
272+
downloadApps.Add (sinkHelper.Install (n1));
273+
274+
InetSocketAddress socketAddress = InetSocketAddress (n1Interface.GetAddress (0), port + i);
275+
socketAddress.SetTos (priorities [i]);
276+
OnOffHelper onOffHelper ("ns3::TcpSocketFactory", Address ());
277+
onOffHelper.SetAttribute ("Remote", AddressValue (socketAddress));
278+
onOffHelper.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
279+
onOffHelper.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
280+
onOffHelper.SetAttribute ("PacketSize", UintegerValue (sizes [i]));
281+
onOffHelper.SetAttribute ("DataRate", StringValue (rates [i]));
282+
sourceApps.Add (onOffHelper.Install (n3));
283+
}
284+
285+
// Configure and install ping
286+
V4PingHelper ping = V4PingHelper (n3Interface.GetAddress (0));
287+
ping.Install (n1);
288+
289+
Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt", MakeCallback (&PingRtt));
290+
291+
uploadApps.Start (Seconds (0));
292+
uploadApps.Stop (Seconds (stopTime));
293+
downloadApps.Start (Seconds (0));
294+
downloadApps.Stop (Seconds (stopTime));
295+
296+
sourceApps.Start (Seconds (0 + 0.1));
297+
sourceApps.Stop (Seconds (stopTime - 0.1));
298+
299+
Ptr<OutputStreamWrapper> uploadGoodputStream = ascii.CreateFileStream (bottleneckQueueDiscType + "-upload-goodput.txt");
300+
Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, bottleneckQueueDiscType + "-upload-goodput.txt", uploadApps,
301+
uploadGoodputStream, samplingPeriod);
302+
Ptr<OutputStreamWrapper> downloadGoodputStream = ascii.CreateFileStream (bottleneckQueueDiscType + "-download-goodput.txt");
303+
Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, bottleneckQueueDiscType + "-download-goodput.txt", downloadApps,
304+
downloadGoodputStream, samplingPeriod);
305+
306+
// Flow monitor
307+
Ptr<FlowMonitor> flowMonitor;
308+
FlowMonitorHelper flowHelper;
309+
flowMonitor = flowHelper.InstallAll();
310+
311+
Simulator::Stop (Seconds (stopTime));
312+
Simulator::Run ();
313+
314+
flowMonitor->SerializeToXmlFile(bottleneckQueueDiscType + "-flowMonitor.xml", true, true);
315+
316+
Simulator::Destroy ();
317+
return 0;
318+
}

examples/traffic-control/wscript

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ def build(bld):
44
obj = bld.create_ns3_program('traffic-control',
55
['internet', 'point-to-point', 'applications', 'traffic-control'])
66
obj.source = 'traffic-control.cc'
7+
8+
obj = bld.create_ns3_program('dynamic-queue-limits',
9+
['internet', 'point-to-point', 'applications', 'internet-apps', 'traffic-control', 'flow-monitor'])
10+
obj.source = 'dynamic-queue-limits.cc'

0 commit comments

Comments
 (0)