Skip to main content

Simulate Multiple Concurrent FTP Sessions and Analyze Aggregate Throughput | NS3 Project 25

Simulate Multiple Concurrent FTP Sessions and Analyze Aggregate Throughput

Simulation Environment: ns-3 | Tools Used: FlowMonitor, NetAnim, TraceMetrics

1. Objective

The primary objective of this experiment is to simulate a network scenario in which multiple concurrent File Transfer Protocol (FTP)-like sessions operate simultaneously over a shared network infrastructure. Using the ns-3 discrete-event network simulator, the study models seven independent TCP bulk-send flows that traverse a common bottleneck link. The experiment aims to measure and analyze the individual throughput of each flow as well as the aggregate throughput delivered to the single receiver node. By configuring access links with high capacity and constraining the router-to-receiver link to a narrow bandwidth, the simulation deliberately induces congestion to study how TCP's congestion control mechanisms influence flow behavior, resource sharing, and overall network efficiency.

Furthermore, the experiment evaluates fairness among competing flows, particularly in light of staggered flow start times, and investigates how late-arriving flows behave in a congested environment relative to established flows. The findings provide practical insight into the dynamics of TCP traffic under real-world-like conditions, offering a foundation for understanding congestion, queuing behaviour, and bandwidth allocation in modern packet-switched networks.

2. Network Topology

The network topology used in this simulation is a dumbbell topology, which is a widely adopted architecture in congestion analysis studies. The topology consists of nine nodes in total: seven sender nodes (S0 through S6), one intermediate router node (R), and one receiver node (D). Each sender is connected to the router through a dedicated access link, while the router is connected to the receiver through a single bottleneck link.

The access links are configured as high-speed point-to-point links with a data rate of 10 Mbps and a propagation delay of 2 ms. These links comfortably support the traffic generated by individual senders, ensuring that congestion does not occur at the ingress side of the router. The bottleneck link, connecting the router to the receiver, is intentionally constrained to 2 Mbps with a propagation delay of 20 ms. Since the aggregate traffic entering the router from all seven senders can potentially reach up to 70 Mbps, the bottleneck link becomes heavily congested, serving as the critical chokepoint of the topology.

This design choice is deliberate: the bottleneck link allows the simulation to study the effects of TCP congestion control, fair bandwidth allocation, and queue management under realistic stress conditions. All communication in this topology follows TCP semantics, making the simulation suitable for analyzing how multiple concurrent FTP-like sessions compete for a shared resource.

Dumbbell Network Topology Diagram
S0–S6 ──(10Mbps/2ms)──> Router ──(2Mbps/20ms)──> Receiver

3. Simulation Setup and Tools Used

The simulation was implemented using the ns-3 (Network Simulator 3) framework, a widely used open-source discrete-event network simulator designed for research and educational purposes. ns-3 provides accurate models of TCP/IP protocol stacks, network devices, and channel characteristics, making it suitable for replicating real-world network behavior.

  • Link Configuration: All links are implemented as point-to-point (P2P) connections. The seven access links (sender to router) each operate at 10 Mbps with a propagation delay of 2 ms. The single bottleneck link (router to receiver) operates at 2 Mbps with a propagation delay of 20 ms, creating a realistic asymmetry between ingress and egress capacity at the router.
  • Application Model: FTP-like traffic is modeled using the ns-3 BulkSendHelper, which continuously transmits data over TCP without any application-level pauses or limits (MaxBytes = 0). At the receiver end, PacketSinkHelper applications are installed to accept and absorb incoming TCP connections on individual ports beginning from port 5000. This ensures that each sender-receiver pair maintains a distinct TCP connection throughout the simulation.
  • Staggered Start Times: To simulate realistic arrival patterns and to study how established flows respond to new competing flows, each sender is assigned a unique start time: Sender 0 begins at t = 1 s, Sender 1 at t = 2 s, and so on up to Sender 6 at t = 7 s. The total simulation duration is 20 seconds, providing sufficient time for all flows to reach steady-state behavior.
  • Tracing and Monitoring: ASCII trace files (access.tr, bottleneck.tr) and PCAP captures are enabled on all links to provide detailed packet-level logs. These files serve as inputs to the TraceMetrics tool for post-simulation analysis. The FlowMonitor module can be enabled to collect per-flow statistics including bytes received, packet loss, and mean delay.
  • Tools Used:
    • ns-3: Core simulation engine for modeling the network topology, protocols, and applications.
    • FlowMonitor: ns-3 module for per-flow performance metrics.
    • TraceMetrics: External GUI-based tool for parsing .tr trace files and generating throughput graphs.
    • NetAnim: XML-based animation tool for visualizing packet flow across the topology.

4. Source Code (dftp.cc)

The following C++ source code implements the described simulation in ns-3. The program creates the dumbbell topology, installs TCP BulkSend applications on each sender node with staggered start times, and enables both ASCII and PCAP trace output for analysis:

#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/flow-monitor-module.h"
#include "ns3/trace-helper.h"
#include "ns3/netanim-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE("MultiFtpExample");

int main() {
    uint32_t nFlows = 7;
    double simTime = 20.0;

    NodeContainer senders; 
    senders.Create(nFlows);
    NodeContainer router;  
    router.Create(1);
    NodeContainer receiver; 
    receiver.Create(1);

    InternetStackHelper stack;
    stack.InstallAll();

    // Access links (fast)
    PointToPointHelper access;
    access.SetDeviceAttribute("DataRate", StringValue("10Mbps"));
    access.SetChannelAttribute("Delay", StringValue("2ms"));

    // Bottleneck link (slow)
    PointToPointHelper bottleneck;
    bottleneck.SetDeviceAttribute("DataRate", StringValue("2Mbps"));
    bottleneck.SetChannelAttribute("Delay", StringValue("20ms"));

    Ipv4AddressHelper address;
    std::vector<Ipv4InterfaceContainer> senderIfs;

    for (uint32_t i = 0; i < nFlows; i++) {
        NodeContainer pair(senders.Get(i), router.Get(0));
        NetDeviceContainer dev = access.Install(pair);
        std::ostringstream subnet;
        subnet << "10.1." << i + 1 << ".0";
        address.SetBase(subnet.str().c_str(), "255.255.255.0");
        senderIfs.push_back(address.Assign(dev));
    }

    NodeContainer rr(router.Get(0), receiver.Get(0));
    NetDeviceContainer devRR = bottleneck.Install(rr);
    address.SetBase("10.2.0.0", "255.255.255.0");
    Ipv4InterfaceContainer rrIf = address.Assign(devRR);

    AsciiTraceHelper ascii;
    access.EnableAsciiAll(ascii.CreateFileStream("access.tr"));
    bottleneck.EnableAsciiAll(ascii.CreateFileStream("bottleneck.tr"));
    access.EnablePcapAll("access");
    bottleneck.EnablePcapAll("bottleneck");

    Ipv4GlobalRoutingHelper::PopulateRoutingTables();

    uint16_t basePort = 5000;
    ApplicationContainer sinkApps;

    for (uint32_t i = 0; i < nFlows; i++) {
        PacketSinkHelper sink("ns3::TcpSocketFactory",
                              InetSocketAddress(Ipv4Address::GetAny(), basePort + i));
        sinkApps.Add(sink.Install(receiver.Get(0)));
    }
    sinkApps.Start(Seconds(0.0)); 
    sinkApps.Stop(Seconds(simTime));

    for (uint32_t i = 0; i < nFlows; i++) {
        BulkSendHelper source("ns3::TcpSocketFactory",
                              InetSocketAddress(rrIf.GetAddress(1), basePort + i));
        source.SetAttribute("MaxBytes", UintegerValue(0));
        ApplicationContainer srcApp = source.Install(senders.Get(i));
        srcApp.Start(Seconds(1.0 + i));
        srcApp.Stop(Seconds(simTime));
    }

    Simulator::Stop(Seconds(simTime));

    // NetAnim Configuration (Uncomment for NetAnim visualization output)
    // AnimationInterface anim("multi-ftp.xml");
    // for (uint32_t i = 0; i < nFlows; i++) {
    //     anim.SetConstantPosition(senders.Get(i), 0.0, i * 20.0);
    // }
    // anim.SetConstantPosition(router.Get(0), 50.0, 50.0);
    // anim.SetConstantPosition(receiver.Get(0), 100.0, 50.0);

    FlowMonitorHelper flowmon;
    Ptr<FlowMonitor> monitor = flowmon.InstallAll();

    Simulator::Run();

    monitor->CheckForLostPackets();
    monitor->SerializeToXmlFile("flowmon.xml", true, true);

    Ptr<Ipv4FlowClassifier> classifier =
        DynamicCast<Ipv4FlowClassifier>(flowmon.GetClassifier());
    std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats();

    std::ofstream outFile("throughput.dat");
    double totalThroughput = 0;

    for (auto &flow : stats) {
        Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(flow.first);
        double throughput = flow.second.rxBytes * 8.0 / (simTime * 1000000.0);
        totalThroughput += throughput;
        outFile << flow.first << " " << throughput << std::endl;
        std::cout << "Flow " << flow.first
                  << " (" << t.sourceAddress << " -> " << t.destinationAddress << ")\n";
        std::cout << "  Throughput: " << throughput << " Mbps\n";
    }

    std::cout << "Aggregate Throughput: " << totalThroughput << " Mbps\n";
    outFile.close();

    Simulator::Destroy();
    return 0;
}

5. Results and Graphs

5.1 FlowMonitor and Aggregate Throughput

FlowMonitor Console Summary
FlowMonitor Throughput Output

5.2 Throughput Graph

The throughput graph, generated using TraceMetrics from the bottleneck.tr trace file, illustrates the time-varying throughput at the bottleneck link over the 20-second simulation. Each new flow entering the network causes a visible perturbation in the throughput profile of existing flows as TCP congestion control mechanisms negotiate bandwidth allocation. The graph shows an initial high-throughput phase for the first sender, followed by progressive reduction as additional flows join and share the bottleneck capacity.

TraceMetrics Bottleneck Throughput Graph
Time-Varying Bottleneck Throughput

5.3 NetAnim Visualization

The NetAnim visualization, generated from the multi-ftp.xml output file, provides a graphical representation of the network topology and packet movement during simulation. Sender nodes are vertically arranged on the left, the router is positioned at the center, and the receiver is placed on the right. Animated packets traveling along each link confirm that all seven TCP flows are active and successfully routing through the router toward the receiver. The animation also visually demonstrates congestion buildup at the bottleneck link as the simulation progresses.

NetAnim Topology and Packet Flow
NetAnim Visualization of 7-Flow Dumbbell Topology

5.4 Throughput Data (throughput.dat)

The throughput.dat file records throughput values for each flow identified by the FlowMonitor module. Due to the bidirectional nature of TCP, even-numbered flow IDs correspond to reverse ACK flows while odd-numbered IDs represent forward data flows:

Flow ID Throughput (Mbps) Direction
1 0.5088370 Data (BulkSend)
2 0.0371472 ACK/Control
3 0.3250900 Data (BulkSend)
4 0.0244176 ACK/Control
5 0.2281870 Data (BulkSend)
6 0.0173952 ACK/Control
7 0.2366540 Data (BulkSend)
8 0.0180512 ACK/Control
9 0.2103120 Data (BulkSend)
10 0.0148272 ACK/Control
11 0.1696220 Data (BulkSend)
12 0.0104800 ACK/Control
13 0.2053730 Data (BulkSend)
14 0.0151568 ACK/Control

The aggregate throughput of all forward (data) flows is approximately 1.884 Mbps, approaching the theoretical maximum of 2 Mbps on the bottleneck link, indicating high link utilization. The sum of ACK flows (approximately 0.135 Mbps) represents control traffic overhead inherent to TCP operation.

5.5 TraceMetrics Output

TraceMetrics Queue Drops and Metrics Summary
TraceMetrics Metric Analysis

TraceMetrics was used to parse the bottleneck.tr and access.tr ASCII trace files produced by the simulation. The tool provides detailed statistics including packet transmission events, queue drop events, throughput timelines, and delay histograms. The trace output confirms the occurrence of packet drops at the router queue, particularly during the period when all seven flows are simultaneously active (after t = 7 s), validating the congestion scenario designed into the topology.

6. Results Analysis

  • Individual Flow Throughput: The data from throughput.dat reveals a clear disparity in per-flow throughput. Flow 1 (the first sender, active from t = 1 s) achieves the highest throughput of approximately 0.509 Mbps, having been the sole occupant of the bottleneck link for one second before any competing flow arrived. Subsequent flows exhibit progressively lower throughput as each arrives into an increasingly congested network. Flow 11, representing the sixth sender (starting at t = 6 s), achieves only 0.170 Mbps, while the last-starting flow (Flow 13) recovers slightly to 0.205 Mbps as TCP's AIMD mechanisms redistribute bandwidth over time.
  • Aggregate Throughput: The sum of all forward data flows (Flows 1, 3, 5, 7, 9, 11, and 13) yields a total aggregate throughput of approximately 1.884 Mbps out of a theoretical maximum of 2.0 Mbps on the bottleneck link. This represents a link utilization of approximately 94.2%, indicating that TCP is effectively saturating the available bandwidth despite its congestion avoidance mechanisms.
  • Impact of the Bottleneck Link: The bottleneck link is the single most important factor governing throughput in this topology. Since the aggregate offered load (up to 70 Mbps from seven 10 Mbps senders) vastly exceeds the bottleneck capacity (2 Mbps), the router's output queue experiences persistent congestion. Packet drops trigger TCP's congestion window reduction, causing all flows to reduce their sending rates.
  • Fairness Analysis: The simulation reveals moderate unfairness among competing flows. Early-starting flows consistently achieve higher throughput than later-arriving flows because they establish larger congestion windows before encountering competition. The throughput difference between Flow 1 (0.509 Mbps) and Flow 11 (0.170 Mbps) illustrates this startup advantage. However, as the simulation approaches steady state, TCP AIMD progressively equalizes bandwidth allocation.
  • Effect of Staggered Start Times: Staggered start times introduce temporal unfairness that persists for several seconds after each new flow joins. Each newly starting flow initially encounters a congested network and must grow its congestion window from a minimal initial value, disadvantaging it relative to flows that have been running longer. Furthermore, each new flow entry causes a temporary throughput reduction in all existing flows as TCP reacts to increased packet loss rates.

7. LLMs and Prompt Used

  • LLM Used: ChatGPT (OpenAI)
  • Prompt Used:
    "I want to simulate Multiple Concurrent FTP Sessions(atleast 7) using ns3.Help me build a versatile code to simulate any number of ftp sessions and analyze the throughput anf flow using tracemetrics and flowmonitor.Teach me the underlying concepts to this simulation and how the code works."

8. Interpretation and Conclusion

Key Observations: This simulation demonstrates several fundamental properties of TCP behavior under congestion. First, the bottleneck link is effectively saturated by seven competing TCP flows, achieving approximately 94% utilization. Second, the staggered start times create an inherent throughput hierarchy, with earlier-starting flows maintaining a persistent advantage over later arrivals. Third, the TCP congestion control mechanism distributes bandwidth in a broadly cooperative manner, though not with perfect fairness. Fourth, ACK traffic constitutes a small but measurable overhead, accounting for roughly 7% of total traffic volume across all flows.

Real-World Relevance: The dumbbell topology with a bottleneck link closely models real-world scenarios such as ISP access networks, last-mile connections, and data center uplinks where multiple users or applications compete for a shared, constrained outbound link. The findings are directly applicable to the design and dimensioning of such networks, particularly in determining the number of concurrent sessions that can be supported while maintaining acceptable quality of service.

Conclusion: This experiment successfully simulates seven concurrent FTP-like TCP sessions over a dumbbell network topology in ns-3. The bottleneck link constrains aggregate throughput to approximately 1.884 Mbps, representing 94.2% utilization of the 2 Mbps capacity. Individual flow throughput varies from 0.170 Mbps to 0.509 Mbps, reflecting the influence of staggered start times and TCP congestion dynamics. While bandwidth sharing is not perfectly equitable, TCP's AIMD mechanism ensures cooperative sharing without complete flow starvation.

Comments

Popular posts from this blog

How to Create Ubuntu 24.04 Bootable USB Using Rufus [Step-by-Step Guide]

How to Create Ubuntu 24.04 Bootable USB Using Rufus [Step-by-Step Guide] Are you planning to install or try Ubuntu 24.04 LTS ? The easiest and most reliable method is to create a bootable USB drive using Rufus on a Windows system. This detailed guide will help you create a Ubuntu 24.04 USB bootloader using Rufus with easy-to-follow steps and screenshots (optional). Here is the complete video of the bootloader creation and OS installation in Windows 11. 🧰 Requirements A USB flash drive (minimum 8GB recommended) A Windows PC Ubuntu 24.04 LTS ISO file Rufus USB creation tool 🧾 Steps to Create a Ubuntu 24.04 Bootable USB Using Rufus ✅ Step 1: Download Ubuntu 24.04 ISO Visit the official Ubuntu website and download the Ubuntu 24.04 LTS ISO file . ✅ Step 2: Download and Run Rufus Head to Rufus official site and download the latest version. Open the executable file (no installation required). ✅ Step 3: Insert USB Drive Plug in your USB drive. Rufus ...

Installing ns3 in Ubuntu 22.04 | Complete Instructions

In this post, we are going to see how to install ns-3.36.1 in Ubuntu 22.04. You can follow the video for complete details Tools used in this simulation: NS3 version ns-3.36.1  OS Used: Ubuntu 22.04 LTS Installation of NS3 (ns-3.36.1) There are some changes in the ns3 installation procedure and the dependencies. So open a terminal and issue the following commands Step 1:  Prerequisites $ sudo apt update In the following packages, all the required dependencies are taken care and you can install all these packages for the complete use of ns3. $ sudo apt install g++ python3 python3-dev pkg-config sqlite3 cmake python3-setuptools git qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools gir1.2-goocanvas-2.0 python3-gi python3-gi-cairo python3-pygraphviz gir1.2-gtk-3.0 ipython3 openmpi-bin openmpi-common openmpi-doc libopenmpi-dev autoconf cvs bzr unrar gsl-bin libgsl-dev libgslcblas0 wireshark tcpdump sqlite sqlite3 libsqlite3-dev  libxml2 libxml2-dev libc6-dev libc6-dev-i386 libc...

NS2 (NS-2.35) Installation in Ubuntu 11.10

This post will help you in installing Network Simulator 2 version NS2.35 in Ubuntu 11.10 Instructions Install Ubuntu Download NS-2.35 ( http://sourceforge.net/projects/nsnam/files/allinone/ns-allinone-2.35/ns-allinone-2.35.tar.gz/download ) Unzip or untar it to any folder (recommended is /home/ loginname) using the following commands one by one sudo apt-get update sudo apt-get install build-essential autoconf automake libxmu-dev tar zxvf ns-allinone-2.35.tar.gz cd ns-allinone-2.35 ./install Once installed the PATH information will be provided to you. Copy the PATH and LD_LIBRARY_PATH Variable to .bashrc (see a dot in the beginning) Input the path information in .bashrc file like this export PATH=$PATH:<Place your paths here> export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: <place the LD_LIBRARY_PATHS> here. Once done, save the file and close execute the command source .bashrc try ns or nam to see whether your installation succeeded.