Aodv_rtable.h
#define __aodv_rtable_h__
#include <assert.h>
#include <sys/types.h>
#include <config.h>
#include <lib/bsd-list.h>
#include <scheduler.h>
#define CURRENT_TIME Scheduler::instance().clock()
#define INFINITY2 0xff
/*
AODV Neighbor Cache Entry
*/
class AODV_Neighbor {
friend class AODV;
friend class aodv_rt_entry;
public:
AODV_Neighbor(u_int32_t a) { nb_addr = a; }
protected:
LIST_ENTRY(AODV_Neighbor) nb_link;
nsaddr_t nb_addr;
double nb_expire; // ALLOWED_HELLO_LOSS * HELLO_INTERVAL
};
LIST_HEAD(aodv_ncache, AODV_Neighbor);
/*
AODV Precursor list data structure
*/
class AODV_Precursor {
friend class AODV;
friend class aodv_rt_entry;
public:
AODV_Precursor(u_int32_t a) { pc_addr = a; }
protected:
LIST_ENTRY(AODV_Precursor) pc_link;
nsaddr_t pc_addr; // precursor address
};
LIST_HEAD(aodv_precursors, AODV_Precursor);
/*
Route Table Entry
*/
class aodv_rt_entry {
friend class aodv_rtable;
friend class AODV;
friend class LocalRepairTimer;
public:
aodv_rt_entry();
~aodv_rt_entry();
void nb_insert(nsaddr_t id);
AODV_Neighbor* nb_lookup(nsaddr_t id);
void pc_insert(nsaddr_t id);
AODV_Precursor* pc_lookup(nsaddr_t id);
void pc_delete(nsaddr_t id);
void pc_delete(void);
bool pc_empty(void);
double rt_req_timeout; // when I can send another req
u_int8_t rt_req_cnt; // number of route requests
protected:
LIST_ENTRY(aodv_rt_entry) rt_link;
nsaddr_t rt_dst;
u_int32_t rt_seqno;
/* u_int8_t rt_interface; */
u_int16_t rt_hops; // hop count
int rt_last_hop_count; // last valid hop count
nsaddr_t rt_nexthop; // next hop IP address
/* list of precursors */
aodv_precursors rt_pclist;
double rt_expire; // when entry expires
u_int8_t rt_flags;
#define RTF_DOWN 0
#define RTF_UP 1
#define RTF_IN_REPAIR 2
/*
* Must receive 4 errors within 3 seconds in order to mark
* the route down.
u_int8_t rt_errors; // error count
double rt_error_time;
#define MAX_RT_ERROR 4 // errors
#define MAX_RT_ERROR_TIME 3 // seconds
*/
#define MAX_HISTORY 3
double rt_disc_latency[MAX_HISTORY];
char hist_indx;
int rt_req_last_ttl; // last ttl value used
// last few route discovery latencies
// double rt_length [MAX_HISTORY];
// last few route lengths
/*
* a list of neighbors that are using this route.
*/
aodv_ncache rt_nblist;
};
/*
The Routing Table
*/
class aodv_rtable {
public:
aodv_rtable() { LIST_INIT(&rthead); }
aodv_rt_entry* head() { return rthead.lh_first; }
aodv_rt_entry* rt_add(nsaddr_t id);
void rt_delete(nsaddr_t id);
aodv_rt_entry* rt_lookup(nsaddr_t id);
private:
LIST_HEAD(aodv_rthead, aodv_rt_entry) rthead;
};
#endif /* _aodv__rtable_h__ */
Aodv_rtable.cc
#include <aodv/aodv_rtable.h>
//#include <cmu/aodv/aodv.h>
/*
The Routing Table
*/
aodv_rt_entry::aodv_rt_entry()
{
int i;
rt_req_timeout = 0.0; //time needed to send the next rreq
rt_req_cnt = 0; //number of route requests
rt_dst = 0;
rt_seqno = 0;
rt_hops = rt_last_hop_count = INFINITY2; //hop count
rt_nexthop = 0;
LIST_INIT(&rt_pclist); //initial a list called rt_pclist with list head set NULL
rt_expire = 0.0; //when entry expires
rt_flags = RTF_DOWN; //rtf_down = 0, toward down layer
/*
rt_errors = 0;
rt_error_time = 0.0;
*/
for (i=0; i < MAX_HISTORY; i++) { //records of last few route discovery info
rt_disc_latency[i] = 0.0; //latency
}
hist_indx = 0; //double , rt_length[MAX_HISTORY]
rt_req_last_ttl = 0; //last few route lengths
LIST_INIT(&rt_nblist); //initial a list called rt_nblist(neighbour list) with list head set NULL
}
aodv_rt_entry::~aodv_rt_entry()
{
AODV_Neighbor *nb;
while((nb = rt_nblist.lh_first)) { //remove list rt_nblist
LIST_REMOVE(nb, nb_link);
delete nb;
}
AODV_Precursor *pc;
while((pc = rt_pclist.lh_first)) { //remove list rt_pclist(precursor list)
LIST_REMOVE(pc, pc_link);
delete pc;
}
}
void
aodv_rt_entry::nb_insert(nsaddr_t id)
{
AODV_Neighbor *nb = new AODV_Neighbor(id);
assert(nb); //duan yan hanshu, regard it as a try and exception function, if nb exist or not
nb->nb_expire = 0; //nb_expire = ALLOWED_HELLO_LOSS * HELLO_INTERVAL, time for no neighbour found, no_neighbour_found_times * per_find_time
LIST_INSERT_HEAD(&rt_nblist, nb, nb_link); //rt_nblist: a list of neighbours that are using this route
//nb: a pointer towards a neighbour
//nb_link: a neighbour's link to next node
//insert a node into rt_nblist, if no node in rt_nblist, then set the node as head of rt_nblist
}
AODV_Neighbor*
aodv_rt_entry::nb_lookup(nsaddr_t id)
{
AODV_Neighbor *nb = rt_nblist.lh_first; //set the head node in rt_nblist as nb
for(; nb; nb = nb->nb_link.le_next) { //find the node with id as id, then return nb
if(nb->nb_addr == id)
break;
}
return nb;
}
void
aodv_rt_entry::pc_insert(nsaddr_t id) //if node(id) is not contained in rt_pclist, then insert it into rt_pclist
{
if (pc_lookup(id) == NULL) {
AODV_Precursor *pc = new AODV_Precursor(id);
assert(pc);
LIST_INSERT_HEAD(&rt_pclist, pc, pc_link);
}
}
AODV_Precursor*
aodv_rt_entry::pc_lookup(nsaddr_t id) //look up for the node(id) in precursor list
{
AODV_Precursor *pc = rt_pclist.lh_first;
for(; pc; pc = pc->pc_link.le_next) {
if(pc->pc_addr == id)
return pc;
}
return NULL;
}
void
aodv_rt_entry::pc_delete(nsaddr_t id) { //delete the node(id) in rt_pclist
AODV_Precursor *pc = rt_pclist.lh_first;
for(; pc; pc = pc->pc_link.le_next) {
if(pc->pc_addr == id) {
LIST_REMOVE(pc,pc_link);
delete pc;
break;
}
}
}
void
aodv_rt_entry::pc_delete(void) { //delete the rt_pclist
AODV_Precursor *pc;
while((pc = rt_pclist.lh_first)) {
LIST_REMOVE(pc, pc_link);
delete pc;
}
}
bool
aodv_rt_entry::pc_empty(void) { //check if rt_pclist is empty
AODV_Precursor *pc;
if ((pc = rt_pclist.lh_first)) return false;
else return true;
}
/*
The Routing Table
*/
aodv_rt_entry*
aodv_rtable::rt_lookup(nsaddr_t id) //look up node(id) in aodv_rtable
{
aodv_rt_entry *rt = rthead.lh_first;
for(; rt; rt = rt->rt_link.le_next) {
if(rt->rt_dst == id)
break;
}
return rt;
}
void
aodv_rtable::rt_delete(nsaddr_t id) //delete node(id) from aodv_rtable
{
aodv_rt_entry *rt = rt_lookup(id);
if(rt) {
LIST_REMOVE(rt, rt_link);
delete rt;
}
}
aodv_rt_entry*
aodv_rtable::rt_add(nsaddr_t id) //if there's no route to node(id) in aodv_rtable, build one and set its dst as node(id)
{
aodv_rt_entry *rt;
assert(rt_lookup(id) == 0);
rt = new aodv_rt_entry;
assert(rt);
rt->rt_dst = id;
LIST_INSERT_HEAD(&rthead, rt, rt_link);
return rt;
}