A homepage subtitle here And an awesome description here!

13 June 2026

Simulation of Selective Repeat ARQ and Go-Back-N under High Error Rates using ns3 | NS3 Project 13

Simulation of Selective Repeat ARQ and Go-Back-N under High Error Rates using ns3 | NS3 Project 13 

To simulate Selective Repeat (SR) and Go-Back-N (GBN) ARQ   protocols using ns-3 and compare their performance under high error  rates in terms of throughput, delay, and packet loss.


LLM + PROMPT (VERY IMPORTANT)

LLM Used:

ChatGPT (OpenAI GPT-5.3)

Prompt Used:

“Simulate Selective Repeat ARQ and compare its performance with Go-Back-N under high error rates using ns-3. Provide complete code, steps, and graph generation.”


NETWORK TOPOLOGY

·         Two nodes:

o   Node 0 → Sender

o   Node 1 → Receiver

·         Connected using Point-to-Point link

Parameters:

·         Bandwidth: 5 Mbps

·         Delay: 2 ms

·         Error Rate: High (e.g., 1e-3)

 

PROTOCOL MAPPING 

·         GBN → TCP Tahoe

·         SR → TCP NewReno

 Source Code:


#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/error-model.h"
#include "ns3/flow-monitor-module.h"
#include “ns3/netanim-module.h”

using namespace ns3;
int main(int argc, char *argv[])
{
std::string tcpType = "TcpNewReno"; // defau2lt
double errorRate = 1e-3;
CommandLine cmd;
cmd.AddValue("tcpType", "Tcp Variant", tcpType);
cmd.AddValue("errorRate", "Error rate", errorRate);
cmd.Parse(argc, argv);
if (tcpType == "TcpNewReno")
{
Config::SetDefault("ns3::TcpL4Protocol::SocketType",
TypeIdValue(TcpNewReno::GetTypeId()));
}
else
{
Config::SetDefault("ns3::TcpL4Protocol::SocketType",
TypeIdValue(TcpHighSpeed::GetTypeId()));
}
NodeContainer nodes;
nodes.Create(2);
PointToPointHelper p2p;
p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
p2p.SetChannelAttribute("Delay", StringValue("2ms"));
NetDeviceContainer devices = p2p.Install(nodes);
p2p.EnablePcapAll("sr_vs_gbn");
Ptr<RateErrorModel> em = CreateObject<RateErrorModel>();
em->SetAttribute("ErrorRate", DoubleValue(errorRate));
devices.Get(1)->SetAttribute("ReceiveErrorModel", PointerValue(em));
InternetStackHelper stack;

stack.Install(nodes);
Ipv4AddressHelper address;
address.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = address.Assign(devices);
uint16_t port = 5000;
PacketSinkHelper sink("ns3::TcpSocketFactory",
InetSocketAddress(Ipv4Address::GetAny(), port));
ApplicationContainer sinkApp = sink.Install(nodes.Get(1));
sinkApp.Start(Seconds(0.0));
sinkApp.Stop(Seconds(20.0));
BulkSendHelper source("ns3::TcpSocketFactory",
InetSocketAddress(interfaces.GetAddress(1), port));
source.SetAttribute("MaxBytes", UintegerValue(0));
ApplicationContainer sourceApp = source.Install(nodes.Get(0));
sourceApp.Start(Seconds(1.0));
sourceApp.Stop(Seconds(20.0));
FlowMonitorHelper flowmon;
Ptr<FlowMonitor> monitor = flowmon.InstallAll();
Simulator::Stop(Seconds(20.0));
Simulator::Run();
monitor->CheckForLostPackets();
auto stats = monitor->GetFlowStats();
for (auto &flow : stats)
{
double throughput = flow.second.rxBytes * 8.0 /
(flow.second.timeLastRxPacket.GetSeconds() -
flow.second.timeFirstTxPacket.GetSeconds()) / 1024;
std::cout << "Throughput: " << throughput << " Kbps\n";
std::cout << "Lost Packets: " << flow.second.lostPackets << "\n";
std::cout << "Delay: "
<< flow.second.delaySum.GetSeconds() << " sec\n";
}
monitor->SerializeToXmlFile("sr_vs_gbn.xml", true, true);
AnimationInterface anim(“sr_vs_gbn.xml”);
Simulator::Destroy();
return 0;
}


  

→ Output:

i)Selective Repeat ARQ(3,4,5)

6405001986d89337b3af25a5d415f611.png

→ IO grahp Using Wireshark

4108dba455c853553106c0f2445be43e.png

→ Net Anim

NetAnim


 

→ Go-Back-N under(3,4,5)

935b431ffd4d3ec562e2e2a777b15379.png

→ IO grahp Using Wireshark

821c3d2c261d687096f48ec22a66bef8.png

→ Net Anim

NetAnim


 SRQ vs GBN

Throughput Difference 

677483599754fbd212324ea2decaadb6.png

 

OBSERVATION

1. Go-Back-N (TCP Tahoe)

·         Retransmits multiple packets after loss

·         High packet loss

·         Lower throughput

·         Higher delay

2. Selective Repeat (TCP NewReno)

·         Retransmits only lost packets

·         Efficient bandwidth usage

·         Higher throughput

·         Lower delay

RESULT

Selective Repeat ARQ performs better than Go-Back-N under high error conditions due to selective retransmission, resulting in improved throughput and reduced delay.

 


12 June 2026

50-Node Ethernet LAN Simulation using CSMA | NS3 Project 12

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.

 

 


11 June 2026

Comparison of Distance-Vector Routing (RIP) and Link-State Routing | NS3 Project 11

Comparison of Distance-Vector Routing (RIP) and Link-State Routing

1. Aim

To simulate and compare the behavior of a Distance-Vector routing protocol (RIP) and a Link-State routing protocol (OLSR) on a 6-node point-to-point network in ns-3.44, visualize packet flow using NetAnim, introduce a mid-simulation link failure to observe convergence behavior, and record throughput data for graph-based analysis.

2. Theory

2.1 Distance-Vector Routing — RIP

Routing Information Protocol (RIP) is a classical distance-vector protocol. Every router periodically broadcasts its entire routing table to its immediate neighbors. Routes are selected based on hop count, with a maximum metric of 15 hops; a value of 16 is considered infinite (unreachable). Each node builds its routing table using the Bellman-Ford algorithm by iteratively updating paths based on the cost information received from neighbors. When a link fails, the affected node must propagate the change hop-by-hop through the network, which can result in slower convergence. ns-3's RipHelper implements this behavior and supports triggered updates and split-horizon with poison reverse.

2.2 Link-State Routing — OLSR

Optimized Link State Routing (OLSR) is a proactive link-state protocol designed for ad-hoc and general IP networks. Each node floods the network with Hello and TC (Topology Control) messages to build a complete topology map. Using Dijkstra's shortest-path algorithm, each node independently computes optimal routes to all destinations. OLSR uses MultiPoint Relays (MPRs) to reduce flooding overhead. Because every node has a global view of the topology, route recomputation after a failure is faster and more accurate than in distance-vector protocols. ns-3's OlsrHelper provides a ready-to-use implementation.

2.3 NetAnim

NetAnim is the ns-3 network animator. During simulation, AnimationInterface writes packet events and node positions to an XML file. The NetAnim GUI reads this file and replays the simulation visually, allowing inspection of packet paths, node labels, and topology changes over time.

3. Network Topology

The simulation uses 6 nodes connected by Point-to-Point links with a data rate of 5 Mbps and a propagation delay of 2 ms. The topology provides two parallel paths and a diagonal shortcut:

Upper path:    N0 — N1 — N2 — N5

Lower path:    N0 — N3 — N4 — N5

Diagonal link: N2 — N4

Node N0 is the traffic source and Node N5 is the destination. UDP traffic at 1 Mbps starts at t = 20 s and ends at t = 85 s. The link N1–N2 is brought down at t = 40 s, forcing the protocols to reroute through the lower path. The link is restored at t = 65 s.

4. LLM Prompt and Tool Used

LLM Used: ChatGPT (GPT-4o)

Prompt Used:

Create an ns-3 program to compare distance-vector routing (RIP) and link-state routing (OLSR) using NetAnim visualization. Use the same 6-node topology for both protocols, generate NetAnim animation XML, create a throughput CSV for graph plotting, introduce a link failure during simulation, and print routing statistics so I can compare convergence and recovery behavior.

5. Commands to Run

Save the source file as scratch/file.cc inside your ns-3.44 folder, then execute:

./ns3 run "scratch/file.cc --protocol=RIP"

./ns3 run "scratch/file.cc --protocol=OLSR"

To open the NetAnim animation after running:

cd netanim && ./NetAnim

Load rip.xml for RIP visualization and olsr.xml for OLSR visualization.

6. Source Code

#include "ns3/applications-module.h"

#include "ns3/core-module.h"

#include "ns3/flow-monitor-module.h"

#include "ns3/internet-module.h"

#include "ns3/mobility-module.h"

#include "ns3/netanim-module.h"

#include "ns3/network-module.h"

#include "ns3/olsr-helper.h"

#include "ns3/point-to-point-module.h"

#include "ns3/rip-helper.h"

#include <fstream>

#include <string>

 

using namespace ns3;

 

NS_LOG_COMPONENT_DEFINE("RipVsOlsrComparison");

 

static Ptr<PacketSink> g_sink;

static std::ofstream g_csv;

static uint64_t g_lastTotalRx = 0;

static double g_interval = 1.0;

 

static void TraceThroughput() {

    double now = Simulator::Now().GetSeconds();

    uint64_t cur = g_sink->GetTotalRx();

    double kbps = ((cur - g_lastTotalRx) * 8.0) / (1000.0 * g_interval);

    g_csv << now << "," << kbps << "," << cur << "\n";

    g_lastTotalRx = cur;

    if (now < 89.0)

        Simulator::Schedule(Seconds(g_interval), &TraceThroughput);

}

 

static void SetInterfaceDown(Ptr<Node> node, Ptr<NetDevice> dev) {

    Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();

    uint32_t ifIndex = ipv4->GetInterfaceForDevice(dev);

    ipv4->SetDown(ifIndex);

}

 

static void SetInterfaceUp(Ptr<Node> node, Ptr<NetDevice> dev) {

    Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();

    uint32_t ifIndex = ipv4->GetInterfaceForDevice(dev);

    ipv4->SetUp(ifIndex);

}

 

int main(int argc, char* argv[]) {

    std::string protocol = "RIP";

    bool enablePcap = true;

    double simTime = 90.0;

 

    CommandLine cmd(__FILE__);

    cmd.AddValue("protocol", "RIP or OLSR", protocol);

    cmd.AddValue("enablePcap", "Enable pcap tracing", enablePcap);

    cmd.Parse(argc, argv);

 

    bool useRip = (protocol != "OLSR" && protocol != "olsr");

    if (!useRip) protocol = "OLSR"; else protocol = "RIP";

 

    NodeContainer nodes;

    nodes.Create(6);

 

    PointToPointHelper p2p;

    p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps"));

    p2p.SetChannelAttribute("Delay", StringValue("2ms"));

 

    NodeContainer n01(nodes.Get(0), nodes.Get(1));

    NodeContainer n12(nodes.Get(1), nodes.Get(2));

    NodeContainer n25(nodes.Get(2), nodes.Get(5));

    NodeContainer n03(nodes.Get(0), nodes.Get(3));

    NodeContainer n34(nodes.Get(3), nodes.Get(4));

    NodeContainer n45(nodes.Get(4), nodes.Get(5));

    NodeContainer n24(nodes.Get(2), nodes.Get(4));

 

    NetDeviceContainer d01 = p2p.Install(n01);

    NetDeviceContainer d12 = p2p.Install(n12);

    NetDeviceContainer d25 = p2p.Install(n25);

    NetDeviceContainer d03 = p2p.Install(n03);

    NetDeviceContainer d34 = p2p.Install(n34);

    NetDeviceContainer d45 = p2p.Install(n45);

    NetDeviceContainer d24 = p2p.Install(n24);

 

    MobilityHelper mobility;

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

    mobility.Install(nodes);

 

    nodes.Get(0)->GetObject<MobilityModel>()->SetPosition(Vector(10, 30, 0));

    nodes.Get(1)->GetObject<MobilityModel>()->SetPosition(Vector(30, 50, 0));

    nodes.Get(2)->GetObject<MobilityModel>()->SetPosition(Vector(55, 50, 0));

    nodes.Get(3)->GetObject<MobilityModel>()->SetPosition(Vector(30, 10, 0));

    nodes.Get(4)->GetObject<MobilityModel>()->SetPosition(Vector(55, 10, 0));

    nodes.Get(5)->GetObject<MobilityModel>()->SetPosition(Vector(78, 30, 0));

 

    InternetStackHelper internet;

    if (useRip) {

        RipHelper rip;

        Ipv4ListRoutingHelper list;

        list.Add(rip, 10);

        internet.SetRoutingHelper(list);

    } else {

        OlsrHelper olsr;

        Ipv4ListRoutingHelper list;

        list.Add(olsr, 10);

        internet.SetRoutingHelper(list);

    }

    internet.Install(nodes);

 

    Ipv4AddressHelper addr;

    addr.SetBase("10.0.1.0", "255.255.255.0");

    Ipv4InterfaceContainer i01 = addr.Assign(d01);

    addr.SetBase("10.0.2.0", "255.255.255.0");

    addr.Assign(d12);

    addr.SetBase("10.0.3.0", "255.255.255.0");

    Ipv4InterfaceContainer i25 = addr.Assign(d25);

    addr.SetBase("10.0.4.0", "255.255.255.0");

    addr.Assign(d03);

    addr.SetBase("10.0.5.0", "255.255.255.0");

    addr.Assign(d34);

    addr.SetBase("10.0.6.0", "255.255.255.0");

    addr.Assign(d45);

    addr.SetBase("10.0.7.0", "255.255.255.0");

    addr.Assign(d24);

 

    uint16_t port = 9999;

    PacketSinkHelper sinkHelper("ns3::UdpSocketFactory",

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

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

    sinkApp.Start(Seconds(0.0));

    sinkApp.Stop(Seconds(simTime));

 

    OnOffHelper onoff("ns3::UdpSocketFactory",

        InetSocketAddress(i25.GetAddress(1), port));

    onoff.SetAttribute("DataRate", StringValue("1Mbps"));

    onoff.SetAttribute("PacketSize", UintegerValue(1024));

    onoff.SetAttribute("OnTime",

        StringValue("ns3::ConstantRandomVariable[Constant=1]"));

    onoff.SetAttribute("OffTime",

        StringValue("ns3::ConstantRandomVariable[Constant=0]"));

    ApplicationContainer srcApp = onoff.Install(nodes.Get(0));

    srcApp.Start(Seconds(20.0));

    srcApp.Stop(Seconds(85.0));

 

    Simulator::Schedule(Seconds(40.0), &SetInterfaceDown, nodes.Get(1), d12.Get(0));

    Simulator::Schedule(Seconds(40.0), &SetInterfaceDown, nodes.Get(2), d12.Get(1));

    Simulator::Schedule(Seconds(65.0), &SetInterfaceUp, nodes.Get(1), d12.Get(0));

    Simulator::Schedule(Seconds(65.0), &SetInterfaceUp, nodes.Get(2), d12.Get(1));

 

    std::string animFile = useRip ? "rip.xml" : "olsr.xml";

    AnimationInterface anim(animFile);

    anim.SetConstantPosition(nodes.Get(0), 10, 30);

    anim.SetConstantPosition(nodes.Get(1), 30, 50);

    anim.SetConstantPosition(nodes.Get(2), 55, 50);

    anim.SetConstantPosition(nodes.Get(3), 30, 10);

    anim.SetConstantPosition(nodes.Get(4), 55, 10);

    anim.SetConstantPosition(nodes.Get(5), 78, 30);

    anim.EnablePacketMetadata(true);

    anim.UpdateNodeDescription(nodes.Get(0), "N0 Source");

    anim.UpdateNodeDescription(nodes.Get(1), "N1");

    anim.UpdateNodeDescription(nodes.Get(2), "N2");

    anim.UpdateNodeDescription(nodes.Get(3), "N3");

    anim.UpdateNodeDescription(nodes.Get(4), "N4");

    anim.UpdateNodeDescription(nodes.Get(5), "N5 Destination");

 

    AsciiTraceHelper ascii;

    if (useRip) {

        Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream("rip-routes.txt");

        RipHelper ripHelper;

        ripHelper.PrintRoutingTableAllAt(Seconds(25.0), stream);

        ripHelper.PrintRoutingTableAllAt(Seconds(45.0), stream);

        ripHelper.PrintRoutingTableAllAt(Seconds(70.0), stream);

    } else {

        Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream("olsr-routes.txt");

        OlsrHelper olsrHelper;

        olsrHelper.PrintRoutingTableAllAt(Seconds(25.0), stream);

        olsrHelper.PrintRoutingTableAllAt(Seconds(45.0), stream);

        olsrHelper.PrintRoutingTableAllAt(Seconds(70.0), stream);

    }

 

    if (enablePcap) {

        p2p.EnablePcapAll(useRip ? "rip" : "olsr");

    }

 

    FlowMonitorHelper flowmon;

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

 

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

    std::string csvFile = useRip ? "rip-throughput.csv" : "olsr-throughput.csv";

    g_csv.open(csvFile.c_str());

    g_csv << "Time,ThroughputKbps,TotalRxBytes\n";

    Simulator::Schedule(Seconds(1.0), &TraceThroughput);

 

    Simulator::Stop(Seconds(simTime));

    Simulator::Run();

 

    monitor->CheckForLostPackets();

    Ptr<Ipv4FlowClassifier> classifier =

        DynamicCast<Ipv4FlowClassifier>(flowmon.GetClassifier());

    std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats();

 

    std::cout << "\n=== " << protocol << " RESULTS ===\n";

    for (const auto& flow : stats) {

        Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(flow.first);

        if (t.destinationPort == port) {

            double throughput = flow.second.rxBytes * 8.0 /

                (flow.second.timeLastRxPacket.GetSeconds() -

                 flow.second.timeFirstTxPacket.GetSeconds()) / 1000.0;

            double avgDelayMs = (flow.second.rxPackets > 0) ?

                1000.0 * flow.second.delaySum.GetSeconds() / flow.second.rxPackets : 0.0;

            double pdr = (flow.second.txPackets > 0) ?

                100.0 * flow.second.rxPackets / flow.second.txPackets : 0.0;

            std::cout << "Flow: " << t.sourceAddress << " -> " << t.destinationAddress << "\n";

            std::cout << "Tx Packets: " << flow.second.txPackets << "\n";

            std::cout << "Rx Packets: " << flow.second.rxPackets << "\n";

            std::cout << "Packet Delivery Ratio: " << pdr << " %\n";

            std::cout << "Average Delay: " << avgDelayMs << " ms\n";

            std::cout << "Throughput: " << throughput << " Kbps\n";

            std::cout << "Lost Packets: " << flow.second.lostPackets << "\n\n";

        }

    }

 

    g_csv.close();

    Simulator::Destroy();

    return 0;

}

7. NetAnim Animation Screenshot

The screenshot below is taken at approximately t = 42–50 s, immediately after the N1–N2 link failure at t = 40 s. This moment is chosen because packets must reroute through the lower path N0–N3–N4–N5, making the visual difference between the two protocols most apparent.

RIP Animation (load rip.xml in NetAnim):

Figure 1 — NetAnim visualization of RIP routing. After the N1–N2 link fails at 40 s, packets are rerouted through N0–N3–N4–N5. Packet activity visible on the lower path.

OLSR Animation (load olsr.xml in NetAnim):

Figure 2 — NetAnim visualization of OLSR routing. Because OLSR maintains a global topology map, rerouting is reflected earlier in the animation. The lower path is active faster than in the RIP case.

Animation Observation: The N1–N2 link fails at 40 s. Both protocols eventually reroute through N0–N3–N4–N5. In OLSR, rerouting becomes visible sooner because the protocol uses proactive link-state updates. In RIP, the transition takes longer because route change information propagates hop-by-hop with periodic update intervals and triggered update cooldowns. 

8. Graphs and Analysis

8.1 Throughput Over Time (from CSV — paste your graph here)

Plot rip-throughput.csv and olsr-throughput.csv together. X-axis = Time (s), Y-axis = Throughput (Kbps), with two lines — one for RIP and one for OLSR.

Figure 3 — Throughput comparison. Throughput is stable before t = 40 s. A drop is observed at link failure. OLSR recovers to near-full throughput sooner; RIP shows a longer recovery gap before re-stabilizing after t = 65 s when the link is restored.

8.2 Protocol Comparison — Terminal Results

The following bar/grouped chart is derived directly from the FlowMonitor terminal output collected after running both simulations.

Metric

RIP (Flow 1)

RIP (Flow 2)

 

Tx Packets

3476

1491

 

Rx Packets

2968

1491

 

Packet Delivery Ratio

85.39 %

100 %

 

Average Delay (ms)

11.06 ms

11.06 ms

 

Throughput (Kbps)

384.30 Kbps

1027.1 Kbps

 

Lost Packets

508

0

 

 

Metric

OLSR (Flow 1)

OLSR (Flow 2)

 

Tx Packets

3093

4841

 

Rx Packets

2440

4841

 

Packet Delivery Ratio

78.89 %

100 %

 

Average Delay (ms)

11.06 ms

11.06 ms

 

Throughput (Kbps)

1027.2 Kbps

1027.27 Kbps

 

Lost Packets

653

0

 

 

Table 1 — FlowMonitor statistics for RIP and OLSR. Flow 1 is the primary traffic flow (N0 → N5). Flow 2 represents traffic on an alternate sub-flow. RIP shows higher PDR on Flow 1 but lower throughput, while OLSR achieves near-line-rate throughput after fast route convergence.

8.3 Side-by-Side Summary Table

Metric

RIP

OLSR

Advantage

Routing Type

Distance-Vector

Link-State

Algorithm

Bellman-Ford

Dijkstra

Update Method

Periodic + Triggered

Proactive flooding

OLSR

Convergence Speed

Slower (hop-by-hop)

Faster (global map)

OLSR

PDR Flow 1

85.39 %

78.89 %

RIP

Throughput Flow 1

384.3 Kbps

1027.2 Kbps

OLSR

Throughput Flow 2

1027.1 Kbps

1027.27 Kbps

Comparable

Lost Packets Flow 1

508

653

RIP

Avg Delay

11.06 ms

11.06 ms

Equal

Table 2 — Side-by-side comparison of RIP and OLSR from simulation results.


9. Result Analysis

Before the link failure at t = 40 s, both protocols deliver traffic normally through the upper path N0–N1–N2–N5. Throughput is stable at approximately 1 Mbps for both. When the N1–N2 link is brought down, the routing layer on both sides must detect the failure and install a new route through N0–N3–N4–N5.

RIP detects the failure via timeout or triggered update, but propagates the change hop-by-hop. During this period, packets that arrive at N1 have no valid route to N2 and are dropped, resulting in 508 lost packets on Flow 1 (PDR 85.39%). The throughput on Flow 1 drops significantly to 384.3 Kbps, reflecting the extended period without a valid route. Once convergence occurs, the alternate path carries traffic correctly (Flow 2: 1027.1 Kbps, 100% PDR).

OLSR, being proactive, already has topology knowledge from Hello and TC messages. When the link fails, the MPR-based flooding quickly propagates updated topology information, and Dijkstra recomputes routes. Despite this, OLSR's Flow 1 has a slightly lower PDR (78.89%) and higher packet loss (653 packets), which may be attributed to OLSR's hello interval timing and the initial topology-build phase. Flow 2 achieves near line-rate throughput (1027.27 Kbps) with perfect delivery.

Average end-to-end delay is equal for both protocols (11.06 ms), which is expected since link delays are identical and both protocols eventually route through the same 3-hop path. The main differentiator in this experiment is throughput recovery speed, where OLSR's Flow 2 shows superior per-flow throughput after rerouting.

10. Conclusion

This experiment successfully demonstrates the behavioural difference between Distance-Vector (RIP) and Link-State (OLSR) routing protocols under a topology change. The ns-3 simulation with NetAnim visualization confirms that both protocols can adapt to link failures. However, OLSR achieves higher peak throughput on the surviving flow due to faster topology awareness. RIP achieves a slightly better PDR on the primary flow in this specific scenario but at a significantly lower throughput due to prolonged convergence delay.

In practical terms, link-state protocols are preferred in networks where rapid convergence after failure is critical. Distance-vector protocols remain simpler to implement and suitable for small, stable networks. This comparison validates the theoretical claims about protocol behavior and demonstrates the utility of ns-3 and NetAnim as simulation and visualization tools.


Powered by Blogger.

About Me

Featured Post

5G Network Simulation in NS3 using mmWave | NS3 Tutorial 2024

5G Network Simulation in NS3 Using mmWave This post shows the installation of ns3mmwave in Ubuntu 24.04 and simulates 5G networks in ns3. In...

Contact form

Name

Email *

Message *

Total Pageviews

Search This Blog

Pages

Pages

Pages - Menu

Most Popular

Popular Posts