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.
Comments
Post a Comment