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