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, Time rtt)
326{
327 *ofStream << Simulator::Now().GetSeconds() << " " << rtt.GetSeconds() * 1000 << std::endl;
328}
329
330void
332{
333 g_n0BytesReceived += packet->GetSize();
334}
335
336void
338{
339 g_n1BytesReceived += packet->GetSize();
340}
341
342void
343TraceDrop(std::ofstream* ofStream, Ptr<const QueueDiscItem> item)
344{
345 *ofStream << Simulator::Now().GetSeconds() << " " << std::hex << item->Hash() << std::endl;
347}
348
349void
350TraceMark(std::ofstream* ofStream, Ptr<const QueueDiscItem> item, const char* reason)
351{
352 *ofStream << Simulator::Now().GetSeconds() << " " << std::hex << item->Hash() << std::endl;
354}
355
356void
357TraceQueueLength(std::ofstream* ofStream, DataRate linkRate, uint32_t oldVal, uint32_t newVal)
358{
359 // output in units of ms
360 *ofStream << Simulator::Now().GetSeconds() << " " << std::fixed
361 << static_cast<double>(newVal * 8) / (linkRate.GetBitRate() / 1000) << std::endl;
362}
363
364void
365TraceDropsFrequency(std::ofstream* ofStream, Time dropsSamplingInterval)
366{
367 *ofStream << Simulator::Now().GetSeconds() << " " << g_dropsObserved << std::endl;
368 g_dropsObserved = 0;
369 Simulator::Schedule(dropsSamplingInterval,
371 ofStream,
372 dropsSamplingInterval);
373}
374
375void
376TraceMarksFrequency(std::ofstream* ofStream, Time marksSamplingInterval)
377{
378 *ofStream << Simulator::Now().GetSeconds() << " " << g_marksObserved << std::endl;
379 g_marksObserved = 0;
380 Simulator::Schedule(marksSamplingInterval,
382 ofStream,
383 marksSamplingInterval);
384}
385
386void
387TraceN0Throughput(std::ofstream* ofStream, Time throughputInterval)
388{
389 *ofStream << Simulator::Now().GetSeconds() << " "
390 << g_n0BytesReceived * 8 / throughputInterval.GetSeconds() / 1e6 << std::endl;
392 Simulator::Schedule(throughputInterval, &TraceN0Throughput, ofStream, throughputInterval);
393}
394
395void
396TraceN1Throughput(std::ofstream* ofStream, Time throughputInterval)
397{
398 *ofStream << Simulator::Now().GetSeconds() << " "
399 << g_n1BytesReceived * 8 / throughputInterval.GetSeconds() / 1e6 << std::endl;
401 Simulator::Schedule(throughputInterval, &TraceN1Throughput, ofStream, throughputInterval);
402}
403
404void
405ScheduleN0TcpCwndTraceConnection(std::ofstream* ofStream)
406{
407 Config::ConnectWithoutContext("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
408 MakeBoundCallback(&TraceN0Cwnd, ofStream));
409}
410
411void
412ScheduleN0TcpRttTraceConnection(std::ofstream* ofStream)
413{
414 Config::ConnectWithoutContext("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/RTT",
415 MakeBoundCallback(&TraceN0Rtt, ofStream));
416}
417
418void
420{
421 Config::ConnectWithoutContext("/NodeList/6/ApplicationList/*/$ns3::PacketSink/Rx",
423}
424
425void
426ScheduleN1TcpCwndTraceConnection(std::ofstream* ofStream)
427{
428 Config::ConnectWithoutContext("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
429 MakeBoundCallback(&TraceN1Cwnd, ofStream));
430}
431
432void
433ScheduleN1TcpRttTraceConnection(std::ofstream* ofStream)
434{
435 Config::ConnectWithoutContext("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/RTT",
436 MakeBoundCallback(&TraceN1Rtt, ofStream));
437}
438
439void
441{
442 Config::ConnectWithoutContext("/NodeList/7/ApplicationList/*/$ns3::PacketSink/Rx",
444}
445
446static void
447PacketDequeue(std::ofstream* n0OfStream, std::ofstream* n1OfStream, Ptr<const QueueDiscItem> item)
448{
449 Ptr<Packet> p = item->GetPacket();
452 Ipv4Address address = iqdi->GetHeader().GetDestination();
453 Time qDelay = Simulator::Now() - item->GetTimeStamp();
454 if (address == "192.168.2.2")
455 {
456 *n0OfStream << Simulator::Now().GetSeconds() << " " << qDelay.GetMicroSeconds() / 1000.0
457 << std::endl;
458 }
459 else if (address == "192.168.3.2")
460 {
461 *n1OfStream << Simulator::Now().GetSeconds() << " " << qDelay.GetMicroSeconds() / 1000.0
462 << std::endl;
463 }
464}
465
466int
467main(int argc, char* argv[])
468{
470 // variables not configured at command line //
472 Time stopTime = Seconds(70);
473 Time baseRtt = MilliSeconds(80);
474 uint32_t pingSize = 100; // bytes
475 Time pingInterval = MilliSeconds(100);
476 Time marksSamplingInterval = MilliSeconds(100);
477 Time throughputSamplingInterval = MilliSeconds(200);
478 DataRate bottleneckRate("100Mbps");
479
480 std::string dir = "results/FqCoDel-L4S/";
481 std::string dirToSave = "mkdir -p " + dir;
482 if (system(dirToSave.c_str()) == -1)
483 {
484 exit(1);
485 }
486
487 std::string pingTraceFile = dir + "ping.dat";
488 std::string n0TcpRttTraceFile = dir + "n0-tcp-rtt.dat";
489 std::string n0TcpCwndTraceFile = dir + "n0-tcp-cwnd.dat";
490 std::string n0TcpThroughputTraceFile = dir + "n0-tcp-throughput.dat";
491 std::string n1TcpRttTraceFile = dir + "n1-tcp-rtt.dat";
492 std::string n1TcpCwndTraceFile = dir + "n1-tcp-cwnd.dat";
493 std::string n1TcpThroughputTraceFile = dir + "n1-tcp-throughput.dat";
494 std::string dropTraceFile = dir + "drops.dat";
495 std::string dropsFrequencyTraceFile = dir + "drops-frequency.dat";
496 std::string lengthTraceFile = dir + "length.dat";
497 std::string markTraceFile = dir + "mark.dat";
498 std::string marksFrequencyTraceFile = dir + "marks-frequency.dat";
499 std::string queueDelayN0TraceFile = dir + "queue-delay-n0.dat";
500 std::string queueDelayN1TraceFile = dir + "queue-delay-n1.dat";
501
503 // variables configured at command line //
505 bool enablePcap = false;
506 bool useCeThreshold = false;
507 Time ceThreshold = MilliSeconds(1);
508 std::string n0TcpType = "bic";
509 std::string n1TcpType = "";
510 bool enableN1Tcp = false;
511 bool useEcn = true;
512 std::string queueType = "fq";
513 std::string linkDataRate = "1Gbps";
514 uint32_t scenarioNum = 0;
515
517 // Override ns-3 defaults //
519 Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(1448));
520 // Increase default buffer sizes to improve throughput over long delay paths
521 Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(8192000));
522 Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(8192000));
523 Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(10));
524 Config::SetDefault("ns3::TcpL4Protocol::RecoveryType",
525 TypeIdValue(TcpPrrRecovery::GetTypeId()));
526
528 // command-line argument parsing //
531 cmd.AddValue("n0TcpType", "n0 TCP type (bic, dctcp, or reno)", n0TcpType);
532 cmd.AddValue("n1TcpType", "n1 TCP type (bic, dctcp, or reno)", n1TcpType);
533 cmd.AddValue("scenarioNum",
534 "Scenario number from the scenarios avalaible in the file (1-9)",
535 scenarioNum);
536 cmd.AddValue("bottleneckQueueType", "n2 queue type (fq or codel)", queueType);
537 cmd.AddValue("baseRtt", "base RTT", baseRtt);
538 cmd.AddValue("useCeThreshold", "use CE Threshold", useCeThreshold);
539 cmd.AddValue("useEcn", "use ECN", useEcn);
540 cmd.AddValue("ceThreshold", "CoDel CE threshold", ceThreshold);
541 cmd.AddValue("bottleneckRate", "data rate of bottleneck", bottleneckRate);
542 cmd.AddValue("linkRate", "data rate of edge link", linkDataRate);
543 cmd.AddValue("stopTime", "simulation stop time", stopTime);
544 cmd.AddValue("enablePcap", "enable Pcap", enablePcap);
545 cmd.AddValue("pingTraceFile", "filename for ping tracing", pingTraceFile);
546 cmd.AddValue("n0TcpRttTraceFile", "filename for n0 rtt tracing", n0TcpRttTraceFile);
547 cmd.AddValue("n0TcpCwndTraceFile", "filename for n0 cwnd tracing", n0TcpCwndTraceFile);
548 cmd.AddValue("n0TcpThroughputTraceFile",
549 "filename for n0 throughput tracing",
550 n0TcpThroughputTraceFile);
551 cmd.AddValue("n1TcpRttTraceFile", "filename for n1 rtt tracing", n1TcpRttTraceFile);
552 cmd.AddValue("n1TcpCwndTraceFile", "filename for n1 cwnd tracing", n1TcpCwndTraceFile);
553 cmd.AddValue("n1TcpThroughputTraceFile",
554 "filename for n1 throughput tracing",
555 n1TcpThroughputTraceFile);
556 cmd.AddValue("dropTraceFile", "filename for n2 drops tracing", dropTraceFile);
557 cmd.AddValue("dropsFrequencyTraceFile",
558 "filename for n2 drop frequency tracing",
559 dropsFrequencyTraceFile);
560 cmd.AddValue("lengthTraceFile", "filename for n2 queue length tracing", lengthTraceFile);
561 cmd.AddValue("markTraceFile", "filename for n2 mark tracing", markTraceFile);
562 cmd.AddValue("marksFrequencyTraceFile",
563 "filename for n2 mark frequency tracing",
564 marksFrequencyTraceFile);
565 cmd.AddValue("queueDelayN0TraceFile",
566 "filename for n0 queue delay tracing",
567 queueDelayN0TraceFile);
568 cmd.AddValue("queueDelayN1TraceFile",
569 "filename for n1 queue delay tracing",
570 queueDelayN1TraceFile);
571 cmd.Parse(argc, argv);
572 Time oneWayDelay = baseRtt / 2;
573 TypeId n0TcpTypeId;
574 TypeId n1TcpTypeId;
575 TypeId queueTypeId;
576 if (!scenarioNum)
577 {
578 if (useEcn)
579 {
580 Config::SetDefault("ns3::TcpSocketBase::UseEcn", StringValue("On"));
581 }
582
583 if (n0TcpType == "reno")
584 {
585 n0TcpTypeId = TcpNewReno::GetTypeId();
586 }
587 else if (n0TcpType == "bic")
588 {
589 n0TcpTypeId = TcpBic::GetTypeId();
590 }
591 else if (n0TcpType == "dctcp")
592 {
593 n0TcpTypeId = TcpDctcp::GetTypeId();
594 }
595 else
596 {
597 NS_FATAL_ERROR("Fatal error: tcp unsupported");
598 }
599
600 if (n1TcpType == "reno")
601 {
602 enableN1Tcp = true;
603 n1TcpTypeId = TcpNewReno::GetTypeId();
604 }
605 else if (n1TcpType == "bic")
606 {
607 enableN1Tcp = true;
608 n1TcpTypeId = TcpBic::GetTypeId();
609 }
610 else if (n1TcpType == "dctcp")
611 {
612 enableN1Tcp = true;
613 n1TcpTypeId = TypeId::LookupByName("ns3::TcpDctcp");
614 }
615 else if (n1TcpType == "")
616 {
617 NS_LOG_DEBUG("No N1 TCP selected");
618 }
619 else
620 {
621 NS_FATAL_ERROR("Fatal error: tcp unsupported");
622 }
623
624 if (queueType == "fq")
625 {
626 queueTypeId = FqCoDelQueueDisc::GetTypeId();
627 }
628 else if (queueType == "codel")
629 {
630 queueTypeId = CoDelQueueDisc::GetTypeId();
631 }
632 else
633 {
634 NS_FATAL_ERROR("Fatal error: queueType unsupported");
635 }
636 if (useCeThreshold)
637 {
638 Config::SetDefault("ns3::FqCoDelQueueDisc::CeThreshold", TimeValue(ceThreshold));
639 }
640 }
641 else if (scenarioNum == 1 || scenarioNum == 2 || scenarioNum == 5 || scenarioNum == 6)
642 {
643 if (scenarioNum == 2 || scenarioNum == 6)
644 {
645 Config::SetDefault("ns3::TcpSocketBase::UseEcn", StringValue("On"));
646 }
647 n0TcpTypeId = TcpBic::GetTypeId();
648 if (scenarioNum == 5 || scenarioNum == 6)
649 {
650 enableN1Tcp = true;
651 n1TcpTypeId = TcpBic::GetTypeId();
652 }
653 queueTypeId = FqCoDelQueueDisc::GetTypeId();
654 }
655 else if (scenarioNum == 3 || scenarioNum == 4 || scenarioNum == 7 || scenarioNum == 8 ||
656 scenarioNum == 9)
657 {
658 Config::SetDefault("ns3::TcpSocketBase::UseEcn", StringValue("On"));
659 n0TcpTypeId = TcpDctcp::GetTypeId();
660 queueTypeId = FqCoDelQueueDisc::GetTypeId();
661 oneWayDelay = MicroSeconds(500);
662 Config::SetDefault("ns3::FqCoDelQueueDisc::CeThreshold", TimeValue(MilliSeconds(1)));
663 if (scenarioNum == 9)
664 {
665 n0TcpTypeId = TcpBic::GetTypeId();
666 // For TCP Bic base RTT is 80 and base RTT for dctcp is set to 1 while setting delay for
667 // p2p devices
668 oneWayDelay = MilliSeconds(40);
669 }
670 if (scenarioNum == 4 || scenarioNum == 8 || scenarioNum == 9)
671 {
672 Config::SetDefault("ns3::FqCoDelQueueDisc::UseL4s", BooleanValue(true));
673 Config::SetDefault("ns3::TcpDctcp::UseEct0", BooleanValue(false));
674 }
675 if (scenarioNum == 7 || scenarioNum == 8 || scenarioNum == 9)
676 {
677 enableN1Tcp = true;
678 n1TcpTypeId = TcpDctcp::GetTypeId();
679 }
680 }
681 else
682 {
683 NS_FATAL_ERROR("Fatal error: scenario unavailble");
684 }
685
686 std::ofstream pingOfStream;
687 pingOfStream.open(pingTraceFile, std::ofstream::out);
688 std::ofstream n0TcpRttOfStream;
689 n0TcpRttOfStream.open(n0TcpRttTraceFile, std::ofstream::out);
690 std::ofstream n0TcpCwndOfStream;
691 n0TcpCwndOfStream.open(n0TcpCwndTraceFile, std::ofstream::out);
692 std::ofstream n0TcpThroughputOfStream;
693 n0TcpThroughputOfStream.open(n0TcpThroughputTraceFile, std::ofstream::out);
694 std::ofstream n1TcpRttOfStream;
695 n1TcpRttOfStream.open(n1TcpRttTraceFile, std::ofstream::out);
696 std::ofstream n1TcpCwndOfStream;
697 n1TcpCwndOfStream.open(n1TcpCwndTraceFile, std::ofstream::out);
698 std::ofstream n1TcpThroughputOfStream;
699 n1TcpThroughputOfStream.open(n1TcpThroughputTraceFile, std::ofstream::out);
700
701 // Queue disc files
702 std::ofstream dropOfStream;
703 dropOfStream.open(dropTraceFile, std::ofstream::out);
704 std::ofstream markOfStream;
705 markOfStream.open(markTraceFile, std::ofstream::out);
706 std::ofstream dropsFrequencyOfStream;
707 dropsFrequencyOfStream.open(dropsFrequencyTraceFile, std::ofstream::out);
708 std::ofstream marksFrequencyOfStream;
709 marksFrequencyOfStream.open(marksFrequencyTraceFile, std::ofstream::out);
710 std::ofstream lengthOfStream;
711 lengthOfStream.open(lengthTraceFile, std::ofstream::out);
712 std::ofstream queueDelayN0OfStream;
713 queueDelayN0OfStream.open(queueDelayN0TraceFile, std::ofstream::out);
714 std::ofstream queueDelayN1OfStream;
715 queueDelayN1OfStream.open(queueDelayN1TraceFile, std::ofstream::out);
716
718 // scenario setup //
720 Ptr<Node> pingServer = CreateObject<Node>();
721 Ptr<Node> n0Server = CreateObject<Node>();
722 Ptr<Node> n1Server = CreateObject<Node>();
723 Ptr<Node> n2 = CreateObject<Node>();
724 Ptr<Node> n3 = CreateObject<Node>();
725 Ptr<Node> pingClient = CreateObject<Node>();
726 Ptr<Node> n4Client = CreateObject<Node>();
727 Ptr<Node> n5Client = CreateObject<Node>();
728
729 // Device containers
730 NetDeviceContainer pingServerDevices;
731 NetDeviceContainer n0ServerDevices;
732 NetDeviceContainer n1ServerDevices;
733 NetDeviceContainer n2n3Devices;
734 NetDeviceContainer pingClientDevices;
735 NetDeviceContainer n4ClientDevices;
736 NetDeviceContainer n5ClientDevices;
737
739 p2p.SetQueue("ns3::DropTailQueue", "MaxSize", QueueSizeValue(QueueSize("3p")));
740 p2p.SetDeviceAttribute("DataRate", DataRateValue(DataRate(linkDataRate)));
741 // Add delay only on the server links
742 p2p.SetChannelAttribute("Delay", TimeValue(oneWayDelay));
743 pingServerDevices = p2p.Install(n2, pingServer);
744 n0ServerDevices = p2p.Install(n2, n0Server);
745
746 // In scenario 9, base RTT of n1server (dctcp) is 1ms
747 if (scenarioNum == 9)
748 {
749 p2p.SetChannelAttribute("Delay", TimeValue(MicroSeconds(500)));
750 }
751 n1ServerDevices = p2p.Install(n2, n1Server);
753 n2n3Devices = p2p.Install(n2, n3);
754 pingClientDevices = p2p.Install(n3, pingClient);
755 n4ClientDevices = p2p.Install(n3, n4Client);
756 n5ClientDevices = p2p.Install(n3, n5Client);
757 Ptr<PointToPointNetDevice> p = n2n3Devices.Get(0)->GetObject<PointToPointNetDevice>();
758 p->SetAttribute("DataRate", DataRateValue(bottleneckRate));
759
760 InternetStackHelper stackHelper;
761 stackHelper.InstallAll();
762
763 // Set the per-node TCP type here
764 Ptr<TcpL4Protocol> proto;
765 proto = n4Client->GetObject<TcpL4Protocol>();
766 proto->SetAttribute("SocketType", TypeIdValue(n0TcpTypeId));
767 proto = n0Server->GetObject<TcpL4Protocol>();
768 proto->SetAttribute("SocketType", TypeIdValue(n0TcpTypeId));
769 if (enableN1Tcp)
770 {
771 proto = n5Client->GetObject<TcpL4Protocol>();
772 proto->SetAttribute("SocketType", TypeIdValue(n1TcpTypeId));
773 proto = n1Server->GetObject<TcpL4Protocol>();
774 proto->SetAttribute("SocketType", TypeIdValue(n1TcpTypeId));
775 }
776
777 // InternetStackHelper will install a base TrafficControLayer on the node,
778 // but the Ipv4AddressHelper below will install the default FqCoDelQueueDisc
779 // on all single device nodes. The below code overrides the configuration
780 // that is normally done by the Ipv4AddressHelper::Install() method by
781 // instead explicitly configuring the queue discs we want on each device.
783 tchFq.SetRootQueueDisc("ns3::FqCoDelQueueDisc");
784 tchFq.SetQueueLimits("ns3::DynamicQueueLimits", "HoldTime", StringValue("1ms"));
785 tchFq.Install(pingServerDevices);
786 tchFq.Install(n0ServerDevices);
787 tchFq.Install(n1ServerDevices);
788 tchFq.Install(n2n3Devices.Get(1)); // n2 queue for bottleneck link
789 tchFq.Install(pingClientDevices);
790 tchFq.Install(n4ClientDevices);
791 tchFq.Install(n5ClientDevices);
793 tchN2.SetRootQueueDisc(queueTypeId.GetName());
794 tchN2.SetQueueLimits("ns3::DynamicQueueLimits", "HoldTime", StringValue("1000ms"));
795 tchN2.Install(n2n3Devices.Get(0));
796
798 ipv4.SetBase("10.1.1.0", "255.255.255.0");
799 Ipv4InterfaceContainer pingServerIfaces = ipv4.Assign(pingServerDevices);
800 ipv4.SetBase("10.1.2.0", "255.255.255.0");
801 Ipv4InterfaceContainer n0ServerIfaces = ipv4.Assign(n0ServerDevices);
802 ipv4.SetBase("10.1.3.0", "255.255.255.0");
803 Ipv4InterfaceContainer secondServerIfaces = ipv4.Assign(n1ServerDevices);
804 ipv4.SetBase("172.16.1.0", "255.255.255.0");
805 Ipv4InterfaceContainer n2n3Ifaces = ipv4.Assign(n2n3Devices);
806 ipv4.SetBase("192.168.1.0", "255.255.255.0");
807 Ipv4InterfaceContainer pingClientIfaces = ipv4.Assign(pingClientDevices);
808 ipv4.SetBase("192.168.2.0", "255.255.255.0");
809 Ipv4InterfaceContainer n4ClientIfaces = ipv4.Assign(n4ClientDevices);
810 ipv4.SetBase("192.168.3.0", "255.255.255.0");
811 Ipv4InterfaceContainer n5ClientIfaces = ipv4.Assign(n5ClientDevices);
812
813 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
814
816 // application setup //
818
819 V4PingHelper pingHelper("192.168.1.2");
820 pingHelper.SetAttribute("Interval", TimeValue(pingInterval));
821 pingHelper.SetAttribute("Size", UintegerValue(pingSize));
822 ApplicationContainer pingContainer = pingHelper.Install(pingServer);
823 Ptr<V4Ping> v4Ping = pingContainer.Get(0)->GetObject<V4Ping>();
824 v4Ping->TraceConnectWithoutContext("Rtt", MakeBoundCallback(&TracePingRtt, &pingOfStream));
825 pingContainer.Start(Seconds(1));
826 pingContainer.Stop(stopTime - Seconds(1));
827
828 BulkSendHelper tcp("ns3::TcpSocketFactory", Address());
829 // set to large value: e.g. 1000 Mb/s for 60 seconds = 7500000000 bytes
830 tcp.SetAttribute("MaxBytes", UintegerValue(7500000000));
831 // Configure n4/n0 TCP client/server pair
832 uint16_t n4Port = 5000;
834 InetSocketAddress n0DestAddress(n4ClientIfaces.GetAddress(1), n4Port);
835 tcp.SetAttribute("Remote", AddressValue(n0DestAddress));
836 n0App = tcp.Install(n0Server);
837 n0App.Start(Seconds(5));
838 n0App.Stop(stopTime - Seconds(1));
839
840 Address n4SinkAddress(InetSocketAddress(Ipv4Address::GetAny(), n4Port));
841 PacketSinkHelper n4SinkHelper("ns3::TcpSocketFactory", n4SinkAddress);
842 ApplicationContainer n4SinkApp;
843 n4SinkApp = n4SinkHelper.Install(n4Client);
844 n4SinkApp.Start(Seconds(5));
845 n4SinkApp.Stop(stopTime - MilliSeconds(500));
846
847 // Configure second TCP client/server pair
848 if (enableN1Tcp)
849 {
850 uint16_t n5Port = 5000;
851 ApplicationContainer secondApp;
852 InetSocketAddress n1DestAddress(n5ClientIfaces.GetAddress(1), n5Port);
853 tcp.SetAttribute("Remote", AddressValue(n1DestAddress));
854 secondApp = tcp.Install(n1Server);
855 secondApp.Start(Seconds(15));
856 secondApp.Stop(stopTime - Seconds(1));
857
858 Address n5SinkAddress(InetSocketAddress(Ipv4Address::GetAny(), n5Port));
859 PacketSinkHelper n5SinkHelper("ns3::TcpSocketFactory", n5SinkAddress);
860 ApplicationContainer n5SinkApp;
861 n5SinkApp = n5SinkHelper.Install(n5Client);
862 n5SinkApp.Start(Seconds(15));
863 n5SinkApp.Stop(stopTime - MilliSeconds(500));
864 }
865
866 // Setup traces that can be hooked now
869 tc = n2n3Devices.Get(0)->GetNode()->GetObject<TrafficControlLayer>();
870 qd = tc->GetRootQueueDiscOnDevice(n2n3Devices.Get(0));
871 qd->TraceConnectWithoutContext("Drop", MakeBoundCallback(&TraceDrop, &dropOfStream));
872 qd->TraceConnectWithoutContext("Mark", MakeBoundCallback(&TraceMark, &markOfStream));
874 "BytesInQueue",
875 MakeBoundCallback(&TraceQueueLength, &lengthOfStream, bottleneckRate));
877 "Dequeue",
878 MakeBoundCallback(&PacketDequeue, &queueDelayN0OfStream, &queueDelayN1OfStream));
879
880 // Setup scheduled traces; TCP traces must be hooked after socket creation
881 Simulator::Schedule(Seconds(5) + MilliSeconds(100),
883 &n0TcpRttOfStream);
884 Simulator::Schedule(Seconds(5) + MilliSeconds(100),
886 &n0TcpCwndOfStream);
887 Simulator::Schedule(Seconds(5) + MilliSeconds(100), &ScheduleN0PacketSinkConnection);
888 Simulator::Schedule(throughputSamplingInterval,
890 &n0TcpThroughputOfStream,
891 throughputSamplingInterval);
892 // Setup scheduled traces; TCP traces must be hooked after socket creation
893 if (enableN1Tcp)
894 {
895 Simulator::Schedule(Seconds(15) + MilliSeconds(100),
897 &n1TcpRttOfStream);
898 Simulator::Schedule(Seconds(15) + MilliSeconds(100),
900 &n1TcpCwndOfStream);
901 Simulator::Schedule(Seconds(15) + MilliSeconds(100), &ScheduleN1PacketSinkConnection);
902 }
903 Simulator::Schedule(throughputSamplingInterval,
905 &n1TcpThroughputOfStream,
906 throughputSamplingInterval);
907 Simulator::Schedule(marksSamplingInterval,
909 &marksFrequencyOfStream,
910 marksSamplingInterval);
911 Simulator::Schedule(marksSamplingInterval,
913 &dropsFrequencyOfStream,
914 marksSamplingInterval);
915
916 if (enablePcap)
917 {
918 p2p.EnablePcapAll("FqCoDel-L4S-example", false);
919 }
920
921 Simulator::Stop(stopTime);
922 Simulator::Run();
923
924 pingOfStream.close();
925 n0TcpCwndOfStream.close();
926 n0TcpRttOfStream.close();
927 n0TcpThroughputOfStream.close();
928 n1TcpCwndOfStream.close();
929 n1TcpRttOfStream.close();
930 n1TcpThroughputOfStream.close();
931 dropOfStream.close();
932 markOfStream.close();
933 dropsFrequencyOfStream.close();
934 marksFrequencyOfStream.close();
935 lengthOfStream.close();
936 queueDelayN0OfStream.close();
937 queueDelayN1OfStream.close();
938}
a polymophic address class
Definition: address.h:92
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)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter.
void Stop(Time stop)
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
A helper to make it easier to instantiate an ns3::BulkSendApplication on a set of nodes.
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:369
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 ...
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:42
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:1425
Build a set of QueueDisc objects.
QueueDiscContainer Install(NetDeviceContainer c)
uint16_t SetRootQueueDisc(const std::string &type, Args &&... args)
Helper function used to set a root queue disc of the given type and with the given attributes.
void SetQueueLimits(std::string type, Args &&... args)
Helper function used to add a queue limits object to the transmission queues of the devices.
Introspection did not find any typical Config paths.
a unique identifier for an interface.
Definition: type-id.h: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
Create a IPv4 ping application and associate it to a node.
Definition: v4ping-helper.h:38
an application which sends one ICMP ECHO request, waits for a REPLYs and reports the calculated RTT.
Definition: v4ping.h:43
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 TracePingRtt(std::ofstream *ofStream, Time rtt)
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 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:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
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