Tuesday, July 6, 2010

How to Configure an $80 File Server in 45 Minutes

I use a modded Xbox and Xbox Media Center for playing media files across the network on my television and sound system. I also download large files, such as Linux ISOs, via BitTorrent. However, leaving my primary computer on all the time seemed like a waste of energy. I wanted a cheap, small headless machine that I could use as a Samba server and BitTorrent client so I could leave my workstation off when I wasn't using it.

I was in luck; HCDI Trading had a great "Fall Extravaganza" deal - a Dell OptiPlex GX150 Desktop for $47.91 (around $30 s/h). The specs:

  • Desktop Form Factor (it fits on a shelf in a media center)
  • Intel Celeron 700 MHz
  • 128MB RAM
  • 10GB HD
  • CD-Rom

Not cutting edge, but perfect for what I needed and priced very reasonably. Instead of using X11 and remote clients, I felt that web interfaces would be optimal out of simplicity. If I configured the server as a LAMP (Linux, Apache, MySQL, and PHP), then I could use web GUIs for configuration, administration, and file transfers.

Out of the popular Linux distributions, I'm most familiar with Gentoo and Ubuntu. Gentoo didn't seem appropriate; it would take hours and hours to get everything set up, configured and updated (even from a Stage 3 install), and any performance gain from the optimization would be negligible. Ubuntu has a history of reliability and ease of set up, so I used the Edgy Eft release as the basis my server.

The Applications

  • Remote Console - OpenSSH
    • The free version of the SSH connectivity tools. Use it for secure access to the console.
  • Web Server - Apache
    • It's free, fast, well supported and documented
  • Network Fileshare - Samba
    • Creates file shares that can be easily accessed from Windows. Notoriously obnoxious to configure by hand, the Samba Web Administration Tool (SWAT) simplifies the process immensely.
  • Database - MySQL
    • The popular free database server. While I can use a command line to administrate MySQL, I prefer using phpMyAdmin.
  • P2P Client - BitTorrent

Directions

  1. Download and burn the Ubuntu Server 6.10 i386 install CD.
  2. Install Ubuntu Server
    1. When asked about Software Installation, choose LAMP.
    2. When the installation is finished, take out the CD (I flip it over and leave it in the drive for the next time I need it) and reboot.
  3. Logon as the regular user that you created during setup.
  4. Give root a password.
    sudo passwd root
  5. We're going to modify the file sources list to allow us access to all the required files. Uncomment the edgy universe, edgy-security main restricted, edgy-security universe, edgy multiverse, edgy-backports main restricted universe multiverse, and edgy-commercial main. In addition, Ubuntu leaves the install CD as one of the file sources after installation, so you'll need to remove the CD from the source list. Comment out the CD from the list and save.
    sudo nano -w /etc/apt/sources.list
  6. Update apt-get to use the new sources.
    sudo apt-get update
  7. Install OpenSSH server
    sudo apt-get install openssh-server
  8. Turn off the computer.
    sudo shutdown -h now
  9. Disconnect the monitor, keyboard, and set the computer wherever it's going to lurk for the next couple years.
  10. Turn on the computer and wait about a minute for it to boot.
  11. Using your preferred SSH client, connect to the machine. I prefer PuTTY for Windows.
  12. Install Samba and SWAT.
    sudo apt-get install samba smbfs swat xinetd
  13. Create a Samba user.
    sudo smbpasswd -a username
  14. Add SWAT to the xinet configuration and save.
    sudo nano -w /etc/xinetd.d/swat
    # description: SAMBA SWAT
    service swat
    {
    disable = no
    socket_type = stream
    protocol = tcp
    #should use a more limited user here
    user = root
    wait = no
    server = /usr/sbin/swat
    }
  15. Reload Xinetd with the new configuration.
    sudo dpkg-reconfigure xinetd
  16. Verify that SWAT is up and running. If you don't get any response, start Googling.
    sudo netstat -tap | grep swat
  17. Make the shared directory for TorrentFlux.
    sudo mkdir /share
    sudo mkdir /share/incoming
    sudo chmod 777 /share/incoming/
  18. Create the Samba share. Using a web browser, go to http://hostname:901/shares
    1. path /share/incoming
    2. valid users - username
    3. read only - no
    4. Commit Changes
  19. Install phpMyAdmin
    sudo apt-get install phpmyadmin
  20. Connect to phpMyadmin using a web browser - http://hostname/phpmyadmin
    1. Secure MySQL / phpMyAdmin
      1. login: root (no pass)
      2. Privileges
        1. Add a password to both root accounts
      1. Create a database for TorrentFlux
        1. Databases - Create New - torrentflux
  21. Install TorrentFlux
    sudo apt-get install torrentflux
    1. Ignore the libphp-adodb message.
    2. Configure database for torrentflux with dbconfig-common? - yes
    3. Password - blank (generates random)
    4. Restart Apache? - Yes
  22. Configure TorrentFlux using a web browser - http://hostname/torrentflux/
    1. Username / Password - root / root
    2. Configuration
      1. Path - /share/incoming/
      2. Save
    3. Click My Profile
      1. Update your password
    4. Create a user account
      1. Admin - New User
  23. Remove the Apache default documents from web root.
    sudo rm -Rf /var/www/apache2-default/
  24. Create a basic web launchpad for easy access your services.
  25. sudo nano -w /var/www/index.php



Post Mortem

Overall, the installation and configuration took me about 45 minutes to go from zero to a fully functional system. The Xbox can see the share, and I've got a new playground for web development. I would suggest cleaning up and securing that home page a bit; research .htaccess files to lock it down.

I put my file server in my media center underneath my router, and it takes up about the same space as a VCR. For $80, I feel that I've made an excellent investment.

Tuesday, April 27, 2010

Interesting blogs

http://www.cse.msu.edu/~wangbo1/ns2/

http://peelmeagrape.net/eoin/swarm/

http://tagus.inesc-id.pt/~pestrela/ns2/ns2_tips.html

http://www.ict.csiro.au/staff/ren.liu/ns-2/simulate-802_11.htm

http://elmurod.net/wps/?p=72

How to Display RTS/CTS Packet Type in NS2 Trace File

http://www.cse.msu.edu/~wangbo1/ns2/

There are several posts on NS2 user mailing list explaining how to display RTS/CTS packet type in NS2 trace file. Here is an example. However, I failed to adopt them in NS 2.26 with new trace format. Here is my solution which just uses code written for old trace format. You only need to modify ns-2.26/trace/cmu-trace.cc in the following way and I think this solution can also work for NS versions later than 2.26.

void
CMUTrace::format_mac(Packet *p, const char *why, int offset)
{

......


/*
sprintf(pt_->buffer() + offset,
"-Ma %x -Md %x -Ms %x -Mt %x ",
mh->dh_duration,
ETHER_ADDR(mh->dh_da),
ETHER_ADDR(mh->dh_sa),
GET_ETHER_TYPE(mh->dh_body));
*/



sprintf(pt_->buffer() + offset,
"-Ma %x -Md %x -Ms %x -Mt %s ",
mh->dh_duration,
ETHER_ADDR(mh->dh_da),
ETHER_ADDR(mh->dh_sa),
((ch->ptype() == PT_MAC) ? (
(mh->dh_fc.fc_subtype == MAC_Subtype_RTS) ? "RTS" :
(mh->dh_fc.fc_subtype == MAC_Subtype_CTS) ? "CTS" :
(mh->dh_fc.fc_subtype == MAC_Subtype_ACK) ? "ACK" :
"UNKN"
) : packet_info.name(ch->ptype())));



return;


}

Here is an exmaple NS2 trace file which displays the RTS/CTS/ACK information of MAC layer frame.

r -t 0.003583515 -Hs 0 -Hd -2 ... -Nl MAC -Nw --- -Ma 0 -Md 0 -Ms 0 -Mt ACK
s -t 0.003853348 -Hs 8 -Hd -2 ...-Nl MAC -Nw --- -Ma 2ff -Md 0 -Ms 8 -Mt RTS
r -t 0.004125515 -Hs 0 -Hd -2 ... -Nl MAC -Nw --- -Ma 2ff -Md 0 -Ms 8 -Mt RTS
s -t 0.004135515 -Hs 0 -Hd -2 ... -Nl MAC -Nw --- -Ma 1fd -Md 8 -Ms 0 -Mt CTS
r -t 0.004383682 -Hs 8 -Hd -2 ... -Nl MAC -Nw --- -Ma 1fd -Md 8 -Ms 0 -Mt CTS

Thursday, April 22, 2010

Notes

Google .. blackhole attack ns2 aodv ..
Examples
http://elmurod.net/wps/?p=196

http://cdsweb.cern.ch/record/1206617?ln=de
http://arxiv.org/pdf/0909.2371.pdf


Some code here : ?
Google .. prevent blackhole ns2 ..
? http://www.nesmd.com/shtml/18947.shtml ?

in reference to:

"Google .. blackhole attack ns2 aodv .. Examples http://elmurod.net/wps/?p=196 http://cdsweb.cern.ch/record/1206617?ln=de http://arxiv.org/pdf/0909.2371.pdf Some code here : ? Google .. prevent blackhole ns2 .. ? http://www.nesmd.com/shtml/18947.shtml ?"
- simulating blackhole attack in ns-29 (view on Google Sidewiki)

Example to create BH node

I want to make a node behave as blackhole node, using the above technique. The above method drops all packets that go through it, but it doesn’t kind of forces a packet to go through it by sending a high sequence number.
For that, i have done this within this fn. AODV::recvRequest(Packet *p):

if(malicious==true) {
sendReply(rq->rq_src, // IP Destination
1, // Hop Count
index, // Dest IP Address
4294967295, // Max. Dest Sequence Num if the node is malicious
MY_ROUTE_TIMEOUT, // Lifetime
rq->rq_timestamp); // timestamp
}
else {
sendReply(rq->rq_src, // IP Destination
1, // Hop Count
index, // Dest IP Address
seqno, // Dest Sequence Num
MY_ROUTE_TIMEOUT, // Lifetime
rq->rq_timestamp); // timestamp
}

and removed
if(malicious == true) {
drop(p, DROP_RTR_ROUTE_LOOP);
}

from rt_resolve() fn.

Now, what changes do i need to make, so that the code can distinguish data packets and management packets, so that it could drop the data packet

if you want to drop only data packets you need to check packet type reger HDR_CMN for more info.

Ns2 code

# Preamble
set ns [new Simulator]

# Tell the simulator to use dynamic routing
$ns rtproto DV
Agent/rtProto/DV set advertInterval 1.0
Agent/rtProto/DV set INFINITY 100

# Set ns color indices
$ns color 0 blue
$ns color 1 black
$ns color 2 turquoise
$ns color 3 orange
$ns color 4 gold
$ns color 5 red


# Open trace files
set f [open SIM.tr w]
$ns trace-all $f
set nf [open SIM.nam w]
$ns namtrace-all $nf


proc finish {} {
global ns f nf
$ns flush-trace
close $nf
close $f
puts "running nam"
exit 0
}


# Create 13 routers
for {set i 0} {$i < 13} {incr i} {
set r($i) [$ns node]
}

# Create 30 pc
for {set i 13} {$i < 43} {incr i} {
set pc($i) [$ns node]
}

for {set i 0} {$i < 13} {incr i} {
$r($i) shape hexagon
$r($i) color green
}

for {set i 13} {$i < 43} {incr i} {
$pc($i) color blue
}





# Create duplex links
$ns duplex-link $r(0) $pc(13) 1Mb 50ms DropTail
$ns duplex-link $r(0) $pc(14) 1Mb 50ms DropTail
$ns duplex-link $r(0) $pc(15) 1Mb 50ms DropTail
$ns duplex-link $r(0) $r(1) 2Mb 50ms DropTail
$ns duplex-link $r(0) $r(5) 2Mb 50ms DropTail
$ns duplex-link $r(1) $pc(16) 1Mb 50ms DropTail
$ns duplex-link $r(1) $pc(17) 1Mb 50ms DropTail
$ns duplex-link $r(1) $pc(18) 1Mb 50ms DropTail
$ns duplex-link $r(1) $r(2) 2Mb 50ms DropTail
$ns duplex-link $r(1) $r(6) 10Mb 50ms DropTail
$ns duplex-link $r(2) $pc(19) 1Mb 50ms DropTail
$ns duplex-link $r(2) $pc(20) 1Mb 50ms DropTail
$ns duplex-link $r(2) $pc(21) 1Mb 50ms DropTail
$ns duplex-link $r(2) $r(3) 2Mb 50ms DropTail
$ns duplex-link $r(2) $r(7) 10Mb 50ms DropTail
$ns duplex-link $r(3) $pc(22) 1Mb 50ms DropTail
$ns duplex-link $r(3) $pc(23) 1Mb 50ms DropTail
$ns duplex-link $r(3) $pc(24) 1Mb 50ms DropTail
$ns duplex-link $r(3) $r(4) 2Mb 50ms DropTail
$ns duplex-link $r(3) $r(8) 10Mb 50ms DropTail
$ns duplex-link $r(4) $pc(25) 1Mb 50ms DropTail
$ns duplex-link $r(4) $pc(26) 1Mb 50ms DropTail
$ns duplex-link $r(4) $pc(27) 1Mb 50ms DropTail
$ns duplex-link $r(4) $r(9) 2Mb 50ms DropTail
$ns duplex-link $r(5) $pc(28) 1Mb 50ms DropTail
$ns duplex-link $r(5) $pc(29) 1Mb 50ms DropTail
$ns duplex-link $r(5) $pc(30) 1Mb 50ms DropTail
$ns duplex-link $r(5) $r(6) 10Mb 50ms DropTail
$ns duplex-link $r(6) $r(7) 10Mb 50ms DropTail
$ns duplex-link $r(6) $r(10) 10Mb 50ms DropTail
$ns duplex-link $r(7) $r(8) 10Mb 50ms DropTail
$ns duplex-link $r(7) $r(11) 10Mb 50ms DropTail
$ns duplex-link $r(8) $r(9) 10Mb 50ms DropTail
$ns duplex-link $r(8) $r(12) 10Mb 50ms DropTail
$ns duplex-link $r(9) $pc(31) 1Mb 50ms DropTail
$ns duplex-link $r(9) $pc(32) 1Mb 50ms DropTail
$ns duplex-link $r(9) $pc(33) 1Mb 50ms DropTail
$ns duplex-link $r(10) $r(11) 2Mb 50ms DropTail
$ns duplex-link $r(10) $pc(34) 1Mb 50ms DropTail
$ns duplex-link $r(10) $pc(35) 1Mb 50ms DropTail
$ns duplex-link $r(10) $pc(36) 1Mb 50ms DropTail
$ns duplex-link $r(11) $r(12) 2Mb 50ms DropTail
$ns duplex-link $r(11) $pc(37) 1Mb 50ms DropTail
$ns duplex-link $r(11) $pc(38) 1Mb 50ms DropTail
$ns duplex-link $r(11) $pc(39) 1Mb 50ms DropTail
$ns duplex-link $r(12) $pc(40) 1Mb 50ms DropTail
$ns duplex-link $r(12) $pc(41) 1Mb 50ms DropTail
$ns duplex-link $r(12) $pc(42) 1Mb 50ms DropTail



# Orient the nodes
$ns duplex-link-op $r(0) $pc(13) orient 165deg
$ns duplex-link-op $r(0) $pc(14) orient 180deg
$ns duplex-link-op $r(0) $pc(15) orient 195deg
$ns duplex-link-op $r(0) $r(1) orient 0deg
$ns duplex-link-op $r(0) $r(5) orient 270deg
$ns duplex-link-op $r(1) $pc(16) orient 105deg
$ns duplex-link-op $r(1) $pc(17) orient 90deg
$ns duplex-link-op $r(1) $pc(18) orient 75deg
$ns duplex-link-op $r(1) $r(2) orient 0deg
$ns duplex-link-op $r(1) $r(6) orient 270deg
$ns duplex-link-op $r(2) $pc(19) orient 105deg
$ns duplex-link-op $r(2) $pc(20) orient 90deg
$ns duplex-link-op $r(2) $pc(21) orient 75deg
$ns duplex-link-op $r(2) $r(3) orient 0deg
$ns duplex-link-op $r(2) $r(7) orient 270deg
$ns duplex-link-op $r(3) $pc(22) orient 105deg
$ns duplex-link-op $r(3) $pc(23) orient 90deg
$ns duplex-link-op

in reference to: [ns] black hole simulation (view on Google Sidewiki)

Wednesday, April 21, 2010

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;
}

Friday, March 12, 2010

802.15.4 NS2 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.

nam-aodv-802-15-4nam

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.

Adding New Routing Protocol in NS2

Writing routing protocol is fairly easy in NS2, but for beginners it seems very difficult. Therefore, if you are new to NS2 and want to write your own routing protocol, I would strongly recommend to revise AODV source code. Because, I believe AODV source code is straightforward and fairly easy to understand due to the simplicity of the AODV protocol.

Before you begin reading this post, I assume that you have already installed NS2 on Linux. I have used version 2.34, which is current release. If you have not installed yet, DOWNLOAD HERE and INSTALL. Okey, simple requirements to write your own routing protocol

  • NS2 installed
  • You should know how to program in C/C++.
  • Optionally, shell scripting and perl.

Let's start with creating directory of routing protocol. Goto the "$NS_ROOT/ ns-2.34/". Create directory named as wfrp, we call it WSN Flooding-based Routing Protocol in which sink nodes periodically send a beacon message and other nodes construct route towards the sink nodes. Then nodes report to sink node every certain period using UDP protocol. Direct Diffusion may be an example of such protocol, but what we are writing is simpler and has more functionalities.

mkdir wfrp

In the directory we create three files : wrfp.cc, wrfp.h, wrfp_packet.h. Download and put these files in wfrp directory. I will not explain the code here, and if you don't understand just leave comment I will try to answer.

Now, we are going to modify following files. Therefore it is better you backup these files before you start adding new protocol, so that you can easily go back.

  • $NS_ROOT/Makefile
  • $NS_ROOT/queue/priqueue.cc
  • $NS_ROOT/common/packet.h
  • $NS_ROOT/trace/cmu-trace.h
  • $NS_ROOT/trace/cmu-trace.cc
  • $NS_ROOT/tcl/lib/ns-packet.tcl
  • $NS_ROOT/tcl/lib/ns-lib.tcl
  • $NS_ROOT/tcl/lib/ns-agent.tcl
  • $NS_ROOT/tcl/lib/ns-mobilenode.tcl

Let's start with ~/ns-allinone-2.34/ns-2.34/Makefile just add following lien at 269

wfrp/wfrp.o \

Add following lines to ~/ns-allinone-2.34/ns-2.34/queue/priqueue.cc from line 93.

// WFRP patch
case PT_WFRP:

To define new routing protocol packet type we have to modify ~/ns-allinone-2.34/ns-2.34/common/packet.h file. We change PT_NTYPE to 63, and for our protocol PT_WFRP = 62. If you have already installed another routing protocol. Just make sure PT_NTYPE is last, and protocol number is ordered sequentially. From line 85 changes would be :

// WFRP packet
static const packet_t PT_WFRP = 62;
// insert new packet types here
static packet_t PT_NTYPE = 63; // This MUST be the LAST one

We make following code change at line 254 of ~/ns-allinone-2.34/ns-2.34/common/packet.h. The code is used that the packet is routing protocol packet and has high priority.

type == PT_AODV ||
type == PT_WFRP)

And at line 390 of the same file

// WFRP patch
name_[PT_WFRP] = "WFRP";

Now we will make NS2 trace our simulation and write it to *something*.tr, in order to do that we have to modify cmu-trace.h and cmu-trace.cc.

To add trace function we add following line to ~/ns-allinone-2.34/ns-2.34/trace/cmu-trace.h at line 163:

void format_wfrp(Packet *p, int offset);

~/ns-allinone-2.34/ns-2.34/trace/cmu-trace.cc must be added following code at line 1071

// WFRP patch
void
CMUTrace::format_wfrp(Packet *p, int offset)
{
struct hdr_wfrp *wh = HDR_WFRP(p);
struct hdr_wfrp_beacon *wb = HDR_WFRP_BEACON(p);
struct hdr_wfrp_error *we = HDR_WFRP_ERROR(p);
switch(wh->pkt_type) {
case WFRP_BEACON:
if (pt_->tagged()) {
sprintf(pt_->buffer() + offset,
"-wfrp:t %x -wfrp:h %d -wfrp:b %d -wfrp:s %d "
"-wfrp:px %d -wfrp:py %d -wfrp:ts %f "
"-wfrp:c BEACON ",
wb->pkt_type,
wb->beacon_hops,
wb->beacon_id,
wb->beacon_src,
wb->beacon_posx,
wb->beacon_posy,
wb->timestamp);
} else if (newtrace_) {
sprintf(pt_->buffer() + offset,
"-P wfrp -Pt 0x%x -Ph %d -Pb %d -Ps %d -Ppx %d -Ppy %d -Pts %f -Pc BEACON ",
wb->pkt_type,
wb->beacon_hops,
wb->beacon_id,
wb->beacon_src,
wb->beacon_posx,
wb->beacon_posy,
wb->timestamp);
} else {
sprintf(pt_->buffer() + offset,
"[0x%x %d %d [%d %d] [%d %f]] (BEACON)",
wb->pkt_type,
wb->beacon_hops,
wb->beacon_id,
wb->beacon_src,
wb->beacon_posx,
wb->beacon_posy,
wb->timestamp);
}
break;
case WFRP_ERROR:
// TODO: need to add code
break;
default:
#ifdef WIN32
fprintf(stderr,
"CMUTrace::format_wfrp: invalid WFRP packet type\n");
#else
fprintf(stderr,
"%s: invalid WFRP packet type\n", __FUNCTION__);
#endif
abort();
}
}

Now we will modify tcl files to create routing agent. First we define protocol name to use in tcl file. It would done by modifying ~/ns-allinone-2.34/ns-2.34/tcl/lib/ns-packet.tcl @ line 172

# WFRP patch
WFRP

Now we set routing agent by modifying ~/ns-allinone-2.34/ns-2.34/tcl/lib/ns-lib.tcl @ line 633

WFRP {
set ragent [$self create-wfrp-agent $node]
}

From line 860 of the same file following code should be added.

Simulator instproc create-wfrp-agent { node } {
# Create WFRP routing agent
set ragent [new Agent/WFRP [$node node-addr]]
$self at 0.0 "$ragent start"
$node set ragent_ $ragent
return $ragent
}

Now we will set port numbers of routing agent. sport is source port, dport is destination port. Modify ~/ns-allinone-2.34/ns-2.34/tcl/lib/ns-agent.tcl line 202

Agent/WFRP instproc init args {
$self next $args
}
Agent/WFRP set sport_ 0
Agent/WFRP set dport_ 0

Frankly speaking I have no idea why I have to add following things. But I believe it should be done according to some tutorial : ~/ns-allinone-2.34/ns-2.34/tcl/lib/ns-mobilenode.tcl line 201

# Special processing for WFRP
set wfrponly [string first "WFRP" [$agent info class]]
if {$wfrponly != -1 } {
$agent if-queue [$self set ifq_(0)] ;# ifq between LL and MAC
}

We are done. got to ~/ns-allinone-2.34/ns-2.34/ directory and do

make clean
make

When the compile is finished, you can test using wfrp_802_15_4.tcl file as :

ns wfrp_802_15_4.tcl

In this test the NODE 0 is sink node, starts sending beacon 1 second after simulation i started, and NODE 10 is reporting node. It starts sending report over CBR/UDP at 5.0 seconds (after simulation is started). Report interval is 2 seconds.

To remove debugging WFRP, uncomment #define DEBUG (line 36 of wfrp.cc & re-make it).

Method to analyse 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