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
282using namespace ns3;
283
284NS_LOG_COMPONENT_DEFINE("FqCoDelL4SExample");
285
288
293
294void
295TraceN0Cwnd(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
303void
304TraceN1Cwnd(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
312void
313TraceN0Rtt(std::ofstream* ofStream, Time oldRtt, Time newRtt)
314{
315 *ofStream << Simulator::Now().GetSeconds() << " " << newRtt.GetSeconds() * 1000 << std::endl;
316}
317
318void
319TraceN1Rtt(std::ofstream* ofStream, Time oldRtt, Time newRtt)
320{
321 *ofStream << Simulator::Now().GetSeconds() << " " << newRtt.GetSeconds() * 1000 << std::endl;
322}
323
324void
325TracePingRtt(std::ofstream* ofStream, uint16_t seqNo, Time rtt)
326{
327 *ofStream << Simulator::Now().GetSeconds() << " " << seqNo << " " << rtt.GetSeconds() * 1000
328 << std::endl;
329}
330
331void
333{
334 g_n0BytesReceived += packet->GetSize();
335}
336
337void
339{
340 g_n1BytesReceived += packet->GetSize();
341}
342
343void
344TraceDrop(std::ofstream* ofStream, Ptr<const QueueDiscItem> item)
345{
346 *ofStream << Simulator::Now().GetSeconds() << " " << std::hex << item->Hash() << std::endl;
348}
349
350void
351TraceMark(std::ofstream* ofStream, Ptr<const QueueDiscItem> item, const char* reason)
352{
353 *ofStream << Simulator::Now().GetSeconds() << " " << std::hex << item->Hash() << std::endl;
355}
356
357void
358TraceQueueLength(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
365void
366TraceDropsFrequency(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
376void
377TraceMarksFrequency(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
387void
388TraceN0Throughput(std::ofstream* ofStream, Time throughputInterval)
389{
390 *ofStream << Simulator::Now().GetSeconds() << " "
391 << g_n0BytesReceived * 8 / throughputInterval.GetSeconds() / 1e6 << std::endl;
393 Simulator::Schedule(throughputInterval, &TraceN0Throughput, ofStream, throughputInterval);
394}
395
396void
397TraceN1Throughput(std::ofstream* ofStream, Time throughputInterval)
398{
399 *ofStream << Simulator::Now().GetSeconds() << " "
400 << g_n1BytesReceived * 8 / throughputInterval.GetSeconds() / 1e6 << std::endl;
402 Simulator::Schedule(throughputInterval, &TraceN1Throughput, ofStream, throughputInterval);
403}
404
405void
406ScheduleN0TcpCwndTraceConnection(std::ofstream* ofStream)
407{
408 Config::ConnectWithoutContext("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
409 MakeBoundCallback(&TraceN0Cwnd, ofStream));
410}
411
412void
413ScheduleN0TcpRttTraceConnection(std::ofstream* ofStream)
414{
415 Config::ConnectWithoutContext("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/RTT",
416 MakeBoundCallback(&TraceN0Rtt, ofStream));
417}
418
419void
421{
422 Config::ConnectWithoutContext("/NodeList/6/ApplicationList/*/$ns3::PacketSink/Rx",
424}
425
426void
427ScheduleN1TcpCwndTraceConnection(std::ofstream* ofStream)
428{
429 Config::ConnectWithoutContext("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
430 MakeBoundCallback(&TraceN1Cwnd, ofStream));
431}
432
433void
434ScheduleN1TcpRttTraceConnection(std::ofstream* ofStream)
435{
436 Config::ConnectWithoutContext("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/RTT",
437 MakeBoundCallback(&TraceN1Rtt, ofStream));
438}
439
440void
442{
443 Config::ConnectWithoutContext("/NodeList/7/ApplicationList/*/$ns3::PacketSink/Rx",
445}
446
447static void
448PacketDequeue(std::ofstream* n0OfStream, std::ofstream* n1OfStream, Ptr<const QueueDiscItem> item)
449{
450 Ptr<Packet> p = item->GetPacket();
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
467int
468main(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",
526 TypeIdValue(TcpPrrRecovery::GetTypeId()));
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 avalaible 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);
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 TrafficControLayer 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.
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);
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
814 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
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;
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
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
882 Simulator::Schedule(Seconds(5) + MilliSeconds(100),
884 &n0TcpRttOfStream);
885 Simulator::Schedule(Seconds(5) + MilliSeconds(100),
887 &n0TcpCwndOfStream);
888 Simulator::Schedule(Seconds(5) + MilliSeconds(100), &ScheduleN0PacketSinkConnection);
889 Simulator::Schedule(throughputSamplingInterval,
891 &n0TcpThroughputOfStream,
892 throughputSamplingInterval);
893 // Setup scheduled traces; TCP traces must be hooked after socket creation
894 if (enableN1Tcp)
895 {
896 Simulator::Schedule(Seconds(15) + MilliSeconds(100),
898 &n1TcpRttOfStream);
899 Simulator::Schedule(Seconds(15) + MilliSeconds(100),
901 &n1TcpCwndOfStream);
902 Simulator::Schedule(Seconds(15) + MilliSeconds(100), &ScheduleN1PacketSinkConnection);
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
922 Simulator::Stop(stopTime);
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:100
AttributeValue implementation for Address.
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)
Start all of the Applications in this container at the start 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.
Parse command-line arguments.
Definition: command-line.h:232
Class for representing data rates.
Definition: data-rate.h:90
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:305
AttributeValue implementation for DataRate.
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.
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:43
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:311
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:863
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 ...
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.
void SetDeviceAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each NetDevice created by the helper.
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
void SetQueue(std::string type, Ts &&... args)
Each point to point net device must have a queue to pass packets through.
NetDeviceContainer Install(NodeContainer c)
A Device for a Point to Point Network Link.
Class for representing queue sizes.
Definition: queue-size.h:96
AttributeValue implementation for QueueSize.
Hold variables of type string.
Definition: string.h:56
TCP socket creation and multiplexing/demultiplexing.
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:402
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:412
AttributeValue implementation for Time.
Definition: nstime.h:1423
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:60
std::string GetName() const
Get the name.
Definition: type-id.cc:995
AttributeValue implementation for TypeId.
Definition: type-id.h:600
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:891
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:951
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:160
#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:752
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:328
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
address
Definition: first.py:40
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:488
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:691
cmd
Definition: second.py:33
std::string dir