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