A Discrete-Event Network Simulator
API
fqcodel-l4s-example.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 NITK Surathkal
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: Bhaskar Kataria <bhaskar.k7920@gmail.com>
19  * Tom Henderson <tomhend@u.washington.edu>
20  * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
21  * Vivek Jain <jain.vivek.anand@gmail.com>
22  * Ankit Deepak <adadeepak8@gmail.com>
23  * This script is written using Tom Henderson's L4S evaluation available at https://gitlab.com/tomhend/modules/l4s-evaluation
24  */
25 
26 // The 9 configurations below test BIC and DCTCP under various scenarios.
27 // Scenarios are numbered 1-9. By default, scenario number 0 (i.e., no
28 // scenario) is configured, which means that the user is free to set
29 // any of the parameters freely; if scenarios 1 through 9 are selected,
30 // the scenario parameters are fixed.
31 //
32 // The configuration of the scenarios starts from basic TCP BIC without ECN
33 // with the base RTT of 80ms and then in the next scenario, ECN is enabled,
34 // and gradually, the complexity of the scenario increases and the last scenario
35 // consists of 2 flows one with BIC and other with DCTCP and finally tests
36 // The performance of the L4S mode of FqCoDel queue disc.
37 
289 #include "ns3/core-module.h"
290 #include "ns3/network-module.h"
291 #include "ns3/internet-module.h"
292 #include "ns3/flow-monitor-helper.h"
293 #include "ns3/point-to-point-module.h"
294 #include "ns3/applications-module.h"
295 #include "ns3/internet-apps-module.h"
296 #include "ns3/traffic-control-module.h"
297 
298 using namespace ns3;
299 
300 NS_LOG_COMPONENT_DEFINE ("FqCoDelL4SExample");
301 
302 uint32_t checkTimes;
304 
305 uint32_t g_n0BytesReceived = 0;
306 uint32_t g_n1BytesReceived = 0;
307 uint32_t g_marksObserved = 0;
308 uint32_t g_dropsObserved = 0;
309 
310 void
311 TraceN0Cwnd (std::ofstream* ofStream, uint32_t oldCwnd, uint32_t newCwnd)
312 {
313  // TCP segment size is configured below to be 1448 bytes
314  // so that we can report cwnd in units of segments
315  *ofStream << Simulator::Now ().GetSeconds () << " " << static_cast<double> (newCwnd) / 1448 << std::endl;
316 }
317 
318 void
319 TraceN1Cwnd (std::ofstream* ofStream, uint32_t oldCwnd, uint32_t newCwnd)
320 {
321  // TCP segment size is configured below to be 1448 bytes
322  // so that we can report cwnd in units of segments
323  *ofStream << Simulator::Now ().GetSeconds () << " " << static_cast<double> (newCwnd) / 1448 << std::endl;
324 }
325 
326 void
327 TraceN0Rtt (std::ofstream* ofStream, Time oldRtt, Time newRtt)
328 {
329  *ofStream << Simulator::Now ().GetSeconds () << " " << newRtt.GetSeconds () * 1000 << std::endl;
330 }
331 
332 void
333 TraceN1Rtt (std::ofstream* ofStream, Time oldRtt, Time newRtt)
334 {
335  *ofStream << Simulator::Now ().GetSeconds () << " " << newRtt.GetSeconds () * 1000 << std::endl;
336 }
337 
338 void
339 TracePingRtt (std::ofstream* ofStream, Time rtt)
340 {
341  *ofStream << Simulator::Now ().GetSeconds () << " " << rtt.GetSeconds () * 1000 << std::endl;
342 }
343 
344 void
346 {
347  g_n0BytesReceived += packet->GetSize ();
348 }
349 
350 void
352 {
353  g_n1BytesReceived += packet->GetSize ();
354 }
355 
356 void
357 TraceDrop (std::ofstream* ofStream, Ptr<const QueueDiscItem> item)
358 {
359  *ofStream << Simulator::Now ().GetSeconds () << " " << std::hex << item->Hash () << std::endl;
360  g_dropsObserved++;
361 }
362 
363 void
364 TraceMark (std::ofstream* ofStream, Ptr<const QueueDiscItem> item, const char* reason)
365 {
366  *ofStream << Simulator::Now ().GetSeconds () << " " << std::hex << item->Hash () << std::endl;
367  g_marksObserved++;
368 }
369 
370 void
371 TraceQueueLength (std::ofstream* ofStream, DataRate linkRate, uint32_t oldVal, uint32_t newVal)
372 {
373  // output in units of ms
374  *ofStream << Simulator::Now ().GetSeconds () << " " << std::fixed << static_cast<double> (newVal * 8) / (linkRate.GetBitRate () / 1000) << std::endl;
375 }
376 
377 void
378 TraceDropsFrequency (std::ofstream* ofStream, Time dropsSamplingInterval)
379 {
380  *ofStream << Simulator::Now ().GetSeconds () << " " << g_dropsObserved << std::endl;
381  g_dropsObserved = 0;
382  Simulator::Schedule (dropsSamplingInterval, &TraceDropsFrequency, ofStream, dropsSamplingInterval);
383 }
384 
385 void
386 TraceMarksFrequency (std::ofstream* ofStream, Time marksSamplingInterval)
387 {
388  *ofStream << Simulator::Now ().GetSeconds () << " " << g_marksObserved << std::endl;
389  g_marksObserved = 0;
390  Simulator::Schedule (marksSamplingInterval, &TraceMarksFrequency, ofStream, marksSamplingInterval);
391 }
392 
393 void
394 TraceN0Throughput (std::ofstream* ofStream, Time throughputInterval)
395 {
396  *ofStream << Simulator::Now ().GetSeconds () << " " << g_n0BytesReceived * 8 / throughputInterval.GetSeconds () / 1e6 << std::endl;
397  g_n0BytesReceived = 0;
398  Simulator::Schedule (throughputInterval, &TraceN0Throughput, ofStream, throughputInterval);
399 }
400 
401 void
402 TraceN1Throughput (std::ofstream* ofStream, Time throughputInterval)
403 {
404  *ofStream << Simulator::Now ().GetSeconds () << " " << g_n1BytesReceived * 8 / throughputInterval.GetSeconds () / 1e6 << std::endl;
405  g_n1BytesReceived = 0;
406  Simulator::Schedule (throughputInterval, &TraceN1Throughput, ofStream, throughputInterval);
407 }
408 
409 void
410 ScheduleN0TcpCwndTraceConnection (std::ofstream* ofStream)
411 {
412  Config::ConnectWithoutContext ("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeBoundCallback (&TraceN0Cwnd, ofStream));
413 }
414 
415 void
416 ScheduleN0TcpRttTraceConnection (std::ofstream* ofStream)
417 {
418  Config::ConnectWithoutContext ("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/RTT", MakeBoundCallback (&TraceN0Rtt, ofStream));
419 }
420 
421 void
423 {
424  Config::ConnectWithoutContext ("/NodeList/6/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&TraceN0Rx));
425 }
426 
427 void
428 ScheduleN1TcpCwndTraceConnection (std::ofstream* ofStream)
429 {
430  Config::ConnectWithoutContext ("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeBoundCallback (&TraceN1Cwnd, ofStream));
431 }
432 
433 void
434 ScheduleN1TcpRttTraceConnection (std::ofstream* ofStream)
435 {
436  Config::ConnectWithoutContext ("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/RTT", MakeBoundCallback (&TraceN1Rtt, ofStream));
437 }
438 
439 void
441 {
442  Config::ConnectWithoutContext ("/NodeList/7/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&TraceN1Rx));
443 }
444 
445 static void
446 PacketDequeue (std::ofstream* n0OfStream, std::ofstream* n1OfStream, Ptr<QueueDiscItem const> item)
447 {
448  Ptr<Packet> p = item->GetPacket ();
450  Ipv4Address address = iqdi->GetHeader ().GetDestination ();
451  Time qDelay = Simulator::Now () - item->GetTimeStamp ();
452  if (address == "192.168.2.2")
453  {
454  *n0OfStream << Simulator::Now ().GetSeconds () << " " << qDelay.GetMicroSeconds () / 1000.0 << std::endl;
455  }
456  else if (address == "192.168.3.2")
457  {
458  *n1OfStream << Simulator::Now ().GetSeconds () << " " << qDelay.GetMicroSeconds () / 1000.0 << std::endl;
459  }
460 }
461 
462 int
463 main (int argc, char *argv[])
464 {
466  // variables not configured at command line //
468  Time stopTime = Seconds (70);
469  Time baseRtt = MilliSeconds (80);
470  uint32_t pingSize = 100; // bytes
471  Time pingInterval = MilliSeconds (100);
472  Time marksSamplingInterval = MilliSeconds (100);
473  Time throughputSamplingInterval = MilliSeconds (200);
474  DataRate bottleneckRate ("100Mbps");
475 
476  std::string dir = "results/FqCoDel-L4S/";
477  std::string dirToSave = "mkdir -p " + dir;
478  if (system (dirToSave.c_str ()) == -1)
479  {
480  exit (1);
481  }
482 
483  std::string pingTraceFile = dir + "ping.dat";
484  std::string n0TcpRttTraceFile = dir + "n0-tcp-rtt.dat";
485  std::string n0TcpCwndTraceFile = dir + "n0-tcp-cwnd.dat";
486  std::string n0TcpThroughputTraceFile = dir + "n0-tcp-throughput.dat";
487  std::string n1TcpRttTraceFile = dir + "n1-tcp-rtt.dat";
488  std::string n1TcpCwndTraceFile = dir + "n1-tcp-cwnd.dat";
489  std::string n1TcpThroughputTraceFile = dir + "n1-tcp-throughput.dat";
490  std::string dropTraceFile = dir + "drops.dat";
491  std::string dropsFrequencyTraceFile = dir + "drops-frequency.dat";
492  std::string lengthTraceFile = dir + "length.dat";
493  std::string markTraceFile = dir + "mark.dat";
494  std::string marksFrequencyTraceFile = dir + "marks-frequency.dat";
495  std::string queueDelayN0TraceFile = dir + "queue-delay-n0.dat";
496  std::string queueDelayN1TraceFile = dir + "queue-delay-n1.dat";
497 
499  // variables configured at command line //
501  bool enablePcap = false;
502  bool useCeThreshold = false;
503  Time ceThreshold = MilliSeconds (1);
504  std::string n0TcpType = "bic";
505  std::string n1TcpType = "";
506  bool enableN1Tcp = false;
507  bool useEcn = true;
508  std::string queueType = "fq";
509  std::string linkDataRate = "1Gbps";
510  uint32_t scenarioNum = 0;
511 
513  // Override ns-3 defaults //
515  Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1448));
516  // Increase default buffer sizes to improve throughput over long delay paths
517  Config::SetDefault ("ns3::TcpSocket::SndBufSize",UintegerValue (8192000));
518  Config::SetDefault ("ns3::TcpSocket::RcvBufSize",UintegerValue (8192000));
519  Config::SetDefault ("ns3::TcpSocket::InitialCwnd", UintegerValue (10));
520  Config::SetDefault ("ns3::TcpL4Protocol::RecoveryType", TypeIdValue (TcpPrrRecovery::GetTypeId ()));
521 
523  // command-line argument parsing //
526  cmd.AddValue ("n0TcpType", "n0 TCP type (bic, dctcp, or reno)", n0TcpType);
527  cmd.AddValue ("n1TcpType", "n1 TCP type (bic, dctcp, or reno)", n1TcpType);
528  cmd.AddValue ("scenarioNum", "Scenario number from the scenarios avalaible in the file (1-9)", scenarioNum);
529  cmd.AddValue ("bottleneckQueueType", "n2 queue type (fq or codel)", queueType);
530  cmd.AddValue ("baseRtt", "base RTT", baseRtt);
531  cmd.AddValue ("useCeThreshold", "use CE Threshold", useCeThreshold);
532  cmd.AddValue ("useEcn", "use ECN", useEcn);
533  cmd.AddValue ("ceThreshold", "CoDel CE threshold", ceThreshold);
534  cmd.AddValue ("bottleneckRate", "data rate of bottleneck", bottleneckRate);
535  cmd.AddValue ("linkRate", "data rate of edge link", linkDataRate);
536  cmd.AddValue ("stopTime", "simulation stop time", stopTime);
537  cmd.AddValue ("enablePcap", "enable Pcap", enablePcap);
538  cmd.AddValue ("pingTraceFile", "filename for ping tracing", pingTraceFile);
539  cmd.AddValue ("n0TcpRttTraceFile", "filename for n0 rtt tracing", n0TcpRttTraceFile);
540  cmd.AddValue ("n0TcpCwndTraceFile", "filename for n0 cwnd tracing", n0TcpCwndTraceFile);
541  cmd.AddValue ("n0TcpThroughputTraceFile", "filename for n0 throughput tracing", n0TcpThroughputTraceFile);
542  cmd.AddValue ("n1TcpRttTraceFile", "filename for n1 rtt tracing", n1TcpRttTraceFile);
543  cmd.AddValue ("n1TcpCwndTraceFile", "filename for n1 cwnd tracing", n1TcpCwndTraceFile);
544  cmd.AddValue ("n1TcpThroughputTraceFile", "filename for n1 throughput tracing", n1TcpThroughputTraceFile);
545  cmd.AddValue ("dropTraceFile", "filename for n2 drops tracing", dropTraceFile);
546  cmd.AddValue ("dropsFrequencyTraceFile", "filename for n2 drop frequency tracing", dropsFrequencyTraceFile);
547  cmd.AddValue ("lengthTraceFile", "filename for n2 queue length tracing", lengthTraceFile);
548  cmd.AddValue ("markTraceFile", "filename for n2 mark tracing", markTraceFile);
549  cmd.AddValue ("marksFrequencyTraceFile", "filename for n2 mark frequency tracing", marksFrequencyTraceFile);
550  cmd.AddValue ("queueDelayN0TraceFile", "filename for n0 queue delay tracing", queueDelayN0TraceFile);
551  cmd.AddValue ("queueDelayN1TraceFile", "filename for n1 queue delay tracing", queueDelayN1TraceFile);
552  cmd.Parse (argc, argv);
553  Time oneWayDelay = baseRtt / 2;
554  TypeId n0TcpTypeId;
555  TypeId n1TcpTypeId;
556  TypeId queueTypeId;
557  if (!scenarioNum)
558  {
559  if (useEcn)
560  {
561  Config::SetDefault ("ns3::TcpSocketBase::UseEcn", StringValue ("On"));
562  }
563 
564  if (n0TcpType == "reno")
565  {
566  n0TcpTypeId = TcpNewReno::GetTypeId ();
567  }
568  else if (n0TcpType == "bic")
569  {
570  n0TcpTypeId = TcpBic::GetTypeId ();
571  }
572  else if (n0TcpType == "dctcp")
573  {
574  n0TcpTypeId = TcpDctcp::GetTypeId ();
575  }
576  else
577  {
578  NS_FATAL_ERROR ("Fatal error: tcp unsupported");
579  }
580 
581  if (n1TcpType == "reno")
582  {
583  enableN1Tcp = true;
584  n1TcpTypeId = TcpNewReno::GetTypeId ();
585  }
586  else if (n1TcpType == "bic")
587  {
588  enableN1Tcp = true;
589  n1TcpTypeId = TcpBic::GetTypeId ();
590  }
591  else if (n1TcpType == "dctcp")
592  {
593  enableN1Tcp = true;
594  n1TcpTypeId = TypeId::LookupByName ("ns3::TcpDctcp");
595  }
596  else if (n1TcpType == "")
597  {
598  NS_LOG_DEBUG ("No N1 TCP selected");
599  }
600  else
601  {
602  NS_FATAL_ERROR ("Fatal error: tcp unsupported");
603  }
604 
605  if (queueType == "fq")
606  {
607  queueTypeId = FqCoDelQueueDisc::GetTypeId ();
608  }
609  else if (queueType == "codel")
610  {
611  queueTypeId = CoDelQueueDisc::GetTypeId ();
612  }
613  else
614  {
615  NS_FATAL_ERROR ("Fatal error: queueType unsupported");
616  }
617  if (useCeThreshold)
618  {
619  Config::SetDefault ("ns3::FqCoDelQueueDisc::CeThreshold", TimeValue (ceThreshold));
620  }
621  }
622  else if (scenarioNum == 1 || scenarioNum == 2 || scenarioNum == 5 || scenarioNum == 6)
623  {
624  if (scenarioNum == 2 || scenarioNum == 6)
625  {
626  Config::SetDefault ("ns3::TcpSocketBase::UseEcn", StringValue ("On"));
627  }
628  n0TcpTypeId = TcpBic::GetTypeId ();
629  if (scenarioNum == 5 || scenarioNum == 6)
630  {
631  enableN1Tcp = true;
632  n1TcpTypeId = TcpBic::GetTypeId ();
633  }
634  queueTypeId = FqCoDelQueueDisc::GetTypeId ();
635  }
636  else if (scenarioNum == 3 || scenarioNum == 4 || scenarioNum == 7 || scenarioNum == 8 || scenarioNum == 9)
637  {
638  Config::SetDefault ("ns3::TcpSocketBase::UseEcn", StringValue ("On"));
639  n0TcpTypeId = TcpDctcp::GetTypeId ();
640  queueTypeId = FqCoDelQueueDisc::GetTypeId ();
641  oneWayDelay = MicroSeconds (500);
642  Config::SetDefault ("ns3::FqCoDelQueueDisc::CeThreshold", TimeValue (MilliSeconds (1)));
643  if (scenarioNum == 9)
644  {
645  n0TcpTypeId = TcpBic::GetTypeId ();
646  // For TCP Bic base RTT is 80 and base RTT for dctcp is set to 1 while setting delay for p2p devices
647  oneWayDelay = MilliSeconds (40);
648  }
649  if (scenarioNum == 4 || scenarioNum == 8 || scenarioNum == 9)
650  {
651  Config::SetDefault ("ns3::FqCoDelQueueDisc::UseL4s", BooleanValue (true));
652  Config::SetDefault ("ns3::TcpDctcp::UseEct0", BooleanValue (false));
653  }
654  if (scenarioNum == 7 || scenarioNum == 8 || scenarioNum == 9)
655  {
656  enableN1Tcp = true;
657  n1TcpTypeId = TcpDctcp::GetTypeId ();
658  }
659  }
660  else
661  {
662  NS_FATAL_ERROR ("Fatal error: scenario unavailble");
663  }
664 
665  std::ofstream pingOfStream;
666  pingOfStream.open (pingTraceFile.c_str (), std::ofstream::out);
667  std::ofstream n0TcpRttOfStream;
668  n0TcpRttOfStream.open (n0TcpRttTraceFile.c_str (), std::ofstream::out);
669  std::ofstream n0TcpCwndOfStream;
670  n0TcpCwndOfStream.open (n0TcpCwndTraceFile.c_str (), std::ofstream::out);
671  std::ofstream n0TcpThroughputOfStream;
672  n0TcpThroughputOfStream.open (n0TcpThroughputTraceFile.c_str (), std::ofstream::out);
673  std::ofstream n1TcpRttOfStream;
674  n1TcpRttOfStream.open (n1TcpRttTraceFile.c_str (), std::ofstream::out);
675  std::ofstream n1TcpCwndOfStream;
676  n1TcpCwndOfStream.open (n1TcpCwndTraceFile.c_str (), std::ofstream::out);
677  std::ofstream n1TcpThroughputOfStream;
678  n1TcpThroughputOfStream.open (n1TcpThroughputTraceFile.c_str (), std::ofstream::out);
679 
680  // Queue disc files
681  std::ofstream dropOfStream;
682  dropOfStream.open (dropTraceFile.c_str (), std::ofstream::out);
683  std::ofstream markOfStream;
684  markOfStream.open (markTraceFile.c_str (), std::ofstream::out);
685  std::ofstream dropsFrequencyOfStream;
686  dropsFrequencyOfStream.open (dropsFrequencyTraceFile.c_str (), std::ofstream::out);
687  std::ofstream marksFrequencyOfStream;
688  marksFrequencyOfStream.open (marksFrequencyTraceFile.c_str (), std::ofstream::out);
689  std::ofstream lengthOfStream;
690  lengthOfStream.open (lengthTraceFile.c_str (), std::ofstream::out);
691  std::ofstream queueDelayN0OfStream;
692  queueDelayN0OfStream.open (queueDelayN0TraceFile.c_str (), std::ofstream::out);
693  std::ofstream queueDelayN1OfStream;
694  queueDelayN1OfStream.open (queueDelayN1TraceFile.c_str (), std::ofstream::out);
695 
697  // scenario setup //
699  Ptr<Node> pingServer = CreateObject<Node> ();
700  Ptr<Node> n0Server = CreateObject<Node> ();
701  Ptr<Node> n1Server = CreateObject<Node> ();
702  Ptr<Node> n2 = CreateObject<Node> ();
703  Ptr<Node> n3 = CreateObject<Node> ();
704  Ptr<Node> pingClient = CreateObject<Node> ();
705  Ptr<Node> n4Client = CreateObject<Node> ();
706  Ptr<Node> n5Client = CreateObject<Node> ();
707 
708  // Device containers
709  NetDeviceContainer pingServerDevices;
710  NetDeviceContainer n0ServerDevices;
711  NetDeviceContainer n1ServerDevices;
712  NetDeviceContainer n2n3Devices;
713  NetDeviceContainer pingClientDevices;
714  NetDeviceContainer n4ClientDevices;
715  NetDeviceContainer n5ClientDevices;
716 
717  PointToPointHelper p2p;
718  p2p.SetQueue ("ns3::DropTailQueue", "MaxSize", QueueSizeValue (QueueSize ("3p")));
719  p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate (linkDataRate)));
720  // Add delay only on the server links
721  p2p.SetChannelAttribute ("Delay", TimeValue (oneWayDelay));
722  pingServerDevices = p2p.Install (n2, pingServer);
723  n0ServerDevices = p2p.Install (n2, n0Server);
724 
725  // In scenario 9, base RTT of n1server (dctcp) is 1ms
726  if (scenarioNum == 9)
727  {
728  p2p.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (500)));
729  }
730  n1ServerDevices = p2p.Install (n2, n1Server);
731  p2p.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (1)));
732  n2n3Devices = p2p.Install (n2, n3);
733  pingClientDevices = p2p.Install (n3, pingClient);
734  n4ClientDevices = p2p.Install (n3, n4Client);
735  n5ClientDevices = p2p.Install (n3, n5Client);
737  p->SetAttribute ("DataRate", DataRateValue (bottleneckRate));
738 
739  InternetStackHelper stackHelper;
740  stackHelper.InstallAll ();
741 
742  // Set the per-node TCP type here
743  Ptr<TcpL4Protocol> proto;
744  proto = n4Client->GetObject<TcpL4Protocol> ();
745  proto->SetAttribute ("SocketType", TypeIdValue (n0TcpTypeId));
746  proto = n0Server->GetObject<TcpL4Protocol> ();
747  proto->SetAttribute ("SocketType", TypeIdValue (n0TcpTypeId));
748  if (enableN1Tcp)
749  {
750  proto = n5Client->GetObject<TcpL4Protocol> ();
751  proto->SetAttribute ("SocketType", TypeIdValue (n1TcpTypeId));
752  proto = n1Server->GetObject<TcpL4Protocol> ();
753  proto->SetAttribute ("SocketType", TypeIdValue (n1TcpTypeId));
754  }
755 
756  // InternetStackHelper will install a base TrafficControLayer on the node,
757  // but the Ipv4AddressHelper below will install the default FqCoDelQueueDisc
758  // on all single device nodes. The below code overrides the configuration
759  // that is normally done by the Ipv4AddressHelper::Install() method by
760  // instead explicitly configuring the queue discs we want on each device.
761  TrafficControlHelper tchFq;
762  tchFq.SetRootQueueDisc ("ns3::FqCoDelQueueDisc");
763  tchFq.SetQueueLimits ("ns3::DynamicQueueLimits", "HoldTime", StringValue ("1ms"));
764  tchFq.Install (pingServerDevices);
765  tchFq.Install (n0ServerDevices);
766  tchFq.Install (n1ServerDevices);
767  tchFq.Install (n2n3Devices.Get (1)); // n2 queue for bottleneck link
768  tchFq.Install (pingClientDevices);
769  tchFq.Install (n4ClientDevices);
770  tchFq.Install (n5ClientDevices);
771  TrafficControlHelper tchN2;
772  tchN2.SetRootQueueDisc (queueTypeId.GetName ());
773  tchN2.SetQueueLimits ("ns3::DynamicQueueLimits", "HoldTime", StringValue ("1000ms"));
774  tchN2.Install (n2n3Devices.Get (0));
775 
776  Ipv4AddressHelper ipv4;
777  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
778  Ipv4InterfaceContainer pingServerIfaces = ipv4.Assign (pingServerDevices);
779  ipv4.SetBase ("10.1.2.0", "255.255.255.0");
780  Ipv4InterfaceContainer n0ServerIfaces = ipv4.Assign (n0ServerDevices);
781  ipv4.SetBase ("10.1.3.0", "255.255.255.0");
782  Ipv4InterfaceContainer secondServerIfaces = ipv4.Assign (n1ServerDevices);
783  ipv4.SetBase ("172.16.1.0", "255.255.255.0");
784  Ipv4InterfaceContainer n2n3Ifaces = ipv4.Assign (n2n3Devices);
785  ipv4.SetBase ("192.168.1.0", "255.255.255.0");
786  Ipv4InterfaceContainer pingClientIfaces = ipv4.Assign (pingClientDevices);
787  ipv4.SetBase ("192.168.2.0", "255.255.255.0");
788  Ipv4InterfaceContainer n4ClientIfaces = ipv4.Assign (n4ClientDevices);
789  ipv4.SetBase ("192.168.3.0", "255.255.255.0");
790  Ipv4InterfaceContainer n5ClientIfaces = ipv4.Assign (n5ClientDevices);
791 
793 
795  // application setup //
797 
798  V4PingHelper pingHelper ("192.168.1.2");
799  pingHelper.SetAttribute ("Interval", TimeValue (pingInterval));
800  pingHelper.SetAttribute ("Size", UintegerValue (pingSize));
801  ApplicationContainer pingContainer = pingHelper.Install (pingServer);
802  Ptr<V4Ping> v4Ping = pingContainer.Get (0)->GetObject<V4Ping> ();
803  v4Ping->TraceConnectWithoutContext ("Rtt", MakeBoundCallback (&TracePingRtt, &pingOfStream));
804  pingContainer.Start (Seconds (1));
805  pingContainer.Stop (stopTime - Seconds (1));
806 
807  BulkSendHelper tcp ("ns3::TcpSocketFactory", Address ());
808  // set to large value: e.g. 1000 Mb/s for 60 seconds = 7500000000 bytes
809  tcp.SetAttribute ("MaxBytes", UintegerValue (7500000000));
810  // Configure n4/n0 TCP client/server pair
811  uint16_t n4Port = 5000;
812  ApplicationContainer n0App;
813  InetSocketAddress n0DestAddress (n4ClientIfaces.GetAddress (1), n4Port);
814  tcp.SetAttribute ("Remote", AddressValue (n0DestAddress));
815  n0App = tcp.Install (n0Server);
816  n0App.Start (Seconds (5));
817  n0App.Stop (stopTime - Seconds (1));
818 
819  Address n4SinkAddress (InetSocketAddress (Ipv4Address::GetAny (), n4Port));
820  PacketSinkHelper n4SinkHelper ("ns3::TcpSocketFactory", n4SinkAddress);
821  ApplicationContainer n4SinkApp;
822  n4SinkApp = n4SinkHelper.Install (n4Client);
823  n4SinkApp.Start (Seconds (5));
824  n4SinkApp.Stop (stopTime - MilliSeconds (500));
825 
826  // Configure second TCP client/server pair
827  if (enableN1Tcp)
828  {
829  uint16_t n5Port = 5000;
830  ApplicationContainer secondApp;
831  InetSocketAddress n1DestAddress (n5ClientIfaces.GetAddress (1), n5Port);
832  tcp.SetAttribute ("Remote", AddressValue (n1DestAddress));
833  secondApp = tcp.Install (n1Server);
834  secondApp.Start (Seconds (15));
835  secondApp.Stop (stopTime - Seconds (1));
836 
837  Address n5SinkAddress (InetSocketAddress (Ipv4Address::GetAny (), n5Port));
838  PacketSinkHelper n5SinkHelper ("ns3::TcpSocketFactory", n5SinkAddress);
839  ApplicationContainer n5SinkApp;
840  n5SinkApp = n5SinkHelper.Install (n5Client);
841  n5SinkApp.Start (Seconds (15));
842  n5SinkApp.Stop (stopTime - MilliSeconds (500));
843  }
844 
845  // Setup traces that can be hooked now
847  Ptr<QueueDisc> qd;
848  tc = n2n3Devices.Get (0)->GetNode ()->GetObject<TrafficControlLayer> ();
849  qd = tc->GetRootQueueDiscOnDevice (n2n3Devices.Get (0));
850  qd->TraceConnectWithoutContext ("Drop", MakeBoundCallback (&TraceDrop, &dropOfStream));
851  qd->TraceConnectWithoutContext ("Mark", MakeBoundCallback (&TraceMark, &markOfStream));
852  qd->TraceConnectWithoutContext ("BytesInQueue", MakeBoundCallback (&TraceQueueLength, &lengthOfStream, bottleneckRate));
853  qd->TraceConnectWithoutContext ("Dequeue", MakeBoundCallback (&PacketDequeue, &queueDelayN0OfStream, &queueDelayN1OfStream));
854 
855  // Setup scheduled traces; TCP traces must be hooked after socket creation
856  Simulator::Schedule (Seconds (5) + MilliSeconds (100), &ScheduleN0TcpRttTraceConnection, &n0TcpRttOfStream);
857  Simulator::Schedule (Seconds (5) + MilliSeconds (100), &ScheduleN0TcpCwndTraceConnection, &n0TcpCwndOfStream);
859  Simulator::Schedule (throughputSamplingInterval, &TraceN0Throughput, &n0TcpThroughputOfStream, throughputSamplingInterval);
860  // Setup scheduled traces; TCP traces must be hooked after socket creation
861  if (enableN1Tcp)
862  {
863  Simulator::Schedule (Seconds (15) + MilliSeconds (100), &ScheduleN1TcpRttTraceConnection, &n1TcpRttOfStream);
864  Simulator::Schedule (Seconds (15) + MilliSeconds (100), &ScheduleN1TcpCwndTraceConnection, &n1TcpCwndOfStream);
866  }
867  Simulator::Schedule (throughputSamplingInterval, &TraceN1Throughput, &n1TcpThroughputOfStream, throughputSamplingInterval);
868  Simulator::Schedule (marksSamplingInterval, &TraceMarksFrequency, &marksFrequencyOfStream, marksSamplingInterval);
869  Simulator::Schedule (marksSamplingInterval, &TraceDropsFrequency, &dropsFrequencyOfStream, marksSamplingInterval);
870 
871  if (enablePcap)
872  {
873  p2p.EnablePcapAll ("FqCoDel-L4S-example", false);
874  }
875 
877  Simulator::Run ();
878 
879  pingOfStream.close ();
880  n0TcpCwndOfStream.close ();
881  n0TcpRttOfStream.close ();
882  n0TcpThroughputOfStream.close ();
883  n1TcpCwndOfStream.close ();
884  n1TcpRttOfStream.close ();
885  n1TcpThroughputOfStream.close ();
886  dropOfStream.close ();
887  markOfStream.close ();
888  dropsFrequencyOfStream.close ();
889  marksFrequencyOfStream.close ();
890  lengthOfStream.close ();
891  queueDelayN0OfStream.close ();
892  queueDelayN1OfStream.close ();
893 }
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Address.
Definition: address.h:278
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 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
A helper to make it easier to instantiate an ns3::BulkSendApplication on a set of nodes.
static TypeId GetTypeId(void)
Get the type ID.
Parse command-line arguments.
Definition: command-line.h:229
Class for representing data rates.
Definition: data-rate.h:89
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:287
AttributeValue implementation for DataRate.
Definition: data-rate.h:298
static TypeId GetTypeId(void)
Get the type ID.
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
void InstallAll(void) const
Aggregate IPv4, IPv6, UDP, and TCP stacks to all nodes in the simulation.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
static Ipv4Address GetAny(void)
static void PopulateRoutingTables(void)
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
Ipv4QueueDiscItem is a subclass of QueueDiscItem which stores IPv4 packets.
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.
virtual Ptr< Node > GetNode(void) const =0
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
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.
void EnablePcapAll(std::string prefix, bool promiscuous=false)
Enable pcap output on each device (which is of the appropriate type) in the set of all nodes created ...
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 SetQueue(std::string type, std::string n1="", const AttributeValue &v1=EmptyAttributeValue(), std::string n2="", const AttributeValue &v2=EmptyAttributeValue(), std::string n3="", const AttributeValue &v3=EmptyAttributeValue(), std::string n4="", const AttributeValue &v4=EmptyAttributeValue())
Each point to point net device must have a queue to pass packets through.
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)
A Device for a Point to Point Network Link.
Class for representing queue sizes.
Definition: queue-size.h:95
AttributeValue implementation for QueueSize.
Definition: queue-size.h:221
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Hold variables of type string.
Definition: string.h:41
static TypeId GetTypeId(void)
Get the type ID.
Definition: tcp-bic.cc:29
static TypeId GetTypeId(void)
Get the type ID.
Definition: tcp-dctcp.cc:33
TCP socket creation and multiplexing/demultiplexing.
static TypeId GetTypeId(void)
Get the type ID.
static TypeId GetTypeId(void)
Get the type ID.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:387
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
AttributeValue implementation for Time.
Definition: nstime.h:1308
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.
void SetQueueLimits(std::string type, Args &&... args)
Helper function used to add a queue limits object to the transmission queues of the devices.
Introspection did not find any typical Config paths.
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:829
std::string GetName(void) const
Get the name.
Definition: type-id.cc:976
AttributeValue implementation for TypeId.
Definition: type-id.h:595
Hold an unsigned integer type.
Definition: uinteger.h:44
Create a IPv4 ping application and associate it to a node.
Definition: v4ping-helper.h:38
an application which sends one ICMP ECHO request, waits for a REPLYs and reports the calculated RTT.
Definition: v4ping.h:42
Time stopTime
std::string dir
void TraceDropsFrequency(std::ofstream *ofStream, Time dropsSamplingInterval)
void TraceN0Rx(Ptr< const Packet > packet, const Address &address)
void ScheduleN0TcpCwndTraceConnection(std::ofstream *ofStream)
void TraceMarksFrequency(std::ofstream *ofStream, Time marksSamplingInterval)
void ScheduleN1TcpRttTraceConnection(std::ofstream *ofStream)
void TraceN0Cwnd(std::ofstream *ofStream, uint32_t oldCwnd, uint32_t newCwnd)
void TraceN1Throughput(std::ofstream *ofStream, Time throughputInterval)
void ScheduleN1PacketSinkConnection(void)
void TraceMark(std::ofstream *ofStream, Ptr< const QueueDiscItem > item, const char *reason)
void TracePingRtt(std::ofstream *ofStream, Time rtt)
void ScheduleN0PacketSinkConnection(void)
void TraceN1Cwnd(std::ofstream *ofStream, uint32_t oldCwnd, uint32_t newCwnd)
uint32_t g_n1BytesReceived
double avgQueueDiscSize
void TraceDrop(std::ofstream *ofStream, Ptr< const QueueDiscItem > item)
uint32_t g_n0BytesReceived
void TraceN0Throughput(std::ofstream *ofStream, Time throughputInterval)
uint32_t g_marksObserved
void TraceN1Rtt(std::ofstream *ofStream, Time oldRtt, Time newRtt)
void ScheduleN1TcpCwndTraceConnection(std::ofstream *ofStream)
void TraceN0Rtt(std::ofstream *ofStream, Time oldRtt, Time newRtt)
uint32_t g_dropsObserved
void TraceQueueLength(std::ofstream *ofStream, DataRate linkRate, uint32_t oldVal, uint32_t newVal)
void TraceN1Rx(Ptr< const Packet > packet, const Address &address)
uint32_t checkTimes
static void PacketDequeue(std::ofstream *n0OfStream, std::ofstream *n1OfStream, Ptr< QueueDiscItem const > item)
void ScheduleN0TcpRttTraceConnection(std::ofstream *ofStream)
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:901
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1709
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
address
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:415
cmd
Definition: second.py:35
bool enablePcap