A Discrete-Event Network Simulator
API
fqcodel-l4s-example.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 NITK Surathkal
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Authors: Bhaskar Kataria <bhaskar.k7920@gmail.com>
18  * Tom Henderson <tomhend@u.washington.edu>
19  * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
20  * Vivek Jain <jain.vivek.anand@gmail.com>
21  * Ankit Deepak <adadeepak8@gmail.com>
22  * This script is written using Tom Henderson's L4S evaluation available at
23  * 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 
273 #include "ns3/applications-module.h"
274 #include "ns3/core-module.h"
275 #include "ns3/flow-monitor-helper.h"
276 #include "ns3/internet-apps-module.h"
277 #include "ns3/internet-module.h"
278 #include "ns3/network-module.h"
279 #include "ns3/point-to-point-module.h"
280 #include "ns3/traffic-control-module.h"
281 
282 using namespace ns3;
283 
284 NS_LOG_COMPONENT_DEFINE("FqCoDelL4SExample");
285 
286 uint32_t checkTimes;
288 
289 uint32_t g_n0BytesReceived = 0;
290 uint32_t g_n1BytesReceived = 0;
291 uint32_t g_marksObserved = 0;
292 uint32_t g_dropsObserved = 0;
293 
294 void
295 TraceN0Cwnd(std::ofstream* ofStream, uint32_t oldCwnd, uint32_t newCwnd)
296 {
297  // TCP segment size is configured below to be 1448 bytes
298  // so that we can report cwnd in units of segments
299  *ofStream << Simulator::Now().GetSeconds() << " " << static_cast<double>(newCwnd) / 1448
300  << std::endl;
301 }
302 
303 void
304 TraceN1Cwnd(std::ofstream* ofStream, uint32_t oldCwnd, uint32_t newCwnd)
305 {
306  // TCP segment size is configured below to be 1448 bytes
307  // so that we can report cwnd in units of segments
308  *ofStream << Simulator::Now().GetSeconds() << " " << static_cast<double>(newCwnd) / 1448
309  << std::endl;
310 }
311 
312 void
313 TraceN0Rtt(std::ofstream* ofStream, Time oldRtt, Time newRtt)
314 {
315  *ofStream << Simulator::Now().GetSeconds() << " " << newRtt.GetSeconds() * 1000 << std::endl;
316 }
317 
318 void
319 TraceN1Rtt(std::ofstream* ofStream, Time oldRtt, Time newRtt)
320 {
321  *ofStream << Simulator::Now().GetSeconds() << " " << newRtt.GetSeconds() * 1000 << std::endl;
322 }
323 
324 void
325 TracePingRtt(std::ofstream* ofStream, uint16_t seqNo, Time rtt)
326 {
327  *ofStream << Simulator::Now().GetSeconds() << " " << seqNo << " " << rtt.GetSeconds() * 1000
328  << std::endl;
329 }
330 
331 void
333 {
334  g_n0BytesReceived += packet->GetSize();
335 }
336 
337 void
339 {
340  g_n1BytesReceived += packet->GetSize();
341 }
342 
343 void
344 TraceDrop(std::ofstream* ofStream, Ptr<const QueueDiscItem> item)
345 {
346  *ofStream << Simulator::Now().GetSeconds() << " " << std::hex << item->Hash() << std::endl;
347  g_dropsObserved++;
348 }
349 
350 void
351 TraceMark(std::ofstream* ofStream, Ptr<const QueueDiscItem> item, const char* reason)
352 {
353  *ofStream << Simulator::Now().GetSeconds() << " " << std::hex << item->Hash() << std::endl;
354  g_marksObserved++;
355 }
356 
357 void
358 TraceQueueLength(std::ofstream* ofStream, DataRate linkRate, uint32_t oldVal, uint32_t newVal)
359 {
360  // output in units of ms
361  *ofStream << Simulator::Now().GetSeconds() << " " << std::fixed
362  << static_cast<double>(newVal * 8) / (linkRate.GetBitRate() / 1000) << std::endl;
363 }
364 
365 void
366 TraceDropsFrequency(std::ofstream* ofStream, Time dropsSamplingInterval)
367 {
368  *ofStream << Simulator::Now().GetSeconds() << " " << g_dropsObserved << std::endl;
369  g_dropsObserved = 0;
370  Simulator::Schedule(dropsSamplingInterval,
372  ofStream,
373  dropsSamplingInterval);
374 }
375 
376 void
377 TraceMarksFrequency(std::ofstream* ofStream, Time marksSamplingInterval)
378 {
379  *ofStream << Simulator::Now().GetSeconds() << " " << g_marksObserved << std::endl;
380  g_marksObserved = 0;
381  Simulator::Schedule(marksSamplingInterval,
383  ofStream,
384  marksSamplingInterval);
385 }
386 
387 void
388 TraceN0Throughput(std::ofstream* ofStream, Time throughputInterval)
389 {
390  *ofStream << Simulator::Now().GetSeconds() << " "
391  << g_n0BytesReceived * 8 / throughputInterval.GetSeconds() / 1e6 << std::endl;
392  g_n0BytesReceived = 0;
393  Simulator::Schedule(throughputInterval, &TraceN0Throughput, ofStream, throughputInterval);
394 }
395 
396 void
397 TraceN1Throughput(std::ofstream* ofStream, Time throughputInterval)
398 {
399  *ofStream << Simulator::Now().GetSeconds() << " "
400  << g_n1BytesReceived * 8 / throughputInterval.GetSeconds() / 1e6 << std::endl;
401  g_n1BytesReceived = 0;
402  Simulator::Schedule(throughputInterval, &TraceN1Throughput, ofStream, throughputInterval);
403 }
404 
405 void
406 ScheduleN0TcpCwndTraceConnection(std::ofstream* ofStream)
407 {
408  Config::ConnectWithoutContext("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
409  MakeBoundCallback(&TraceN0Cwnd, ofStream));
410 }
411 
412 void
413 ScheduleN0TcpRttTraceConnection(std::ofstream* ofStream)
414 {
415  Config::ConnectWithoutContext("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/RTT",
416  MakeBoundCallback(&TraceN0Rtt, ofStream));
417 }
418 
419 void
421 {
422  Config::ConnectWithoutContext("/NodeList/6/ApplicationList/*/$ns3::PacketSink/Rx",
424 }
425 
426 void
427 ScheduleN1TcpCwndTraceConnection(std::ofstream* ofStream)
428 {
429  Config::ConnectWithoutContext("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
430  MakeBoundCallback(&TraceN1Cwnd, ofStream));
431 }
432 
433 void
434 ScheduleN1TcpRttTraceConnection(std::ofstream* ofStream)
435 {
436  Config::ConnectWithoutContext("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/RTT",
437  MakeBoundCallback(&TraceN1Rtt, ofStream));
438 }
439 
440 void
442 {
443  Config::ConnectWithoutContext("/NodeList/7/ApplicationList/*/$ns3::PacketSink/Rx",
445 }
446 
447 static void
448 PacketDequeue(std::ofstream* n0OfStream, std::ofstream* n1OfStream, Ptr<const QueueDiscItem> item)
449 {
450  Ptr<Packet> p = item->GetPacket();
452  Ptr<const Ipv4QueueDiscItem>(dynamic_cast<const Ipv4QueueDiscItem*>(PeekPointer(item)));
453  Ipv4Address address = iqdi->GetHeader().GetDestination();
454  Time qDelay = Simulator::Now() - item->GetTimeStamp();
455  if (address == "192.168.2.2")
456  {
457  *n0OfStream << Simulator::Now().GetSeconds() << " " << qDelay.GetMicroSeconds() / 1000.0
458  << std::endl;
459  }
460  else if (address == "192.168.3.2")
461  {
462  *n1OfStream << Simulator::Now().GetSeconds() << " " << qDelay.GetMicroSeconds() / 1000.0
463  << std::endl;
464  }
465 }
466 
467 int
468 main(int argc, char* argv[])
469 {
471  // variables not configured at command line //
473  Time stopTime = Seconds(70);
474  Time baseRtt = MilliSeconds(80);
475  uint32_t pingSize = 100; // bytes
476  Time pingInterval = MilliSeconds(100);
477  Time marksSamplingInterval = MilliSeconds(100);
478  Time throughputSamplingInterval = MilliSeconds(200);
479  DataRate bottleneckRate("100Mbps");
480 
481  std::string dir = "results/FqCoDel-L4S/";
482  std::string dirToSave = "mkdir -p " + dir;
483  if (system(dirToSave.c_str()) == -1)
484  {
485  exit(1);
486  }
487 
488  std::string pingTraceFile = dir + "ping.dat";
489  std::string n0TcpRttTraceFile = dir + "n0-tcp-rtt.dat";
490  std::string n0TcpCwndTraceFile = dir + "n0-tcp-cwnd.dat";
491  std::string n0TcpThroughputTraceFile = dir + "n0-tcp-throughput.dat";
492  std::string n1TcpRttTraceFile = dir + "n1-tcp-rtt.dat";
493  std::string n1TcpCwndTraceFile = dir + "n1-tcp-cwnd.dat";
494  std::string n1TcpThroughputTraceFile = dir + "n1-tcp-throughput.dat";
495  std::string dropTraceFile = dir + "drops.dat";
496  std::string dropsFrequencyTraceFile = dir + "drops-frequency.dat";
497  std::string lengthTraceFile = dir + "length.dat";
498  std::string markTraceFile = dir + "mark.dat";
499  std::string marksFrequencyTraceFile = dir + "marks-frequency.dat";
500  std::string queueDelayN0TraceFile = dir + "queue-delay-n0.dat";
501  std::string queueDelayN1TraceFile = dir + "queue-delay-n1.dat";
502 
504  // variables configured at command line //
506  bool enablePcap = false;
507  bool useCeThreshold = false;
508  Time ceThreshold = MilliSeconds(1);
509  std::string n0TcpType = "bic";
510  std::string n1TcpType = "";
511  bool enableN1Tcp = false;
512  bool useEcn = true;
513  std::string queueType = "fq";
514  std::string linkDataRate = "1Gbps";
515  uint32_t scenarioNum = 0;
516 
518  // Override ns-3 defaults //
520  Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(1448));
521  // Increase default buffer sizes to improve throughput over long delay paths
522  Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(8192000));
523  Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(8192000));
524  Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(10));
525  Config::SetDefault("ns3::TcpL4Protocol::RecoveryType",
527 
529  // command-line argument parsing //
532  cmd.AddValue("n0TcpType", "n0 TCP type (bic, dctcp, or reno)", n0TcpType);
533  cmd.AddValue("n1TcpType", "n1 TCP type (bic, dctcp, or reno)", n1TcpType);
534  cmd.AddValue("scenarioNum",
535  "Scenario number from the scenarios available in the file (1-9)",
536  scenarioNum);
537  cmd.AddValue("bottleneckQueueType", "n2 queue type (fq or codel)", queueType);
538  cmd.AddValue("baseRtt", "base RTT", baseRtt);
539  cmd.AddValue("useCeThreshold", "use CE Threshold", useCeThreshold);
540  cmd.AddValue("useEcn", "use ECN", useEcn);
541  cmd.AddValue("ceThreshold", "CoDel CE threshold", ceThreshold);
542  cmd.AddValue("bottleneckRate", "data rate of bottleneck", bottleneckRate);
543  cmd.AddValue("linkRate", "data rate of edge link", linkDataRate);
544  cmd.AddValue("stopTime", "simulation stop time", stopTime);
545  cmd.AddValue("enablePcap", "enable Pcap", enablePcap);
546  cmd.AddValue("pingTraceFile", "filename for ping tracing", pingTraceFile);
547  cmd.AddValue("n0TcpRttTraceFile", "filename for n0 rtt tracing", n0TcpRttTraceFile);
548  cmd.AddValue("n0TcpCwndTraceFile", "filename for n0 cwnd tracing", n0TcpCwndTraceFile);
549  cmd.AddValue("n0TcpThroughputTraceFile",
550  "filename for n0 throughput tracing",
551  n0TcpThroughputTraceFile);
552  cmd.AddValue("n1TcpRttTraceFile", "filename for n1 rtt tracing", n1TcpRttTraceFile);
553  cmd.AddValue("n1TcpCwndTraceFile", "filename for n1 cwnd tracing", n1TcpCwndTraceFile);
554  cmd.AddValue("n1TcpThroughputTraceFile",
555  "filename for n1 throughput tracing",
556  n1TcpThroughputTraceFile);
557  cmd.AddValue("dropTraceFile", "filename for n2 drops tracing", dropTraceFile);
558  cmd.AddValue("dropsFrequencyTraceFile",
559  "filename for n2 drop frequency tracing",
560  dropsFrequencyTraceFile);
561  cmd.AddValue("lengthTraceFile", "filename for n2 queue length tracing", lengthTraceFile);
562  cmd.AddValue("markTraceFile", "filename for n2 mark tracing", markTraceFile);
563  cmd.AddValue("marksFrequencyTraceFile",
564  "filename for n2 mark frequency tracing",
565  marksFrequencyTraceFile);
566  cmd.AddValue("queueDelayN0TraceFile",
567  "filename for n0 queue delay tracing",
568  queueDelayN0TraceFile);
569  cmd.AddValue("queueDelayN1TraceFile",
570  "filename for n1 queue delay tracing",
571  queueDelayN1TraceFile);
572  cmd.Parse(argc, argv);
573  Time oneWayDelay = baseRtt / 2;
574  TypeId n0TcpTypeId;
575  TypeId n1TcpTypeId;
576  TypeId queueTypeId;
577  if (!scenarioNum)
578  {
579  if (useEcn)
580  {
581  Config::SetDefault("ns3::TcpSocketBase::UseEcn", StringValue("On"));
582  }
583 
584  if (n0TcpType == "reno")
585  {
586  n0TcpTypeId = TcpNewReno::GetTypeId();
587  }
588  else if (n0TcpType == "bic")
589  {
590  n0TcpTypeId = TcpBic::GetTypeId();
591  }
592  else if (n0TcpType == "dctcp")
593  {
594  n0TcpTypeId = TcpDctcp::GetTypeId();
595  }
596  else
597  {
598  NS_FATAL_ERROR("Fatal error: tcp unsupported");
599  }
600 
601  if (n1TcpType == "reno")
602  {
603  enableN1Tcp = true;
604  n1TcpTypeId = TcpNewReno::GetTypeId();
605  }
606  else if (n1TcpType == "bic")
607  {
608  enableN1Tcp = true;
609  n1TcpTypeId = TcpBic::GetTypeId();
610  }
611  else if (n1TcpType == "dctcp")
612  {
613  enableN1Tcp = true;
614  n1TcpTypeId = TypeId::LookupByName("ns3::TcpDctcp");
615  }
616  else if (n1TcpType.empty())
617  {
618  NS_LOG_DEBUG("No N1 TCP selected");
619  }
620  else
621  {
622  NS_FATAL_ERROR("Fatal error: tcp unsupported");
623  }
624 
625  if (queueType == "fq")
626  {
627  queueTypeId = FqCoDelQueueDisc::GetTypeId();
628  }
629  else if (queueType == "codel")
630  {
631  queueTypeId = CoDelQueueDisc::GetTypeId();
632  }
633  else
634  {
635  NS_FATAL_ERROR("Fatal error: queueType unsupported");
636  }
637  if (useCeThreshold)
638  {
639  Config::SetDefault("ns3::FqCoDelQueueDisc::CeThreshold", TimeValue(ceThreshold));
640  }
641  }
642  else if (scenarioNum == 1 || scenarioNum == 2 || scenarioNum == 5 || scenarioNum == 6)
643  {
644  if (scenarioNum == 2 || scenarioNum == 6)
645  {
646  Config::SetDefault("ns3::TcpSocketBase::UseEcn", StringValue("On"));
647  }
648  n0TcpTypeId = TcpBic::GetTypeId();
649  if (scenarioNum == 5 || scenarioNum == 6)
650  {
651  enableN1Tcp = true;
652  n1TcpTypeId = TcpBic::GetTypeId();
653  }
654  queueTypeId = FqCoDelQueueDisc::GetTypeId();
655  }
656  else if (scenarioNum == 3 || scenarioNum == 4 || scenarioNum == 7 || scenarioNum == 8 ||
657  scenarioNum == 9)
658  {
659  Config::SetDefault("ns3::TcpSocketBase::UseEcn", StringValue("On"));
660  n0TcpTypeId = TcpDctcp::GetTypeId();
661  queueTypeId = FqCoDelQueueDisc::GetTypeId();
662  oneWayDelay = MicroSeconds(500);
663  Config::SetDefault("ns3::FqCoDelQueueDisc::CeThreshold", TimeValue(MilliSeconds(1)));
664  if (scenarioNum == 9)
665  {
666  n0TcpTypeId = TcpBic::GetTypeId();
667  // For TCP Bic base RTT is 80 and base RTT for dctcp is set to 1 while setting delay for
668  // p2p devices
669  oneWayDelay = MilliSeconds(40);
670  }
671  if (scenarioNum == 4 || scenarioNum == 8 || scenarioNum == 9)
672  {
673  Config::SetDefault("ns3::FqCoDelQueueDisc::UseL4s", BooleanValue(true));
674  Config::SetDefault("ns3::TcpDctcp::UseEct0", BooleanValue(false));
675  }
676  if (scenarioNum == 7 || scenarioNum == 8 || scenarioNum == 9)
677  {
678  enableN1Tcp = true;
679  n1TcpTypeId = TcpDctcp::GetTypeId();
680  }
681  }
682  else
683  {
684  NS_FATAL_ERROR("Fatal error: scenario unavailble");
685  }
686 
687  std::ofstream pingOfStream;
688  pingOfStream.open(pingTraceFile, std::ofstream::out);
689  std::ofstream n0TcpRttOfStream;
690  n0TcpRttOfStream.open(n0TcpRttTraceFile, std::ofstream::out);
691  std::ofstream n0TcpCwndOfStream;
692  n0TcpCwndOfStream.open(n0TcpCwndTraceFile, std::ofstream::out);
693  std::ofstream n0TcpThroughputOfStream;
694  n0TcpThroughputOfStream.open(n0TcpThroughputTraceFile, std::ofstream::out);
695  std::ofstream n1TcpRttOfStream;
696  n1TcpRttOfStream.open(n1TcpRttTraceFile, std::ofstream::out);
697  std::ofstream n1TcpCwndOfStream;
698  n1TcpCwndOfStream.open(n1TcpCwndTraceFile, std::ofstream::out);
699  std::ofstream n1TcpThroughputOfStream;
700  n1TcpThroughputOfStream.open(n1TcpThroughputTraceFile, std::ofstream::out);
701 
702  // Queue disc files
703  std::ofstream dropOfStream;
704  dropOfStream.open(dropTraceFile, std::ofstream::out);
705  std::ofstream markOfStream;
706  markOfStream.open(markTraceFile, std::ofstream::out);
707  std::ofstream dropsFrequencyOfStream;
708  dropsFrequencyOfStream.open(dropsFrequencyTraceFile, std::ofstream::out);
709  std::ofstream marksFrequencyOfStream;
710  marksFrequencyOfStream.open(marksFrequencyTraceFile, std::ofstream::out);
711  std::ofstream lengthOfStream;
712  lengthOfStream.open(lengthTraceFile, std::ofstream::out);
713  std::ofstream queueDelayN0OfStream;
714  queueDelayN0OfStream.open(queueDelayN0TraceFile, std::ofstream::out);
715  std::ofstream queueDelayN1OfStream;
716  queueDelayN1OfStream.open(queueDelayN1TraceFile, std::ofstream::out);
717 
719  // scenario setup //
721  Ptr<Node> pingServer = CreateObject<Node>();
722  Ptr<Node> n0Server = CreateObject<Node>();
723  Ptr<Node> n1Server = CreateObject<Node>();
724  Ptr<Node> n2 = CreateObject<Node>();
725  Ptr<Node> n3 = CreateObject<Node>();
726  Ptr<Node> pingClient = CreateObject<Node>();
727  Ptr<Node> n4Client = CreateObject<Node>();
728  Ptr<Node> n5Client = CreateObject<Node>();
729 
730  // Device containers
731  NetDeviceContainer pingServerDevices;
732  NetDeviceContainer n0ServerDevices;
733  NetDeviceContainer n1ServerDevices;
734  NetDeviceContainer n2n3Devices;
735  NetDeviceContainer pingClientDevices;
736  NetDeviceContainer n4ClientDevices;
737  NetDeviceContainer n5ClientDevices;
738 
740  p2p.SetQueue("ns3::DropTailQueue", "MaxSize", QueueSizeValue(QueueSize("3p")));
741  p2p.SetDeviceAttribute("DataRate", DataRateValue(DataRate(linkDataRate)));
742  // Add delay only on the server links
743  p2p.SetChannelAttribute("Delay", TimeValue(oneWayDelay));
744  pingServerDevices = p2p.Install(n2, pingServer);
745  n0ServerDevices = p2p.Install(n2, n0Server);
746 
747  // In scenario 9, base RTT of n1server (dctcp) is 1ms
748  if (scenarioNum == 9)
749  {
750  p2p.SetChannelAttribute("Delay", TimeValue(MicroSeconds(500)));
751  }
752  n1ServerDevices = p2p.Install(n2, n1Server);
753  p2p.SetChannelAttribute("Delay", TimeValue(MicroSeconds(1)));
754  n2n3Devices = p2p.Install(n2, n3);
755  pingClientDevices = p2p.Install(n3, pingClient);
756  n4ClientDevices = p2p.Install(n3, n4Client);
757  n5ClientDevices = p2p.Install(n3, n5Client);
758  Ptr<PointToPointNetDevice> p = n2n3Devices.Get(0)->GetObject<PointToPointNetDevice>();
759  p->SetAttribute("DataRate", DataRateValue(bottleneckRate));
760 
761  InternetStackHelper stackHelper;
762  stackHelper.InstallAll();
763 
764  // Set the per-node TCP type here
765  Ptr<TcpL4Protocol> proto;
766  proto = n4Client->GetObject<TcpL4Protocol>();
767  proto->SetAttribute("SocketType", TypeIdValue(n0TcpTypeId));
768  proto = n0Server->GetObject<TcpL4Protocol>();
769  proto->SetAttribute("SocketType", TypeIdValue(n0TcpTypeId));
770  if (enableN1Tcp)
771  {
772  proto = n5Client->GetObject<TcpL4Protocol>();
773  proto->SetAttribute("SocketType", TypeIdValue(n1TcpTypeId));
774  proto = n1Server->GetObject<TcpL4Protocol>();
775  proto->SetAttribute("SocketType", TypeIdValue(n1TcpTypeId));
776  }
777 
778  // InternetStackHelper will install a base TrafficControlLayer on the node,
779  // but the Ipv4AddressHelper below will install the default FqCoDelQueueDisc
780  // on all single device nodes. The below code overrides the configuration
781  // that is normally done by the Ipv4AddressHelper::Install() method by
782  // instead explicitly configuring the queue discs we want on each device.
783  TrafficControlHelper tchFq;
784  tchFq.SetRootQueueDisc("ns3::FqCoDelQueueDisc");
785  tchFq.SetQueueLimits("ns3::DynamicQueueLimits", "HoldTime", StringValue("1ms"));
786  tchFq.Install(pingServerDevices);
787  tchFq.Install(n0ServerDevices);
788  tchFq.Install(n1ServerDevices);
789  tchFq.Install(n2n3Devices.Get(1)); // n2 queue for bottleneck link
790  tchFq.Install(pingClientDevices);
791  tchFq.Install(n4ClientDevices);
792  tchFq.Install(n5ClientDevices);
793  TrafficControlHelper tchN2;
794  tchN2.SetRootQueueDisc(queueTypeId.GetName());
795  tchN2.SetQueueLimits("ns3::DynamicQueueLimits", "HoldTime", StringValue("1000ms"));
796  tchN2.Install(n2n3Devices.Get(0));
797 
799  ipv4.SetBase("10.1.1.0", "255.255.255.0");
800  Ipv4InterfaceContainer pingServerIfaces = ipv4.Assign(pingServerDevices);
801  ipv4.SetBase("10.1.2.0", "255.255.255.0");
802  Ipv4InterfaceContainer n0ServerIfaces = ipv4.Assign(n0ServerDevices);
803  ipv4.SetBase("10.1.3.0", "255.255.255.0");
804  Ipv4InterfaceContainer secondServerIfaces = ipv4.Assign(n1ServerDevices);
805  ipv4.SetBase("172.16.1.0", "255.255.255.0");
806  Ipv4InterfaceContainer n2n3Ifaces = ipv4.Assign(n2n3Devices);
807  ipv4.SetBase("192.168.1.0", "255.255.255.0");
808  Ipv4InterfaceContainer pingClientIfaces = ipv4.Assign(pingClientDevices);
809  ipv4.SetBase("192.168.2.0", "255.255.255.0");
810  Ipv4InterfaceContainer n4ClientIfaces = ipv4.Assign(n4ClientDevices);
811  ipv4.SetBase("192.168.3.0", "255.255.255.0");
812  Ipv4InterfaceContainer n5ClientIfaces = ipv4.Assign(n5ClientDevices);
813 
815 
817  // application setup //
819 
820  PingHelper pingHelper(Ipv4Address("192.168.1.2"));
821  pingHelper.SetAttribute("Interval", TimeValue(pingInterval));
822  pingHelper.SetAttribute("Size", UintegerValue(pingSize));
823  ApplicationContainer pingContainer = pingHelper.Install(pingServer);
824  Ptr<Ping> ping = pingContainer.Get(0)->GetObject<Ping>();
825  ping->TraceConnectWithoutContext("Rtt", MakeBoundCallback(&TracePingRtt, &pingOfStream));
826  pingContainer.Start(Seconds(1));
827  pingContainer.Stop(stopTime - Seconds(1));
828 
829  BulkSendHelper tcp("ns3::TcpSocketFactory", Address());
830  // set to large value: e.g. 1000 Mb/s for 60 seconds = 7500000000 bytes
831  tcp.SetAttribute("MaxBytes", UintegerValue(7500000000));
832  // Configure n4/n0 TCP client/server pair
833  uint16_t n4Port = 5000;
834  ApplicationContainer n0App;
835  InetSocketAddress n0DestAddress(n4ClientIfaces.GetAddress(1), n4Port);
836  tcp.SetAttribute("Remote", AddressValue(n0DestAddress));
837  n0App = tcp.Install(n0Server);
838  n0App.Start(Seconds(5));
839  n0App.Stop(stopTime - Seconds(1));
840 
841  Address n4SinkAddress(InetSocketAddress(Ipv4Address::GetAny(), n4Port));
842  PacketSinkHelper n4SinkHelper("ns3::TcpSocketFactory", n4SinkAddress);
843  ApplicationContainer n4SinkApp;
844  n4SinkApp = n4SinkHelper.Install(n4Client);
845  n4SinkApp.Start(Seconds(5));
846  n4SinkApp.Stop(stopTime - MilliSeconds(500));
847 
848  // Configure second TCP client/server pair
849  if (enableN1Tcp)
850  {
851  uint16_t n5Port = 5000;
852  ApplicationContainer secondApp;
853  InetSocketAddress n1DestAddress(n5ClientIfaces.GetAddress(1), n5Port);
854  tcp.SetAttribute("Remote", AddressValue(n1DestAddress));
855  secondApp = tcp.Install(n1Server);
856  secondApp.Start(Seconds(15));
857  secondApp.Stop(stopTime - Seconds(1));
858 
859  Address n5SinkAddress(InetSocketAddress(Ipv4Address::GetAny(), n5Port));
860  PacketSinkHelper n5SinkHelper("ns3::TcpSocketFactory", n5SinkAddress);
861  ApplicationContainer n5SinkApp;
862  n5SinkApp = n5SinkHelper.Install(n5Client);
863  n5SinkApp.Start(Seconds(15));
864  n5SinkApp.Stop(stopTime - MilliSeconds(500));
865  }
866 
867  // Setup traces that can be hooked now
869  Ptr<QueueDisc> qd;
870  tc = n2n3Devices.Get(0)->GetNode()->GetObject<TrafficControlLayer>();
871  qd = tc->GetRootQueueDiscOnDevice(n2n3Devices.Get(0));
872  qd->TraceConnectWithoutContext("Drop", MakeBoundCallback(&TraceDrop, &dropOfStream));
873  qd->TraceConnectWithoutContext("Mark", MakeBoundCallback(&TraceMark, &markOfStream));
875  "BytesInQueue",
876  MakeBoundCallback(&TraceQueueLength, &lengthOfStream, bottleneckRate));
878  "Dequeue",
879  MakeBoundCallback(&PacketDequeue, &queueDelayN0OfStream, &queueDelayN1OfStream));
880 
881  // Setup scheduled traces; TCP traces must be hooked after socket creation
884  &n0TcpRttOfStream);
887  &n0TcpCwndOfStream);
889  Simulator::Schedule(throughputSamplingInterval,
891  &n0TcpThroughputOfStream,
892  throughputSamplingInterval);
893  // Setup scheduled traces; TCP traces must be hooked after socket creation
894  if (enableN1Tcp)
895  {
898  &n1TcpRttOfStream);
901  &n1TcpCwndOfStream);
903  }
904  Simulator::Schedule(throughputSamplingInterval,
906  &n1TcpThroughputOfStream,
907  throughputSamplingInterval);
908  Simulator::Schedule(marksSamplingInterval,
910  &marksFrequencyOfStream,
911  marksSamplingInterval);
912  Simulator::Schedule(marksSamplingInterval,
914  &dropsFrequencyOfStream,
915  marksSamplingInterval);
916 
917  if (enablePcap)
918  {
919  p2p.EnablePcapAll("FqCoDel-L4S-example", false);
920  }
921 
923  Simulator::Run();
924 
925  pingOfStream.close();
926  n0TcpCwndOfStream.close();
927  n0TcpRttOfStream.close();
928  n0TcpThroughputOfStream.close();
929  n1TcpCwndOfStream.close();
930  n1TcpRttOfStream.close();
931  n1TcpThroughputOfStream.close();
932  dropOfStream.close();
933  markOfStream.close();
934  dropsFrequencyOfStream.close();
935  marksFrequencyOfStream.close();
936  lengthOfStream.close();
937  queueDelayN0OfStream.close();
938  queueDelayN1OfStream.close();
939 
940  return 0;
941 }
a polymophic address class
Definition: address.h:101
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.
A helper to make it easier to instantiate an ns3::BulkSendApplication on a set of nodes.
static TypeId GetTypeId()
Get the type ID.
Parse command-line arguments.
Definition: command-line.h:232
Class for representing data rates.
Definition: data-rate.h:89
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:305
static TypeId GetTypeId()
Get the type ID.
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
void InstallAll() 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.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
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
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.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:315
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
Create a ping application and associate it to a node.
Definition: ping-helper.h:48
This application behaves similarly to the Unix ping application, although with fewer options supporte...
Definition: ping.h:56
Build a set of PointToPointNetDevice objects.
A Device for a Point to Point Network Link.
Class for representing queue sizes.
Definition: queue-size.h:96
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
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
static TypeId GetTypeId()
Get the type ID.
Definition: tcp-bic.cc:30
static TypeId GetTypeId()
Get the type ID.
Definition: tcp-dctcp.cc:36
TCP socket creation and multiplexing/demultiplexing.
static TypeId GetTypeId()
Get the type ID.
static TypeId GetTypeId()
Get the type ID.
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.
void SetQueueLimits(std::string type, Args &&... args)
Helper function used to add a queue limits object to the transmission queues of the devices.
The Traffic Control layer aims at introducing an equivalent of the Linux Traffic Control infrastructu...
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:835
std::string GetName() const
Get the name.
Definition: type-id.cc:991
Hold an unsigned integer type.
Definition: uinteger.h:45
Time stopTime
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 TraceMark(std::ofstream *ofStream, Ptr< const QueueDiscItem > item, const char *reason)
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 ScheduleN1PacketSinkConnection()
void ScheduleN1TcpCwndTraceConnection(std::ofstream *ofStream)
void ScheduleN0PacketSinkConnection()
void TraceN0Rtt(std::ofstream *ofStream, Time oldRtt, Time newRtt)
uint32_t g_dropsObserved
static void PacketDequeue(std::ofstream *n0OfStream, std::ofstream *n1OfStream, Ptr< const QueueDiscItem > item)
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
void TracePingRtt(std::ofstream *ofStream, uint16_t seqNo, Time rtt)
void ScheduleN0TcpRttTraceConnection(std::ofstream *ofStream)
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:890
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:950
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:765
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:327
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
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
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:449
cmd
Definition: second.py:40
std::string dir