Friday, July 5, 2013

Overhearing Packets (or) Entering a node into Promiscuous Mode in NS-2

This post is an extension to the broadcast example. In this, I am going to explain how a node can be entered into promiscuous mode so that it can overhear the packets sent, forward or received by neighboring nodes. It all require a class called Tap which is available in mac.h header file. Tap class offer a function called void tap(const Packet *p).  To define the tap function, we need to inherit the class Tap. Usage of tap function and Tap class has shown with the broadcast example.

/* This Protocol perform Simple broad cast and overhear the packets of neighboring nodes
 * sbcast.h
 *
 *  Created on: 19-May-2013
 *      Author: P. RAGHU VAMSI
 *      @ JAYPEE INSTITUTE OF INFORMATION TECHNOLOGY UNIVERSITY, INDIA
 *      @ prvonline@yahoo.co.in
 */

#ifndef SBCAST_H_
#define SBCAST_H_

// Include mac header to overhear
#include

#define CURRENT_TIME Scheduler::instance().clock()

#define MAX_NODES 20

#define JITTER (Random::uniform()*0.5)
#define CURRENT_TIME Scheduler::instance().clock()
#define HDR_BEACON(p) (hdr_beacon *) hdr_beacon::access(p)

struct hdr_beacon {
nsaddr_t addr_;
u_int8_t seq_num_;
inline nsaddr_t & addr() { return addr_; }
inline u_int8_t & seq_num() { return seq_num_; }
static int offset_;
inline static int & offset() { return offset_; }
inline static hdr_beacon * access(const Packet *p) {
return (hdr_beacon*) p->access(offset_);
}
};


class SBAgent;

class BcastTimer : public TimerHandler {
protected:
SBAgent *agent_;
virtual void expire(Event *e);
public:
BcastTimer(SBAgent *agent):TimerHandler(),agent_(agent) { }
};





class SBAgent : public Tap,public Agent {
protected:
friend class BcastTimer;
private:
BcastTimer btimer_;
PortClassifier *dmux_;
Trace *logtarget_;
nsaddr_t my_addr_;
int seq_num_;
int node_count;
// for obtaining the mac of the node
Mac *mac_;
public:
static int pkt_received[MAX_NODES];
static int pkt_send[MAX_NODES];
static int no_of_nodes;
static int color_count;

SBAgent();
int command(int,const char*const*);
void recv(Packet *,Handler *);
void sendBeacon();
void resetBcastTimer();
inline nsaddr_t & my_addr() { return my_addr_;}
void changeColor();
//Tap to overhear the packets (or) to enter into promiscous mode
void tap(const Packet *);
};

#endif /* SBCAST_H_ */

sbcast.cc

/*
 * sbcast.cc
 * This Protocol perform Simple broad cast
 *  Created on: 19-May-2013
 *      Author: P. RAGHU VAMSI
 *      @ JAYPEE INSTITUTE OF INFORMATION TECHNOLOGY UNIVERSITY, INDIA
 *      @ prvonline@yahoo.co.in
 */

#include "sbcast.h"
#include "mobilenode.h"
// TCL Hooks

int hdr_beacon::offset_;

static class SBcastHeaderClass : public PacketHeaderClass {
public:
SBcastHeaderClass():PacketHeaderClass("PacketHeader/SB",sizeof(hdr_beacon)) {
bind_offset(&hdr_beacon::offset_);
}
}class_hdr_sbcast;

static class SBcastClass : public TclClass {
public:
SBcastClass():TclClass("Agent/SB") { }
TclObject *create(int argc,const char*const* argv) {
return (new SBAgent());
}
virtual void bind();   // for access of static variables
virtual int method(int argc, const char*const* argv);
}class_sbagent;

int SBAgent::pkt_received[MAX_NODES];
int SBAgent::pkt_send[MAX_NODES];
int SBAgent::no_of_nodes;
int SBAgent::color_count;

void SBcastClass::bind() {
TclClass::bind();
add_method("print-stats");
}

int SBcastClass::method(int ac, const char*const* av) {
    int argc = ac - 2;
    const char*const* argv = av + 2;
    if (argc == 2) {
    if(strcmp(argv[1],"print-stats")==0){

for(int i=0;
i          printf("Packets Sent By Node %d : %d \n",i,SBAgent::pkt_send[i]);
          printf("Packets Received By Node %d : %d \n",i,SBAgent::pkt_received[i]);
 

            }
    }
    return TCL_OK;
    }
}


SBAgent::SBAgent():Agent(PT_SB),btimer_(this) {
bind("node_count",&node_count);
no_of_nodes = node_count;
}

int SBAgent::command(int argc,const char*const* argv) {
if(argc==2){
if(strcmp(argv[1],"start")==0){
my_addr_ = addr();
return TCL_OK;
}
if(strcmp(argv[1],"base-station")==0){
btimer_.resched((double)0.1);
my_addr_ = addr();
return TCL_OK;
}
}else if (argc == 3) {
// Obtains corresponding dmux to carry packets to upper layers
if (strcmp(argv[1], "port-dmux") == 0) {
dmux_ = (PortClassifier*)TclObject::lookup(argv[2]);
if (dmux_ == 0) {
fprintf(stderr, "%s: %s lookup of %s failed\n",
__FILE__,
argv[1],
argv[2]);
return TCL_ERROR;
}
return TCL_OK;
}

if (strcmp(argv[1], "log-target") == 0 ||
strcmp(argv[1], "tracetarget") == 0) {
logtarget_ = (Trace*)TclObject::lookup(argv[2]);
if (logtarget_ == 0)
return TCL_ERROR;
return TCL_OK;
}
/* Add a command to install tap on a mac layer of a node */
if (strcmp(argv[1], "install-tap") == 0) {
  mac_ = (Mac*) TclObject::lookup(argv[2]);
  mac_->installTap(this);
  return TCL_OK;
   }
}
return (Agent::command(argc,argv));
}

void BcastTimer::expire(Event *e) {
agent_->sendBeacon();
agent_->changeColor();
agent_->resetBcastTimer();
}

void SBAgent::resetBcastTimer() {
btimer_.resched((double)0.5);

}

void SBAgent::sendBeacon() {
Packet* p = allocpkt();
struct hdr_cmn* ch = HDR_CMN(p);
struct hdr_ip* ih = HDR_IP(p);
struct hdr_beacon * ph = HDR_BEACON(p);

ph->addr() = my_addr();
ph->seq_num() = seq_num_++;

ch->ptype() = PT_SB;
ch->direction() = hdr_cmn::DOWN;
ch->size() = IP_HDR_LEN;
ch->error() = 0;
ch->next_hop() = IP_BROADCAST;
ch->addr_type() = NS_AF_INET;

ih->saddr() = my_addr();
ih->daddr() = IP_BROADCAST;
ih->sport() = RT_PORT;
ih->dport() = RT_PORT;
ih->ttl() = IP_DEF_TTL;

pkt_send[my_addr()]++;
send(p,0);
}

void SBAgent::recv(Packet *p,Handler *h) {

struct hdr_cmn *ch = HDR_CMN(p);
if(ch->ptype() == PT_SB) {
pkt_received[my_addr()]++;
}

}

void SBAgent::changeColor() {
char *color[5] = {"blue","brown","red","yellow","purple"};
Tcl& tcl = Tcl::instance();
tcl.evalf("%s set node_", name());
const char *node_object = tcl.result();
 Tcl::instance().evalf("$ns at %f \"%s color %s\"",CURRENT_TIME,
node_object,color[color_count]);

 if(color_count >= 4) color_count=0;
  else color_count++;
}

/* Define the tap function to overhear the packets (or) to enter
 * into promiscuos mode.
 */
void SBAgent::tap(const Packet *p) {
struct hdr_cmn* ch = HDR_CMN(p);
struct hdr_beacon * ph = HDR_BEACON(p);

printf("\n Node: %d IN TAP: from %d Seq Number: %d Packet Type: %d",my_addr(),ph->addr_,ph->seq_num_,ch->ptype());


}


bcast.tcl

#===================================
#     Simulation parameters setup
#===================================
set val(chan)   Channel/WirelessChannel    ;# channel type
set val(prop)   Propagation/TwoRayGround   ;# radio-propagation model
set val(netif)  Phy/WirelessPhy            ;# network interface type
set val(mac)    Mac/802_11                 ;# 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) 50                         ;# max packet in ifq
set val(nn)     5                         ;# number of mobilenodes
set val(rp)     SB                      ;# routing protocol
set val(ie)     100     ; # initial energy of a node
set val(em)     EnergyModel     ; # Energy model 
set val(x)      100                      ;# X dimension of topography
set val(y)      100                      ;# Y dimension of topography
set val(stop)   50 

Agent/SB set node_count $val(nn)

#===================================
#  Attaching selected headers    
#===================================

remove-all-packet-headers
add-packet-header Mac LL IP ARP LL SB

#===================================
#        Initialization        
#===================================
#Create a ns simulator
set ns [new Simulator]

#Setup topography object
set topo       [new Topography]
$topo load_flatgrid $val(x) $val(y)
create-god $val(nn)


#Open the NS trace file
set tracefile [open bcast.tr w]
$ns trace-all $tracefile

#Open the NAM trace file
set namfile [open bcast.nam w]
$ns namtrace-all $namfile
$ns namtrace-all-wireless $namfile $val(x) $val(y)

set chan [new $val(chan)];#Create wireless channel

Mac/802_11 set dataRate 512Kbps

#===================================
#     Node parameter setup
#===================================
$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       $chan \
                -topoInstance  $topo \
                -agentTrace    ON \
                -routerTrace   ON \
                -macTrace      ON \
                -movementTrace OFF \
-energyModel   $val(em) \
-initialEnergy  $val(ie) \
-rxPower  35.25e-23 \
-txPower 31.21e-23 \
-idlePower 712e-6 \
-sleepPower 144e-9 

#===================================
#        Nodes Definition        
#===================================

for {set i 0} {$i < $val(nn)} {incr i} {
 set node_($i) [$ns node] 
 $node_($i) color blue
}

for {set i 0} {$i < $val(nn)} {incr i} {
 set u_($i) [new Agent/SB]
 $ns attach-agent $node_($i) $u_($i)
}


$node_(0) set X_ 0.0
$node_(0) set Y_ 0.0
$node_(0) set Z_ 0
$node_(1) set X_ 40.0
$node_(1) set Y_ 0.0
$node_(1) set Z_ 0
$node_(2) set X_ 25.0
$node_(2) set Y_ 0.0
$node_(2) set Z_ 0
$node_(3) set X_ 0.0
$node_(3) set Y_ 75.0
$node_(3) set Z_ 0
$node_(4) set X_ 60.0
$node_(4) set Y_ 20.0
$node_(4) set Z_ 0



#$ns at 1.0 "$node_(0) setdest 99.0 99.0 15.0"
for {set i 0} {$i < $val(nn)} {incr i} {
$ns at 0.0 "[$node_($i) set ragent_] base-station"
}


for {set i 0} {$i < $val(nn)} {incr i} {
 $ns initial_node_pos $node_($i) 10  
}

for {set i 0} {$i < $val(nn)} {incr i} {
[$node_($i) set ragent_] install-tap [$node_($i) set mac_(0)]
}


proc finish {} {
    global ns tracefile namfile 
    $ns flush-trace
    close $tracefile
    close $namfile
    Agent/SB print-stats
    exec nam bcast.nam &
    exit 0
}

#===================================
#  Reset the nodes   
#===================================

for {set i 0} {$i < $val(nn) } { incr i } {
    $ns at $val(stop) "$node_($i) reset"
}

#===================================
#  Simulation start up  
#===================================

$ns at $val(stop) "$ns nam-end-wireless $val(stop)"
$ns at $val(stop) "finish"
$ns at $val(stop) "puts \"done\" ; $ns halt"
puts "before sim run"
$ns run