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 
104 using namespace ns3;
105 
106 std::stringstream filePlotQueue1;
107 std::stringstream filePlotQueue2;
108 std::ofstream rxS1R1Throughput;
109 std::ofstream rxS2R2Throughput;
110 std::ofstream rxS3R1Throughput;
111 std::ofstream fairnessIndex;
112 std::ofstream t1QueueLength;
113 std::ofstream t2QueueLength;
114 std::vector<uint64_t> rxS1R1Bytes;
115 std::vector<uint64_t> rxS2R2Bytes;
116 std::vector<uint64_t> rxS3R1Bytes;
117 
118 void
119 PrintProgress (Time interval)
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 
125 void
126 TraceS1R1Sink (std::size_t index, Ptr<const Packet> p, const Address& a)
127 {
128  rxS1R1Bytes[index] += p->GetSize ();
129 }
130 
131 void
132 TraceS2R2Sink (std::size_t index, Ptr<const Packet> p, const Address& a)
133 {
134  rxS2R2Bytes[index] += p->GetSize ();
135 }
136 
137 void
138 TraceS3R1Sink (std::size_t index, Ptr<const Packet> p, const Address& a)
139 {
140  rxS3R1Bytes[index] += p->GetSize ();
141 }
142 
143 void
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 
160 void
161 PrintThroughput (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
178 void
179 PrintFairness (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 
245 void
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
255 }
256 
257 void
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
266 }
267 
268 int 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 
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));
551 
552  Simulator::Run ();
553 
554  rxS1R1Throughput.close ();
555  rxS2R2Throughput.close ();
556  rxS3R1Throughput.close ();
557  fairnessIndex.close ();
558  t1QueueLength.close ();
559  t2QueueLength.close ();
561  return 0;
562 }
holds a vector of ns3::Application pointers.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
uint32_t GetNPackets(void) const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:440
an Inet address class
static Ipv4Address GetAny(void)
AttributeValue implementation for Boolean.
Definition: boolean.h:36
QueueDiscContainer Install(NetDeviceContainer c)
Class for representing queue sizes.
Definition: queue-size.h:94
holds a vector of std::pair of Ptr<Ipv4> and interface index.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
static void PopulateRoutingTables(void)
Build a routing database and initialize the routing tables of the nodes in the simulation.
Hold variables of type string.
Definition: string.h:41
NetDeviceContainer Install(NodeContainer c)
void Add(ApplicationContainer other)
Append the contents of another ApplicationContainer to the end of this container. ...
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1703
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:361
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1070
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes...
cmd
Definition: second.py:35
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.
A helper to make it easier to instantiate an ns3::OnOffApplication on a set of nodes.
Definition: on-off-helper.h:42
stack
Definition: first.py:41
double stopTime
std::ofstream t2QueueLength
uint16_t port
Definition: dsdv-manet.cc:45
a polymophic address class
Definition: address.h:90
Holds a vector of ns3::QueueDisc pointers.
std::vector< uint64_t > rxS2R2Bytes
Class for representing data rates.
Definition: data-rate.h:88
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
void TraceS1R1Sink(std::size_t index, Ptr< const Packet > p, const Address &a)
Hold an unsigned integer type.
Definition: uinteger.h:44
double startTime
holds a vector of ns3::NetDevice pointers
std::stringstream filePlotQueue1
std::ofstream t1QueueLength
std::vector< uint64_t > rxS1R1Bytes
Build a set of QueueDisc objects.
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...
void Start(Time start)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter...
Parse command-line arguments.
Definition: command-line.h:221
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:369
std::ofstream rxS1R1Throughput
Every class exported by the ns3 library is enclosed in the ns3 namespace.
keep track of a set of node pointers.
address
Definition: first.py:44
void CheckT2QueueSize(Ptr< QueueDisc > queue)
Ptr< QueueDisc > Get(std::size_t i) const
Get the Ptr<QueueDisc> stored in this container at a given index.
void PrintThroughput(Time measurementWindow)
uint16_t SetRootQueueDisc(std::string type, std::string n01="", const AttributeValue &v01=EmptyAttributeValue(), std::string n02="", const AttributeValue &v02=EmptyAttributeValue(), std::string n03="", const AttributeValue &v03=EmptyAttributeValue(), std::string n04="", const AttributeValue &v04=EmptyAttributeValue(), std::string n05="", const AttributeValue &v05=EmptyAttributeValue(), std::string n06="", const AttributeValue &v06=EmptyAttributeValue(), std::string n07="", const AttributeValue &v07=EmptyAttributeValue(), std::string n08="", const AttributeValue &v08=EmptyAttributeValue(), std::string n09="", const AttributeValue &v09=EmptyAttributeValue(), std::string n10="", const AttributeValue &v10=EmptyAttributeValue(), std::string n11="", const AttributeValue &v11=EmptyAttributeValue(), std::string n12="", const AttributeValue &v12=EmptyAttributeValue(), std::string n13="", const AttributeValue &v13=EmptyAttributeValue(), std::string n14="", const AttributeValue &v14=EmptyAttributeValue(), std::string n15="", const AttributeValue &v15=EmptyAttributeValue())
Helper function used to set a root queue disc of the given type and with the given attributes...
void InitializeCounters(void)
Time TimeStep(uint64_t ts)
Definition: nstime.h:1119
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
void PrintProgress(Time interval)
void TraceS3R1Sink(std::size_t index, Ptr< const Packet > p, const Address &a)
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
void PrintFairness(Time measurementWindow)
AttributeValue implementation for Address.
Definition: address.h:278
void Stop(Time stop)
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter...
std::ofstream rxS2R2Throughput
void TraceS2R2Sink(std::size_t index, Ptr< const Packet > p, const Address &a)
AttributeValue implementation for DataRate.
Definition: data-rate.h:229
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1062
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
std::vector< uint64_t > rxS3R1Bytes
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
std::ofstream rxS3R1Throughput
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Receive and consume traffic generated to an IP address and port.
Definition: packet-sink.h:71
std::ofstream fairnessIndex
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
void CheckT1QueueSize(Ptr< QueueDisc > queue)
std::stringstream filePlotQueue2