//#include <ip.h>
#include <aodv/aodv.h>
#include <aodv/aodv_packet.h>
#include <random.h>
#include <cmu-trace.h>
//#include <energy-model.h>
#define max(a,b) ( (a) > (b) ? (a) : (b) )
#define CURRENT_TIME Scheduler::instance().clock()
//#define DEBUG
//#define ERROR
#ifdef DEBUG
static int extra_route_reply = 0;
static int limit_route_request = 0;
static int route_request = 0;
#endif
/*
TCL Hooks
*/
int hdr_aodv::offset_;
static class AODVHeaderClass : public PacketHeaderClass {
public:
AODVHeaderClass() : PacketHeaderClass("PacketHeader/AODV",
sizeof(hdr_all_aodv)) {
bind_offset(&hdr_aodv::offset_);
}
} class_rtProtoAODV_hdr;
/*AODVclass 只有两个函数,构造函数和creat函数*/
static class AODVclass : public TclClass {
public:
AODVclass() : TclClass("Agent/AODV") {}
TclObject* create(int argc, const char*const* argv) {
assert(argc == 5);
//return (new AODV((nsaddr_t) atoi(argv[4])));
return (new AODV((nsaddr_t) Address::instance().str2addr(argv[4])));
}
} class_rtProtoAODV;
/*command函数实现了命令的分发*/
int
AODV::command(int argc, const char*const* argv) {
if(argc == 2) {//命令的参数个数是2
Tcl& tcl = Tcl::instance();
if(strncasecmp(argv[1], "id", 2) == 0) {//命令所要求的操作为id
tcl.resultf("%d", index);
return TCL_OK;
}
if(strncasecmp(argv[1], "start", 2) == 0) {//命令所要求的操作为start
btimer.handle((Event*) 0);
#ifndef AODV_LINK_LAYER_DETECTION
htimer.handle((Event*) 0);
ntimer.handle((Event*) 0);
#endif // LINK LAYER DETECTION
rtimer.handle((Event*) 0);
return TCL_OK;
}
}
else if(argc == 3) {//命令参数个数等于3
if(strcmp(argv[1], "index") == 0) {//命令所要求的操作为index
index = atoi(argv[2]);
return TCL_OK;
}
//命令所要求的操作为log-target或者tracetarget
else 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;
}
else if(strcmp(argv[1], "drop-target") == 0)
{
//命令所要求的操作为drop-target
int stat = rqueue.command(argc,argv);
if (stat != TCL_OK) return stat;
return Agent::command(argc, argv);
}
//命令所要求的操作if-queue
else if(strcmp(argv[1], "if-queue") == 0) {
ifqueue = (PriQueue*) TclObject::lookup(argv[2]);
if(ifqueue == 0)
return TCL_ERROR;
return TCL_OK;
}
//命令所要求的操作为port-dmux
else 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;
}
}
return Agent::command(argc, argv);
}
/*
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;
LIST_INIT(&nbhead);
LIST_INIT(&bihead);
logtarget = 0;
ifqueue = 0;
}
/*
Timers
*/
//广播定时器
void
BroadcastTimer::handle(Event*) {
agent->id_purge();
Scheduler::instance().schedule(this, &intr, BCAST_ID_SAVE);
}
//hello报文定时器
void
HelloTimer::handle(Event*) {
agent->sendHello();
double interval = MinHelloInterval +
((MaxHelloInterval - MinHelloInterval) * Random::uniform());
assert(interval >= 0);
Scheduler::instance().schedule(this, &intr, interval);
}
//邻居定时器
void
NeighborTimer::handle(Event*) {
agent->nb_purge();
Scheduler::instance().schedule(this, &intr, HELLO_INTERVAL);
}
路由缓存定时器
void
RouteCacheTimer::handle(Event*) {
agent->rt_purge();
#define FREQUENCY 0.5 // sec
Scheduler::instance().schedule(this, &intr, FREQUENCY);
}
//路由缓存定时器
void
LocalRepairTimer::handle(Event* p) { // SRD: 5/4/99
aodv_rt_entry *rt;
struct hdr_ip *ih = HDR_IP( (Packet *)p);
/* you get here after the timeout in a local repair attempt */
/* fprintf(stderr, "%s\n", __FUNCTION__); */
rt = agent->rtable.rt_lookup(ih->daddr());
if (rt && rt->rt_flags != RTF_UP) {
// route is yet to be repaired
// I will be conservative and bring down the route
// and send route errors upstream.
/* The following assert fails, not sure why */
/* assert (rt->rt_flags == RTF_IN_REPAIR); */
//rt->rt_seqno++;
agent->rt_down(rt);
// send RERR
#ifdef DEBUG
fprintf(stderr,"Node %d: Dst - %d, failed local repair\n",index, rt->rt_dst);
#endif
}
Packet::free((Packet *)p);
}
/*
Broadcast ID Management Functions
*/
void
AODV::id_insert(nsaddr_t id, u_int32_t bid) {
BroadcastID *b = new BroadcastID(id, bid);
assert(b);
b->expire = CURRENT_TIME + BCAST_ID_SAVE;
LIST_INSERT_HEAD(&bihead, b, link);
}
/* SRD */
bool
AODV::id_lookup(nsaddr_t id, u_int32_t bid) {
BroadcastID *b = bihead.lh_first;
// Search the list for a match of source and bid
for( ; b; b = b->link.le_next) {
if ((b->src == id) && (b->id == bid))
return true;
}
return false;
}
void
AODV::id_purge() {
BroadcastID *b = bihead.lh_first;
BroadcastID *bn;
double now = CURRENT_TIME;
for(; b; b = bn) {
bn = b->link.le_next;
if(b->expire <= now) {
LIST_REMOVE(b,link);
delete b;
}
}
}
/*
Helper Functions
*/
double
AODV::PerHopTime(aodv_rt_entry *rt) {
int num_non_zero = 0, i;
double total_latency = 0.0;
if (!rt)
return ((double) NODE_TRAVERSAL_TIME );
for (i=0; i < MAX_HISTORY; i++) {
if (rt->rt_disc_latency[i] > 0.0) {
num_non_zero++;
total_latency += rt->rt_disc_latency[i];
}
}
if (num_non_zero > 0)
return(total_latency / (double) num_non_zero);
else
return((double) NODE_TRAVERSAL_TIME);
}
/*
Link Failure Management Functions
*/
static void
aodv_rt_failed_callback(Packet *p, void *arg) {
((AODV*) arg)->rt_ll_failed(p);
}
/*
* This routine is invoked when the link-layer reports a route failed.
*/
/*邻居链路down掉,处理*/
void
AODV::rt_ll_failed(Packet *p) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
aodv_rt_entry *rt;
nsaddr_t broken_nbr = ch->next_hop_;//记录下一跳邻居的地址
#ifndef AODV_LINK_LAYER_DETECTION
drop(p, DROP_RTR_MAC_CALLBACK);
#else
/*
* Non-data packets and Broadcast Packets can be dropped.
*/
//如果是非数据或者广播报文,则可以直接丢弃
if(! DATA_PACKET(ch->ptype()) ||
(u_int32_t) ih->daddr() == IP_BROADCAST) {
drop(p, DROP_RTR_MAC_CALLBACK);
return;
}
log_link_broke(p);
//如果不存在到达目的节点的路径,丢弃报文
if((rt = rtable.rt_lookup(ih->daddr())) == 0) {
drop(p, DROP_RTR_MAC_CALLBACK);
return;
}
log_link_del(ch->next_hop_);
#ifdef AODV_LOCAL_REPAIR
/* if the broken link is closer to the dest than source,
attempt a local repair. Otherwise, bring down the route. */
//如果转发的跳数大于到达目的节点的跳数,则进行路由修复;否则丢弃通过此邻居的
//数据并且删除此邻居
if (ch->num_forwards() > rt->rt_hops) {
local_rt_repair(rt, p); // local repair
// retrieve all the packets in the ifq using this link,
// queue the packets for which local repair is done,
return;
}
else
#endif // LOCAL REPAIR
NS2下AODV协议aodv.cc注释
最新推荐文章于 2020-09-12 22:00:01 发布