50-Node Ethernet LAN Simulation using CSMA - Measuring Average Collision Count vs. Packet Size
1. Objective
The aim of this exercise is to simulate a 50-node Ethernet Local Area Network using the CSMA (Carrier Sense Multiple Access) protocol in NS-3 and quantitatively measure how the average number of collisions per node varies with packet size ranging from 64 bytes to 1500 bytes.
2. Write-Up
2.1 Why CSMA and Why Collisions Happen
Think of a shared Ethernet LAN like a walkie-talkie channel shared among 50 people. Everyone can hear everyone, but only one person can speak at a time. If two people press 'talk' simultaneously, their voices collide and the message is lost. CSMA tries to solve this by making each device listen before transmitting, but when 49 nodes all sense silence at the same moment and transmit together, collisions are unavoidable.
In NS-3, the CsmaNetDevice models this exactly. Every time a node detects a collision and backs off, it fires a MacTxBackoff trace event — which our simulation intercepts and counts. The exponential random back-off then makes it wait a random interval before retrying, mimicking real 802.3 Ethernet behaviour.
2.2 The Packet Size Effect — Why It Matters
Packet size has a compounding effect on collisions for a simple reason: larger packets occupy the shared wire for longer. During that entire duration, any other node that starts transmitting causes a collision. A 64-byte packet is a quick message — it clears the channel fast. A 1500-byte packet is a lengthy speech that keeps the channel busy, creating a much larger window for simultaneous transmissions from other nodes.
With Node 0 hammering all 49 server nodes at 100 packets per second each, the channel load is extreme --- this is intentional, to stress-test the CSMA mechanism and amplify the collision effect across the full packet size range.
However, under high network load, this relationship may become non-linear due to the influence of the CSMA backoff algorithm, which can reduce collisions at intermediate packet sizes.
2.3 Simulation Design
50 nodes are created on a single CSMA channel configured at 100 Mbps with a propagation delay of 6560 microseconds (matching the maximum round-trip delay for a 100BASE-T segment). Node 0 acts as the UDP Echo Client, sending packets to each of the 49 server nodes (Nodes 1–49). Each server node runs a UDP Echo Server on port 9. Six discrete packet sizes are evaluated: 64, 128, 256, 512, 1024, and 1500 bytes. For each size, the simulation runs for 2 simulated seconds. The NetAnim XML is generated during the 64-byte run.
Collision Measurement Note:
The MacTxBackoff trace source is used as an approximation of collision events. This trace is triggered whenever a node defers or retransmits due to channel contention. While not every backoff corresponds to a direct collision, it closely reflects collision behavior in high-load shared CSMA environments.
3. LLM Used and Prompt
LLM Used: Claude (Anthropic) — Claude Sonnet 4.6
Prompt Given:
"I am a second-year B.Tech Computer Science student at VIT Chennai. My CN lab assignment asks me to simulate a 50-node Ethernet LAN using the CSMA protocol in NS-3 and measure how the average number of collisions per node changes as packet size increases from 64 bytes to 1500 bytes. Please help me write a complete NS-3 C++ simulation file runnable as ./ns3 run scratch/24bps1102.cc. The simulation should create 50 nodes on a single CSMA channel at 100 Mbps, use UDP Echo clients on all nodes sending to one server node, vary packet size across 64, 128, 256, 512, 1024 and 1500 bytes, and track collisions using the MacTxBackoff trace source. Also generate a Gnuplot script for plotting average collisions vs packet size, and a NetAnim XML file."
4. Source Code
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/applications-module.h"
#include "ns3/flow-monitor-module.h"
#include "ns3/netanim-module.h"
#include "ns3/gnuplot.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE("CsmaCollisionSim");
uint32_t g_collisionCount = 0;
void CollisionCallback(std::string context, Ptr<const Packet> packet)
{
g_collisionCount++;
}
int main(int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse(argc, argv);
uint32_t numNodes = 50;
std::vector<uint32_t> packetSizes = {64, 128, 256, 512, 1024, 1500};
std::vector<double> avgCollisions;
Gnuplot2dDataset dataset;
dataset.SetTitle("Avg Collisions vs Packet Size");
dataset.SetStyle(Gnuplot2dDataset::LINES_POINTS);
for (uint32_t pktSize : packetSizes)
{
g_collisionCount = 0;
NodeContainer nodes;
nodes.Create(numNodes);
CsmaHelper csma;
csma.SetChannelAttribute("DataRate", StringValue("100Mbps"));
csma.SetChannelAttribute("Delay", TimeValue(MicroSeconds(6560)));
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);
Config::Connect("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/MacTxBackoff",
MakeCallback(&CollisionCallback));
uint16_t port = 9;
double simTime = 2.0;
for (uint32_t i = 1; i < numNodes; i++)
{
UdpEchoServerHelper echoServer(port);
ApplicationContainer serverApp = echoServer.Install(nodes.Get(i));
serverApp.Start(Seconds(0.0));
serverApp.Stop(Seconds(simTime));
UdpEchoClientHelper echoClient(interfaces.GetAddress(i), port);
echoClient.SetAttribute("MaxPackets", UintegerValue(200));
echoClient.SetAttribute("Interval", TimeValue(MilliSeconds(10)));
echoClient.SetAttribute("PacketSize", UintegerValue(pktSize));
ApplicationContainer clientApp = echoClient.Install(nodes.Get(0));
clientApp.Start(Seconds(0.1));
clientApp.Stop(Seconds(simTime));
}
if (pktSize == 64)
{
AnimationInterface anim("csma_animation.xml");
uint32_t row = 0, col = 0;
for (uint32_t i = 0; i < numNodes; i++)
{
anim.SetConstantPosition(nodes.Get(i), col * 20 + 10, row * 20 + 10);
col++;
if (col >= 10) { col = 0; row++; }
}
anim.EnablePacketMetadata(true);
Simulator::Run();
Simulator::Destroy();
}
else
{
Simulator::Run();
Simulator::Destroy();
}
double avgColl = (double)g_collisionCount / (numNodes - 1);
avgCollisions.push_back(avgColl);
dataset.Add(pktSize, avgColl);
std::cout << "PacketSize=" << pktSize
<< " TotalCollisions=" << g_collisionCount
<< " AvgCollisions=" << avgColl << std::endl;
}
Gnuplot plot("collision_vs_pktsize.png");
plot.SetTitle("50-Node CSMA LAN: Average Collisions vs Packet Size");
plot.SetTerminal("png");
plot.SetLegend("Packet Size (bytes)", "Average Collision Count per Node");
plot.AddDataset(dataset);
std::ofstream plotFile("collision_vs_pktsize.plt");
plot.GenerateOutput(plotFile);
plotFile.close();
system("gnuplot collision_vs_pktsize.plt");
std::cout << "\n=== Summary ===" << std::endl;
for (size_t i = 0; i < packetSizes.size(); i++)
{
std::cout << "Packet Size: " << packetSizes[i]
<< " bytes | Avg Collisions: " << avgCollisions[i] << std::endl;
}
return 0;
}
5. Results — Collision Data
| Packet Size (bytes) | Total Collisions | Avg Collisions / Node |
|---|---|---|
| 64 | 57,429 | 1172.0 |
| 128 | 61,893 | 1263.1 |
| 256 | 45,703 | 932.7 |
| 512 | 36,268 | 740.2 |
| 1024 | 26,498 | 540.8 |
| 1500 | 78,989 | 1612.0 |
6. Graph — Average Collisions vs Packet Size
The graph plots average collision count per node against packet size. The trend shows that collisions are not strictly monotonic — they peak at 128 bytes, dip through 256–1024 bytes (back-off algorithm spreading retransmissions), then spike dramatically at 1500 bytes. This non-linear behaviour is a real characteristic of CSMA under heavy load and is more interesting than a simple straight line.
7. NetAnim Animation
Figure 2: NetAnim shows all 50 nodes in a 10x5 grid connected to a shared CSMA bus. Node 0 (top-left) is the client. Animated packet flows from Node 0 fan out to all 49 server nodes simultaneously, visually demonstrating the congestion that causes high collision counts in this topology.
8. Result Analysis
The simulation revealed an interesting non-monotonic collision pattern rather than a simple linear increase. Key findings:
- Collisions peak at 128 bytes (1263 avg) — not at the largest packet size. This is because at this size, nodes transmit frequently enough that the back-off algorithm hasn't yet introduced sufficient spacing between retransmissions.
- From 256 to 1024 bytes, collisions actually decrease. Larger packets mean fewer total transmissions within the 2-second window, allowing the exponential back-off to be more effective.
- At 1500 bytes, collisions spike to their absolute maximum (1612 avg). At MTU size, the channel occupancy per packet is so long that even with fewer transmissions, the probability of overlap is highest.
- Real-world implication: shared Ethernet under extreme load behaves non-intuitively. This is precisely why modern networks use switches (not hubs/buses) — to eliminate shared collision domains entirely.
9. Conclusion
This simulation demonstrates that collision behavior in a shared CSMA Ethernet LAN is non-linear with respect to packet size. While very large packets increase collisions due to longer channel occupancy, medium-sized packets reduce collisions due to more effective backoff spacing. These results highlight the importance of packet size selection and reinforce why modern networks avoid shared collision domains by using switches.
Comments
Post a Comment