A Discrete-Event Network Simulator
API
dctcp-example.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2017-20 NITK Surathkal
4 * Copyright (c) 2020 Tom Henderson (better alignment with experiment)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation;
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Authors: Shravya K.S. <shravya.ks0@gmail.com>
20 * Apoorva Bhargava <apoorvabhargava13@gmail.com>
21 * Shikha Bakshi <shikhabakshi912@gmail.com>
22 * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
23 * Tom Henderson <tomh@tomh.org>
24 */
25
26// The network topology used in this example is based on Fig. 17 described in
27// Mohammad Alizadeh, Albert Greenberg, David A. Maltz, Jitendra Padhye,
28// Parveen Patel, Balaji Prabhakar, Sudipta Sengupta, and Murari Sridharan.
29// "Data Center TCP (DCTCP)." In ACM SIGCOMM Computer Communication Review,
30// Vol. 40, No. 4, pp. 63-74. ACM, 2010.
31
32// The topology is roughly as follows
33//
34// S1 S3
35// | | (1 Gbps)
36// T1 ------- T2 -- R1
37// | | (1 Gbps)
38// S2 R2
39//
40// The link between switch T1 and T2 is 10 Gbps. All other
41// links are 1 Gbps. In the SIGCOMM paper, there is a Scorpion switch
42// between T1 and T2, but it doesn't contribute another bottleneck.
43//
44// S1 and S3 each have 10 senders sending to receiver R1 (20 total)
45// S2 (20 senders) sends traffic to R2 (20 receivers)
46//
47// This sets up two bottlenecks: 1) T1 -> T2 interface (30 senders
48// using the 10 Gbps link) and 2) T2 -> R1 (20 senders using 1 Gbps link)
49//
50// RED queues configured for ECN marking are used at the bottlenecks.
51//
52// Figure 17 published results are that each sender in S1 gets 46 Mbps
53// and each in S3 gets 54 Mbps, while each S2 sender gets 475 Mbps, and
54// that these are within 10% of their fair-share throughputs (Jain index
55// of 0.99).
56//
57// This program runs the program by default for five seconds. The first
58// second is devoted to flow startup (all 40 TCP flows are stagger started
59// during this period). There is a three second convergence time where
60// no measurement data is taken, and then there is a one second measurement
61// interval to gather raw throughput for each flow. These time intervals
62// can be changed at the command line.
63//
64// The program outputs six files. The first three:
65// * dctcp-example-s1-r1-throughput.dat
66// * dctcp-example-s2-r2-throughput.dat
67// * dctcp-example-s3-r1-throughput.dat
68// provide per-flow throughputs (in Mb/s) for each of the forty flows, summed
69// over the measurement window. The fourth file,
70// * dctcp-example-fairness.dat
71// provides average throughputs for the three flow paths, and computes
72// Jain's fairness index for each flow group (i.e. across each group of
73// 10, 20, and 10 flows). It also sums the throughputs across each bottleneck.
74// The fifth and sixth:
75// * dctcp-example-t1-length.dat
76// * dctcp-example-t2-length.dat
77// report on the bottleneck queue length (in packets and microseconds
78// of delay) at 10 ms intervals during the measurement window.
79//
80// By default, the throughput averages are 23 Mbps for S1 senders, 471 Mbps
81// for S2 senders, and 74 Mbps for S3 senders, and the Jain index is greater
82// than 0.99 for each group of flows. The average queue delay is about 1ms
83// for the T2->R2 bottleneck, and about 200us for the T1->T2 bottleneck.
84//
85// The RED parameters (min_th and max_th) are set to the same values as
86// reported in the paper, but we observed that throughput distributions
87// and queue delays are very sensitive to these parameters, as was also
88// observed in the paper; it is likely that the paper's throughput results
89// could be achieved by further tuning of the RED parameters. However,
90// the default results show that DCTCP is able to achieve high link
91// utilization and low queueing delay and fairness across competing flows
92// sharing the same path.
93
94#include <iostream>
95#include <iomanip>
96
97#include "ns3/core-module.h"
98#include "ns3/network-module.h"
99#include "ns3/internet-module.h"
100#include "ns3/point-to-point-module.h"
101#include "ns3/applications-module.h"
102#include "ns3/traffic-control-module.h"
103
104using namespace ns3;
105
106std::stringstream filePlotQueue1;
107std::stringstream filePlotQueue2;
108std::ofstream rxS1R1Throughput;
109std::ofstream rxS2R2Throughput;
110std::ofstream rxS3R1Throughput;
111std::ofstream fairnessIndex;
112std::ofstream t1QueueLength;
113std::ofstream t2QueueLength;
114std::vector<uint64_t> rxS1R1Bytes;
115std::vector<uint64_t> rxS2R2Bytes;
116std::vector<uint64_t> rxS3R1Bytes;
117
118void
120{
121 std::cout << "Progress to " << std::fixed << std::setprecision (1) << Simulator::Now ().GetSeconds () << " seconds simulation time" << std::endl;
122 Simulator::Schedule (interval, &PrintProgress, interval);
123}
124
125void
126TraceS1R1Sink (std::size_t index, Ptr<const Packet> p, const Address& a)
127{
128 rxS1R1Bytes[index] += p->GetSize ();
129}
130
131void
132TraceS2R2Sink (std::size_t index, Ptr<const Packet> p, const Address& a)
133{
134 rxS2R2Bytes[index] += p->GetSize ();
135}
136
137void
138TraceS3R1Sink (std::size_t index, Ptr<const Packet> p, const Address& a)
139{
140 rxS3R1Bytes[index] += p->GetSize ();
141}
142
143void
145{
146 for (std::size_t i = 0; i < 10; i++)
147 {
148 rxS1R1Bytes[i] = 0;
149 }
150 for (std::size_t i = 0; i < 20; i++)
151 {
152 rxS2R2Bytes[i] = 0;
153 }
154 for (std::size_t i = 0; i < 10; i++)
155 {
156 rxS3R1Bytes[i] = 0;
157 }
158}
159
160void
161PrintThroughput (Time measurementWindow)
162{
163 for (std::size_t i = 0; i < 10; i++)
164 {
165 rxS1R1Throughput << measurementWindow.GetSeconds () << "s " << i << " " << (rxS1R1Bytes[i] * 8) / (measurementWindow.GetSeconds ()) / 1e6 << std::endl;
166 }
167 for (std::size_t i = 0; i < 20; i++)
168 {
169 rxS2R2Throughput << Simulator::Now ().GetSeconds () << "s " << i << " " << (rxS2R2Bytes[i] * 8) / (measurementWindow.GetSeconds ()) / 1e6 << std::endl;
170 }
171 for (std::size_t i = 0; i < 10; i++)
172 {
173 rxS3R1Throughput << Simulator::Now ().GetSeconds () << "s " << i << " " << (rxS3R1Bytes[i] * 8) / (measurementWindow.GetSeconds ()) / 1e6 << std::endl;
174 }
175}
176
177// Jain's fairness index: https://en.wikipedia.org/wiki/Fairness_measure
178void
179PrintFairness (Time measurementWindow)
180{
181 double average = 0;
182 uint64_t sumSquares = 0;
183 uint64_t sum = 0;
184 double fairness = 0;
185 for (std::size_t i = 0; i < 10; i++)
186 {
187 sum += rxS1R1Bytes[i];
188 sumSquares += (rxS1R1Bytes[i] * rxS1R1Bytes[i]);
189 }
190 average = ((sum / 10) * 8 / measurementWindow.GetSeconds ()) / 1e6;
191 fairness = static_cast<double> (sum * sum) / (10 * sumSquares);
192 fairnessIndex << "Average throughput for S1-R1 flows: "
193 << std::fixed << std::setprecision (2) << average << " Mbps; fairness: "
194 << std::fixed << std::setprecision (3) << fairness << std::endl;
195 average = 0;
196 sumSquares = 0;
197 sum = 0;
198 fairness = 0;
199 for (std::size_t i = 0; i < 20; i++)
200 {
201 sum += rxS2R2Bytes[i];
202 sumSquares += (rxS2R2Bytes[i] * rxS2R2Bytes[i]);
203 }
204 average = ((sum / 20) * 8 / measurementWindow.GetSeconds ()) / 1e6;
205 fairness = static_cast<double> (sum * sum) / (20 * sumSquares);
206 fairnessIndex << "Average throughput for S2-R2 flows: "
207 << std::fixed << std::setprecision (2) << average << " Mbps; fairness: "
208 << std::fixed << std::setprecision (3) << fairness << std::endl;
209 average = 0;
210 sumSquares = 0;
211 sum = 0;
212 fairness = 0;
213 for (std::size_t i = 0; i < 10; i++)
214 {
215 sum += rxS3R1Bytes[i];
216 sumSquares += (rxS3R1Bytes[i] * rxS3R1Bytes[i]);
217 }
218 average = ((sum / 10) * 8 / measurementWindow.GetSeconds ()) / 1e6;
219 fairness = static_cast<double> (sum * sum) / (10 * sumSquares);
220 fairnessIndex << "Average throughput for S3-R1 flows: "
221 << std::fixed << std::setprecision (2) << average << " Mbps; fairness: "
222 << std::fixed << std::setprecision (3) << fairness << std::endl;
223 sum = 0;
224 for (std::size_t i = 0; i < 10; i++)
225 {
226 sum += rxS1R1Bytes[i];
227 }
228 for (std::size_t i = 0; i < 20; i++)
229 {
230 sum += rxS2R2Bytes[i];
231 }
232 fairnessIndex << "Aggregate user-level throughput for flows through T1: " << static_cast<double> (sum * 8) / 1e9 << " Gbps" << std::endl;
233 sum = 0;
234 for (std::size_t i = 0; i < 10; i++)
235 {
236 sum += rxS3R1Bytes[i];
237 }
238 for (std::size_t i = 0; i < 10; i++)
239 {
240 sum += rxS1R1Bytes[i];
241 }
242 fairnessIndex << "Aggregate user-level throughput for flows to R1: " << static_cast<double> (sum * 8) / 1e9 << " Gbps" << std::endl;
243}
244
245void
247{
248 // 1500 byte packets
249 uint32_t qSize = queue->GetNPackets ();
250 Time backlog = Seconds (static_cast<double> (qSize * 1500 * 8) / 1e10); // 10 Gb/s
251 // report size in units of packets and ms
252 t1QueueLength << std::fixed << std::setprecision (2) << Simulator::Now ().GetSeconds () << " " << qSize << " " << backlog.GetMicroSeconds () << std::endl;
253 // check queue size every 1/100 of a second
254 Simulator::Schedule (MilliSeconds (10), &CheckT1QueueSize, queue);
255}
256
257void
259{
260 uint32_t qSize = queue->GetNPackets ();
261 Time backlog = Seconds (static_cast<double> (qSize * 1500 * 8) / 1e9); // 1 Gb/s
262 // report size in units of packets and ms
263 t2QueueLength << std::fixed << std::setprecision (2) << Simulator::Now ().GetSeconds () << " " << qSize << " " << backlog.GetMicroSeconds () << std::endl;
264 // check queue size every 1/100 of a second
265 Simulator::Schedule (MilliSeconds (10), &CheckT2QueueSize, queue);
266}
267
268int main (int argc, char *argv[])
269{
270 std::string outputFilePath = ".";
271 std::string tcpTypeId = "TcpDctcp";
272 Time flowStartupWindow = Seconds (1);
273 Time convergenceTime = Seconds (3);
274 Time measurementWindow = Seconds (1);
275 bool enableSwitchEcn = true;
276 Time progressInterval = MilliSeconds (100);
277
278 CommandLine cmd (__FILE__);
279 cmd.AddValue ("tcpTypeId", "ns-3 TCP TypeId", tcpTypeId);
280 cmd.AddValue ("flowStartupWindow", "startup time window (TCP staggered starts)", flowStartupWindow);
281 cmd.AddValue ("convergenceTime", "convergence time", convergenceTime);
282 cmd.AddValue ("measurementWindow", "measurement window", measurementWindow);
283 cmd.AddValue ("enableSwitchEcn", "enable ECN at switches", enableSwitchEcn);
284 cmd.Parse (argc, argv);
285
286 Config::SetDefault ("ns3::TcpL4Protocol::SocketType", StringValue ("ns3::" + tcpTypeId));
287
288 Time startTime = Seconds (0);
289 Time stopTime = flowStartupWindow + convergenceTime + measurementWindow;
290
291 Time clientStartTime = startTime;
292
293 rxS1R1Bytes.reserve (10);
294 rxS2R2Bytes.reserve (20);
295 rxS3R1Bytes.reserve (10);
296
297 NodeContainer S1, S2, S3, R2;
298 Ptr<Node> T1 = CreateObject<Node> ();
299 Ptr<Node> T2 = CreateObject<Node> ();
300 Ptr<Node> R1 = CreateObject<Node> ();
301 S1.Create (10);
302 S2.Create (20);
303 S3.Create (10);
304 R2.Create (20);
305
306 Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1448));
307 Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (2));
308 GlobalValue::Bind ("ChecksumEnabled", BooleanValue (false));
309
310 // Set default parameters for RED queue disc
311 Config::SetDefault ("ns3::RedQueueDisc::UseEcn", BooleanValue (enableSwitchEcn));
312 // ARED may be used but the queueing delays will increase; it is disabled
313 // here because the SIGCOMM paper did not mention it
314 // Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
315 // Config::SetDefault ("ns3::RedQueueDisc::Gentle", BooleanValue (true));
316 Config::SetDefault ("ns3::RedQueueDisc::UseHardDrop", BooleanValue (false));
317 Config::SetDefault ("ns3::RedQueueDisc::MeanPktSize", UintegerValue (1500));
318 // Triumph and Scorpion switches used in DCTCP Paper have 4 MB of buffer
319 // If every packet is 1500 bytes, 2666 packets can be stored in 4 MB
320 Config::SetDefault ("ns3::RedQueueDisc::MaxSize", QueueSizeValue (QueueSize ("2666p")));
321 // DCTCP tracks instantaneous queue length only; so set QW = 1
322 Config::SetDefault ("ns3::RedQueueDisc::QW", DoubleValue (1));
323 Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (20));
324 Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (60));
325
326 PointToPointHelper pointToPointSR;
327 pointToPointSR.SetDeviceAttribute ("DataRate", StringValue ("1Gbps"));
328 pointToPointSR.SetChannelAttribute ("Delay", StringValue ("10us"));
329
330 PointToPointHelper pointToPointT;
331 pointToPointT.SetDeviceAttribute ("DataRate", StringValue ("10Gbps"));
332 pointToPointT.SetChannelAttribute ("Delay", StringValue ("10us"));
333
334
335 // Create a total of 62 links.
336 std::vector<NetDeviceContainer> S1T1;
337 S1T1.reserve (10);
338 std::vector<NetDeviceContainer> S2T1;
339 S2T1.reserve (20);
340 std::vector<NetDeviceContainer> S3T2;
341 S3T2.reserve (10);
342 std::vector<NetDeviceContainer> R2T2;
343 R2T2.reserve (20);
344 NetDeviceContainer T1T2 = pointToPointT.Install (T1, T2);
345 NetDeviceContainer R1T2 = pointToPointSR.Install (R1, T2);
346
347 for (std::size_t i = 0; i < 10; i++)
348 {
349 Ptr<Node> n = S1.Get (i);
350 S1T1.push_back (pointToPointSR.Install (n, T1));
351 }
352 for (std::size_t i = 0; i < 20; i++)
353 {
354 Ptr<Node> n = S2.Get (i);
355 S2T1.push_back (pointToPointSR.Install (n, T1));
356 }
357 for (std::size_t i = 0; i < 10; i++)
358 {
359 Ptr<Node> n = S3.Get (i);
360 S3T2.push_back (pointToPointSR.Install (n, T2));
361 }
362 for (std::size_t i = 0; i < 20; i++)
363 {
364 Ptr<Node> n = R2.Get (i);
365 R2T2.push_back (pointToPointSR.Install (n, T2));
366 }
367
369 stack.InstallAll ();
370
371 TrafficControlHelper tchRed10;
372 // MinTh = 50, MaxTh = 150 recommended in ACM SIGCOMM 2010 DCTCP Paper
373 // This yields a target (MinTh) queue depth of 60us at 10 Gb/s
374 tchRed10.SetRootQueueDisc ("ns3::RedQueueDisc",
375 "LinkBandwidth", StringValue ("10Gbps"),
376 "LinkDelay", StringValue ("10us"),
377 "MinTh", DoubleValue (50),
378 "MaxTh", DoubleValue (150));
379 QueueDiscContainer queueDiscs1 = tchRed10.Install (T1T2);
380
381 TrafficControlHelper tchRed1;
382 // MinTh = 20, MaxTh = 60 recommended in ACM SIGCOMM 2010 DCTCP Paper
383 // This yields a target queue depth of 250us at 1 Gb/s
384 tchRed1.SetRootQueueDisc ("ns3::RedQueueDisc",
385 "LinkBandwidth", StringValue ("1Gbps"),
386 "LinkDelay", StringValue ("10us"),
387 "MinTh", DoubleValue (20),
388 "MaxTh", DoubleValue (60));
389 QueueDiscContainer queueDiscs2 = tchRed1.Install (R1T2.Get (1));
390 for (std::size_t i = 0; i < 10; i++)
391 {
392 tchRed1.Install (S1T1[i].Get (1));
393 }
394 for (std::size_t i = 0; i < 20; i++)
395 {
396 tchRed1.Install (S2T1[i].Get (1));
397 }
398 for (std::size_t i = 0; i < 10; i++)
399 {
400 tchRed1.Install (S3T2[i].Get (1));
401 }
402 for (std::size_t i = 0; i < 20; i++)
403 {
404 tchRed1.Install (R2T2[i].Get (1));
405 }
406
408 std::vector<Ipv4InterfaceContainer> ipS1T1;
409 ipS1T1.reserve (10);
410 std::vector<Ipv4InterfaceContainer> ipS2T1;
411 ipS2T1.reserve (20);
412 std::vector<Ipv4InterfaceContainer> ipS3T2;
413 ipS3T2.reserve (10);
414 std::vector<Ipv4InterfaceContainer> ipR2T2;
415 ipR2T2.reserve (20);
416 address.SetBase ("172.16.1.0", "255.255.255.0");
417 Ipv4InterfaceContainer ipT1T2 = address.Assign (T1T2);
418 address.SetBase ("192.168.0.0", "255.255.255.0");
419 Ipv4InterfaceContainer ipR1T2 = address.Assign (R1T2);
420 address.SetBase ("10.1.1.0", "255.255.255.0");
421 for (std::size_t i = 0; i < 10; i++)
422 {
423 ipS1T1.push_back (address.Assign (S1T1[i]));
424 address.NewNetwork ();
425 }
426 address.SetBase ("10.2.1.0", "255.255.255.0");
427 for (std::size_t i = 0; i < 20; i++)
428 {
429 ipS2T1.push_back (address.Assign (S2T1[i]));
430 address.NewNetwork ();
431 }
432 address.SetBase ("10.3.1.0", "255.255.255.0");
433 for (std::size_t i = 0; i < 10; i++)
434 {
435 ipS3T2.push_back (address.Assign (S3T2[i]));
436 address.NewNetwork ();
437 }
438 address.SetBase ("10.4.1.0", "255.255.255.0");
439 for (std::size_t i = 0; i < 20; i++)
440 {
441 ipR2T2.push_back (address.Assign (R2T2[i]));
442 address.NewNetwork ();
443 }
444
445 Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
446
447 // Each sender in S2 sends to a receiver in R2
448 std::vector<Ptr<PacketSink> > r2Sinks;
449 r2Sinks.reserve (20);
450 for (std::size_t i = 0; i < 20; i++)
451 {
452 uint16_t port = 50000 + i;
453 Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
454 PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress);
455 ApplicationContainer sinkApp = sinkHelper.Install (R2.Get (i));
456 Ptr<PacketSink> packetSink = sinkApp.Get (0)->GetObject<PacketSink> ();
457 r2Sinks.push_back (packetSink);
458 sinkApp.Start (startTime);
459 sinkApp.Stop (stopTime);
460
461 OnOffHelper clientHelper1 ("ns3::TcpSocketFactory", Address ());
462 clientHelper1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
463 clientHelper1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
464 clientHelper1.SetAttribute ("DataRate", DataRateValue (DataRate ("1Gbps")));
465 clientHelper1.SetAttribute ("PacketSize", UintegerValue (1000));
466
467 ApplicationContainer clientApps1;
468 AddressValue remoteAddress (InetSocketAddress (ipR2T2[i].GetAddress (0), port));
469 clientHelper1.SetAttribute ("Remote", remoteAddress);
470 clientApps1.Add (clientHelper1.Install (S2.Get (i)));
471 clientApps1.Start (i * flowStartupWindow / 20 + clientStartTime + MilliSeconds (i * 5));
472 clientApps1.Stop (stopTime);
473 }
474
475 // Each sender in S1 and S3 sends to R1
476 std::vector<Ptr<PacketSink> > s1r1Sinks;
477 std::vector<Ptr<PacketSink> > s3r1Sinks;
478 s1r1Sinks.reserve (10);
479 s3r1Sinks.reserve (10);
480 for (std::size_t i = 0; i < 20; i++)
481 {
482 uint16_t port = 50000 + i;
483 Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
484 PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress);
485 ApplicationContainer sinkApp = sinkHelper.Install (R1);
486 Ptr<PacketSink> packetSink = sinkApp.Get (0)->GetObject<PacketSink> ();
487 if (i < 10)
488 {
489 s1r1Sinks.push_back (packetSink);
490 }
491 else
492 {
493 s3r1Sinks.push_back (packetSink);
494 }
495 sinkApp.Start (startTime);
496 sinkApp.Stop (stopTime);
497
498 OnOffHelper clientHelper1 ("ns3::TcpSocketFactory", Address ());
499 clientHelper1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
500 clientHelper1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
501 clientHelper1.SetAttribute ("DataRate", DataRateValue (DataRate ("1Gbps")));
502 clientHelper1.SetAttribute ("PacketSize", UintegerValue (1000));
503
504 ApplicationContainer clientApps1;
505 AddressValue remoteAddress (InetSocketAddress (ipR1T2.GetAddress (0), port));
506 clientHelper1.SetAttribute ("Remote", remoteAddress);
507 if (i < 10)
508 {
509 clientApps1.Add (clientHelper1.Install (S1.Get (i)));
510 clientApps1.Start (i * flowStartupWindow / 10 + clientStartTime + MilliSeconds (i * 5));
511 }
512 else
513 {
514 clientApps1.Add (clientHelper1.Install (S3.Get (i - 10)));
515 clientApps1.Start ((i - 10) * flowStartupWindow / 10 + clientStartTime + MilliSeconds (i * 5));
516 }
517
518 clientApps1.Stop (stopTime);
519 }
520
521 rxS1R1Throughput.open ("dctcp-example-s1-r1-throughput.dat", std::ios::out);
522 rxS1R1Throughput << "#Time(s) flow thruput(Mb/s)" << std::endl;
523 rxS2R2Throughput.open ("dctcp-example-s2-r2-throughput.dat", std::ios::out);
524 rxS2R2Throughput << "#Time(s) flow thruput(Mb/s)" << std::endl;
525 rxS3R1Throughput.open ("dctcp-example-s3-r1-throughput.dat", std::ios::out);
526 rxS3R1Throughput << "#Time(s) flow thruput(Mb/s)" << std::endl;
527 fairnessIndex.open ("dctcp-example-fairness.dat", std::ios::out);
528 t1QueueLength.open ("dctcp-example-t1-length.dat", std::ios::out);
529 t1QueueLength << "#Time(s) qlen(pkts) qlen(us)" << std::endl;
530 t2QueueLength.open ("dctcp-example-t2-length.dat", std::ios::out);
531 t2QueueLength << "#Time(s) qlen(pkts) qlen(us)" << std::endl;
532 for (std::size_t i = 0; i < 10; i++)
533 {
534 s1r1Sinks[i]->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&TraceS1R1Sink, i));
535 }
536 for (std::size_t i = 0; i < 20; i++)
537 {
538 r2Sinks[i]->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&TraceS2R2Sink, i));
539 }
540 for (std::size_t i = 0; i < 10; i++)
541 {
542 s3r1Sinks[i]->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&TraceS3R1Sink, i));
543 }
544 Simulator::Schedule (flowStartupWindow + convergenceTime, &InitializeCounters);
545 Simulator::Schedule (flowStartupWindow + convergenceTime + measurementWindow, &PrintThroughput, measurementWindow);
546 Simulator::Schedule (flowStartupWindow + convergenceTime + measurementWindow, &PrintFairness, measurementWindow);
547 Simulator::Schedule (progressInterval, &PrintProgress, progressInterval);
548 Simulator::Schedule (flowStartupWindow + convergenceTime, &CheckT1QueueSize, queueDiscs1.Get (0));
549 Simulator::Schedule (flowStartupWindow + convergenceTime, &CheckT2QueueSize, queueDiscs2.Get (0));
550 Simulator::Stop (stopTime + TimeStep (1));
551
553
554 rxS1R1Throughput.close ();
555 rxS2R2Throughput.close ();
556 rxS3R1Throughput.close ();
557 fairnessIndex.close ();
558 t1QueueLength.close ();
559 t2QueueLength.close ();
560 Simulator::Destroy ();
561 return 0;
562}
void Run(ObjectFactory &factory, uint32_t pop, uint32_t total, uint32_t runs, Ptr< RandomVariableStream > eventStream, bool calRev)
Perform the runs for a single scheduler type.
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.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Parse command-line arguments.
Definition: command-line.h:229
Class for representing data rates.
Definition: data-rate.h:89
AttributeValue implementation for DataRate.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
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.
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.
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.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
A helper to make it easier to instantiate an ns3::OnOffApplication on a set of nodes.
Definition: on-off-helper.h:43
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
Receive and consume traffic generated to an IP address and port.
Definition: packet-sink.h:73
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.
NetDeviceContainer Install(NodeContainer c)
Holds a vector of ns3::QueueDisc pointers.
Ptr< QueueDisc > Get(std::size_t i) const
Get the Ptr<QueueDisc> stored in this container at a given index.
uint32_t GetNPackets(void) const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:438
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:104
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:388
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
Time TimeStep(uint64_t ts)
Scheduler interface.
Definition: nstime.h:1304
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.
Hold an unsigned integer type.
Definition: uinteger.h:44
void TraceS1R1Sink(std::size_t index, Ptr< const Packet > p, const Address &a)
std::ofstream rxS3R1Throughput
std::ofstream fairnessIndex
std::ofstream t1QueueLength
std::vector< uint64_t > rxS3R1Bytes
std::stringstream filePlotQueue1
void PrintFairness(Time measurementWindow)
void TraceS2R2Sink(std::size_t index, Ptr< const Packet > p, const Address &a)
std::vector< uint64_t > rxS2R2Bytes
void PrintThroughput(Time measurementWindow)
void CheckT1QueueSize(Ptr< QueueDisc > queue)
void PrintProgress(Time interval)
std::stringstream filePlotQueue2
std::ofstream rxS2R2Throughput
void TraceS3R1Sink(std::size_t index, Ptr< const Packet > p, const Address &a)
std::vector< uint64_t > rxS1R1Bytes
std::ofstream rxS1R1Throughput
void InitializeCounters(void)
std::ofstream t2QueueLength
void CheckT2QueueSize(Ptr< QueueDisc > queue)
uint16_t port
Definition: dsdv-manet.cc:45
Time stopTime
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:714
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:1245
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1253
address
Definition: first.py:40
stack
Definition: first.py:37
Every class exported by the ns3 library is enclosed in the ns3 namespace.
cmd
Definition: second.py:43