Sei sulla pagina 1di 31

aodv.

cc
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 1997, 1998 Carnegie Mellon University. All Rights
00003 Reserved.
00004
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions
are met:
00007
00008 1. Redistributions of source code must retain the above copyright
notice,
00009 this list of conditions and the following disclaimer.
00010 2. Redistributions in binary form must reproduce the above
copyright notice,
00011 this list of conditions and the following disclaimer in the
documentation
00012 and/or other materials provided with the distribution.
00013 3. The name of the author may not be used to endorse or promote
products
00014 derived from this software without specific prior written
permission.
00015
00016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR
00017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES
00018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
00019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
00020 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO,
00021 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS;
00022 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY,
00023 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR
00024 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF
00025 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026
00027 The AODV code developed by the CMU/MONARCH group was optimized and
tuned by Samir Das and Mahesh Marina, University of Cincinnati. The work
was partially done in Sun Microsystems. Modified for gratuitous replies
by Anant Utgikar, 09/16/02.
00028
00029 */
00030

00031 //#include <ip.h>


00032
00033 #include <aodv/aodv.h>
00034 #include <aodv/aodv_packet.h>
00035 #include <random.h>
00036 #include <cmu-trace.h>
00037 //#include <energy-model.h>
00038
00039 #define max(a,b)
( (a) > (b) ? (a) : (b) )
00040 #define CURRENT_TIME
Scheduler::instance().clock()
00041
00042 //#define DEBUG
00043 //#define ERROR
00044
00045 #ifdef DEBUG
00046 static int extra_route_reply = 0;
00047 static int limit_route_request = 0;
00048 static int route_request = 0;
00049 #endif
00050
00051
00052 /*
00053
TCL Hooks
00054 */
00055
00056
00057 int hdr_aodv::offset_;
00058 static class AODVHeaderClass : public PacketHeaderClass {
00059 public:
00060
AODVHeaderClass() : PacketHeaderClass("PacketHeader/AODV",
00061
sizeof(hdr_all_aodv)) {
00062
bind_offset(&hdr_aodv::offset_);
00063
}
00064 } class_rtProtoAODV_hdr;
00065
00066 static class AODVclass : public TclClass {
00067 public:
00068
AODVclass() : TclClass("Agent/AODV") {}
00069
TclObject* create(int argc, const char*const* argv) {
00070
assert(argc == 5);
00071
//return (new AODV((nsaddr_t) atoi(argv[4])));
00072
return (new AODV((nsaddr_t)
Address::instance().str2addr(argv[4])));
00073
}
00074 } class_rtProtoAODV;
00075
00076

00077 int
00078 AODV::command(int argc, const char*const* argv) {
00079
if(argc == 2) {
00080
Tcl& tcl = Tcl::instance();
00081
00082
if(strncasecmp(argv[1], "id", 2) == 0) {
00083
tcl.resultf("%d", index);
00084
return TCL_OK;
00085
}
00086
00087
if(strncasecmp(argv[1], "start", 2) == 0) {
00088
btimer.handle((Event*) 0);
00089
00090 #ifndef AODV_LINK_LAYER_DETECTION
00091
htimer.handle((Event*) 0);
00092
ntimer.handle((Event*) 0);
00093 #endif // LINK LAYER DETECTION
00094
00095
rtimer.handle((Event*) 0);
00096
return TCL_OK;
00097
}
00098
}
00099
else if(argc == 3) {
00100
if(strcmp(argv[1], "index") == 0) {
00101
index = atoi(argv[2]);
00102
return TCL_OK;
00103
}
00104
00105
else if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1],
"tracetarget") == 0) {
00106
logtarget = (Trace*) TclObject::lookup(argv[2]);
00107
if(logtarget == 0)
00108
return TCL_ERROR;
00109
return TCL_OK;
00110
}
00111
else if(strcmp(argv[1], "drop-target") == 0) {
00112
int stat = rqueue.command(argc,argv);
00113
if (stat != TCL_OK) return stat;
00114
return Agent::command(argc, argv);
00115
}
00116
else if(strcmp(argv[1], "if-queue") == 0) {
00117
ifqueue = (PriQueue*) TclObject::lookup(argv[2]);
00118
00119
if(ifqueue == 0)
00120
return TCL_ERROR;
00121
return TCL_OK;
00122
}
00123
else if (strcmp(argv[1], "port-dmux") == 0) {

00124
dmux_ = (PortClassifier *)TclObject::lookup(argv[2]);
00125
if (dmux_ == 0) {
00126
fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__,
00127
argv[1], argv[2]);
00128
return TCL_ERROR;
00129
}
00130
return TCL_OK;
00131
}
00132
}
00133
return Agent::command(argc, argv);
00134 }
00135
00136 /*
00137
Constructor
00138 */
00139
00140 AODV::AODV(nsaddr_t id) : Agent(PT_AODV),
00141
btimer(this), htimer(this), ntimer(this),
00142
rtimer(this), lrtimer(this), rqueue() {
00143
00144
00145
index = id;
00146
seqno = 2;
00147
bid = 1;
00148
00149
LIST_INIT(&nbhead);
00150
LIST_INIT(&bihead);
00151
00152
logtarget = 0;
00153
ifqueue = 0;
00154 }
00155
00156 /*
00157
Timers
00158 */
00159
00160 void
00161 BroadcastTimer::handle(Event*) {
00162
agent->id_purge();
00163
Scheduler::instance().schedule(this, &intr, BCAST_ID_SAVE);
00164 }
00165
00166 void
00167 HelloTimer::handle(Event*) {
00168
agent->sendHello();
00169
double interval = MinHelloInterval +
00170
((MaxHelloInterval - MinHelloInterval) *
Random::uniform());

00171
assert(interval >= 0);
00172
Scheduler::instance().schedule(this, &intr, interval);
00173 }
00174
00175 void
00176 NeighborTimer::handle(Event*) {
00177
agent->nb_purge();
00178
Scheduler::instance().schedule(this, &intr, HELLO_INTERVAL);
00179 }
00180
00181 void
00182 RouteCacheTimer::handle(Event*) {
00183
agent->rt_purge();
00184 #define FREQUENCY 0.5 // sec
00185
Scheduler::instance().schedule(this, &intr, FREQUENCY);
00186 }
00187
00188 void
00189 LocalRepairTimer::handle(Event* p) { // SRD: 5/4/99
00190 aodv_rt_entry *rt;
00191 struct hdr_ip *ih = HDR_IP( (Packet *)p);
00192
00193
/* you get here after the timeout in a local repair attempt */
00194
/*
fprintf(stderr, "%s\n", __FUNCTION__); */
00195
00196
00197
rt = agent->rtable.rt_lookup(ih->daddr());
00198
00199
if (rt && rt->rt_flags != RTF_UP) {
00200
// route is yet to be repaired
00201
// I will be conservative and bring down the route
00202
// and send route errors upstream.
00203
/* The following assert fails, not sure why */
00204
/* assert (rt->rt_flags == RTF_IN_REPAIR); */
00205
00206
//rt->rt_seqno++;
00207
agent->rt_down(rt);
00208
// send RERR
00209 #ifdef DEBUG
00210
fprintf(stderr,"Node %d: Dst - %d, failed local
repair\n",index, rt->rt_dst);
00211 #endif
00212
}
00213
Packet::free((Packet *)p);
00214 }
00215
00216
00217 /*

00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265

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;

00266 double total_latency = 0.0;


00267
00268 if (!rt)
00269
return ((double) NODE_TRAVERSAL_TIME );
00270
00271 for (i=0; i < MAX_HISTORY; i++) {
00272
if (rt->rt_disc_latency[i] > 0.0) {
00273
num_non_zero++;
00274
total_latency += rt->rt_disc_latency[i];
00275
}
00276 }
00277 if (num_non_zero > 0)
00278
return(total_latency / (double) num_non_zero);
00279 else
00280
return((double) NODE_TRAVERSAL_TIME);
00281
00282 }
00283
00284 /*
00285
Link Failure Management Functions
00286 */
00287
00288 static void
00289 aodv_rt_failed_callback(Packet *p, void *arg) {
00290
((AODV*) arg)->rt_ll_failed(p);
00291 }
00292
00293 /*
00294 * This routine is invoked when the link-layer reports a route
failed.
00295 */
00296 void
00297 AODV::rt_ll_failed(Packet *p) {
00298 struct hdr_cmn *ch = HDR_CMN(p);
00299 struct hdr_ip *ih = HDR_IP(p);
00300 aodv_rt_entry *rt;
00301 nsaddr_t broken_nbr = ch->next_hop_;
00302
00303 #ifndef AODV_LINK_LAYER_DETECTION
00304 drop(p, DROP_RTR_MAC_CALLBACK);
00305 #else
00306
00307 /*
00308
* Non-data packets and Broadcast Packets can be dropped.
00309
*/
00310
if(! DATA_PACKET(ch->ptype()) ||
00311
(u_int32_t) ih->daddr() == IP_BROADCAST) {
00312
drop(p, DROP_RTR_MAC_CALLBACK);

00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
using
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359

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
{
drop(p, DROP_RTR_MAC_CALLBACK);
// Do the same thing for other packets in the interface queue
the
// broken link -Mahesh
while((p = ifqueue->filter(broken_nbr))) {
drop(p, DROP_RTR_MAC_CALLBACK);
}
nb_delete(broken_nbr);
}
#endif // LINK LAYER DETECTION
}
void
AODV::handle_link_failure(nsaddr_t id) {
aodv_rt_entry *rt, *rtn;
Packet *rerr = Packet::alloc();
struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr);
re->DestCount = 0;
for(rt = rtable.head(); rt; rt = rtn) { // for each rt entry
rtn = rt->rt_link.le_next;
if ((rt->rt_hops != INFINITY2) && (rt->rt_nexthop == id) ) {
assert (rt->rt_flags == RTF_UP);

00360
assert((rt->rt_seqno%2) == 0);
00361
rt->rt_seqno++;
00362
re->unreachable_dst[re->DestCount] = rt->rt_dst;
00363
re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno;
00364 #ifdef DEBUG
00365
fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\n", __FUNCTION__,
CURRENT_TIME,
00366
index, re->unreachable_dst[re->DestCount],
00367
re->unreachable_dst_seqno[re->DestCount], rt>rt_nexthop);
00368 #endif // DEBUG
00369
re->DestCount += 1;
00370
rt_down(rt);
00371
}
00372
// remove the lost neighbor from all the precursor lists
00373
rt->pc_delete(id);
00374 }
00375
00376 if (re->DestCount > 0) {
00377 #ifdef DEBUG
00378
fprintf(stderr, "%s(%f): %d\tsending RERR...\n", __FUNCTION__,
CURRENT_TIME, index);
00379 #endif // DEBUG
00380
sendError(rerr, false);
00381 }
00382 else {
00383
Packet::free(rerr);
00384 }
00385 }
00386
00387 void
00388 AODV::local_rt_repair(aodv_rt_entry *rt, Packet *p) {
00389 #ifdef DEBUG
00390
fprintf(stderr,"%s: Dst - %d\n", __FUNCTION__, rt->rt_dst);
00391 #endif
00392
// Buffer the packet
00393
rqueue.enque(p);
00394
00395
// mark the route as under repair
00396
rt->rt_flags = RTF_IN_REPAIR;
00397
00398
sendRequest(rt->rt_dst);
00399
00400
// set up a timer interrupt
00401
Scheduler::instance().schedule(&lrtimer, p->copy(), rt>rt_req_timeout);
00402 }
00403
00404 void

00405 AODV::rt_update(aodv_rt_entry *rt, u_int32_t seqnum, u_int16_t


metric,
00406
nsaddr_t nexthop, double expire_time) {
00407
00408
rt->rt_seqno = seqnum;
00409
rt->rt_hops = metric;
00410
rt->rt_flags = RTF_UP;
00411
rt->rt_nexthop = nexthop;
00412
rt->rt_expire = expire_time;
00413 }
00414
00415 void
00416 AODV::rt_down(aodv_rt_entry *rt) {
00417
/*
00418
* Make sure that you don't "down" a route more than once.
00419
*/
00420
00421
if(rt->rt_flags == RTF_DOWN) {
00422
return;
00423
}
00424
00425
// assert (rt->rt_seqno%2); // is the seqno odd?
00426
rt->rt_last_hop_count = rt->rt_hops;
00427
rt->rt_hops = INFINITY2;
00428
rt->rt_flags = RTF_DOWN;
00429
rt->rt_nexthop = 0;
00430
rt->rt_expire = 0;
00431
00432 } /* rt_down function */
00433
00434 /*
00435
Route Handling Functions
00436 */
00437
00438 void
00439 AODV::rt_resolve(Packet *p) {
00440 struct hdr_cmn *ch = HDR_CMN(p);
00441 struct hdr_ip *ih = HDR_IP(p);
00442 aodv_rt_entry *rt;
00443
00444 /*
00445
* Set the transmit failure callback. That
00446
* won't change.
00447
*/
00448 ch->xmit_failure_ = aodv_rt_failed_callback;
00449 ch->xmit_failure_data_ = (void*) this;
00450
rt = rtable.rt_lookup(ih->daddr());
00451 if(rt == 0) {

00452
rt = rtable.rt_add(ih->daddr());
00453 }
00454
00455 /*
00456
* If the route is up, forward the packet
00457
*/
00458
00459 if(rt->rt_flags == RTF_UP) {
00460
assert(rt->rt_hops != INFINITY2);
00461
forward(rt, p, NO_DELAY);
00462 }
00463 /*
00464
* if I am the source of the packet, then do a Route Request.
00465
*/
00466
else if(ih->saddr() == index) {
00467
rqueue.enque(p);
00468
sendRequest(rt->rt_dst);
00469 }
00470 /*
00471
* A local repair is in progress. Buffer the packet.
00472
*/
00473 else if (rt->rt_flags == RTF_IN_REPAIR) {
00474
rqueue.enque(p);
00475 }
00476
00477 /*
00478
* I am trying to forward a packet for someone else to which
00479
* I don't have a route.
00480
*/
00481 else {
00482 Packet *rerr = Packet::alloc();
00483 struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr);
00484 /*
00485
* For now, drop the packet and send error upstream.
00486
* Now the route errors are broadcast to upstream
00487
* neighbors - Mahesh 09/11/99
00488
*/
00489
00490
assert (rt->rt_flags == RTF_DOWN);
00491
re->DestCount = 0;
00492
re->unreachable_dst[re->DestCount] = rt->rt_dst;
00493
re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno;
00494
re->DestCount += 1;
00495 #ifdef DEBUG
00496
fprintf(stderr, "%s: sending RERR...\n", __FUNCTION__);
00497 #endif
00498
sendError(rerr, false);
00499

00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547

drop(p, DROP_RTR_NO_ROUTE);
}
}
void
AODV::rt_purge() {
aodv_rt_entry *rt, *rtn;
double now = CURRENT_TIME;
double delay = 0.0;
Packet *p;
for(rt = rtable.head(); rt; rt = rtn) { // for each rt entry
rtn = rt->rt_link.le_next;
if ((rt->rt_flags == RTF_UP) && (rt->rt_expire < now)) {
// if a valid route has expired, purge all packets from
// send buffer and invalidate the route.
assert(rt->rt_hops != INFINITY2);
while((p = rqueue.deque(rt->rt_dst))) {
#ifdef DEBUG
fprintf(stderr, "%s: calling drop()\n",
__FUNCTION__);
#endif // DEBUG
drop(p, DROP_RTR_NO_ROUTE);
}
rt->rt_seqno++;
assert (rt->rt_seqno%2);
rt_down(rt);
}
else if (rt->rt_flags == RTF_UP) {
// If the route is not expired,
// and there are packets in the sendbuffer waiting,
// forward them. This should not be needed, but this extra
// check does no harm.
assert(rt->rt_hops != INFINITY2);
while((p = rqueue.deque(rt->rt_dst))) {
forward (rt, p, delay);
delay += ARP_DELAY;
}
}
else if (rqueue.find(rt->rt_dst))
// If the route is down and
// if there is a packet for this destination waiting in
// the sendbuffer, then send out route request. sendRequest
// will check whether it is time to really send out request
// or not.
// This may not be crucial to do it here, as each generated
// packet will do a sendRequest anyway.

00548
00549
sendRequest(rt->rt_dst);
00550
}
00551
00552 }
00553
00554 /*
00555
Packet Reception Routines
00556 */
00557
00558 void
00559 AODV::recv(Packet *p, Handler*) {
00560 struct hdr_cmn *ch = HDR_CMN(p);
00561 struct hdr_ip *ih = HDR_IP(p);
00562
00563 assert(initialized());
00564 //assert(p->incoming == 0);
00565 // XXXXX NOTE: use of incoming flag has been depracated; In order
to track direction of pkt flow, direction_ in hdr_cmn is used instead.
see packet.h for details.
00566
00567 if(ch->ptype() == PT_AODV) {
00568
ih->ttl_ -= 1;
00569
recvAODV(p);
00570
return;
00571 }
00572
00573
00574 /*
00575
* Must be a packet I'm originating...
00576
*/
00577 if((ih->saddr() == index) && (ch->num_forwards() == 0)) {
00578 /*
00579
* Add the IP Header
00580
*/
00581
ch->size() += IP_HDR_LEN;
00582
// Added by Parag Dadhania && John Novatnack to handle
broadcasting
00583
if ( (u_int32_t)ih->daddr() != IP_BROADCAST)
00584
ih->ttl_ = NETWORK_DIAMETER;
00585 }
00586 /*
00587
* I received a packet that I sent. Probably
00588
* a routing loop.
00589
*/
00590 else if(ih->saddr() == index) {
00591
drop(p, DROP_RTR_ROUTE_LOOP);
00592
return;

00593 }
00594 /*
00595
* Packet I'm forwarding...
00596
*/
00597 else {
00598 /*
00599
* Check the TTL. If it is zero, then discard.
00600
*/
00601
if(--ih->ttl_ == 0) {
00602
drop(p, DROP_RTR_TTL);
00603
return;
00604
}
00605 }
00606 // Added by Parag Dadhania && John Novatnack to handle
broadcasting
00607 if ( (u_int32_t)ih->daddr() != IP_BROADCAST)
00608
rt_resolve(p);
00609 else
00610
forward((aodv_rt_entry*) 0, p, NO_DELAY);
00611 }
00612
00613
00614 void
00615 AODV::recvAODV(Packet *p) {
00616 struct hdr_aodv *ah = HDR_AODV(p);
00617
00618 assert(HDR_IP (p)->sport() == RT_PORT);
00619 assert(HDR_IP (p)->dport() == RT_PORT);
00620
00621 /*
00622
* Incoming Packets.
00623
*/
00624 switch(ah->ah_type) {
00625
00626 case AODVTYPE_RREQ:
00627
recvRequest(p);
00628
break;
00629
00630 case AODVTYPE_RREP:
00631
recvReply(p);
00632
break;
00633
00634 case AODVTYPE_RERR:
00635
recvError(p);
00636
break;
00637
00638 case AODVTYPE_HELLO:
00639
recvHello(p);

00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687

break;
default:
fprintf(stderr, "Invalid AODV type (%x)\n", ah->ah_type);
exit(1);
}
}

void
AODV::recvRequest(Packet *p) {
struct hdr_ip *ih = HDR_IP(p);
struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p);
aodv_rt_entry *rt;
/*
* Drop if:
*
- I'm the source
*
- I recently heard this request.
*/
if(rq->rq_src == index) {
#ifdef DEBUG
fprintf(stderr, "%s: got my own REQUEST\n", __FUNCTION__);
#endif // DEBUG
Packet::free(p);
return;
}
if (id_lookup(rq->rq_src, rq->rq_bcast_id)) {
#ifdef DEBUG
fprintf(stderr, "%s: discarding request\n", __FUNCTION__);
#endif // DEBUG
Packet::free(p);
return;
}
/*
* Cache the broadcast ID
*/
id_insert(rq->rq_src, rq->rq_bcast_id);

/*

00688
* We are either going to forward the REQUEST or generate a
00689
* REPLY. Before we do anything, we make sure that the REVERSE
00690
* route is in the route table.
00691
*/
00692 aodv_rt_entry *rt0; // rt0 is the reverse route
00693
00694
rt0 = rtable.rt_lookup(rq->rq_src);
00695
if(rt0 == 0) { /* if not in the route table */
00696
// create an entry for the reverse route.
00697
rt0 = rtable.rt_add(rq->rq_src);
00698
}
00699
00700
rt0->rt_expire = max(rt0->rt_expire, (CURRENT_TIME +
REV_ROUTE_LIFE));
00701
00702
if ( (rq->rq_src_seqno > rt0->rt_seqno ) ||
00703
((rq->rq_src_seqno == rt0->rt_seqno) &&
00704
(rq->rq_hop_count < rt0->rt_hops)) ) {
00705
// If we have a fresher seq no. or lesser #hops for the
00706
// same seq no., update the rt entry. Else don't bother.
00707 rt_update(rt0, rq->rq_src_seqno, rq->rq_hop_count, ih->saddr(),
00708
max(rt0->rt_expire, (CURRENT_TIME +
REV_ROUTE_LIFE)) );
00709
if (rt0->rt_req_timeout > 0.0) {
00710
// Reset the soft state and
00711
// Set expiry time to CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT
00712
// This is because route is used in the forward direction,
00713
// but only sources get benefited by this change
00714
rt0->rt_req_cnt = 0;
00715
rt0->rt_req_timeout = 0.0;
00716
rt0->rt_req_last_ttl = rq->rq_hop_count;
00717
rt0->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
00718
}
00719
00720
/* Find out whether any buffered packet can benefit from the
00721
* reverse route.
00722
* May need some change in the following code - Mahesh
09/11/99
00723
*/
00724
assert (rt0->rt_flags == RTF_UP);
00725
Packet *buffered_pkt;
00726
while ((buffered_pkt = rqueue.deque(rt0->rt_dst))) {
00727
if (rt0 && (rt0->rt_flags == RTF_UP)) {
00728
assert(rt0->rt_hops != INFINITY2);
00729
forward(rt0, buffered_pkt, NO_DELAY);
00730
}
00731
}
00732
}

00733
// End for putting reverse route in rt table
00734
00735
00736 /*
00737
* We have taken care of the reverse route stuff.
00738
* Now see whether we can send a route reply.
00739
*/
00740
00741 rt = rtable.rt_lookup(rq->rq_dst);
00742
00743 // First check if I am the destination ..
00744
00745 if(rq->rq_dst == index) {
00746
00747 #ifdef DEBUG
00748
fprintf(stderr, "%d - %s: destination sending reply\n",
00749
index, __FUNCTION__);
00750 #endif // DEBUG
00751
00752
00753
// Just to be safe, I use the max. Somebody may have
00754
// incremented the dst seqno.
00755
seqno = max(seqno, rq->rq_dst_seqno)+1;
00756
if (seqno%2) seqno++;
00757
00758
sendReply(rq->rq_src,
// IP Destination
00759
1,
// Hop Count
00760
index,
// Dest IP Address
00761
seqno,
// Dest Sequence Num
00762
MY_ROUTE_TIMEOUT,
// Lifetime
00763
rq->rq_timestamp);
// timestamp
00764
00765
Packet::free(p);
00766 }
00767
00768 // I am not the destination, but I may have a fresh enough route.
00769
00770 else if (rt && (rt->rt_hops != INFINITY2) &&
00771
(rt->rt_seqno >= rq->rq_dst_seqno) ) {
00772
00773
//assert (rt->rt_flags == RTF_UP);
00774
assert(rq->rq_dst == rt->rt_dst);
00775
//assert ((rt->rt_seqno%2) == 0);
// is the seqno even?
00776
sendReply(rq->rq_src,
00777
rt->rt_hops + 1,
00778
rq->rq_dst,
00779
rt->rt_seqno,
00780
(u_int32_t) (rt->rt_expire - CURRENT_TIME),

00781
//
rt->rt_expire - CURRENT_TIME,
00782
rq->rq_timestamp);
00783
// Insert nexthops to RREQ source and RREQ destination in the
00784
// precursor lists of destination and source respectively
00785
rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source
00786
rt0->pc_insert(rt->rt_nexthop); // nexthop to RREQ destination
00787
00788 #ifdef RREQ_GRAT_RREP
00789
00790
sendReply(rq->rq_dst,
00791
rq->rq_hop_count,
00792
rq->rq_src,
00793
rq->rq_src_seqno,
00794
(u_int32_t) (rt->rt_expire - CURRENT_TIME),
00795
//
rt->rt_expire - CURRENT_TIME,
00796
rq->rq_timestamp);
00797 #endif
00798
00799 // TODO: send grat RREP to dst if G flag set in RREQ using rq>rq_src_seqno, rq->rq_hop_counT
00800
00801 // DONE: Included gratuitous replies to be sent as per IETF aodv
draft specification. As of now, G flag has not been dynamically used and
is always set or reset in aodv-packet.h --- Anant Utgikar, 09/16/02.
00802
00803
Packet::free(p);
00804 }
00805 /*
00806
* Can't reply. So forward the Route Request
00807
*/
00808 else {
00809
ih->saddr() = index;
00810
ih->daddr() = IP_BROADCAST;
00811
rq->rq_hop_count += 1;
00812
// Maximum sequence number seen en route
00813
if (rt) rq->rq_dst_seqno = max(rt->rt_seqno, rq->rq_dst_seqno);
00814
forward((aodv_rt_entry*) 0, p, DELAY);
00815 }
00816
00817 }
00818
00819
00820 void
00821 AODV::recvReply(Packet *p) {
00822 //struct hdr_cmn *ch = HDR_CMN(p);
00823 struct hdr_ip *ih = HDR_IP(p);
00824 struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);
00825 aodv_rt_entry *rt;

00826 char suppress_reply = 0;


00827 double delay = 0.0;
00828
00829 #ifdef DEBUG
00830 fprintf(stderr, "%d - %s: received a REPLY\n", index,
__FUNCTION__);
00831 #endif // DEBUG
00832
00833
00834 /*
00835
* Got a reply. So reset the "soft state" maintained for
00836
* route requests in the request table. We don't really have
00837
* have a separate request table. It is just a part of the
00838
* routing table itself.
00839
*/
00840 // Note that rp_dst is the dest of the data packets, not the
00841 // the dest of the reply, which is the src of the data packets.
00842
00843 rt = rtable.rt_lookup(rp->rp_dst);
00844
00845 /*
00846
* If I don't have a rt entry to this host... adding
00847
*/
00848 if(rt == 0) {
00849
rt = rtable.rt_add(rp->rp_dst);
00850 }
00851
00852 /*
00853
* Add a forward route table entry... here I am following
00854
* Perkins-Royer AODV paper almost literally - SRD 5/99
00855
*/
00856
00857 if ( (rt->rt_seqno < rp->rp_dst_seqno) ||
// newer route
00858
((rt->rt_seqno == rp->rp_dst_seqno) &&
00859
(rt->rt_hops > rp->rp_hop_count)) ) { // shorter or better
route
00860
00861
// Update the rt entry
00862
rt_update(rt, rp->rp_dst_seqno, rp->rp_hop_count,
00863
rp->rp_src, CURRENT_TIME + rp->rp_lifetime);
00864
00865
// reset the soft state
00866
rt->rt_req_cnt = 0;
00867
rt->rt_req_timeout = 0.0;
00868
rt->rt_req_last_ttl = rp->rp_hop_count;
00869
00870 if (ih->daddr() == index) { // If I am the original source
00871
// Update the route discovery latency statistics

00872
// rp->rp_timestamp is the time of request origination
00873
00874
rt->rt_disc_latency[(unsigned char)rt->hist_indx] =
(CURRENT_TIME - rp->rp_timestamp)
00875
/ (double) rp>rp_hop_count;
00876
// increment indx for next time
00877
rt->hist_indx = (rt->hist_indx + 1) % MAX_HISTORY;
00878
}
00879
00880
/*
00881
* Send all packets queued in the sendbuffer destined for
00882
* this destination.
00883
* XXX - observe the "second" use of p.
00884
*/
00885
Packet *buf_pkt;
00886
while((buf_pkt = rqueue.deque(rt->rt_dst))) {
00887
if(rt->rt_hops != INFINITY2) {
00888
assert (rt->rt_flags == RTF_UP);
00889
// Delay them a little to help ARP. Otherwise ARP
00890
// may drop packets. -SRD 5/23/99
00891
forward(rt, buf_pkt, delay);
00892
delay += ARP_DELAY;
00893
}
00894
}
00895 }
00896 else {
00897
suppress_reply = 1;
00898 }
00899
00900 /*
00901
* If reply is for me, discard it.
00902
*/
00903
00904 if(ih->daddr() == index || suppress_reply) {
00905
Packet::free(p);
00906 }
00907 /*
00908
* Otherwise, forward the Route Reply.
00909
*/
00910 else {
00911 // Find the rt entry
00912 aodv_rt_entry *rt0 = rtable.rt_lookup(ih->daddr());
00913
// If the rt is up, forward
00914
if(rt0 && (rt0->rt_hops != INFINITY2)) {
00915
assert (rt0->rt_flags == RTF_UP);
00916
rp->rp_hop_count += 1;
00917
rp->rp_src = index;

00918
forward(rt0, p, NO_DELAY);
00919
// Insert the nexthop towards the RREQ source to
00920
// the precursor list of the RREQ destination
00921
rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source
00922
00923
}
00924
else {
00925
// I don't know how to forward .. drop the reply.
00926 #ifdef DEBUG
00927
fprintf(stderr, "%s: dropping Route Reply\n", __FUNCTION__);
00928 #endif // DEBUG
00929
drop(p, DROP_RTR_NO_ROUTE);
00930
}
00931 }
00932 }
00933
00934
00935 void
00936 AODV::recvError(Packet *p) {
00937 struct hdr_ip *ih = HDR_IP(p);
00938 struct hdr_aodv_error *re = HDR_AODV_ERROR(p);
00939 aodv_rt_entry *rt;
00940 u_int8_t i;
00941 Packet *rerr = Packet::alloc();
00942 struct hdr_aodv_error *nre = HDR_AODV_ERROR(rerr);
00943
00944 nre->DestCount = 0;
00945
00946 for (i=0; i<re->DestCount; i++) {
00947 // For each unreachable destination
00948
rt = rtable.rt_lookup(re->unreachable_dst[i]);
00949
if ( rt && (rt->rt_hops != INFINITY2) &&
00950
(rt->rt_nexthop == ih->saddr()) &&
00951
(rt->rt_seqno <= re->unreachable_dst_seqno[i]) ) {
00952
assert(rt->rt_flags == RTF_UP);
00953
assert((rt->rt_seqno%2) == 0); // is the seqno even?
00954 #ifdef DEBUG
00955
fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\t(%d\t%u\t%d)\n",
__FUNCTION__,CURRENT_TIME,
00956
index, rt->rt_dst, rt->rt_seqno, rt->rt_nexthop,
00957
re->unreachable_dst[i],re->unreachable_dst_seqno[i],
00958
ih->saddr());
00959 #endif // DEBUG
00960
rt->rt_seqno = re->unreachable_dst_seqno[i];
00961
rt_down(rt);
00962
00963
// Not sure whether this is the right thing to do
00964
Packet *pkt;

00965
while((pkt = ifqueue->filter(ih->saddr()))) {
00966
drop(pkt, DROP_RTR_MAC_CALLBACK);
00967
}
00968
00969
// if precursor list non-empty add to RERR and delete the
precursor list
00970
if (!rt->pc_empty()) {
00971
nre->unreachable_dst[nre->DestCount] = rt->rt_dst;
00972
nre->unreachable_dst_seqno[nre->DestCount] = rt>rt_seqno;
00973
nre->DestCount += 1;
00974
rt->pc_delete();
00975
}
00976
}
00977 }
00978
00979 if (nre->DestCount > 0) {
00980 #ifdef DEBUG
00981
fprintf(stderr, "%s(%f): %d\t sending RERR...\n", __FUNCTION__,
CURRENT_TIME, index);
00982 #endif // DEBUG
00983
sendError(rerr);
00984 }
00985 else {
00986
Packet::free(rerr);
00987 }
00988
00989 Packet::free(p);
00990 }
00991
00992
00993 /*
00994
Packet Transmission Routines
00995 */
00996
00997 void
00998 AODV::forward(aodv_rt_entry *rt, Packet *p, double delay) {
00999 struct hdr_cmn *ch = HDR_CMN(p);
01000 struct hdr_ip *ih = HDR_IP(p);
01001
01002 if(ih->ttl_ == 0) {
01003
01004 #ifdef DEBUG
01005
fprintf(stderr, "%s: calling drop()\n", __PRETTY_FUNCTION__);
01006 #endif // DEBUG
01007
01008
drop(p, DROP_RTR_TTL);
01009
return;

01010 }
01011
01012 if (ch->ptype() != PT_AODV && ch->direction() == hdr_cmn::UP &&
01013
((u_int32_t)ih->daddr() == IP_BROADCAST)
01014
|| (ih->daddr() == here_.addr_)) {
01015
dmux_->recv(p,0);
01016
return;
01017 }
01018
01019 if (rt) {
01020
assert(rt->rt_flags == RTF_UP);
01021
rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
01022
ch->next_hop_ = rt->rt_nexthop;
01023
ch->addr_type() = NS_AF_INET;
01024
ch->direction() = hdr_cmn::DOWN;
//important: change the
packet's direction
01025 }
01026 else { // if it is a broadcast packet
01027
// assert(ch->ptype() == PT_AODV); // maybe a diff pkt type
like gaf
01028
assert(ih->daddr() == (nsaddr_t) IP_BROADCAST);
01029
ch->addr_type() = NS_AF_NONE;
01030
ch->direction() = hdr_cmn::DOWN;
//important: change the
packet's direction
01031 }
01032
01033 if (ih->daddr() == (nsaddr_t) IP_BROADCAST) {
01034 // If it is a broadcast packet
01035
assert(rt == 0);
01036
/*
01037
* Jitter the sending of broadcast packets by 10ms
01038
*/
01039
Scheduler::instance().schedule(target_, p,
01040
0.01 * Random::uniform());
01041 }
01042 else { // Not a broadcast packet
01043
if(delay > 0.0) {
01044
Scheduler::instance().schedule(target_, p, delay);
01045
}
01046
else {
01047
// Not a broadcast packet, no delay, send immediately
01048
Scheduler::instance().schedule(target_, p, 0.);
01049
}
01050 }
01051
01052 }
01053
01054

01055 void
01056 AODV::sendRequest(nsaddr_t dst) {
01057 // Allocate a RREQ packet
01058 Packet *p = Packet::alloc();
01059 struct hdr_cmn *ch = HDR_CMN(p);
01060 struct hdr_ip *ih = HDR_IP(p);
01061 struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p);
01062 aodv_rt_entry *rt = rtable.rt_lookup(dst);
01063
01064 assert(rt);
01065
01066 /*
01067
* Rate limit sending of Route Requests. We are very
conservative
01068
* about sending out route requests.
01069
*/
01070
01071 if (rt->rt_flags == RTF_UP) {
01072
assert(rt->rt_hops != INFINITY2);
01073
Packet::free((Packet *)p);
01074
return;
01075 }
01076
01077 if (rt->rt_req_timeout > CURRENT_TIME) {
01078
Packet::free((Packet *)p);
01079
return;
01080 }
01081
01082 // rt_req_cnt is the no. of times we did network-wide broadcast
01083 // RREQ_RETRIES is the maximum number we will allow before
01084 // going to a long timeout.
01085
01086 if (rt->rt_req_cnt > RREQ_RETRIES) {
01087
rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
01088
rt->rt_req_cnt = 0;
01089 Packet *buf_pkt;
01090
while ((buf_pkt = rqueue.deque(rt->rt_dst))) {
01091
drop(buf_pkt, DROP_RTR_NO_ROUTE);
01092
}
01093
Packet::free((Packet *)p);
01094
return;
01095 }
01096
01097 #ifdef DEBUG
01098
fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d\n",
01099
++route_request, index, rt->rt_dst);
01100 #endif // DEBUG
01101

01102 // Determine the TTL to be used this time.


01103 // Dynamic TTL evaluation - SRD
01104
01105 rt->rt_req_last_ttl = max(rt->rt_req_last_ttl,rt>rt_last_hop_count);
01106
01107 if (0 == rt->rt_req_last_ttl) {
01108 // first time query broadcast
01109
ih->ttl_ = TTL_START;
01110 }
01111 else {
01112 // Expanding ring search.
01113
if (rt->rt_req_last_ttl < TTL_THRESHOLD)
01114
ih->ttl_ = rt->rt_req_last_ttl + TTL_INCREMENT;
01115
else {
01116
// network-wide broadcast
01117
ih->ttl_ = NETWORK_DIAMETER;
01118
rt->rt_req_cnt += 1;
01119
}
01120 }
01121
01122 // remember the TTL used for the next time
01123 rt->rt_req_last_ttl = ih->ttl_;
01124
01125 // PerHopTime is the roundtrip time per hop for route requests.
01126 // The factor 2.0 is just to be safe .. SRD 5/22/99
01127 // Also note that we are making timeouts to be larger if we have
01128 // done network wide broadcast before.
01129
01130 rt->rt_req_timeout = 2.0 * (double) ih->ttl_ * PerHopTime(rt);
01131 if (rt->rt_req_cnt > 0)
01132
rt->rt_req_timeout *= rt->rt_req_cnt;
01133 rt->rt_req_timeout += CURRENT_TIME;
01134
01135 // Don't let the timeout to be too large, however .. SRD 6/8/99
01136 if (rt->rt_req_timeout > CURRENT_TIME + MAX_RREQ_TIMEOUT)
01137
rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
01138 rt->rt_expire = 0;
01139
01140 #ifdef DEBUG
01141 fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d, tout
%f ms\n",
01142
++route_request,
01143
index, rt->rt_dst,
01144
rt->rt_req_timeout - CURRENT_TIME);
01145 #endif // DEBUG
01146
01147

01148 // Fill out the RREQ packet


01149 // ch->uid() = 0;
01150 ch->ptype() = PT_AODV;
01151 ch->size() = IP_HDR_LEN + rq->size();
01152 ch->iface() = -2;
01153 ch->error() = 0;
01154 ch->addr_type() = NS_AF_NONE;
01155 ch->prev_hop_ = index;
// AODV hack
01156
01157 ih->saddr() = index;
01158 ih->daddr() = IP_BROADCAST;
01159 ih->sport() = RT_PORT;
01160 ih->dport() = RT_PORT;
01161
01162 // Fill up some more fields.
01163 rq->rq_type = AODVTYPE_RREQ;
01164 rq->rq_hop_count = 1;
01165 rq->rq_bcast_id = bid++;
01166 rq->rq_dst = dst;
01167 rq->rq_dst_seqno = (rt ? rt->rt_seqno : 0);
01168 rq->rq_src = index;
01169 seqno += 2;
01170 assert ((seqno%2) == 0);
01171 rq->rq_src_seqno = seqno;
01172 rq->rq_timestamp = CURRENT_TIME;
01173
01174 Scheduler::instance().schedule(target_, p, 0.);
01175
01176 }
01177
01178 void
01179 AODV::sendReply(nsaddr_t ipdst, u_int32_t hop_count, nsaddr_t
rpdst,
01180
u_int32_t rpseq, u_int32_t lifetime, double
timestamp) {
01181 Packet *p = Packet::alloc();
01182 struct hdr_cmn *ch = HDR_CMN(p);
01183 struct hdr_ip *ih = HDR_IP(p);
01184 struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);
01185 aodv_rt_entry *rt = rtable.rt_lookup(ipdst);
01186
01187 #ifdef DEBUG
01188 fprintf(stderr, "sending Reply from %d at %.2f\n", index,
Scheduler::instance().clock());
01189 #endif // DEBUG
01190 assert(rt);
01191
01192 rp->rp_type = AODVTYPE_RREP;

01193 //rp->rp_flags = 0x00;


01194 rp->rp_hop_count = hop_count;
01195 rp->rp_dst = rpdst;
01196 rp->rp_dst_seqno = rpseq;
01197 rp->rp_src = index;
01198 rp->rp_lifetime = lifetime;
01199 rp->rp_timestamp = timestamp;
01200
01201 // ch->uid() = 0;
01202 ch->ptype() = PT_AODV;
01203 ch->size() = IP_HDR_LEN + rp->size();
01204 ch->iface() = -2;
01205 ch->error() = 0;
01206 ch->addr_type() = NS_AF_INET;
01207 ch->next_hop_ = rt->rt_nexthop;
01208 ch->prev_hop_ = index;
// AODV hack
01209 ch->direction() = hdr_cmn::DOWN;
01210
01211 ih->saddr() = index;
01212 ih->daddr() = ipdst;
01213 ih->sport() = RT_PORT;
01214 ih->dport() = RT_PORT;
01215 ih->ttl_ = NETWORK_DIAMETER;
01216
01217 Scheduler::instance().schedule(target_, p, 0.);
01218
01219 }
01220
01221 void
01222 AODV::sendError(Packet *p, bool jitter) {
01223 struct hdr_cmn *ch = HDR_CMN(p);
01224 struct hdr_ip *ih = HDR_IP(p);
01225 struct hdr_aodv_error *re = HDR_AODV_ERROR(p);
01226
01227 #ifdef ERROR
01228 fprintf(stderr, "sending Error from %d at %.2f\n", index,
Scheduler::instance().clock());
01229 #endif // DEBUG
01230
01231 re->re_type = AODVTYPE_RERR;
01232 //re->reserved[0] = 0x00; re->reserved[1] = 0x00;
01233 // DestCount and list of unreachable destinations are already
filled
01234
01235 // ch->uid() = 0;
01236 ch->ptype() = PT_AODV;
01237 ch->size() = IP_HDR_LEN + re->size();
01238 ch->iface() = -2;

01239 ch->error() = 0;
01240 ch->addr_type() = NS_AF_NONE;
01241 ch->next_hop_ = 0;
01242 ch->prev_hop_ = index;
// AODV hack
01243 ch->direction() = hdr_cmn::DOWN;
//important: change the
packet's direction
01244
01245 ih->saddr() = index;
01246 ih->daddr() = IP_BROADCAST;
01247 ih->sport() = RT_PORT;
01248 ih->dport() = RT_PORT;
01249 ih->ttl_ = 1;
01250
01251 // Do we need any jitter? Yes
01252 if (jitter)
01253
Scheduler::instance().schedule(target_, p,
0.01*Random::uniform());
01254 else
01255
Scheduler::instance().schedule(target_, p, 0.0);
01256
01257 }
01258
01259
01260 /*
01261
Neighbor Management Functions
01262 */
01263
01264 void
01265 AODV::sendHello() {
01266 Packet *p = Packet::alloc();
01267 struct hdr_cmn *ch = HDR_CMN(p);
01268 struct hdr_ip *ih = HDR_IP(p);
01269 struct hdr_aodv_reply *rh = HDR_AODV_REPLY(p);
01270
01271 #ifdef DEBUG
01272 fprintf(stderr, "sending Hello from %d at %.2f\n", index,
Scheduler::instance().clock());
01273 #endif // DEBUG
01274
01275 rh->rp_type = AODVTYPE_HELLO;
01276 //rh->rp_flags = 0x00;
01277 rh->rp_hop_count = 1;
01278 rh->rp_dst = index;
01279 rh->rp_dst_seqno = seqno;
01280 rh->rp_lifetime = (1 + ALLOWED_HELLO_LOSS) * HELLO_INTERVAL;
01281
01282 // ch->uid() = 0;
01283 ch->ptype() = PT_AODV;

01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331

ch->size() = IP_HDR_LEN + rh->size();


ch->iface() = -2;
ch->error() = 0;
ch->addr_type() = NS_AF_NONE;
ch->prev_hop_ = index;
// AODV hack
ih->saddr() =
ih->daddr() =
ih->sport() =
ih->dport() =
ih->ttl_ = 1;

index;
IP_BROADCAST;
RT_PORT;
RT_PORT;

Scheduler::instance().schedule(target_, p, 0.0);
}

void
AODV::recvHello(Packet *p) {
//struct hdr_ip *ih = HDR_IP(p);
struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);
AODV_Neighbor *nb;
nb = nb_lookup(rp->rp_dst);
if(nb == 0) {
nb_insert(rp->rp_dst);
}
else {
nb->nb_expire = CURRENT_TIME +
(1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
}
Packet::free(p);
}
void
AODV::nb_insert(nsaddr_t id) {
AODV_Neighbor *nb = new AODV_Neighbor(id);
assert(nb);
nb->nb_expire = CURRENT_TIME +
(1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
LIST_INSERT_HEAD(&nbhead, nb, nb_link);
seqno += 2;
// set of neighbors changed
assert ((seqno%2) == 0);
}

AODV_Neighbor*

01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379

AODV::nb_lookup(nsaddr_t id) {
AODV_Neighbor *nb = nbhead.lh_first;
for(; nb; nb = nb->nb_link.le_next) {
if(nb->nb_addr == id) break;
}
return nb;
}

/*
* Called when we receive *explicit* notification that a Neighbor
* is no longer reachable.
*/
void
AODV::nb_delete(nsaddr_t id) {
AODV_Neighbor *nb = nbhead.lh_first;
log_link_del(id);
seqno += 2;
// Set of neighbors changed
assert ((seqno%2) == 0);
for(; nb; nb = nb->nb_link.le_next) {
if(nb->nb_addr == id) {
LIST_REMOVE(nb,nb_link);
delete nb;
break;
}
}
handle_link_failure(id);
}

/*
* Purges all timed-out Neighbor Entries - runs every
* HELLO_INTERVAL * 1.5 seconds.
*/
void
AODV::nb_purge() {
AODV_Neighbor *nb = nbhead.lh_first;
AODV_Neighbor *nbn;
double now = CURRENT_TIME;
for(; nb; nb = nbn) {
nbn = nb->nb_link.le_next;
if(nb->nb_expire <= now) {

01380
nb_delete(nb->nb_addr);
01381
}
01382 }
01383
01384 }

Potrebbero piacerti anche