Skip to main content

Effect of Frame Size on Collision Probability and Throughput in a CSMA-Based LAN Using ns-3 Simulation | NS3 Project 18

Effect of Frame Size on Collision Probability and Throughput in a CSMA-Based LAN Using ns-3 Simulation 

Aim :

To study the effect of frame size on collision probability in a CSMA-based LAN by varying frame sizes and observing the corresponding contention behavior and throughput using ns-3 simulation.

LLM Used and Prompt

LLM Used: ChatGPT (GPT-5.4 Thinking)

Prompt Used:

Write an ns-3 C++ program runnable using ./ns3 run scratch/24BPS1151.cc to study the effect of frame size on collision probability in a CSMA-based LAN. Use multiple sender nodes connected via a CSMA channel to a receiver node. Vary frame sizes, estimate collision probability using a contention-based proxy, compute throughput, generate output files for plotting graphs, and include NetAnim support.

Topology Description

The network consists of a shared CSMA LAN topology:

·         6 Sender Nodes

·         1 Receiver Node

·         All nodes are connected using a single CSMA bus (shared medium)

Key Characteristics:

·         Channel Type: CSMA (shared broadcast medium)

·         Data Rate: 10 Mbps

·         Channel Delay: 5 microseconds

·         Transport Protocol: UDP

·         Traffic Type: Random (Poisson-like arrivals using exponential distribution)

Behavior:

·         All sender nodes transmit data packets to a single receiver node.

·         Since the channel is shared, multiple nodes may attempt transmission simultaneously, leading to contention.

Source Code:

#include "ns3/applications-module.h"

#include "ns3/core-module.h"

#include "ns3/csma-module.h"

#include "ns3/internet-module.h"

#include "ns3/mobility-module.h"

#include "ns3/netanim-module.h"

#include "ns3/network-module.h"

 #include <fstream>

#include <iomanip>

#include <string>

#include <vector>

 

using namespace ns3;

 NS_LOG_COMPONENT_DEFINE("FrameSizeCollisionStudy");

 // ------------------------------------------------------------

// Global statistics class

// ------------------------------------------------------------

class StudyStats

{

public:

  void Configure(uint32_t frameSize, DataRate rate, Time channelDelay)

  {

    m_frameSize = frameSize;

    m_rate = rate;

    m_channelDelay = channelDelay;

    m_attempts = 0;

    m_collisionProxyCount = 0;

    m_busyUntil = Seconds(0);

  }

   void RecordAttempt()

  {

    Time now = Simulator::Now();

    m_attempts++;

 

    // Approximate on-medium transmission time

    uint32_t effectiveBytes = m_frameSize + 38; // rough overhead

    double txSeconds = (effectiveBytes * 8.0) / m_rate.GetBitRate();

    Time txTime = Seconds(txSeconds);

 

    // Proxy: if a send attempt happens while medium is already busy

    if (now < m_busyUntil)

    {

      m_collisionProxyCount++;

    }

     Time start = (now > m_busyUntil) ? now : m_busyUntil;

    m_busyUntil = start + txTime + m_channelDelay;

  }

   uint64_t GetAttempts() const

  {

    return m_attempts;

  }

   uint64_t GetCollisionProxyCount() const

  {

    return m_collisionProxyCount;

  }

  double GetCollisionProxyProbability() const

  {

    if (m_attempts == 0)

    {

      return 0.0;

    }

    return static_cast<double>(m_collisionProxyCount) / static_cast<double>(m_attempts);

  }

private:

  uint32_t m_frameSize = 0;

  DataRate m_rate = DataRate("10Mbps");

  Time m_channelDelay = MicroSeconds(5);

  uint64_t m_attempts = 0;

  uint64_t m_collisionProxyCount = 0;

  Time m_busyUntil = Seconds(0);

};

 static StudyStats g_stats;

 // ------------------------------------------------------------

// Custom traffic application

// ------------------------------------------------------------

class TrafficApp : public Application

{

public:

  TrafficApp() = default;

 

  void Setup(Ptr<Socket> socket,

             Address peer,

             uint32_t packetSize,

             uint32_t maxPackets,

             double lambda)

  {

    m_socket = socket;

    m_peer = peer;

    m_packetSize = packetSize;

    m_maxPackets = maxPackets;

    m_lambda = lambda;

  }

 private:

  virtual void StartApplication() override

  {

    m_running = true;

    m_packetsSent = 0;

     if (!m_socket)

    {

      return;

    }

 

    m_socket->Bind();

    m_socket->Connect(m_peer);

 

    m_exp = CreateObject<ExponentialRandomVariable>();

    m_exp->SetAttribute("Mean", DoubleValue(1.0 / m_lambda));

 

    Ptr<UniformRandomVariable> uv = CreateObject<UniformRandomVariable>();

    Time startOffset = Seconds(uv->GetValue(0.001, 0.02));

    m_sendEvent = Simulator::Schedule(startOffset, &TrafficApp::SendPacket, this);

  }

   virtual void StopApplication() override

  {

    m_running = false;

     if (m_sendEvent.IsPending())

    {

      Simulator::Cancel(m_sendEvent);

    }

     if (m_socket)

    {

      m_socket->Close();

    }

  }

   void SendPacket()

  {

    if (!m_running || m_packetsSent >= m_maxPackets)

    {

      return;

    }

     Ptr<Packet> packet = Create<Packet>(m_packetSize);

     g_stats.RecordAttempt();

    m_socket->Send(packet);

    m_packetsSent++;

     if (m_packetsSent < m_maxPackets)

    {

      ScheduleNextTx();

    }

  }

  void ScheduleNextTx()

  {

    double nextGap = m_exp->GetValue();

    m_sendEvent = Simulator::Schedule(Seconds(nextGap), &TrafficApp::SendPacket, this);

  }

  Ptr<Socket> m_socket;

  Address m_peer;

  bool m_running = false;

  uint32_t m_packetSize = 512;

  uint32_t m_maxPackets = 0;

  uint32_t m_packetsSent = 0;

  double m_lambda = 100.0;

  EventId m_sendEvent;

  Ptr<ExponentialRandomVariable> m_exp;

};

// ------------------------------------------------------------

// Result structure

// ------------------------------------------------------------

struct Result

{

  uint32_t frameSize;

  uint64_t attempts;

  uint64_t collisionProxyCount;

  double collisionProxyProbability;

  double throughputMbps;

  uint64_t rxBytes;

};

 // ------------------------------------------------------------

// Run one case

// ------------------------------------------------------------

Result

RunOneCase(uint32_t frameSize,

           bool createAnim,

           uint32_t nSenders,

           double offeredPpsPerSender,

           double simTimeSec)

{

  NodeContainer nodes;

  nodes.Create(nSenders + 1); // last node = receiver

 

  // Attach a fixed mobility model for NetAnim

  MobilityHelper mobility;

  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");

  mobility.Install(nodes);

 

  CsmaHelper csma;

  DataRate channelRate("10Mbps");

  Time channelDelay = MicroSeconds(5);

   csma.SetChannelAttribute("DataRate", DataRateValue(channelRate));

  csma.SetChannelAttribute("Delay", TimeValue(channelDelay));

   NetDeviceContainer devices = csma.Install(nodes);

   InternetStackHelper internet;

  internet.Install(nodes);

   Ipv4AddressHelper ipv4;

  ipv4.SetBase("10.1.1.0", "255.255.255.0");

  Ipv4InterfaceContainer interfaces = ipv4.Assign(devices);

   uint16_t port = 9999;

  Address sinkAddress(InetSocketAddress(interfaces.GetAddress(nSenders), port));

   PacketSinkHelper sinkHelper("ns3::UdpSocketFactory",

                              InetSocketAddress(Ipv4Address::GetAny(), port));

  ApplicationContainer sinkApp = sinkHelper.Install(nodes.Get(nSenders));

  sinkApp.Start(Seconds(0.0));

  sinkApp.Stop(Seconds(simTimeSec));

   g_stats.Configure(frameSize, channelRate, channelDelay);

   for (uint32_t i = 0; i < nSenders; ++i)

  {

    Ptr<Socket> socket = Socket::CreateSocket(nodes.Get(i), UdpSocketFactory::GetTypeId());

    Ptr<TrafficApp> app = CreateObject<TrafficApp>();

    app->Setup(socket, sinkAddress, frameSize, 4000, offeredPpsPerSender);

    nodes.Get(i)->AddApplication(app);

    app->SetStartTime(Seconds(0.5));

    app->SetStopTime(Seconds(simTimeSec - 0.2));

  }

   AnimationInterface* anim = nullptr;

  if (createAnim)

  {

    anim = new AnimationInterface("framesize-study-animation.xml", 50000);

    for (uint32_t i = 0; i < nSenders; ++i)

    {

      anim->SetConstantPosition(nodes.Get(i), 10 + i * 20, 20);

      anim->UpdateNodeDescription(nodes.Get(i), "Sender-" + std::to_string(i));

      anim->UpdateNodeColor(nodes.Get(i), 255, 0, 0);

    }

 

    anim->SetConstantPosition(nodes.Get(nSenders), 60, 80);

    anim->UpdateNodeDescription(nodes.Get(nSenders), "Receiver");

    anim->UpdateNodeColor(nodes.Get(nSenders), 0, 255, 0);

  }

 

  Simulator::Stop(Seconds(simTimeSec));

  Simulator::Run();

 

  Ptr<PacketSink> sink = DynamicCast<PacketSink>(sinkApp.Get(0));

  uint64_t rxBytes = sink->GetTotalRx();

  double throughputMbps = (rxBytes * 8.0) / (simTimeSec * 1000000.0);

 

  Result r;

  r.frameSize = frameSize;

  r.attempts = g_stats.GetAttempts();

  r.collisionProxyCount = g_stats.GetCollisionProxyCount();

  r.collisionProxyProbability = g_stats.GetCollisionProxyProbability();

  r.throughputMbps = throughputMbps;

  r.rxBytes = rxBytes;

 

  Simulator::Destroy();

 

  if (anim)

  {

    delete anim;

  }

 

  return r;

}

 

// ------------------------------------------------------------

// Write output files

// ------------------------------------------------------------

void

WritePlotFiles(const std::vector<Result>& results)

{

  std::ofstream dat("framesize-results.dat");

  dat << "#FrameSize CollisionProxyProbability ThroughputMbps Attempts CollisionProxyCount RxBytes\n";

  for (const auto& r : results)

  {

    dat << r.frameSize << " "

        << std::fixed << std::setprecision(6) << r.collisionProxyProbability << " "

        << std::fixed << std::setprecision(6) << r.throughputMbps << " "

        << r.attempts << " "

        << r.collisionProxyCount << " "

        << r.rxBytes << "\n";

  }

  dat.close();

 

  std::ofstream plt1("collision-vs-framesize.plt");

  plt1 << "set terminal png size 1000,700\n";

  plt1 << "set output 'collision-vs-framesize.png'\n";

  plt1 << "set title 'Frame Size vs Collision Proxy Probability in CSMA LAN'\n";

  plt1 << "set xlabel 'Frame Size (bytes)'\n";

  plt1 << "set ylabel 'Collision Proxy Probability'\n";

  plt1 << "set grid\n";

  plt1 << "plot 'framesize-results.dat' using 1:2 with linespoints lw 2 pt 7 title 'Collision Proxy'\n";

  plt1.close();

 

  std::ofstream plt2("throughput-vs-framesize.plt");

  plt2 << "set terminal png size 1000,700\n";

  plt2 << "set output 'throughput-vs-framesize.png'\n";

  plt2 << "set title 'Frame Size vs Throughput in CSMA LAN'\n";

  plt2 << "set xlabel 'Frame Size (bytes)'\n";

  plt2 << "set ylabel 'Throughput (Mbps)'\n";

  plt2 << "set grid\n";

  plt2 << "plot 'framesize-results.dat' using 1:3 with linespoints lw 2 pt 7 title 'Throughput'\n";

  plt2.close();

}

 

// ------------------------------------------------------------

// Main

// ------------------------------------------------------------

int

main(int argc, char* argv[])

{

  uint32_t nSenders = 6;

  double offeredPpsPerSender = 150.0;

  double simTimeSec = 10.0;

 

  CommandLine cmd(__FILE__);

  cmd.AddValue("nSenders", "Number of sender nodes", nSenders);

  cmd.AddValue("pps", "Offered packets/sec per sender", offeredPpsPerSender);

  cmd.AddValue("simTime", "Simulation time in seconds", simTimeSec);

  cmd.Parse(argc, argv);

 

  std::vector<uint32_t> frameSizes = {128, 256, 512, 1024, 1500};

  std::vector<Result> results;

 

  std::cout << "\n===== CSMA Frame Size Study =====\n";

  std::cout << "Senders: " << nSenders

            << ", Offered Load per Sender: " << offeredPpsPerSender

            << " pps, Simulation Time: " << simTimeSec << " s\n\n";

   for (uint32_t i = 0; i < frameSizes.size(); ++i)

  {

    bool createAnim = (frameSizes[i] == 512); // one representative animation case

    Result r = RunOneCase(frameSizes[i], createAnim, nSenders, offeredPpsPerSender, simTimeSec);

    results.push_back(r);

 

    std::cout << "FrameSize=" << std::setw(4) << r.frameSize

              << " bytes | Attempts=" << std::setw(8) << r.attempts

              << " | BusyAttempts=" << std::setw(8) << r.collisionProxyCount

              << " | CollisionProxy=" << std::fixed << std::setprecision(6) << r.collisionProxyProbability

              << " | Throughput=" << std::fixed << std::setprecision(4) << r.throughputMbps

              << " Mbps\n";

  }

   WritePlotFiles(results);

   std::cout << "\nOutput files generated:\n";

  std::cout << "  framesize-results.dat\n";

  std::cout << "  collision-vs-framesize.plt\n";

  std::cout << "  throughput-vs-framesize.plt\n";

  std::cout << "  framesize-study-animation.xml\n\n";

  std::cout << "To generate graphs using gnuplot:\n";

  std::cout << "  gnuplot collision-vs-framesize.plt\n";

  std::cout << "  gnuplot throughput-vs-framesize.plt\n\n";

  std::cout << "NOTE: ns-3 CSMA does not model true Ethernet collisions.\n";

  std::cout << "The reported collision value is a contention-based proxy.\n";

  return 0;

}

584c1e43cd67143835dc262c33c17216.png


Animation Screenshots:

4b657134434d7ff1a542fb4e9a95bac0.png230e1ea7a18ca91ec170de6c0641ce41.png
5142e7a82fb62eb3967c6d587d184f6b.png

e05e16849029d5defd846d7aafa657ff.png

    The animation shows multiple sender nodes transmitting packets over a shared CSMA channel to a single receiver node. The shared medium leads to contention among nodes.


Graph Screenshot(s)

Graph 2: Frame Size vs Throughput

9a945a1e93cc28cfb3934756d39ad777.png

Throughput Graph Explanation

The throughput initially increases with frame size because larger frames carry more payload relative to overhead. However, as frame size continues to increase, the channel remains occupied for longer durations, increasing contention among nodes. This results in diminishing returns or slight degradation in throughput at higher frame sizes under heavy load conditions.

 

Graph 1: Frame Size vs Collision Probability

c0c49269c01dd91fc0f9444d3a90a8a4.png

Collision Probability Graph Explanation

The graph shows that collision probability increases with frame size. Larger frames occupy the shared medium for a longer duration, which increases the likelihood that other nodes attempt transmission while the channel is busy. This leads to higher contention levels. At higher frame sizes, the collision probability approaches saturation due to continuous channel occupancy under heavy traffic conditions.


Conclusion

From the experiment, it is observed that frame size has a significant impact on collision behavior in a CSMA-based LAN. As frame size increases, the duration for which the channel remains occupied also increases, leading to higher chances of contention among nodes. This results in an increase in collision probability. While larger frames improve data efficiency by reducing overhead, excessive frame size can negatively affect network performance due to increased contention. Therefore, an optimal frame size must balance efficiency and collision probability.

 

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.