Simple method to analyze NS2 Trace file
Today I am going to show a simple perl code to analyze NS2 trace file as an example of AODV routing protocol. As you know when you run simulation, NS2 generates a trace file like sometrace.tr. It will give a lot of information about your simulation result. Not knowing how to analyze this file it is useless to run NS2 simulator. In this topic we will learn how to compute delivery ratio and message overhead.
First go to your home directory and create bin directory there. We will create trace file here so that we can access it from anywhere we want.
cd ~ mkdir bin cd bin
Download analyze.pl file, which is attached to the post, to the bin directory. I will explain main points of the code. Following code opens a file to write simulation results.
$ofile="simulation_result.csv"; open OUT, ">$ofile" or die "$0 cannot open output file $ofile: $!";
Usually in trace file each line is started with some letter like r, s, D, N. Each of the letters has meaning. For detailed meaning of the letter refer to the NS Manual Page . And following perl code extracts lines which start with "s", which means sent packets. It maybe : control packets (AODV), data packets (cbr). We are only interested in packets those are sent by routers (RTR). If you enable MAC trace, the packets sent or received by MAC layer is also shown.
if (/^s/){
if (/^s.*AODV/) {
$aodvSent++;
if (/^s.*REQUEST/) {
$aodvSendRequest++;
}
elsif (/^s.*REPLY/) {
$aodvSendReply++;
}
}
elsif (/^s.*AGT/) {
$dataSent++;
}
}
REQUEST - AODV Route Request (RREQ) packets
REPLY - AODV Route Reply (RREP) packets;
AGT - Packets those are sent by agent such as cbr, udp, tcp;
And following code counts packet received by each function.
elsif (/^r/){
if (/^r.*AODV/) {
$aodvRecv++;
if (/^r.*REQUEST/) {
$aodvRecvRequest++;
}
elsif (/^r.*REPLY/) {
$aodvRecvReply++;
}
}
elsif (/^r.*AGT/) {
$dataRecv++;
}
}
Finally packets which are dropped are counted using following code :
elsif (/^D/) {
if (/^D.*AODV/) {
if (/^D.*REQUEST/) {
$aodvDropRequest++;
}
elsif (/^D.*REPLY/) {
$aodvDropReply++;
}
}
if (/^D.*RTR/) {
$routerDrop++;
}
}
Now we will analyze example file. In this post I have written about simulating WSN with AODV protocol, download it and do following. ( I am assuming you have already put analyze.pl file into your bin directory). Here is full source code to the analyze file : analyze.pl. More trace analyzer code is available in the this archive.
ns aodv_802_15_4.tcl cat trace-aodv-802-15-4.tr | analyze.pl
The result would something like this :

Adding Malicious Node to AODV
Many people have asked me how to implement malicious drop in AODV. I have decided to write simple code for adding malicious node in AODV ( or in any routing protocol).
First you need to modify aodv.cc and aodv.h files. In aodv.h after
/* The Routing Agent */
class AODV: public Agent {
...
/*
* History management
*/
double PerHopTime(aodv_rt_entry *rt);
...
add following line
bool malicious;
With this variable we are trying to define if the node is malicious or not. In aodv.cc after
/*
Constructor
*/
AODV::AODV(nsaddr_t id) : Agent(PT_AODV), btimer(this), htimer(this), ntimer(this), rtimer(this), lrtimer(this), rqueue() {
index = id;
seqno = 2;
bid = 1;
...
add following line
malicious = false;
The above code is needed to initialize, and all nodes are initially not malicious. Then we will write a code to catch which node is set as malicious. In aodv.cc after
if(argc == 2) {
Tcl& tcl = Tcl::instance();
if(strncasecmp(argv[1], "id", 2) == 0) {
tcl.resultf("%d", index);
return TCL_OK;
}
add following line
if(strcmp(argv[1], "hacker") == 0) {
malicious = true;
return TCL_OK;
}
Now we will do some work in TCL to set a malicious node. Using script in my post , we add following line to set node 5 as malicious node.
$ns at 0.0 "[$mnode_(5) set ragent_] hacker"
You may add this line after
for {set i 0} {$i < $val(nn)} { incr i } {
$ns initial_node_pos $mnode_($i) 10
}
...
Alright, we have set malicious node but we did not tell malicious node what to do. As it is known, rt_resolve(Packet *p) function is used to select next hop node when routing data packets. So, we tell malicious node just drop any packet when it receives. To do that after
/*
Route Handling Functions
*/
void
AODV::rt_resolve(Packet *p) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
aodv_rt_entry *rt;
...
We add a few lines
// if I am malicious node
if (malicious == true ) {
drop(p, DROP_RTR_ROUTE_LOOP);
// DROP_RTR_ROUTE_LOOP is added for no reason.
}
And implementing malicious node is done. I hope the post will be helpful to design your secure routing protocol.
P.S. Guys please don't ask me c/c++ questions, check your book first
Sensor Network 802.15.4 AODV Simulation
The reason to write this topic is many people asked me how to simulate sensor networks. Obviously, authors of 802.15.4/Zigbee protocol developers on NS2 have given a sample examples. But, these examples do not run correctly, and give some kind of unknown error (at least I don't know what errors mean). Therefore, I have decided to test AODV using 802.15.4 MAC/PHY. Thus, if my tests work, I hope you can test your own routing protocols using this source code.
Alright, the TCL file is fairly simple. I briefly explain what means what. We first set simulation environment. We are going to deploy 500 nodes, in 1000x500 sqm area, simulation time is 500 seconds. And we are using 802.15.4 MAC/PHY and interface queue is 100. We also set simulator and files to trace the simulation.
# Generated by Topology Generator for Network Simulator (c) Elmurod Talipov set val(chan) Channel/WirelessChannel ;# channel type set val(prop) Propagation/TwoRayGround ;# radio-propagation model set val(netif) Phy/WirelessPhy/802_15_4 ;# network interface type set val(mac) Mac/802_15_4 ;# MAC type set val(ifq) Queue/DropTail/PriQueue ;# interface queue type set val(ll) LL ;# link layer type set val(ant) Antenna/OmniAntenna ;# antenna model set val(ifqlen) 100 ;# max packet in ifq set val(nn) 500 ;# number of mobilenodes set val(rp) AODV ;# protocol tye set val(x) 1000 ;# X dimension of topography set val(y) 500 ;# Y dimension of topography set val(stop) 500 ;# simulation period set val(energymodel) EnergyModel ;# Energy Model set val(initialenergy) 100 ;# value set ns [new Simulator] set tracefd [open trace-aodv-802-15-4.tr w] set namtrace [open nam-aodv-802-15-4.nam w] $ns trace-all $tracefd $ns namtrace-all-wireless $namtrace $val(x) $val(y)
Let's set radio transmission range to 40 meters, but this does not mean exactly 40 meters. The code below filters packet with receiving signal strength above "40 meters".
set dist(5m) 7.69113e-06 set dist(9m) 2.37381e-06 set dist(10m) 1.92278e-06 set dist(11m) 1.58908e-06 set dist(12m) 1.33527e-06 set dist(13m) 1.13774e-06 set dist(14m) 9.81011e-07 set dist(15m) 8.54570e-07 set dist(16m) 7.51087e-07 set dist(20m) 4.80696e-07 set dist(25m) 3.07645e-07 set dist(30m) 2.13643e-07 set dist(35m) 1.56962e-07 set dist(40m) 1.20174e-07 Phy/WirelessPhy set CSThresh_ $dist(40m) Phy/WirelessPhy set RXThresh_ $dist(40m)
And lets set topography as flat, deploy nodes randomly in an area of 1000 x 500 sqm.
# set up topography object
set topo [new Topography]
$topo load_flatgrid $val(x) $val(y)
create-god $val(nn)
# configure the nodes
$ns node-config -adhocRouting $val(rp) \
-llType $val(ll) \
-macType $val(mac) \
-ifqType $val(ifq) \
-ifqLen $val(ifqlen) \
-antType $val(ant) \
-propType $val(prop) \
-phyType $val(netif) \
-channel [new $val(chan)] \
-topoInstance $topo \
-agentTrace ON \
-routerTrace ON \
-macTrace OFF \
-movementTrace OFF \
-energyModel $val(energymodel) \
-initialEnergy $val(initialenergy) \
-rxPower 35.28e-3 \
-txPower 31.32e-3 \
-idlePower 712e-6 \
-sleepPower 144e-9
#-IncomingErrProc MultistateErrorProc \
#-OutgoingErrProc MultistateErrorProc
for {set i 0} {$i < $val(nn) } { incr i } {
set mnode_($i) [$ns node]
}
for {set i 1} {$i < $val(nn) } { incr i } {
$mnode_($i) set X_ [ expr {$val(x) * rand()} ]
$mnode_($i) set Y_ [ expr {$val(y) * rand()} ]
$mnode_($i) set Z_ 0
}
And we are goig to deploy sink node in the center of area, i.e. at [500, 250].
# Position of Sink
$mnode_(0) set X_ [ expr {$val(x)/2} ]
$mnode_(0) set Y_ [ expr {$val(y)/2} ]
$mnode_(0) set Z_ 0.0
$mnode_(0) label "Sink"
The code below is useful how big the nodes are going to be shown in NAM (network animator), thus it does not have meaning in real simulation.
for {set i 0} {$i < $val(nn)} { incr i } {
$ns initial_node_pos $mnode_($i) 10
}
Finally, we have deployed nodes, and remained important thing is establish connection. We are going to use UDP protocol with CBR (constant bit rate, interval (interval_) is set to 2 seconds)
#Setup a UDP connection
set udp [new Agent/UDP]
$ns attach-agent $mnode_(10) $udp
set sink [new Agent/Null]
$ns attach-agent $mnode_(0) $sink
$ns connect $udp $sink
$udp set fid_ 2
#Setup a CBR over UDP connection
set cbr [new Application/Traffic/CBR]
$cbr attach-agent $udp
$cbr set type_ CBR
$cbr set packet_size_ 50
$cbr set rate_ 0.1Mb
$cbr set interval_ 2
#$cbr set random_ false
$ns at 5.0 "$cbr start"
$ns at [expr $val(stop) - 5] "$cbr stop"
# Telling nodes when the simulation ends
for {set i 0} {$i < $val(nn) } { incr i } {
$ns at $val(stop) "$mnode_($i) reset;"
}
# ending nam and the simulation
$ns at $val(stop) "$ns nam-end-wireless $val(stop)"
$ns at $val(stop) "stop"
$ns at [expr $val(stop) + 0.01] "puts \"end simulation\"; $ns halt"
proc stop {} {
global ns tracefd namtrace
$ns flush-trace
close $tracefd
close $namtrace
}
$ns run
We have finished writing sample AODV TCL script, we can run it
ns aodv_802_15_4.tcl
NAM gives me following deployment result.

Download whole source code here : aodv_802_15_4.tcl . If you find any problem with that, leave comment here. If you want to test your own routing protocol simply change $val(rp) AODV with your own.
NS2: Printing Routing Table in AODV
Actually you can find all this information in trace file which NS2 made, however using following code simplifies getting required informaiton during running time. The code stores
Add following code to aodv.h after void rt_down(aodv_rt_entry *rt);
void rt_print(nsaddr_t node_id);
Add following code to aodv.cc after void AODV::rt_down(aodv_rt_entry *rt)
void AODV::rt_print(nsaddr_t node_id) {
FILE * dumpFile;
char dumpFileName[50] = "rtable.txt";
dumpFile = fopen(dumpFileName, 'a');
aodv_rt_entry *rt;
fprintf(dumpFile, "=======================================================");
for (rt=rtable.head();rt; rt = rt->rt_link.le_next) {
fprintf(dumpFile, "NODE: %i\t %.4lf\t %i\t %i\t %i\t %i\t %i\t %.4lf\t %d \n", node_id, CURRENT_TIME, rt->rt_dst, rt->rt_nexthop, rt->rt_hops, rt->rt_seqno, rt->rt_expire, rt->rt_flags)
}
fclose(dumpFile);
}
The function (rt_print) can be used anywhere in AODV. For example, I am using the function, when route request generated node receives route reply message (RREP).
if (ih->daddr() == index) { // If I am the original source
// Update the route discovery latency statistics
// rp->rp_timestamp is the time of request origination
rt_print(index); // print this nodes whole routing table
rt->rt_disc_latency[(unsigned char)rt->hist_indx] = (CURRENT_TIME - rp->rp_timestamp)
/ (double) rp->rp_hop_count;
// increment indx for next time
rt->hist_indx = (rt->hist_indx + 1) % MAX_HISTORY;
}