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