Sunteți pe pagina 1din 71

1. /* 2. Copyright (c) 1997, 1998 Carnegie Mellon University. All Rights 3. Reserved. 4. 5.

Permission to use, copy, modify, and distribute this 6. software and its documentation is hereby granted (including for 7. commercial or for-profit use), provided that both the copyright notice and this permission notice appear in all copies of the software, derivative wor s, or modified versions, and any portions thereof, and that both notices appear in supporting documentation, and that credit is given to Carnegie Mellon University in all publications reporting on direct or indirect use of this code or its der ivatives. 8. 9. ALL CODE, SOFTWARE, PROTOCOLS, AND ARCHITECTURES DEVELOPED BY THE CMU 10. MONARCH PROJECT ARE EXPERIMENTAL AND ARE KNOWN TO HAVE BUGS, SOME OF 11. WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON PROVIDES THIS 12. SOFTWARE OR OTHER INTELLECTUAL PROPERTY IN ITS ``AS IS'' CONDITION, 13. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 14. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY 16. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 18. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 19. BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 21. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE OR 22. INTELLECTUAL PROPERTY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 23. DAMAGE. 24. 25. Carnegie Mellon encourages (but does not require) users of this 26. software or intellectual property to return any improvements or 27. extensions that they ma e, and to grant Carnegie Mellon the rights to redi stribute these changes without encumbrance. 28. 29. The AODV code developed by the CMU/MONARCH group was optimized and tuned b y Samir Das and Mahesh Marina, University of Cincinnati. The wor was partially done in Sun Microsystems. Modified for gratuitous replies by Anant Utgi ar, 09/1 6/02. 30. 31. */ 32. 33. //#include <ip.h> 34. 35. #include <aodv/aodv.h> 36. #include <aodv/aodv_pac et.h> 37. #include <random.h> 38. #include <cmu-trace.h> 39. //#include <energy-model.h> 40. 41. #define max(a,b) ( (a) > (b) ? (a) : (b) ) 42. #define CURRENT_TIME Scheduler::instance().cloc () 43. 44. //#define DEBUG 45. //#define ERROR 46. 47. #ifdef DEBUG 48. static int extra_route_reply = 0;

int hdr_aodv::offset_; static class AODVHeaderClass : public Pac etHeaderClass { public: AODVHeaderClass() : Pac etHeaderClass("Pac etHeader/AODV", sizeof(hdr_all_aodv)) { bind_offset(&hdr_aodv::offset_); } } class_rtProtoAODV_hdr; 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; int AODV::command(int argc, const char*const* argv) { if(argc == 2) { Tcl& tcl = Tcl::instance(); if(strncasecmp(argv[1], "id", 2) == 0) { tcl.resultf("%d", index); return TCL_OK; } if(strncasecmp(argv[1], "start", 2) == 0) { 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) { if(strcmp(argv[1], "index") == 0) { index = atoi(argv[2]); return TCL_OK; } else if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "traceta

75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107.

49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74.

static int limit_route_request = 0; static int route_request = 0; #endif /* TCL Hoo s */

rget") == 0) { 108. logtarget = (Trace*) TclObject::loo up(argv[2]); 109. if(logtarget == 0) 110. return TCL_ERROR; 111. return TCL_OK; 112. } 113. else if(strcmp(argv[1], "drop-target") == 0) { 114. int stat = rqueue.command(argc,argv); 115. if (stat != TCL_OK) return stat; 116. return Agent::command(argc, argv); 117. } 118. else if(strcmp(argv[1], "if-queue") == 0) { 119. ifqueue = (PriQueue*) TclObject::loo up(argv[2]); 120. 121. if(ifqueue == 0) 122. return TCL_ERROR; 123. return TCL_OK; 124. } 125. } 126. return Agent::command(argc, argv); 127. } 128. 129. /* 130. Constructor 131. */ 132. 133. AODV::AODV(nsaddr_t id) : Agent(PT_AODV), 134. btimer(this), htimer(this), ntimer(this), 135. rtimer(this), lrtimer(this), rqueue() { 136. 137. 138. index = id; 139. seqno = 2; 140. bid = 1; 141. 142. LIST_INIT(&nbhead); 143. LIST_INIT(&bihead); 144. 145. logtarget = 0; 146. ifqueue = 0; 147. } 148. 149. /* 150. Timers 151. */ 152. 153. void 154. BroadcastTimer::handle(Event*) { 155. agent->id_purge(); 156. Scheduler::instance().schedule(this, &intr, BCAST_ID_SAVE); 157. } 158. 159. void 160. HelloTimer::handle(Event*) { 161. agent->sendHello(); 162. double interval = MinHelloInterval + 163. ((MaxHelloInterval - MinHelloInterval) * Random::uniform( )); 164. assert(interval >= 0); 165. Scheduler::instance().schedule(this, &intr, interval);

166. } 167. 168. void 169. NeighborTimer::handle(Event*) { 170. agent->nb_purge(); 171. Scheduler::instance().schedule(this, &intr, HELLO_INTERVAL); 172. } 173. 174. void 175. RouteCacheTimer::handle(Event*) { 176. agent->rt_purge(); 177. #define FREQUENCY 0.5 // sec 178. Scheduler::instance().schedule(this, &intr, FREQUENCY); 179. } 180. 181. void 182. LocalRepairTimer::handle(Event* p) { // SRD: 5/4/99 183. aodv_rt_entry *rt; 184. struct hdr_ip *ih = HDR_IP( (Pac et *)p); 185. 186. /* you get here after the timeout in a local repair attempt */ 187. /* fprintf(stderr, "%s\n", __FUNCTION__); */ 188. 189. 190. rt = agent->rtable.rt_loo up(ih->daddr()); 191. 192. if (rt && rt->rt_flags != RTF_UP) { 193. // route is yet to be repaired 194. // I will be conservative and bring down the route 195. // and send route errors upstream. 196. /* The following assert fails, not sure why */ 197. /* assert (rt->rt_flags == RTF_IN_REPAIR); */ 198. 199. //rt->rt_seqno++; 200. agent->rt_down(rt); 201. // send RERR 202. #ifdef DEBUG 203. fprintf(stderr,"Node %d: Dst - %d, failed local repair\n",index, rt>rt_dst); 204. #endif 205. } 206. Pac et::free((Pac et *)p); 207. } 208. 209. /* 210. Broadcast ID Management Functions 211. */ 212. void 213. AODV::id_insert(nsaddr_t id, u_int32_t bid) { 214. BroadcastID *b = new BroadcastID(id, bid); 215. 216. assert(b); 217. b->expire = CURRENT_TIME + BCAST_ID_SAVE; 218. LIST_INSERT_HEAD(&bihead, b, lin ); 219. } 220. 221. /* SRD */ 222. bool 223. AODV::id_loo up(nsaddr_t id, u_int32_t bid) { 224. BroadcastID *b = bihead.lh_first;

void AODV::id_purge() { BroadcastID *b = bihead.lh_first; BroadcastID *bn; double now = CURRENT_TIME; for(; b; b = bn) { bn = b->lin .le_next; if(b->expire = now) { LIST_REMOVE(b,lin ); 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); } /*

static void aodv_rt_failed_callbac (Pac et *p, void *arg) { ((AODV*) arg)->rt_ll_failed(p); } /* * This routine is invo ed when the lin -layer reports a route failed.

Lin */

Failure Management Functions

225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284.

// Search the list for a match of source and bid for( ; b; b = b->lin .le_next) { if ((b->src == id) && (b->id == bid)) return true; } return false; }

#ifndef AODV_LINK_LAYER_DETECTION drop(p, DROP_RTR_MAC_CALLBACK); #else /* * Non-data pac ets and Broadcast Pac ets can be dropped. */ if(! DATA_PACKET(ch->ptype()) || (u_int32_t) ih->daddr() == IP_BROADCAST) { drop(p, DROP_RTR_MAC_CALLBACK); return; } log_lin _bro e(p); if((rt = rtable.rt_loo up(ih->daddr())) == 0) { drop(p, DROP_RTR_MAC_CALLBACK); return; } log_lin _del(ch->next_hop_); #ifdef AODV_LOCAL_REPAIR /* if the bro en lin 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 pac ets in the ifq using this lin , // queue the pac ets for which local repair is done, return; } else #endif // LOCAL REPAIR { drop(p, DROP_RTR_MAC_CALLBACK); // Do the same thing for other pac ets in the interface queue using th // bro en lin -Mahesh while((p = ifqueue->filter(bro en_nbr))) { drop(p, DROP_RTR_MAC_CALLBACK); } nb_delete(bro en_nbr); } #endif // LINK LAYER DETECTION } void AODV::handle_lin _failure(nsaddr_t id) { aodv_rt_entry *rt, *rtn; Pac et *rerr = Pac et::alloc(); struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr);

285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305. 306. 307. 308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327. 328. e 329. 330. 331. 332. 333. 334. 335. 336. 337. 338. 339. 340. 341. 342. 343.

*/ void AODV::rt_ll_failed(Pac et *p) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); aodv_rt_entry *rt; nsaddr_t bro en_nbr = ch->next_hop_;

index, re->unreachable_dst[re->DestCount], re->unreachable_dst_seqno[re->DestCount], rt->rt_nexthop); #endif // DEBUG re->DestCount += 1; rt_down(rt); } // remove the lost neighbor from all the precursor lists rt->pc_delete(id); } if (re->DestCount > 0) { #ifdef DEBUG fprintf(stderr, "%s(%f): %d\tsending RERR...\n", __FUNCTION__, CURRENT_ index); #endif // DEBUG sendError(rerr, false); } else { Pac et::free(rerr); } } void AODV::local_rt_repair(aodv_rt_entry *rt, Pac et *p) { #ifdef DEBUG fprintf(stderr,"%s: Dst - %d\n", __FUNCTION__, rt->rt_dst); #endif // Buffer the pac et rqueue.enque(p); // mar the route as under repair rt->rt_flags = RTF_IN_REPAIR; sendRequest(rt->rt_dst); // set up a timer interrupt Scheduler::instance().schedule(&lrtimer, p->copy(), rt->rt_req_timeout);

392. } 393. 394. void 395. AODV::rt_update(aodv_rt_entry *rt, u_int32_t seqnum, u_int16_t metric, 396. nsaddr_t nexthop, double expire_time) { 397. 398. rt->rt_seqno = seqnum; 399. rt->rt_hops = metric; 400. rt->rt_flags = RTF_UP;

344. 345. 346. 347. 348. 349. 350. 351. 352. 353. 354. 355. IME, 356. 357. 358. 359. 360. 361. 362. 363. 364. 365. 366. 367. 368. TIME, 369. 370. 371. 372. 373. 374. 375. 376. 377. 378. 379. 380. 381. 382. 383. 384. 385. 386. 387. 388. 389. 390. 391.

re->DestCount = 0; for(rt = rtable.head(); rt; rt = rtn) { // for each rt entry rtn = rt->rt_lin .le_next; if ((rt->rt_hops != INFINITY2) && (rt->rt_nexthop == id) ) { assert (rt->rt_flags == RTF_UP); assert((rt->rt_seqno%2) == 0); rt->rt_seqno++; re->unreachable_dst[re->DestCount] = rt->rt_dst; re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno; #ifdef DEBUG fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\n", __FUNCTION__, CURRENT_T

if(rt->rt_flags == RTF_DOWN) { return; } // assert (rt->rt_seqno%2); // is the seqno odd? rt->rt_last_hop_count = rt->rt_hops; rt->rt_hops = INFINITY2; rt->rt_flags = RTF_DOWN; rt->rt_nexthop = 0; rt->rt_expire = 0; } /* rt_down function */

/* Route Handling Functions */ void AODV::rt_resolve(Pac et *p) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); aodv_rt_entry *rt; /* * Set the transmit failure callbac . That * won't change. */ ch->xmit_failure_ = aodv_rt_failed_callbac ; ch->xmit_failure_data_ = (void*) this; rt = rtable.rt_loo up(ih->daddr()); if(rt == 0) { rt = rtable.rt_add(ih->daddr()); } /* * If the route is up, forward the pac et */ if(rt->rt_flags == RTF_UP) {

401. 402. 403. 404. 405. 406. 407. 408. 409. 410. 411. 412. 413. 414. 415. 416. 417. 418. 419. 420. 421. 422. 423. 424. 425. 426. 427. 428. 429. 430. 431. 432. 433. 434. 435. 436. 437. 438. 439. 440. 441. 442. 443. 444. 445. 446. 447. 448. 449. 450. 451. 452. 453. 454. 455. 456. 457. 458. 459. 460.

rt->rt_nexthop = nexthop; rt->rt_expire = expire_time; } void AODV::rt_down(aodv_rt_entry *rt) { /* * Ma e sure that you don't "down" a route more than once. */

/* * I am trying to forward a pac et for someone else to which * I don't have a route. */ else { Pac et *rerr = Pac et::alloc(); struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr); /* * For now, drop the pac et and send error upstream. * Now the route errors are broadcast to upstream * neighbors - Mahesh 09/11/99 */ assert (rt->rt_flags == RTF_DOWN); re->DestCount = 0; re->unreachable_dst[re->DestCount] = rt->rt_dst; re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno; re->DestCount += 1; #ifdef DEBUG fprintf(stderr, "%s: sending RERR...\n", __FUNCTION__); #endif sendError(rerr, false); drop(p, DROP_RTR_NO_ROUTE); } } void AODV::rt_purge() { aodv_rt_entry *rt, *rtn; double now = CURRENT_TIME; double delay = 0.0; Pac et *p; for(rt = rtable.head(); rt; rt = rtn) { // for each rt entry rtn = rt->rt_lin .le_next; if ((rt->rt_flags == RTF_UP) && (rt->rt_expire now)) { // if a valid route has expired, purge all pac ets from // send buffer and invalidate the route. assert(rt->rt_hops != INFINITY2); while((p = rqueue.deque(rt->rt_dst))) { #ifdef DEBUG

461. 462. 463. 464. 465. 466. 467. 468. 469. 470. 471. 472. 473. 474. 475. 476. 477. 478. 479. 480. 481. 482. 483. 484. 485. 486. 487. 488. 489. 490. 491. 492. 493. 494. 495. 496. 497. 498. 499. 500. 501. 502. 503. 504. 505. 506. 507. 508. 509. 510. 511. 512. 513. 514. 515. 516. 517. 518. 519. 520.

assert(rt->rt_hops != INFINITY2); forward(rt, p, NO_DELAY); } /* * if I am the source of the pac et, then do a Route Request. */ else if(ih->saddr() == index) { rqueue.enque(p); sendRequest(rt->rt_dst); } /* * A local repair is in progress. Buffer the pac et. */ else if (rt->rt_flags == RTF_IN_REPAIR) { rqueue.enque(p); }

521. fprintf(stderr, "%s: calling drop()\n", 522. __FUNCTION__); 523. #endif // DEBUG 524. drop(p, DROP_RTR_NO_ROUTE); 525. } 526. rt->rt_seqno++; 527. assert (rt->rt_seqno%2); 528. rt_down(rt); 529. } 530. else if (rt->rt_flags == RTF_UP) { 531. // If the route is not expired, 532. // and there are pac ets in the sendbuffer waiting, 533. // forward them. This should not be needed, but this extra 534. // chec does no harm. 535. assert(rt->rt_hops != INFINITY2); 536. while((p = rqueue.deque(rt->rt_dst))) { 537. forward (rt, p, delay); 538. delay += ARP_DELAY; 539. } 540. } 541. else if (rqueue.find(rt->rt_dst)) 542. // If the route is down and 543. // if there is a pac et for this destination waiting in 544. // the sendbuffer, then send out route request. sendRequest 545. // will chec whether it is time to really send out request 546. // or not. 547. // This may not be crucial to do it here, as each generated 548. // pac et will do a sendRequest anyway. 549. 550. sendRequest(rt->rt_dst); 551. } 552. 553. } 554. 555. /* 556. Pac et Reception Routines 557. */ 558. 559. void 560. AODV::recv(Pac et *p, Handler*) { 561. struct hdr_cmn *ch = HDR_CMN(p); 562. struct hdr_ip *ih = HDR_IP(p); 563. 564. assert(initialized()); 565. //assert(p->incoming == 0); 566. // XXXXX NOTE: use of incoming flag has been depracated; In order to trac direction of p t flow, direction_ in hdr_cmn is used instead. see pac et.h for details. 567. 568. if(ch->ptype() == PT_AODV) { 569. ih->ttl_ -= 1; 570. recvAODV(p); 571. return; 572. } 573. 574. /* 575. * Must be a pac et I'm originating... 576. */ 577. if((ih->saddr() == index) && (ch->num_forwards() == 0)) { 578. /*

} /* * I received a pac et that I sent. Probably * a routing loop. */ else if(ih->saddr() == index) { drop(p, DROP_RTR_ROUTE_LOOP); return; } /* * Pac et I'm forwarding... */ else { /* * Chec the TTL. If it is zero, then discard. */ if(--ih->ttl_ == 0) { drop(p, DROP_RTR_TTL); return; } } // Added by Parag Dadhania && John Novatnac to handle broadcasting if ( (u_int32_t)ih->daddr() != IP_BROADCAST) rt_resolve(p); else forward((aodv_rt_entry*) 0, p, NO_DELAY); } void AODV::recvAODV(Pac et *p) { struct hdr_aodv *ah = HDR_AODV(p); struct hdr_ip *ih = HDR_IP(p); assert(ih->sport() == RT_PORT); assert(ih->dport() == RT_PORT); /* * Incoming Pac ets. */ switch(ah->ah_type) { case AODVTYPE_RREQ: recvRequest(p); brea ; case AODVTYPE_RREP: recvReply(p); brea ; case AODVTYPE_RERR: recvError(p); brea ;

579. 580. 581. 582. 583. 584. 585. 586. 587. 588. 589. 590. 591. 592. 593. 594. 595. 596. 597. 598. 599. 600. 601. 602. 603. 604. 605. 606. 607. 608. 609. 610. 611. 612. 613. 614. 615. 616. 617. 618. 619. 620. 621. 622. 623. 624. 625. 626. 627. 628. 629. 630. 631. 632. 633. 634. 635. 636. 637. 638.

* Add the IP Header */ ch->size() += IP_HDR_LEN; // Added by Parag Dadhania && John Novatnac to handle broadcasting if ( (u_int32_t)ih->daddr() != IP_BROADCAST) ih->ttl_ = NETWORK_DIAMETER;

default: fprintf(stderr, "Invalid AODV type (%x)\n", ah->ah_type); exit(1); } } void AODV::recvRequest(Pac et *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 Pac et::free(p); return; } if (id_loo up(rq->rq_src, rq->rq_bcast_id)) { #ifdef DEBUG fprintf(stderr, "%s: discarding request\n", __FUNCTION__); #endif // DEBUG Pac et::free(p); return; } /* * Cache the broadcast ID */ id_insert(rq->rq_src, rq->rq_bcast_id);

/* * We are either going to forward the REQUEST or generate a * REPLY. Before we do anything, we ma e sure that the REVERSE * route is in the route table. */ aodv_rt_entry *rt0; // rt0 is the reverse route rt0 = rtable.rt_loo up(rq->rq_src); if(rt0 == 0) { /* if not in the route table */ // create an entry for the reverse route. rt0 = rtable.rt_add(rq->rq_src);

639. 640. 641. 642. 643. 644. 645. 646. 647. 648. 649. 650. 651. 652. 653. 654. 655. 656. 657. 658. 659. 660. 661. 662. 663. 664. 665. 666. 667. 668. 669. 670. 671. 672. 673. 674. 675. 676. 677. 678. 679. 680. 681. 682. 683. 684. 685. 686. 687. 688. 689. 690. 691. 692. 693. 694. 695. 696. 697. 698.

case AODVTYPE_HELLO: recvHello(p); brea ;

699. 700. 701.

} rt0->rt_expire = max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE));

702. 703. if ( (rq->rq_src_seqno > rt0->rt_seqno ) ||((rq->rq_src_seqno == rt0->r t_seqno) && 704. (rq->rq_hop_count rt0->rt_hops)) ) { 705. // If we have a fresher seq no. or lesser #hops for the 706. // same seq no., update the rt entry. Else don't bother. 707. rt_update(rt0, rq->rq_src_seqno, rq->rq_hop_count, ih->saddr(),max (rt0->rt_expire, 708. (CURRENT_TIME + REV_ROUTE_LIFE)) ); 709. if (rt0->rt_req_timeout > 0.0) { 710. // Reset the soft state and 711. // Set expiry time to CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT 712. // This is because route is used in the forward direction, 713. // but only sources get benefited by this change 714. rt0->rt_req_cnt = 0; 715. rt0->rt_req_timeout = 0.0; 716. rt0->rt_req_last_ttl = rq->rq_hop_count; 717. rt0->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT; 718. } 719. 720. /* Find out whether any buffered pac et can benefit from the 721. * reverse route. 722. * May need some change in the following code - Mahesh 09/11/99 723. */ 724. assert (rt0->rt_flags == RTF_UP); 725. Pac et *buffered_p t; 726. while ((buffered_p t = rqueue.deque(rt0->rt_dst))) { 727. if (rt0 && (rt0->rt_flags == RTF_UP)) { 728. assert(rt0->rt_hops != INFINITY2); 729. forward(rt0, buffered_p t, NO_DELAY); 730. } 731. } 732. } 733. // End for putting reverse route in rt table 734. 735. 736. /* 737. * We have ta en care of the reverse route stuff. 738. * Now see whether we can send a route reply. 739. */ 740. 741. rt = rtable.rt_loo up(rq->rq_dst); 742. 743. // First chec if I am the destination .. 744. 745. if(rq->rq_dst == index) { 746. 747. #ifdef DEBUG 748. fprintf(stderr, "%d - %s: destination sending reply\n", 749. index, __FUNCTION__); 750. #endif // DEBUG 751. 752. 753. // Just to be safe, I use the max. Somebody may have 754. // incremented the dst seqno. 755. seqno = max(seqno, rq->rq_dst_seqno)+1;

756. if (seqno%2) seqno++; 757. 758. sendReply(rq->rq_src, // IP Destination 759. 1, // Hop Count 760. index, // Dest IP Address 761. seqno, // Dest Sequence Num 762. MY_ROUTE_TIMEOUT, // Lifetime 763. rq->rq_timestamp); // timestamp 764. 765. Pac et::free(p); 766. } 767. 768. // I am not the destination, but I may have a fresh enough route. 769. 770. else if (rt && (rt->rt_hops != INFINITY2) && (rt->rt_seqno >= rq->rq_dst_ seqno) ) { 771. 772. //assert (rt->rt_flags == RTF_UP); 773. assert(rq->rq_dst == rt->rt_dst); 774. //assert ((rt->rt_seqno%2) == 0); // is the seqno even? 775. sendReply(rq->rq_src, 776. rt->rt_hops + 1, 777. rq->rq_dst, 778. rt->rt_seqno, 779. (u_int32_t) (rt->rt_expire - CURRENT_TIME), 780. // rt->rt_expire - CURRENT_TIME, 781. rq->rq_timestamp); 782. // Insert nexthops to RREQ source and RREQ destination in the 783. // precursor lists of destination and source respectively 784. rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source 785. rt0->pc_insert(rt->rt_nexthop); // nexthop to RREQ destination 786. 787. #ifdef RREQ_GRAT_RREP 788. 789. sendReply(rq->rq_dst, 790. rq->rq_hop_count, 791. rq->rq_src, 792. rq->rq_src_seqno, 793. (u_int32_t) (rt->rt_expire - CURRENT_TIME), 794. // rt->rt_expire - CURRENT_TIME, 795. rq->rq_timestamp); 796. #endif 797. 798. // TODO: send grat RREP to dst if G flag set in RREQ using rq->rq_src_seqn o, rq->rq_hop_counT 799. 800. // DONE: Included gratuitous replies to be sent as per IETF aodv draft spe cification. As of now, G flag has not been dynamically used and is always set or reset in aodv-pac et.h --- Anant Utgi ar, 09/16/02. 801. 802. Pac et::free(p); 803. } 804. /* 805. * Can't reply. So forward the Route Request 806. */ 807. else { 808. ih->saddr() = index; 809. ih->daddr() = IP_BROADCAST; 810. rq->rq_hop_count += 1; 811. // Maximum sequence number seen en route

#ifdef DEBUG fprintf(stderr, "%d - %s: received a REPLY\n", index, __FUNCTION__); #endif // DEBUG /* * Got a reply. So reset the "soft state" maintained for * route requests in the request table. We don't really have * have a separate request table. It is just a part of the * routing table itself. */ // Note that rp_dst is the dest of the data pac ets, not the // the dest of the reply, which is the src of the data pac ets. rt = rtable.rt_loo up(rp->rp_dst); /* * If I don't have a rt entry to this host... adding */ if(rt == 0) { rt = rtable.rt_add(rp->rp_dst); } /* * Add a forward route table entry... here I am following * Per ins-Royer AODV paper almost literally - SRD 5/99 */ if ( (rt->rt_seqno rp->rp_dst_seqno) || // newer route ((rt->rt_seqno == rp->rp_dst_seqno) && (rt->rt_hops > rp->rp_hop_count)) ) { // shorter or better route // Update the rt entry rt_update(rt, rp->rp_dst_seqno, rp->rp_hop_count, rp->rp_src, CURRENT_TIME + rp->rp_lifetime); // reset the soft state rt->rt_req_cnt = 0; rt->rt_req_timeout = 0.0; rt->rt_req_last_ttl = rp->rp_hop_count; 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

812. 813. 814. 815. 816. 817. 818. 819. 820. 821. 822. 823. 824. 825. 826. 827. 828. 829. 830. 831. 832. 833. 834. 835. 836. 837. 838. 839. 840. 841. 842. 843. 844. 845. 846. 847. 848. 849. 850. 851. 852. 853. 854. 855. 856. 857. 858. 859. 860. 861. 862. 863. 864. 865. 866. 867. 868. 869. 870. 871.

if (rt) rq->rq_dst_seqno = max(rt->rt_seqno, rq->rq_dst_seqno); forward((aodv_rt_entry*) 0, p, DELAY); } } void AODV::recvReply(Pac et *p) { //struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p); aodv_rt_entry *rt; char suppress_reply = 0; double delay = 0.0;

872. 873. 874. 875. 876. 877. 878. 879. 880. 881. 882. 883. 884. 885. 886. 887. 888. 889. 890. 891. 892. 893. 894. 895. 896. 897. 898. 899. 900. 901. 902. 903. 904. 905. 906. 907. 908. 909. 910. 911. 912. 913. 914. 915. 916. 917. 918. 919. 920. 921. 922. 923. 924. 925. 926. 927. 928. 929. 930.

rt->rt_disc_latency[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; } /* * Send all pac ets queued in the sendbuffer destined for * this destination. * XXX - observe the "second" use of p. */ Pac et *buf_p t; while((buf_p t = rqueue.deque(rt->rt_dst))) { if(rt->rt_hops != INFINITY2) { assert (rt->rt_flags == RTF_UP); // Delay them a little to help ARP. Otherwise ARP // may drop pac ets. -SRD 5/23/99 forward(rt, buf_p t, delay); delay += ARP_DELAY; } } } else { suppress_reply = 1; } /* * If reply is for me, discard it. */ if(ih->daddr() == index || suppress_reply) { Pac et::free(p); } /* * Otherwise, forward the Route Reply. */ else { // Find the rt entry aodv_rt_entry *rt0 = rtable.rt_loo up(ih->daddr()); // If the rt is up, forward if(rt0 && (rt0->rt_hops != INFINITY2)) { assert (rt0->rt_flags == RTF_UP); rp->rp_hop_count += 1; rp->rp_src = index; forward(rt0, p, NO_DELAY); // Insert the nexthop towards the RREQ source to // the precursor list of the RREQ destination rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source } else { // I don't now how to forward .. drop the reply. #ifdef DEBUG fprintf(stderr, "%s: dropping Route Reply\n", __FUNCTION__); #endif // DEBUG drop(p, DROP_RTR_NO_ROUTE); } }

931. } 932. 933. 934. void 935. AODV::recvError(Pac et *p) { 936. struct hdr_ip *ih = HDR_IP(p); 937. struct hdr_aodv_error *re = HDR_AODV_ERROR(p); 938. aodv_rt_entry *rt; 939. u_int8_t i; 940. Pac et *rerr = Pac et::alloc(); 941. struct hdr_aodv_error *nre = HDR_AODV_ERROR(rerr); 942. 943. nre->DestCount = 0; 944. 945. for (i=0; i<re->DestCount; i++) { 946. // For each unreachable destination 947. rt = rtable.rt_loo up(re->unreachable_dst[i]); 948. if ( rt && (rt->rt_hops != INFINITY2) && 949. (rt->rt_nexthop == ih->saddr()) && 950. (rt->rt_seqno = re->unreachable_dst_seqno[i]) ) { 951. assert(rt->rt_flags == RTF_UP); 952. assert((rt->rt_seqno%2) == 0); // is the seqno even? 953. #ifdef DEBUG 954. fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\t(%d\t%u\t%d)\n", __FUNCTIO N__,CURRENT_TIME, 955. index, rt->rt_dst, rt->rt_seqno, rt->rt_nexthop, 956. re->unreachable_dst[i],re->unreachable_dst_seqno[i], 957. ih->saddr()); 958. #endif // DEBUG 959. rt->rt_seqno = re->unreachable_dst_seqno[i]; 960. rt_down(rt); 961. 962. // Not sure whether this is the right thing to do 963. Pac et *p t; 964. while((p t = ifqueue->filter(ih->saddr()))) { 965. drop(p t, DROP_RTR_MAC_CALLBACK); 966. } 967. 968. // if precursor list non-empty add to RERR and delete the precursor l ist 969. if (!rt->pc_empty()) { 970. nre->unreachable_dst[nre->DestCount] = rt->rt_dst; 971. nre->unreachable_dst_seqno[nre->DestCount] = rt->rt_seqno; 972. nre->DestCount += 1; 973. rt->pc_delete(); 974. } 975. } 976. } 977. 978. if (nre->DestCount > 0) { 979. #ifdef DEBUG 980. fprintf(stderr, "%s(%f): %d\t sending RERR...\n", __FUNCTION__, CURRENT _TIME, index); 981. #endif // DEBUG 982. sendError(rerr); 983. } 984. else { 985. Pac et::free(rerr); 986. } 987.

988. Pac et::free(p); 989. } 990. 991. 992. 993. 994. 995. 996. 997. /* 998. Pac et Transmission Routines 999. */ 1000. 1001. void 1002. AODV::forward(aodv_rt_entry *rt, Pac et *p, double delay) { 1003. struct hdr_cmn *ch = HDR_CMN(p); 1004. struct hdr_ip *ih = HDR_IP(p); 1005. 1006. if(ih->ttl_ == 0) { 1007. 1008. #ifdef DEBUG 1009. fprintf(stderr, "%s: calling drop()\n", __PRETTY_FUNCTION__); 1010. #endif // DEBUG 1011. 1012. drop(p, DROP_RTR_TTL); 1013. return; 1014. } 1015. 1016. if (rt) { 1017. assert(rt->rt_flags == RTF_UP); 1018. rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT; 1019. ch->next_hop_ = rt->rt_nexthop; 1020. ch->addr_type() = NS_AF_INET; 1021. ch->direction() = hdr_cmn::DOWN; //important: change the pac et's direction 1022. } 1023. else { // if it is a broadcast pac et 1024. // assert(ch->ptype() == PT_AODV); // maybe a diff p t type li e gaf 1025. assert(ih->daddr() == (nsaddr_t) IP_BROADCAST); 1026. ch->addr_type() = NS_AF_NONE; 1027. ch->direction() = hdr_cmn::DOWN; //important: change the pac et's direction 1028. } 1029. 1030. if (ih->daddr() == (nsaddr_t) IP_BROADCAST) { 1031. // If it is a broadcast pac et 1032. assert(rt == 0); 1033. /* 1034. * Jitter the sending of broadcast pac ets by 10ms 1035. */ 1036. Scheduler::instance().schedule(target_, p, 1037. 0.01 * Random::uniform()); 1038. } 1039. else { // Not a broadcast pac et 1040. if(delay > 0.0) { 1041. Scheduler::instance().schedule(target_, p, delay); 1042. } 1043. else { 1044. // Not a broadcast pac et, no delay, send immediately 1045. Scheduler::instance().schedule(target_, p, 0.);

assert(rt); /* * Rate limit sending of Route Requests. We are very conservative * about sending out route requests. */ if (rt->rt_flags == RTF_UP) { assert(rt->rt_hops != INFINITY2); Pac et::free((Pac et *)p); return; } if (rt->rt_req_timeout > CURRENT_TIME) { Pac et::free((Pac et *)p); return; } // rt_req_cnt is the no. of times we did networ -wide broadcast // RREQ_RETRIES is the maximum number we will allow before // going to a long timeout. if (rt->rt_req_cnt > RREQ_RETRIES) { rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT; rt->rt_req_cnt = 0; Pac et *buf_p t; while ((buf_p t = rqueue.deque(rt->rt_dst))) { drop(buf_p t, DROP_RTR_NO_ROUTE); } Pac et::free((Pac et *)p); return; } #ifdef DEBUG fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d\n", ++route_request, index, rt->rt_dst); #endif // DEBUG // Determine the TTL to be used this time. // Dynamic TTL evaluation - SRD rt->rt_req_last_ttl = max(rt->rt_req_last_ttl,rt->rt_last_hop_count); if (0 == rt->rt_req_last_ttl) { // first time query broadcast

1046. 1047. 1048. 1049. 1050. 1051. 1052. 1053. 1054. 1055. 1056. 1057. 1058. 1059. 1060. 1061. 1062. 1063. 1064. 1065. 1066. 1067. 1068. 1069. 1070. 1071. 1072. 1073. 1074. 1075. 1076. 1077. 1078. 1079. 1080. 1081. 1082. 1083. 1084. 1085. 1086. 1087. 1088. 1089. 1090. 1091. 1092. 1093. 1094. 1095. 1096. 1097. 1098. 1099. 1100. 1101. 1102. 1103. 1104. 1105.

} } } void AODV::sendRequest(nsaddr_t dst) { // Allocate a RREQ pac et Pac et *p = Pac et::alloc(); struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p); aodv_rt_entry *rt = rtable.rt_loo up(dst);

// remember the TTL used for the next time rt->rt_req_last_ttl = ih->ttl_; // // // // PerHopTime is the The factor 2.0 is Also note that we done networ wide roundtrip time per hop for route requests. just to be safe .. SRD 5/22/99 are ma ing timeouts to be larger if we have broadcast before.

rt->rt_req_timeout = 2.0 * (double) ih->ttl_ * PerHopTime(rt); if (rt->rt_req_cnt > 0) rt->rt_req_timeout *= rt->rt_req_cnt; rt->rt_req_timeout += CURRENT_TIME; // Don't let the timeout to be too large, however .. SRD 6/8/99 if (rt->rt_req_timeout > CURRENT_TIME + MAX_RREQ_TIMEOUT) rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT; rt->rt_expire = 0; #ifdef DEBUG fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d, tout %f ms\n ++route_request, index, rt->rt_dst, rt->rt_req_timeout - CURRENT_TIME); #endif // DEBUG // Fill out the RREQ pac et // ch->uid() = 0; ch->ptype() = PT_AODV; ch->size() = IP_HDR_LEN + rq->size(); ch->iface() = -2; ch->error() = 0; ch->addr_type() = NS_AF_NONE; ch->prev_hop_ = index; // AODV hac ih->saddr() ih->daddr() ih->sport() ih->dport() = = = = index; IP_BROADCAST; RT_PORT; RT_PORT;

// Fill up some more fields. rq->rq_type = AODVTYPE_RREQ; rq->rq_hop_count = 1; rq->rq_bcast_id = bid++; rq->rq_dst = dst; rq->rq_dst_seqno = (rt ? rt->rt_seqno : 0);

1106. 1107. 1108. 1109. 1110. 1111. 1112. 1113. 1114. 1115. 1116. 1117. 1118. 1119. 1120. 1121. 1122. 1123. 1124. 1125. 1126. 1127. 1128. 1129. 1130. 1131. 1132. 1133. 1134. 1135. 1136. 1137. 1138. ", 1139. 1140. 1141. 1142. 1143. 1144. 1145. 1146. 1147. 1148. 1149. 1150. 1151. 1152. 1153. 1154. 1155. 1156. 1157. 1158. 1159. 1160. 1161. 1162. 1163. 1164.

ih->ttl_ = TTL_START; } else { // Expanding ring search. if (rt->rt_req_last_ttl TTL_THRESHOLD) ih->ttl_ = rt->rt_req_last_ttl + TTL_INCREMENT; else { // networ -wide broadcast ih->ttl_ = NETWORK_DIAMETER; rt->rt_req_cnt += 1; } }

1165. rq->rq_src = index; 1166. seqno += 2; 1167. assert ((seqno%2) == 0); 1168. rq->rq_src_seqno = seqno; 1169. rq->rq_timestamp = CURRENT_TIME; 1170. 1171. Scheduler::instance().schedule(target_, p, 0.); 1172. 1173. } 1174. 1175. void 1176. AODV::sendReply(nsaddr_t ipdst, u_int32_t hop_count, nsaddr_t rpdst, 1177. u_int32_t rpseq, u_int32_t lifetime, double timestamp) { 1178. Pac et *p = Pac et::alloc(); 1179. struct hdr_cmn *ch = HDR_CMN(p); 1180. struct hdr_ip *ih = HDR_IP(p); 1181. struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p); 1182. aodv_rt_entry *rt = rtable.rt_loo up(ipdst); 1183. 1184. #ifdef DEBUG 1185. fprintf(stderr, "sending Reply from %d at %.2f\n", index, Scheduler::insta nce().cloc ()); 1186. #endif // DEBUG 1187. assert(rt); 1188. 1189. rp->rp_type = AODVTYPE_RREP; 1190. //rp->rp_flags = 0x00; 1191. rp->rp_hop_count = hop_count; 1192. rp->rp_dst = rpdst; 1193. rp->rp_dst_seqno = rpseq; 1194. rp->rp_src = index; 1195. rp->rp_lifetime = lifetime; 1196. rp->rp_timestamp = timestamp; 1197. 1198. // ch->uid() = 0; 1199. ch->ptype() = PT_AODV; 1200. ch->size() = IP_HDR_LEN + rp->size(); 1201. ch->iface() = -2; 1202. ch->error() = 0; 1203. ch->addr_type() = NS_AF_INET; 1204. ch->next_hop_ = rt->rt_nexthop; 1205. ch->prev_hop_ = index; // AODV hac 1206. ch->direction() = hdr_cmn::DOWN; 1207. 1208. ih->saddr() = index; 1209. ih->daddr() = ipdst; 1210. ih->sport() = RT_PORT; 1211. ih->dport() = RT_PORT; 1212. ih->ttl_ = NETWORK_DIAMETER; 1213. 1214. Scheduler::instance().schedule(target_, p, 0.); 1215. 1216. } 1217. 1218. void 1219. AODV::sendError(Pac et *p, bool jitter) { 1220. struct hdr_cmn *ch = HDR_CMN(p); 1221. struct hdr_ip *ih = HDR_IP(p); 1222. struct hdr_aodv_error *re = HDR_AODV_ERROR(p); 1223.

1224. #ifdef ERROR 1225. fprintf(stderr, "sending Error from %d at %.2f\n", index, Scheduler::insta nce().cloc ()); 1226. #endif // DEBUG 1227. 1228. re->re_type = AODVTYPE_RERR; 1229. //re->reserved[0] = 0x00; re->reserved[1] = 0x00; 1230. // DestCount and list of unreachable destinations are already filled 1231. 1232. // ch->uid() = 0; 1233. ch->ptype() = PT_AODV; 1234. ch->size() = IP_HDR_LEN + re->size(); 1235. ch->iface() = -2; 1236. ch->error() = 0; 1237. ch->addr_type() = NS_AF_NONE; 1238. ch->next_hop_ = 0; 1239. ch->prev_hop_ = index; // AODV hac 1240. ch->direction() = hdr_cmn::DOWN;//important: change the pac et's directio n 1241. 1242. ih->saddr() = index; 1243. ih->daddr() = IP_BROADCAST; 1244. ih->sport() = RT_PORT; 1245. ih->dport() = RT_PORT; 1246. ih->ttl_ = 1; 1247. 1248. // Do we need any jitter? Yes 1249. if (jitter) 1250. Scheduler::instance().schedule(target_, p, 0.01*Random::uniform()); 1251. else 1252. Scheduler::instance().schedule(target_, p, 0.0); 1253. 1254. } 1255. 1256. 1257. /* 1258. Neighbor Management Functions 1259. */ 1260. 1261. void 1262. AODV::sendHello() { 1263. Pac et *p = Pac et::alloc(); 1264. struct hdr_cmn *ch = HDR_CMN(p); 1265. struct hdr_ip *ih = HDR_IP(p); 1266. struct hdr_aodv_reply *rh = HDR_AODV_REPLY(p); 1267. 1268. #ifdef DEBUG 1269. fprintf(stderr, "sending Hello from %d at %.2f\n", index, Scheduler::insta nce().cloc ()); 1270. #endif // DEBUG 1271. 1272. rh->rp_type = AODVTYPE_HELLO; 1273. //rh->rp_flags = 0x00; 1274. rh->rp_hop_count = 1; 1275. rh->rp_dst = index; 1276. rh->rp_dst_seqno = seqno; 1277. rh->rp_lifetime = (1 + ALLOWED_HELLO_LOSS) * HELLO_INTERVAL; 1278. 1279. // ch->uid() = 0; 1280. ch->ptype() = PT_AODV;

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(Pac et *p) { //struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p); AODV_Neighbor *nb; nb = nb_loo up(rp->rp_dst); if(nb == 0) { nb_insert(rp->rp_dst); } else { nb->nb_expire = CURRENT_TIME + (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL); } Pac et::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_lin ); seqno += 2; // set of neighbors changed assert ((seqno%2) == 0); } AODV_Neighbor* AODV::nb_loo up(nsaddr_t id) { AODV_Neighbor *nb = nbhead.lh_first; for(; nb; nb = nb->nb_lin .le_next) { if(nb->nb_addr == id) brea ; } return nb; } /* * Called when we receive *explicit* notification that a Neighbor

1281. 1282. 1283. 1284. 1285. 1286. 1287. 1288. 1289. 1290. 1291. 1292. 1293. 1294. 1295. 1296. 1297. 1298. 1299. 1300. 1301. 1302. 1303. 1304. 1305. 1306. 1307. 1308. 1309. 1310. 1311. 1312. 1313. 1314. 1315. 1316. 1317. 1318. 1319. 1320. 1321. 1322. 1323. 1324. 1325. 1326. 1327. 1328. 1329. 1330. 1331. 1332. 1333. 1334. 1335. 1336. 1337. 1338. 1339. 1340.

ch->size() = IP_HDR_LEN + rh->size(); ch->iface() = -2; ch->error() = 0; ch->addr_type() = NS_AF_NONE; ch->prev_hop_ = index; // AODV hac

for(; nb; nb = nb->nb_lin .le_next) { if(nb->nb_addr == id) { LIST_REMOVE(nb,nb_lin ); delete nb; brea ; } } handle_lin _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_lin .le_next; if(nb->nb_expire = now) { nb_delete(nb->nb_addr); } } }

1. /* 2. Copyright (c) 1997, 1998 Carnegie Mellon University. All Rights 3. Reserved. 4. 5. Permission to use, copy, modify, and distribute this 6. software and its documentation is hereby granted (including for 7. commercial or for-profit use), provided that both the copyright notice and this permission notice appear in all copies of the software, derivative wor s, or modified versions, and any portions thereof, and that both notices appear in supporting documentation, and that credit is given to Carnegie Mellon University in all publications reporting on direct or indirect use of this code or its der ivatives. 8. 9. ALL CODE, SOFTWARE, PROTOCOLS, AND ARCHITECTURES DEVELOPED BY THE CMU 10. MONARCH PROJECT ARE EXPERIMENTAL AND ARE KNOWN TO HAVE BUGS, SOME OF 11. WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON PROVIDES THIS 12. SOFTWARE OR OTHER INTELLECTUAL PROPERTY IN ITS ``AS IS'' CONDITION, 13. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,

1341. 1342. 1343. 1344. 1345. 1346. 1347. 1348. 1349. 1350. 1351. 1352. 1353. 1354. 1355. 1356. 1357. 1358. 1359. 1360. 1361. 1362. 1363. 1364. 1365. 1366. 1367. 1368. 1369. 1370. 1371. 1372. 1373. 1374. 1375. 1376. 1377. 1378. 1379. 1380. 1381.

* is no longer reachable. */ void AODV::nb_delete(nsaddr_t id) { AODV_Neighbor *nb = nbhead.lh_first; log_lin _del(id); seqno += 2; // Set of neighbors changed assert ((seqno%2) == 0);

14. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY 16. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 18. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 19. BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 21. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE OR 22. INTELLECTUAL PROPERTY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 23. DAMAGE. 24. 25. Carnegie Mellon encourages (but does not require) users of this 26. software or intellectual property to return any improvements or 27. extensions that they ma e, and to grant Carnegie Mellon the rights to redi stribute these changes without encumbrance. 28. 29. The AODV code developed by the CMU/MONARCH group was optimized and tuned b y Samir Das and Mahesh Marina, University of Cincinnati. The wor was partially done in Sun Microsystems. Modified for gratuitous replies by Anant Utgi ar, 09/1 6/02. 30. 31. */ 32. 33. //#include <ip.h> 34. 35. #include <aodv/aodv.h> 36. #include <aodv/aodv_pac et.h> 37. #include <random.h> 38. #include <cmu-trace.h> 39. //#include <energy-model.h> 40. 41. #define max(a,b) ( (a) > (b) ? (a) : (b) ) 42. #define CURRENT_TIME Scheduler::instance().cloc () 43. 44. //#define DEBUG 45. //#define ERROR 46. 47. #ifdef DEBUG 48. static int extra_route_reply = 0; 49. static int limit_route_request = 0; 50. static int route_request = 0; 51. #endif 52. 53. 54. /* 55. TCL Hoo s 56. */ 57. 58. 59. int hdr_aodv::offset_; 60. static class AODVHeaderClass : public Pac etHeaderClass { 61. public: 62. AODVHeaderClass() : Pac etHeaderClass("Pac etHeader/AODV", 63. sizeof(hdr_all_aodv)) { 64. bind_offset(&hdr_aodv::offset_); 65. } 66. } class_rtProtoAODV_hdr; 67. 68. static class AODVclass : public TclClass { 69. public:

70. 71. 72. 73. 74.

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])));

75. } 76. } class_rtProtoAODV; 77. 78. 79. int 80. AODV::command(int argc, const char*const* argv) { 81. if(argc == 2) { 82. Tcl& tcl = Tcl::instance(); 83. 84. if(strncasecmp(argv[1], "id", 2) == 0) { 85. tcl.resultf("%d", index); 86. return TCL_OK; 87. } 88. 89. if(strncasecmp(argv[1], "start", 2) == 0) { 90. btimer.handle((Event*) 0); 91. 92. #ifndef AODV_LINK_LAYER_DETECTION 93. htimer.handle((Event*) 0); 94. ntimer.handle((Event*) 0); 95. #endif // LINK LAYER DETECTION 96. 97. rtimer.handle((Event*) 0); 98. return TCL_OK; 99. } 100. } 101. else if(argc == 3) { 102. if(strcmp(argv[1], "index") == 0) { 103. index = atoi(argv[2]); 104. return TCL_OK; 105. } 106. 107. else if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "traceta rget") == 0) { 108. logtarget = (Trace*) TclObject::loo up(argv[2]); 109. if(logtarget == 0) 110. return TCL_ERROR; 111. return TCL_OK; 112. } 113. else if(strcmp(argv[1], "drop-target") == 0) { 114. int stat = rqueue.command(argc,argv); 115. if (stat != TCL_OK) return stat; 116. return Agent::command(argc, argv); 117. } 118. else if(strcmp(argv[1], "if-queue") == 0) { 119. ifqueue = (PriQueue*) TclObject::loo up(argv[2]); 120. 121. if(ifqueue == 0) 122. return TCL_ERROR; 123. return TCL_OK; 124. } 125. } 126. return Agent::command(argc, argv); 127. }

/* you get here after the timeout in a local repair attempt */

128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. )); 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186.

/* 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); } 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( (Pac et *)p);

187. /* fprintf(stderr, "%s\n", __FUNCTION__); */ 188. 189. 190. rt = agent->rtable.rt_loo up(ih->daddr()); 191. 192. if (rt && rt->rt_flags != RTF_UP) { 193. // route is yet to be repaired 194. // I will be conservative and bring down the route 195. // and send route errors upstream. 196. /* The following assert fails, not sure why */ 197. /* assert (rt->rt_flags == RTF_IN_REPAIR); */ 198. 199. //rt->rt_seqno++; 200. agent->rt_down(rt); 201. // send RERR 202. #ifdef DEBUG 203. fprintf(stderr,"Node %d: Dst - %d, failed local repair\n",index, rt>rt_dst); 204. #endif 205. } 206. Pac et::free((Pac et *)p); 207. } 208. 209. /* 210. Broadcast ID Management Functions 211. */ 212. void 213. AODV::id_insert(nsaddr_t id, u_int32_t bid) { 214. BroadcastID *b = new BroadcastID(id, bid); 215. 216. assert(b); 217. b->expire = CURRENT_TIME + BCAST_ID_SAVE; 218. LIST_INSERT_HEAD(&bihead, b, lin ); 219. } 220. 221. /* SRD */ 222. bool 223. AODV::id_loo up(nsaddr_t id, u_int32_t bid) { 224. BroadcastID *b = bihead.lh_first; 225. 226. // Search the list for a match of source and bid 227. for( ; b; b = b->lin .le_next) { 228. if ((b->src == id) && (b->id == bid)) 229. return true; 230. } 231. return false; 232. } 233. 234. void 235. AODV::id_purge() { 236. BroadcastID *b = bihead.lh_first; 237. BroadcastID *bn; 238. double now = CURRENT_TIME; 239. 240. for(; b; b = bn) { 241. bn = b->lin .le_next; 242. if(b->expire = now) { 243. LIST_REMOVE(b,lin ); 244. delete b; 245. }

static void aodv_rt_failed_callbac (Pac et *p, void *arg) { ((AODV*) arg)->rt_ll_failed(p); } /* * This routine is invo ed when the lin -layer reports a route failed. */ void AODV::rt_ll_failed(Pac et *p) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); aodv_rt_entry *rt; nsaddr_t bro en_nbr = ch->next_hop_; #ifndef AODV_LINK_LAYER_DETECTION drop(p, DROP_RTR_MAC_CALLBACK); #else /* * Non-data pac ets and Broadcast Pac ets can be dropped. */ if(! DATA_PACKET(ch->ptype()) || (u_int32_t) ih->daddr() == IP_BROADCAST) { drop(p, DROP_RTR_MAC_CALLBACK); return; } log_lin _bro e(p);

246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305.

} } /* 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); } /* Lin */ Failure Management Functions

} log_lin _del(ch->next_hop_); #ifdef AODV_LOCAL_REPAIR /* if the bro en lin 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 pac ets in the ifq using this lin , // queue the pac ets for which local repair is done, return; } else #endif // LOCAL REPAIR { drop(p, DROP_RTR_MAC_CALLBACK); // Do the same thing for other pac ets in the interface queue using th // bro en lin -Mahesh while((p = ifqueue->filter(bro en_nbr))) { drop(p, DROP_RTR_MAC_CALLBACK); } nb_delete(bro en_nbr); } #endif // LINK LAYER DETECTION } void AODV::handle_lin _failure(nsaddr_t id) { aodv_rt_entry *rt, *rtn; Pac et *rerr = Pac et::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_lin .le_next; if ((rt->rt_hops != INFINITY2) && (rt->rt_nexthop == id) ) { assert (rt->rt_flags == RTF_UP); assert((rt->rt_seqno%2) == 0); rt->rt_seqno++; re->unreachable_dst[re->DestCount] = rt->rt_dst; re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno; #ifdef DEBUG fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\n", __FUNCTION__, CURRENT_T index, re->unreachable_dst[re->DestCount], re->unreachable_dst_seqno[re->DestCount], rt->rt_nexthop); #endif // DEBUG re->DestCount += 1; rt_down(rt); } // remove the lost neighbor from all the precursor lists rt->pc_delete(id);

306. 307. 308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327. 328. e 329. 330. 331. 332. 333. 334. 335. 336. 337. 338. 339. 340. 341. 342. 343. 344. 345. 346. 347. 348. 349. 350. 351. 352. 353. 354. 355. IME, 356. 357. 358. 359. 360. 361. 362. 363.

if((rt = rtable.rt_loo up(ih->daddr())) == 0) { drop(p, DROP_RTR_MAC_CALLBACK); return;

void AODV::local_rt_repair(aodv_rt_entry *rt, Pac et *p) { #ifdef DEBUG fprintf(stderr,"%s: Dst - %d\n", __FUNCTION__, rt->rt_dst); #endif // Buffer the pac et rqueue.enque(p); // mar the route as under repair rt->rt_flags = RTF_IN_REPAIR; sendRequest(rt->rt_dst); // set up a timer interrupt Scheduler::instance().schedule(&lrtimer, p->copy(), rt->rt_req_timeout); } void AODV::rt_update(aodv_rt_entry *rt, u_int32_t seqnum, u_int16_t metric, nsaddr_t nexthop, double expire_time) { rt->rt_seqno = seqnum; rt->rt_hops = metric; rt->rt_flags = RTF_UP; rt->rt_nexthop = nexthop; rt->rt_expire = expire_time; } void AODV::rt_down(aodv_rt_entry *rt) { /* * Ma e sure that you don't "down" a route more than once. */ if(rt->rt_flags == RTF_DOWN) { return; } // assert (rt->rt_seqno%2); // is the seqno odd? rt->rt_last_hop_count = rt->rt_hops; rt->rt_hops = INFINITY2; rt->rt_flags = RTF_DOWN; rt->rt_nexthop = 0; rt->rt_expire = 0;

392. 393. 394. 395. 396. 397. 398. 399. 400. 401. 402. 403. 404. 405. 406. 407. 408. 409. 410. 411. 412. 413. 414. 415. 416. 417. 418. 419. 420. 421.

364. 365. 366. 367. 368. TIME, 369. 370. 371. 372. 373. 374. 375. 376. 377. 378. 379. 380. 381. 382. 383. 384. 385. 386. 387. 388. 389. 390. 391.

} if (re->DestCount > 0) { #ifdef DEBUG fprintf(stderr, "%s(%f): %d\tsending RERR...\n", __FUNCTION__, CURRENT_ index); #endif // DEBUG sendError(rerr, false); } else { Pac et::free(rerr); } }

/* * Set the transmit failure callbac . That * won't change. */ ch->xmit_failure_ = aodv_rt_failed_callbac ; ch->xmit_failure_data_ = (void*) this; rt = rtable.rt_loo up(ih->daddr()); if(rt == 0) { rt = rtable.rt_add(ih->daddr()); } /* * If the route is up, forward the pac et */ if(rt->rt_flags == RTF_UP) { assert(rt->rt_hops != INFINITY2); forward(rt, p, NO_DELAY); } /* * if I am the source of the pac et, then do a Route Request. */ else if(ih->saddr() == index) { rqueue.enque(p); sendRequest(rt->rt_dst); } /* * A local repair is in progress. Buffer the pac et. */ else if (rt->rt_flags == RTF_IN_REPAIR) { rqueue.enque(p); } /* * I am trying to forward a pac et for someone else to which * I don't have a route. */

422. 423. 424. 425. 426. 427. 428. 429. 430. 431. 432. 433. 434. 435. 436. 437. 438. 439. 440. 441. 442. 443. 444. 445. 446. 447. 448. 449. 450. 451. 452. 453. 454. 455. 456. 457. 458. 459. 460. 461. 462. 463. 464. 465. 466. 467. 468. 469. 470. 471. 472. 473. 474. 475. 476. 477. 478. 479. 480. 481.

} /* rt_down function */

/* Route Handling Functions */ void AODV::rt_resolve(Pac et *p) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); aodv_rt_entry *rt;

assert (rt->rt_flags == RTF_DOWN); re->DestCount = 0; re->unreachable_dst[re->DestCount] = rt->rt_dst; re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno; re->DestCount += 1; #ifdef DEBUG fprintf(stderr, "%s: sending RERR...\n", __FUNCTION__); #endif sendError(rerr, false); drop(p, DROP_RTR_NO_ROUTE); } } void AODV::rt_purge() { aodv_rt_entry *rt, *rtn; double now = CURRENT_TIME; double delay = 0.0; Pac et *p; for(rt = rtable.head(); rt; rt = rtn) { // for each rt entry rtn = rt->rt_lin .le_next; if ((rt->rt_flags == RTF_UP) && (rt->rt_expire now)) { // if a valid route has expired, purge all pac ets 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 pac ets in the sendbuffer waiting, // forward them. This should not be needed, but this extra // chec 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))

482. 483. 484. 485. 486. 487. 488. 489. 490. 491. 492. 493. 494. 495. 496. 497. 498. 499. 500. 501. 502. 503. 504. 505. 506. 507. 508. 509. 510. 511. 512. 513. 514. 515. 516. 517. 518. 519. 520. 521. 522. 523. 524. 525. 526. 527. 528. 529. 530. 531. 532. 533. 534. 535. 536. 537. 538. 539. 540. 541.

else { Pac et *rerr = Pac et::alloc(); struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr); /* * For now, drop the pac et and send error upstream. * Now the route errors are broadcast to upstream * neighbors - Mahesh 09/11/99 */

542. // If the route is down and 543. // if there is a pac et for this destination waiting in 544. // the sendbuffer, then send out route request. sendRequest 545. // will chec whether it is time to really send out request 546. // or not. 547. // This may not be crucial to do it here, as each generated 548. // pac et will do a sendRequest anyway. 549. 550. sendRequest(rt->rt_dst); 551. } 552. 553. } 554. 555. /* 556. Pac et Reception Routines 557. */ 558. 559. void 560. AODV::recv(Pac et *p, Handler*) { 561. struct hdr_cmn *ch = HDR_CMN(p); 562. struct hdr_ip *ih = HDR_IP(p); 563. 564. assert(initialized()); 565. //assert(p->incoming == 0); 566. // XXXXX NOTE: use of incoming flag has been depracated; In order to trac direction of p t flow, direction_ in hdr_cmn is used instead. see pac et.h for details. 567. 568. if(ch->ptype() == PT_AODV) { 569. ih->ttl_ -= 1; 570. recvAODV(p); 571. return; 572. } 573. 574. /* 575. * Must be a pac et I'm originating... 576. */ 577. if((ih->saddr() == index) && (ch->num_forwards() == 0)) { 578. /* 579. * Add the IP Header 580. */ 581. ch->size() += IP_HDR_LEN; 582. // Added by Parag Dadhania && John Novatnac to handle broadcasting 583. if ( (u_int32_t)ih->daddr() != IP_BROADCAST) 584. ih->ttl_ = NETWORK_DIAMETER; 585. } 586. /* 587. * I received a pac et that I sent. Probably 588. * a routing loop. 589. */ 590. else if(ih->saddr() == index) { 591. drop(p, DROP_RTR_ROUTE_LOOP); 592. return; 593. } 594. /* 595. * Pac et I'm forwarding... 596. */ 597. else { 598. /* 599. * Chec the TTL. If it is zero, then discard.

void AODV::recvAODV(Pac et *p) { struct hdr_aodv *ah = HDR_AODV(p); struct hdr_ip *ih = HDR_IP(p); assert(ih->sport() == RT_PORT); assert(ih->dport() == RT_PORT); /* * Incoming Pac ets. */ switch(ah->ah_type) { case AODVTYPE_RREQ: recvRequest(p); brea ; case AODVTYPE_RREP: recvReply(p); brea ; case AODVTYPE_RERR: recvError(p); brea ; case AODVTYPE_HELLO: recvHello(p); brea ; default: fprintf(stderr, "Invalid AODV type (%x)\n", ah->ah_type); exit(1); } } void AODV::recvRequest(Pac et *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

600. 601. 602. 603. 604. 605. 606. 607. 608. 609. 610. 611. 612. 613. 614. 615. 616. 617. 618. 619. 620. 621. 622. 623. 624. 625. 626. 627. 628. 629. 630. 631. 632. 633. 634. 635. 636. 637. 638. 639. 640. 641. 642. 643. 644. 645. 646. 647. 648. 649. 650. 651. 652. 653. 654. 655. 656. 657. 658. 659.

*/ if(--ih->ttl_ == 0) { drop(p, DROP_RTR_TTL); return; } } // Added by Parag Dadhania && John Novatnac to handle broadcasting if ( (u_int32_t)ih->daddr() != IP_BROADCAST) rt_resolve(p); else forward((aodv_rt_entry*) 0, p, NO_DELAY); }

if (id_loo up(rq->rq_src, rq->rq_bcast_id)) { #ifdef DEBUG fprintf(stderr, "%s: discarding request\n", __FUNCTION__); #endif // DEBUG Pac et::free(p); return; } /* * Cache the broadcast ID */ id_insert(rq->rq_src, rq->rq_bcast_id);

/* * We are either going to forward the REQUEST or generate a * REPLY. Before we do anything, we ma e sure that the REVERSE * route is in the route table. */ aodv_rt_entry *rt0; // rt0 is the reverse route rt0 = rtable.rt_loo up(rq->rq_src); if(rt0 == 0) { /* if not in the route table */ // create an entry for the reverse route. rt0 = rtable.rt_add(rq->rq_src); } rt0->rt_expire = max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE));

702. 703. if ( (rq->rq_src_seqno > rt0->rt_seqno ) ||((rq->rq_src_seqno == rt0->r t_seqno) && 704. (rq->rq_hop_count rt0->rt_hops)) ) { 705. // If we have a fresher seq no. or lesser #hops for the 706. // same seq no., update the rt entry. Else don't bother. 707. rt_update(rt0, rq->rq_src_seqno, rq->rq_hop_count, ih->saddr(),max (rt0->rt_expire, 708. (CURRENT_TIME + REV_ROUTE_LIFE)) ); 709. if (rt0->rt_req_timeout > 0.0) { 710. // Reset the soft state and 711. // Set expiry time to CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT 712. // This is because route is used in the forward direction, 713. // but only sources get benefited by this change 714. rt0->rt_req_cnt = 0; 715. rt0->rt_req_timeout = 0.0; 716. rt0->rt_req_last_ttl = rq->rq_hop_count;

660. 661. 662. 663. 664. 665. 666. 667. 668. 669. 670. 671. 672. 673. 674. 675. 676. 677. 678. 679. 680. 681. 682. 683. 684. 685. 686. 687. 688. 689. 690. 691. 692. 693. 694. 695. 696. 697. 698. 699. 700. 701.

* */

- I recently heard this request.

if(rq->rq_src == index) { #ifdef DEBUG fprintf(stderr, "%s: got my own REQUEST\n", __FUNCTION__); #endif // DEBUG Pac et::free(p); return; }

717. rt0->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT; 718. } 719. 720. /* Find out whether any buffered pac et can benefit from the 721. * reverse route. 722. * May need some change in the following code - Mahesh 09/11/99 723. */ 724. assert (rt0->rt_flags == RTF_UP); 725. Pac et *buffered_p t; 726. while ((buffered_p t = rqueue.deque(rt0->rt_dst))) { 727. if (rt0 && (rt0->rt_flags == RTF_UP)) { 728. assert(rt0->rt_hops != INFINITY2); 729. forward(rt0, buffered_p t, NO_DELAY); 730. } 731. } 732. } 733. // End for putting reverse route in rt table 734. 735. 736. /* 737. * We have ta en care of the reverse route stuff. 738. * Now see whether we can send a route reply. 739. */ 740. 741. rt = rtable.rt_loo up(rq->rq_dst); 742. 743. // First chec if I am the destination .. 744. 745. if(rq->rq_dst == index) { 746. 747. #ifdef DEBUG 748. fprintf(stderr, "%d - %s: destination sending reply\n", 749. index, __FUNCTION__); 750. #endif // DEBUG 751. 752. 753. // Just to be safe, I use the max. Somebody may have 754. // incremented the dst seqno. 755. seqno = max(seqno, rq->rq_dst_seqno)+1; 756. if (seqno%2) seqno++; 757. 758. sendReply(rq->rq_src, // IP Destination 759. 1, // Hop Count 760. index, // Dest IP Address 761. seqno, // Dest Sequence Num 762. MY_ROUTE_TIMEOUT, // Lifetime 763. rq->rq_timestamp); // timestamp 764. 765. Pac et::free(p); 766. } 767. 768. // I am not the destination, but I may have a fresh enough route. 769. 770. else if (rt && (rt->rt_hops != INFINITY2) && (rt->rt_seqno >= rq->rq_dst_ seqno) ) { 771. 772. //assert (rt->rt_flags == RTF_UP); 773. assert(rq->rq_dst == rt->rt_dst); 774. //assert ((rt->rt_seqno%2) == 0); // is the seqno even? 775. sendReply(rq->rq_src,

776. rt->rt_hops + 1, 777. rq->rq_dst, 778. rt->rt_seqno, 779. (u_int32_t) (rt->rt_expire - CURRENT_TIME), 780. // rt->rt_expire - CURRENT_TIME, 781. rq->rq_timestamp); 782. // Insert nexthops to RREQ source and RREQ destination in the 783. // precursor lists of destination and source respectively 784. rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source 785. rt0->pc_insert(rt->rt_nexthop); // nexthop to RREQ destination 786. 787. #ifdef RREQ_GRAT_RREP 788. 789. sendReply(rq->rq_dst, 790. rq->rq_hop_count, 791. rq->rq_src, 792. rq->rq_src_seqno, 793. (u_int32_t) (rt->rt_expire - CURRENT_TIME), 794. // rt->rt_expire - CURRENT_TIME, 795. rq->rq_timestamp); 796. #endif 797. 798. // TODO: send grat RREP to dst if G flag set in RREQ using rq->rq_src_seqn o, rq->rq_hop_counT 799. 800. // DONE: Included gratuitous replies to be sent as per IETF aodv draft spe cification. As of now, G flag has not been dynamically used and is always set or reset in aodv-pac et.h --- Anant Utgi ar, 09/16/02. 801. 802. Pac et::free(p); 803. } 804. /* 805. * Can't reply. So forward the Route Request 806. */ 807. else { 808. ih->saddr() = index; 809. ih->daddr() = IP_BROADCAST; 810. rq->rq_hop_count += 1; 811. // Maximum sequence number seen en route 812. if (rt) rq->rq_dst_seqno = max(rt->rt_seqno, rq->rq_dst_seqno); 813. forward((aodv_rt_entry*) 0, p, DELAY); 814. } 815. 816. } 817. 818. 819. void 820. AODV::recvReply(Pac et *p) { 821. //struct hdr_cmn *ch = HDR_CMN(p); 822. struct hdr_ip *ih = HDR_IP(p); 823. struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p); 824. aodv_rt_entry *rt; 825. char suppress_reply = 0; 826. double delay = 0.0; 827. 828. #ifdef DEBUG 829. fprintf(stderr, "%d - %s: received a REPLY\n", index, __FUNCTION__); 830. #endif // DEBUG 831. 832.

rt = rtable.rt_loo up(rp->rp_dst); /* * If I don't have a rt entry to this host... adding */ if(rt == 0) { rt = rtable.rt_add(rp->rp_dst); } /* * Add a forward route table entry... here I am following * Per ins-Royer AODV paper almost literally - SRD 5/99 */ if ( (rt->rt_seqno rp->rp_dst_seqno) || // newer route ((rt->rt_seqno == rp->rp_dst_seqno) && (rt->rt_hops > rp->rp_hop_count)) ) { // shorter or better route // Update the rt entry rt_update(rt, rp->rp_dst_seqno, rp->rp_hop_count, rp->rp_src, CURRENT_TIME + rp->rp_lifetime); // reset the soft state rt->rt_req_cnt = 0; rt->rt_req_timeout = 0.0; rt->rt_req_last_ttl = rp->rp_hop_count; 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->rt_disc_latency[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; } /* * Send all pac ets queued in the sendbuffer destined for * this destination. * XXX - observe the "second" use of p. */ Pac et *buf_p t; while((buf_p t = rqueue.deque(rt->rt_dst))) { if(rt->rt_hops != INFINITY2) { assert (rt->rt_flags == RTF_UP); // Delay them a little to help ARP. Otherwise ARP // may drop pac ets. -SRD 5/23/99 forward(rt, buf_p t, delay); delay += ARP_DELAY;

874. 875. 876. 877. 878. 879. 880. 881. 882. 883. 884. 885. 886. 887. 888. 889. 890. 891.

833. 834. 835. 836. 837. 838. 839. 840. 841. 842. 843. 844. 845. 846. 847. 848. 849. 850. 851. 852. 853. 854. 855. 856. 857. 858. 859. 860. 861. 862. 863. 864. 865. 866. 867. 868. 869. 870. 871. 872. 873.

/* * Got a reply. So reset the "soft state" maintained for * route requests in the request table. We don't really have * have a separate request table. It is just a part of the * routing table itself. */ // Note that rp_dst is the dest of the data pac ets, not the // the dest of the reply, which is the src of the data pac ets.

} else { // I don't now how to forward .. drop the reply. #ifdef DEBUG fprintf(stderr, "%s: dropping Route Reply\n", __FUNCTION__); #endif // DEBUG drop(p, DROP_RTR_NO_ROUTE); } } } void AODV::recvError(Pac et *p) { struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_error *re = HDR_AODV_ERROR(p); aodv_rt_entry *rt; u_int8_t i; Pac et *rerr = Pac et::alloc(); struct hdr_aodv_error *nre = HDR_AODV_ERROR(rerr); nre->DestCount = 0; for (i=0; i<re->DestCount; i++) { // For each unreachable destination rt = rtable.rt_loo up(re->unreachable_dst[i]); if ( rt && (rt->rt_hops != INFINITY2) && (rt->rt_nexthop == ih->saddr()) && (rt->rt_seqno = re->unreachable_dst_seqno[i]) ) { assert(rt->rt_flags == RTF_UP);

892. 893. 894. 895. 896. 897. 898. 899. 900. 901. 902. 903. 904. 905. 906. 907. 908. 909. 910. 911. 912. 913. 914. 915. 916. 917. 918. 919. 920. 921. 922. 923. 924. 925. 926. 927. 928. 929. 930. 931. 932. 933. 934. 935. 936. 937. 938. 939. 940. 941. 942. 943. 944. 945. 946. 947. 948. 949. 950. 951.

} } } else { suppress_reply = 1; } /* * If reply is for me, discard it. */ if(ih->daddr() == index || suppress_reply) { Pac et::free(p); } /* * Otherwise, forward the Route Reply. */ else { // Find the rt entry aodv_rt_entry *rt0 = rtable.rt_loo up(ih->daddr()); // If the rt is up, forward if(rt0 && (rt0->rt_hops != INFINITY2)) { assert (rt0->rt_flags == RTF_UP); rp->rp_hop_count += 1; rp->rp_src = index; forward(rt0, p, NO_DELAY); // Insert the nexthop towards the RREQ source to // the precursor list of the RREQ destination rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source

952. assert((rt->rt_seqno%2) == 0); // is the seqno even? 953. #ifdef DEBUG 954. fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\t(%d\t%u\t%d)\n", __FUNCTIO N__,CURRENT_TIME, 955. index, rt->rt_dst, rt->rt_seqno, rt->rt_nexthop, 956. re->unreachable_dst[i],re->unreachable_dst_seqno[i], 957. ih->saddr()); 958. #endif // DEBUG 959. rt->rt_seqno = re->unreachable_dst_seqno[i]; 960. rt_down(rt); 961. 962. // Not sure whether this is the right thing to do 963. Pac et *p t; 964. while((p t = ifqueue->filter(ih->saddr()))) { 965. drop(p t, DROP_RTR_MAC_CALLBACK); 966. } 967. 968. // if precursor list non-empty add to RERR and delete the precursor l ist 969. if (!rt->pc_empty()) { 970. nre->unreachable_dst[nre->DestCount] = rt->rt_dst; 971. nre->unreachable_dst_seqno[nre->DestCount] = rt->rt_seqno; 972. nre->DestCount += 1; 973. rt->pc_delete(); 974. } 975. } 976. } 977. 978. if (nre->DestCount > 0) { 979. #ifdef DEBUG 980. fprintf(stderr, "%s(%f): %d\t sending RERR...\n", __FUNCTION__, CURRENT _TIME, index); 981. #endif // DEBUG 982. sendError(rerr); 983. } 984. else { 985. Pac et::free(rerr); 986. } 987. 988. Pac et::free(p); 989. } 990. 991. 992. 993. 994. 995. 996. 997. /* 998. Pac et Transmission Routines 999. */ 1000. 1001. void 1002. AODV::forward(aodv_rt_entry *rt, Pac et *p, double delay) { 1003. struct hdr_cmn *ch = HDR_CMN(p); 1004. struct hdr_ip *ih = HDR_IP(p); 1005. 1006. if(ih->ttl_ == 0) { 1007. 1008. #ifdef DEBUG

1009. fprintf(stderr, "%s: calling drop()\n", __PRETTY_FUNCTION__); 1010. #endif // DEBUG 1011. 1012. drop(p, DROP_RTR_TTL); 1013. return; 1014. } 1015. 1016. if (rt) { 1017. assert(rt->rt_flags == RTF_UP); 1018. rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT; 1019. ch->next_hop_ = rt->rt_nexthop; 1020. ch->addr_type() = NS_AF_INET; 1021. ch->direction() = hdr_cmn::DOWN; //important: change the pac et's direction 1022. } 1023. else { // if it is a broadcast pac et 1024. // assert(ch->ptype() == PT_AODV); // maybe a diff p t type li e gaf 1025. assert(ih->daddr() == (nsaddr_t) IP_BROADCAST); 1026. ch->addr_type() = NS_AF_NONE; 1027. ch->direction() = hdr_cmn::DOWN; //important: change the pac et's direction 1028. } 1029. 1030. if (ih->daddr() == (nsaddr_t) IP_BROADCAST) { 1031. // If it is a broadcast pac et 1032. assert(rt == 0); 1033. /* 1034. * Jitter the sending of broadcast pac ets by 10ms 1035. */ 1036. Scheduler::instance().schedule(target_, p, 1037. 0.01 * Random::uniform()); 1038. } 1039. else { // Not a broadcast pac et 1040. if(delay > 0.0) { 1041. Scheduler::instance().schedule(target_, p, delay); 1042. } 1043. else { 1044. // Not a broadcast pac et, no delay, send immediately 1045. Scheduler::instance().schedule(target_, p, 0.); 1046. } 1047. } 1048. 1049. } 1050. 1051. 1052. void 1053. AODV::sendRequest(nsaddr_t dst) { 1054. // Allocate a RREQ pac et 1055. Pac et *p = Pac et::alloc(); 1056. struct hdr_cmn *ch = HDR_CMN(p); 1057. struct hdr_ip *ih = HDR_IP(p); 1058. struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p); 1059. aodv_rt_entry *rt = rtable.rt_loo up(dst); 1060. 1061. assert(rt); 1062. 1063. /* 1064. * Rate limit sending of Route Requests. We are very conservative 1065. * about sending out route requests. 1066. */

if (rt->rt_req_timeout > CURRENT_TIME) { Pac et::free((Pac et *)p); return; } // rt_req_cnt is the no. of times we did networ -wide broadcast // RREQ_RETRIES is the maximum number we will allow before // going to a long timeout. if (rt->rt_req_cnt > RREQ_RETRIES) { rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT; rt->rt_req_cnt = 0; Pac et *buf_p t; while ((buf_p t = rqueue.deque(rt->rt_dst))) { drop(buf_p t, DROP_RTR_NO_ROUTE); } Pac et::free((Pac et *)p); return; } #ifdef DEBUG fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d\n", ++route_request, index, rt->rt_dst); #endif // DEBUG // Determine the TTL to be used this time. // Dynamic TTL evaluation - SRD rt->rt_req_last_ttl = max(rt->rt_req_last_ttl,rt->rt_last_hop_count); if (0 == rt->rt_req_last_ttl) { // first time query broadcast ih->ttl_ = TTL_START; } else { // Expanding ring search. if (rt->rt_req_last_ttl TTL_THRESHOLD) ih->ttl_ = rt->rt_req_last_ttl + TTL_INCREMENT; else { // networ -wide broadcast ih->ttl_ = NETWORK_DIAMETER; rt->rt_req_cnt += 1; } } // remember the TTL used for the next time rt->rt_req_last_ttl = ih->ttl_; // // // // PerHopTime is the The factor 2.0 is Also note that we done networ wide roundtrip time per hop for route requests. just to be safe .. SRD 5/22/99 are ma ing timeouts to be larger if we have broadcast before.

1067. 1068. 1069. 1070. 1071. 1072. 1073. 1074. 1075. 1076. 1077. 1078. 1079. 1080. 1081. 1082. 1083. 1084. 1085. 1086. 1087. 1088. 1089. 1090. 1091. 1092. 1093. 1094. 1095. 1096. 1097. 1098. 1099. 1100. 1101. 1102. 1103. 1104. 1105. 1106. 1107. 1108. 1109. 1110. 1111. 1112. 1113. 1114. 1115. 1116. 1117. 1118. 1119. 1120. 1121. 1122. 1123. 1124. 1125. 1126.

if (rt->rt_flags == RTF_UP) { assert(rt->rt_hops != INFINITY2); Pac et::free((Pac et *)p); return; }

ih->saddr() ih->daddr() ih->sport() ih->dport()

= = = =

index; IP_BROADCAST; RT_PORT; RT_PORT;

// Fill up some more fields. rq->rq_type = AODVTYPE_RREQ; rq->rq_hop_count = 1; rq->rq_bcast_id = bid++; rq->rq_dst = dst; rq->rq_dst_seqno = (rt ? rt->rt_seqno : 0); rq->rq_src = index; seqno += 2; assert ((seqno%2) == 0); rq->rq_src_seqno = seqno; rq->rq_timestamp = CURRENT_TIME; Scheduler::instance().schedule(target_, p, 0.); } void AODV::sendReply(nsaddr_t ipdst, u_int32_t hop_count, nsaddr_t rpdst, u_int32_t rpseq, u_int32_t lifetime, double timestamp) { Pac et *p = Pac et::alloc(); struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p); aodv_rt_entry *rt = rtable.rt_loo up(ipdst); #ifdef DEBUG fprintf(stderr, "sending Reply from %d at %.2f\n", index, Scheduler::insta

1127. 1128. 1129. 1130. 1131. 1132. 1133. 1134. 1135. 1136. 1137. 1138. ", 1139. 1140. 1141. 1142. 1143. 1144. 1145. 1146. 1147. 1148. 1149. 1150. 1151. 1152. 1153. 1154. 1155. 1156. 1157. 1158. 1159. 1160. 1161. 1162. 1163. 1164. 1165. 1166. 1167. 1168. 1169. 1170. 1171. 1172. 1173. 1174. 1175. 1176. 1177. 1178. 1179. 1180. 1181. 1182. 1183. 1184. 1185.

rt->rt_req_timeout = 2.0 * (double) ih->ttl_ * PerHopTime(rt); if (rt->rt_req_cnt > 0) rt->rt_req_timeout *= rt->rt_req_cnt; rt->rt_req_timeout += CURRENT_TIME; // Don't let the timeout to be too large, however .. SRD 6/8/99 if (rt->rt_req_timeout > CURRENT_TIME + MAX_RREQ_TIMEOUT) rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT; rt->rt_expire = 0; #ifdef DEBUG fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d, tout %f ms\n ++route_request, index, rt->rt_dst, rt->rt_req_timeout - CURRENT_TIME); #endif // DEBUG // Fill out the RREQ pac et // ch->uid() = 0; ch->ptype() = PT_AODV; ch->size() = IP_HDR_LEN + rq->size(); ch->iface() = -2; ch->error() = 0; ch->addr_type() = NS_AF_NONE; ch->prev_hop_ = index; // AODV hac

nce().cloc ()); 1186. #endif // DEBUG 1187. assert(rt); 1188. 1189. rp->rp_type = AODVTYPE_RREP; 1190. //rp->rp_flags = 0x00; 1191. rp->rp_hop_count = hop_count; 1192. rp->rp_dst = rpdst; 1193. rp->rp_dst_seqno = rpseq; 1194. rp->rp_src = index; 1195. rp->rp_lifetime = lifetime; 1196. rp->rp_timestamp = timestamp; 1197. 1198. // ch->uid() = 0; 1199. ch->ptype() = PT_AODV; 1200. ch->size() = IP_HDR_LEN + rp->size(); 1201. ch->iface() = -2; 1202. ch->error() = 0; 1203. ch->addr_type() = NS_AF_INET; 1204. ch->next_hop_ = rt->rt_nexthop; 1205. ch->prev_hop_ = index; // AODV hac 1206. ch->direction() = hdr_cmn::DOWN; 1207. 1208. ih->saddr() = index; 1209. ih->daddr() = ipdst; 1210. ih->sport() = RT_PORT; 1211. ih->dport() = RT_PORT; 1212. ih->ttl_ = NETWORK_DIAMETER; 1213. 1214. Scheduler::instance().schedule(target_, p, 0.); 1215. 1216. } 1217. 1218. void 1219. AODV::sendError(Pac et *p, bool jitter) { 1220. struct hdr_cmn *ch = HDR_CMN(p); 1221. struct hdr_ip *ih = HDR_IP(p); 1222. struct hdr_aodv_error *re = HDR_AODV_ERROR(p); 1223. 1224. #ifdef ERROR 1225. fprintf(stderr, "sending Error from %d at %.2f\n", index, Scheduler::insta nce().cloc ()); 1226. #endif // DEBUG 1227. 1228. re->re_type = AODVTYPE_RERR; 1229. //re->reserved[0] = 0x00; re->reserved[1] = 0x00; 1230. // DestCount and list of unreachable destinations are already filled 1231. 1232. // ch->uid() = 0; 1233. ch->ptype() = PT_AODV; 1234. ch->size() = IP_HDR_LEN + re->size(); 1235. ch->iface() = -2; 1236. ch->error() = 0; 1237. ch->addr_type() = NS_AF_NONE; 1238. ch->next_hop_ = 0; 1239. ch->prev_hop_ = index; // AODV hac 1240. ch->direction() = hdr_cmn::DOWN;//important: change the pac et's directio n 1241. 1242. ih->saddr() = index;

1243. ih->daddr() = IP_BROADCAST; 1244. ih->sport() = RT_PORT; 1245. ih->dport() = RT_PORT; 1246. ih->ttl_ = 1; 1247. 1248. // Do we need any jitter? Yes 1249. if (jitter) 1250. Scheduler::instance().schedule(target_, p, 0.01*Random::uniform()); 1251. else 1252. Scheduler::instance().schedule(target_, p, 0.0); 1253. 1254. } 1255. 1256. 1257. /* 1258. Neighbor Management Functions 1259. */ 1260. 1261. void 1262. AODV::sendHello() { 1263. Pac et *p = Pac et::alloc(); 1264. struct hdr_cmn *ch = HDR_CMN(p); 1265. struct hdr_ip *ih = HDR_IP(p); 1266. struct hdr_aodv_reply *rh = HDR_AODV_REPLY(p); 1267. 1268. #ifdef DEBUG 1269. fprintf(stderr, "sending Hello from %d at %.2f\n", index, Scheduler::insta nce().cloc ()); 1270. #endif // DEBUG 1271. 1272. rh->rp_type = AODVTYPE_HELLO; 1273. //rh->rp_flags = 0x00; 1274. rh->rp_hop_count = 1; 1275. rh->rp_dst = index; 1276. rh->rp_dst_seqno = seqno; 1277. rh->rp_lifetime = (1 + ALLOWED_HELLO_LOSS) * HELLO_INTERVAL; 1278. 1279. // ch->uid() = 0; 1280. ch->ptype() = PT_AODV; 1281. ch->size() = IP_HDR_LEN + rh->size(); 1282. ch->iface() = -2; 1283. ch->error() = 0; 1284. ch->addr_type() = NS_AF_NONE; 1285. ch->prev_hop_ = index; // AODV hac 1286. 1287. ih->saddr() = index; 1288. ih->daddr() = IP_BROADCAST; 1289. ih->sport() = RT_PORT; 1290. ih->dport() = RT_PORT; 1291. ih->ttl_ = 1; 1292. 1293. Scheduler::instance().schedule(target_, p, 0.0); 1294. } 1295. 1296. 1297. void 1298. AODV::recvHello(Pac et *p) { 1299. //struct hdr_ip *ih = HDR_IP(p); 1300. struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p); 1301. AODV_Neighbor *nb;

Pac et::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_lin ); seqno += 2; // set of neighbors changed assert ((seqno%2) == 0); } AODV_Neighbor* AODV::nb_loo up(nsaddr_t id) { AODV_Neighbor *nb = nbhead.lh_first; for(; nb; nb = nb->nb_lin .le_next) { if(nb->nb_addr == id) brea ; } 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_lin _del(id); seqno += 2; // Set of neighbors changed assert ((seqno%2) == 0); for(; nb; nb = nb->nb_lin .le_next) { if(nb->nb_addr == id) { LIST_REMOVE(nb,nb_lin ); delete nb; brea ; } } handle_lin _failure(id); }

1302. 1303. 1304. 1305. 1306. 1307. 1308. 1309. 1310. 1311. 1312. 1313. 1314. 1315. 1316. 1317. 1318. 1319. 1320. 1321. 1322. 1323. 1324. 1325. 1326. 1327. 1328. 1329. 1330. 1331. 1332. 1333. 1334. 1335. 1336. 1337. 1338. 1339. 1340. 1341. 1342. 1343. 1344. 1345. 1346. 1347. 1348. 1349. 1350. 1351. 1352. 1353. 1354. 1355. 1356. 1357. 1358. 1359. 1360. 1361.

nb = nb_loo up(rp->rp_dst); if(nb == 0) { nb_insert(rp->rp_dst); } else { nb->nb_expire = CURRENT_TIME + (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL); }

/* Copyright (c) 1997, 1998 Carnegie Mellon University. All Rights Reserved. Permission to use, copy, modify, and distribute this software and its documentation is hereby granted (including for commercial or for-profit use), provided that both the copyright notice and this permission notice appear in all copies of the software, derivative wor s, or mod ified versions, and any portions thereof, and that both notices appear in suppor ting documentation, and that credit is given to Carnegie Mellon University in al l publications reporting on direct or indirect use of this code or its derivativ es. ALL CODE, SOFTWARE, PROTOCOLS, AND ARCHITECTURES DEVELOPED BY THE CMU MONARCH PROJECT ARE EXPERIMENTAL AND ARE KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON PROVIDES THIS SOFTWARE OR OTHER INTELLECTUAL PROPERTY IN ITS ``AS IS'' CONDITION, AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE OR INTELLECTUAL PROPERTY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Carnegie Mellon encourages (but does not require) users of this software or intellectual property to return any improvements or extensions that they ma e, and to grant Carnegie Mellon the rights to redistribu te these changes without encumbrance. The AODV code developed by the CMU/MONARCH group was optimized and tuned by Sami r Das and Mahesh Marina, University of Cincinnati. The wor was partially done i n Sun Microsystems. Modified for gratuitous replies by Anant Utgi ar, 09/16/02. */

1362. 1363. 1364. 1365. 1366. 1367. 1368. 1369. 1370. 1371. 1372. 1373. 1374. 1375. 1376. 1377. 1378. 1379. 1380. 1381.

/* * 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_lin .le_next; if(nb->nb_expire = now) { nb_delete(nb->nb_addr); } }

//#include <ip.h> #include <aodv/aodv.h> #include <aodv/aodv_pac et.h> #include <random.h> #include <cmu-trace.h> //#include <energy-model.h>

//#define DEBUG //#define ERROR #ifdef static static static #endif /* TCL Hoo s */ int hdr_aodv::offset_; static class AODVHeaderClass : public Pac etHeaderClass { public: AODVHeaderClass() : Pac etHeaderClass("Pac etHeader/AODV", sizeof(hdr_all_aodv)) { bind_offset(&hdr_aodv::offset_); } } class_rtProtoAODV_hdr; 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; int AODV::command(int argc, const char*const* argv) { if(argc == 2) { Tcl& tcl = Tcl::instance(); if(strncasecmp(argv[1], "id", 2) == 0) { tcl.resultf("%d", index); return TCL_OK; } if(strncasecmp(argv[1], "start", 2) == 0) { btimer.handle((Event*) 0); DEBUG int extra_route_reply = 0; int limit_route_request = 0; int route_request = 0;

#define max(a,b) #define CURRENT_TIME

( (a) > (b) ? (a) : (b) ) Scheduler::instance().cloc ()

#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) { if(strcmp(argv[1], "index") == 0) { index = atoi(argv[2]); return TCL_OK; } else if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "tracetarget") == 0) { logtarget = (Trace*) TclObject::loo up(argv[2]); if(logtarget == 0) return TCL_ERROR; return TCL_OK; } else if(strcmp(argv[1], "drop-target") == 0) { int stat = rqueue.command(argc,argv); if (stat != TCL_OK) return stat; return Agent::command(argc, argv); } else if(strcmp(argv[1], "if-queue") == 0) { ifqueue = (PriQueue*) TclObject::loo up(argv[2]); if(ifqueue == 0) 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); } 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( (Pac et *)p); /* you get here after the timeout in a local repair attempt */ /* fprintf(stderr, "%s\n", __FUNCTION__); */ rt = agent->rtable.rt_loo up(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_ds t); #endif } Pac et::free((Pac et *)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, lin ); } /* SRD */ bool AODV::id_loo up(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->lin .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->lin .le_next; if(b->expire = now) { LIST_REMOVE(b,lin ); 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); } /* Lin Failure Management Functions */ static void aodv_rt_failed_callbac (Pac et *p, void *arg) { ((AODV*) arg)->rt_ll_failed(p); } /* * This routine is invo ed when the lin -layer reports a route failed. */ void AODV::rt_ll_failed(Pac et *p) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); aodv_rt_entry *rt; nsaddr_t bro en_nbr = ch->next_hop_; #ifndef AODV_LINK_LAYER_DETECTION drop(p, DROP_RTR_MAC_CALLBACK); #else /* * Non-data pac ets and Broadcast Pac ets can be dropped. */ if(! DATA_PACKET(ch->ptype()) || (u_int32_t) ih->daddr() == IP_BROADCAST) { drop(p, DROP_RTR_MAC_CALLBACK); return; } log_lin _bro e(p); if((rt = rtable.rt_loo up(ih->daddr())) == 0) { drop(p, DROP_RTR_MAC_CALLBACK); return; } log_lin _del(ch->next_hop_); #ifdef AODV_LOCAL_REPAIR /* if the bro en lin 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 pac ets in the ifq using this lin , // queue the pac ets for which local repair is done, return; } else #endif // LOCAL REPAIR { drop(p, DROP_RTR_MAC_CALLBACK); // Do the same thing for other pac ets in the interface queue using the // bro en lin -Mahesh

while((p = ifqueue->filter(bro en_nbr))) { drop(p, DROP_RTR_MAC_CALLBACK); } nb_delete(bro en_nbr); } #endif // LINK LAYER DETECTION } void AODV::handle_lin _failure(nsaddr_t id) { aodv_rt_entry *rt, *rtn; Pac et *rerr = Pac et::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_lin .le_next; if ((rt->rt_hops != INFINITY2) && (rt->rt_nexthop == id) ) { assert (rt->rt_flags == RTF_UP); assert((rt->rt_seqno%2) == 0); rt->rt_seqno++; re->unreachable_dst[re->DestCount] = rt->rt_dst; re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno; #ifdef DEBUG fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\n", __FUNCTION__, CURRENT_TIME, index, re->unreachable_dst[re->DestCount], re->unreachable_dst_seqno[re->DestCount], rt->rt_nexthop); #endif // DEBUG re->DestCount += 1; rt_down(rt); } // remove the lost neighbor from all the precursor lists rt->pc_delete(id); } if (re->DestCount > 0) { #ifdef DEBUG fprintf(stderr, "%s(%f): %d\tsending RERR...\n", __FUNCTION__, CURRENT_TIME, index); #endif // DEBUG sendError(rerr, false); } else { Pac et::free(rerr); } } void AODV::local_rt_repair(aodv_rt_entry *rt, Pac et *p) { #ifdef DEBUG fprintf(stderr,"%s: Dst - %d\n", __FUNCTION__, rt->rt_dst); #endif // Buffer the pac et rqueue.enque(p); // mar the route as under repair rt->rt_flags = RTF_IN_REPAIR; sendRequest(rt->rt_dst);

// set up a timer interrupt Scheduler::instance().schedule(&lrtimer, p->copy(), rt->rt_req_timeout); } void AODV::rt_update(aodv_rt_entry *rt, u_int32_t seqnum, u_int16_t metric, nsaddr_t nexthop, double expire_time) { rt->rt_seqno = seqnum; rt->rt_hops = metric; rt->rt_flags = RTF_UP; rt->rt_nexthop = nexthop; rt->rt_expire = expire_time; } void AODV::rt_down(aodv_rt_entry *rt) { /* * Ma e sure that you don't "down" a route more than once. */ if(rt->rt_flags == RTF_DOWN) { return; } // assert (rt->rt_seqno%2); // is the seqno odd? rt->rt_last_hop_count = rt->rt_hops; rt->rt_hops = INFINITY2; rt->rt_flags = RTF_DOWN; rt->rt_nexthop = 0; rt->rt_expire = 0; } /* rt_down function */

/* Route Handling Functions */ void AODV::rt_resolve(Pac et *p) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); aodv_rt_entry *rt; /* * Set the transmit failure callbac . That * won't change. */

ch->xmit_failure_ = aodv_rt_failed_callbac ; ch->xmit_failure_data_ = (void*) this; rt = rtable.rt_loo up(ih->daddr()); if(rt == 0) { rt = rtable.rt_add(ih->daddr()); } /* * If the route is up, forward the pac et */ if(rt->rt_flags == RTF_UP) { assert(rt->rt_hops != INFINITY2); forward(rt, p, NO_DELAY); } /* * if I am the source of the pac et, then do a Route Request. */ else if(ih->saddr() == index) { rqueue.enque(p); sendRequest(rt->rt_dst); } /* * A local repair is in progress. Buffer the pac et. */ else if (rt->rt_flags == RTF_IN_REPAIR) { rqueue.enque(p); } /* * I am trying to forward a pac et for someone else to which * I don't have a route. */ else { Pac et *rerr = Pac et::alloc(); struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr); /* * For now, drop the pac et and send error upstream. * Now the route errors are broadcast to upstream * neighbors - Mahesh 09/11/99 */ assert (rt->rt_flags == RTF_DOWN); re->DestCount = 0; re->unreachable_dst[re->DestCount] = rt->rt_dst; re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno; re->DestCount += 1; #ifdef DEBUG fprintf(stderr, "%s: sending RERR...\n", __FUNCTION__); #endif sendError(rerr, false); drop(p, DROP_RTR_NO_ROUTE); } } void AODV::rt_purge() { aodv_rt_entry *rt, *rtn;

double now = CURRENT_TIME; double delay = 0.0; Pac et *p; for(rt = rtable.head(); rt; rt = rtn) { // for each rt entry rtn = rt->rt_lin .le_next; if ((rt->rt_flags == RTF_UP) && (rt->rt_expire now)) { // if a valid route has expired, purge all pac ets 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 pac ets in the sendbuffer waiting, // forward them. This should not be needed, but this extra // chec 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 pac et for this destination waiting in // the sendbuffer, then send out route request. sendRequest // will chec whether it is time to really send out request // or not. // This may not be crucial to do it here, as each generated // pac et will do a sendRequest anyway. sendRequest(rt->rt_dst); } } /* Pac et Reception Routines */ void AODV::recv(Pac et *p, Handler*) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); assert(initialized()); //assert(p->incoming == 0); // XXXXX NOTE: use of incoming flag has been depracated; In order to trac dire ction of p t flow, direction_ in hdr_cmn is used instead. see pac et.h for detai ls.

if(ch->ptype() == PT_AODV) { ih->ttl_ -= 1; recvAODV(p); return; } /* * Must be a pac et I'm originating... */ if((ih->saddr() == index) && (ch->num_forwards() == 0)) { /* * Add the IP Header */ ch->size() += IP_HDR_LEN; // Added by Parag Dadhania && John Novatnac to handle broadcasting if ( (u_int32_t)ih->daddr() != IP_BROADCAST) ih->ttl_ = NETWORK_DIAMETER; } /* * I received a pac et that I sent. Probably * a routing loop. */ else if(ih->saddr() == index) { drop(p, DROP_RTR_ROUTE_LOOP); return; } /* * Pac et I'm forwarding... */ else { /* * Chec the TTL. If it is zero, then discard. */ if(--ih->ttl_ == 0) { drop(p, DROP_RTR_TTL); return; } } // Added by Parag Dadhania && John Novatnac to handle broadcasting if ( (u_int32_t)ih->daddr() != IP_BROADCAST) rt_resolve(p); else forward((aodv_rt_entry*) 0, p, NO_DELAY); } void AODV::recvAODV(Pac et *p) { struct hdr_aodv *ah = HDR_AODV(p); struct hdr_ip *ih = HDR_IP(p); assert(ih->sport() == RT_PORT); assert(ih->dport() == RT_PORT); /* * Incoming Pac ets. */ switch(ah->ah_type) {

case AODVTYPE_RREQ: recvRequest(p); brea ; case AODVTYPE_RREP: recvReply(p); brea ; case AODVTYPE_RERR: recvError(p); brea ; case AODVTYPE_HELLO: recvHello(p); brea ; default: fprintf(stderr, "Invalid AODV type (%x)\n", ah->ah_type); exit(1); } } void AODV::recvRequest(Pac et *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 Pac et::free(p); return; } if (id_loo up(rq->rq_src, rq->rq_bcast_id)) { #ifdef DEBUG fprintf(stderr, "%s: discarding request\n", __FUNCTION__); #endif // DEBUG Pac et::free(p); return; } /* * Cache the broadcast ID */ id_insert(rq->rq_src, rq->rq_bcast_id);

/* * We are either going to forward the REQUEST or generate a * REPLY. Before we do anything, we ma e sure that the REVERSE * route is in the route table. */ aodv_rt_entry *rt0; // rt0 is the reverse route rt0 = rtable.rt_loo up(rq->rq_src); if(rt0 == 0) { /* if not in the route table */ // create an entry for the reverse route. rt0 = rtable.rt_add(rq->rq_src); } rt0->rt_expire = max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE)); if ( (rq->rq_src_seqno > rt0->rt_seqno ) ||((rq->rq_src_seqno == rt0->rt_seqn o) && (rq->rq_hop_count rt0->rt_hops)) ) { // If we have a fresher seq no. or lesser #hops for the // same seq no., update the rt entry. Else don't bother. rt_update(rt0, rq->rq_src_seqno, rq->rq_hop_count, ih->saddr(),m ax(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE)) ); if (rt0->rt_req_timeout > 0.0) { // Reset the soft state and // Set expiry time to CURRENT_TIME + ACTIVE_ROUTE_TIMEOU T // This is because route is used in the forward directio n, // but only sources get benefited by this change rt0->rt_req_cnt = 0; rt0->rt_req_timeout = 0.0; rt0->rt_req_last_ttl = rq->rq_hop_count; rt0->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT; } /* Find out whether any buffered pac et can benefit from the * reverse route. * May need some change in the following code - Mahesh 09/11/99 */ assert (rt0->rt_flags == RTF_UP); Pac et *buffered_p t; while ((buffered_p t = rqueue.deque(rt0->rt_dst))) { if (rt0 && (rt0->rt_flags == RTF_UP)) { assert(rt0->rt_hops != INFINITY2); forward(rt0, buffered_p t, NO_DELAY); } } } // End for putting reverse route in rt table /* * We have ta en care of the reverse route stuff. * Now see whether we can send a route reply. */ rt = rtable.rt_loo up(rq->rq_dst);

// First chec if I am the destination .. if(rq->rq_dst == index) { #ifdef DEBUG fprintf(stderr, "%d - %s: destination sending reply\n", index, __FUNCTION__); #endif // DEBUG // Just to be safe, I use the max. Somebody may have // incremented the dst seqno. seqno = max(seqno, rq->rq_dst_seqno)+1; if (seqno%2) seqno++; sendReply(rq->rq_src, 1, index, seqno, MY_ROUTE_TIMEOUT, rq->rq_timestamp); Pac et::free(p); } // I am not the destination, but I may have a fresh enough route. else if (rt && (rt->rt_hops != INFINITY2) && (rt->rt_seqno >= rq->rq_dst_seqno) ) { //assert (rt->rt_flags == RTF_UP); assert(rq->rq_dst == rt->rt_dst); //assert ((rt->rt_seqno%2) == 0); // is the seqno even? sendReply(rq->rq_src, rt->rt_hops + 1, rq->rq_dst, rt->rt_seqno, (u_int32_t) (rt->rt_expire - CURRENT_TIME), // rt->rt_expire - CURRENT_TIME, rq->rq_timestamp); // Insert nexthops to RREQ source and RREQ destination in the // precursor lists of destination and source respectively rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source rt0->pc_insert(rt->rt_nexthop); // nexthop to RREQ destination #ifdef RREQ_GRAT_RREP sendReply(rq->rq_dst, rq->rq_hop_count, rq->rq_src, rq->rq_src_seqno, (u_int32_t) (rt->rt_expire - CURRENT_TIME), // rt->rt_expire - CURRENT_TIME, rq->rq_timestamp); #endif // TODO: send grat RREP to dst if G flag set in RREQ using rq->rq_src_seqno, rq>rq_hop_counT // DONE: Included gratuitous replies to be sent as per IETF aodv draft specifica // // // // // // IP Destination Hop Count Dest IP Address Dest Sequence Num Lifetime timestamp

tion. As of now, G flag has not been dynamically used and is always set or reset in aodv-pac et.h --- Anant Utgi ar, 09/16/02. Pac et::free(p); } /* * Can't reply. So forward the Route Request */ else { ih->saddr() = index; ih->daddr() = IP_BROADCAST; rq->rq_hop_count += 1; // Maximum sequence number seen en route if (rt) rq->rq_dst_seqno = max(rt->rt_seqno, rq->rq_dst_seqno); forward((aodv_rt_entry*) 0, p, DELAY); } } void AODV::recvReply(Pac et *p) { //struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p); aodv_rt_entry *rt; char suppress_reply = 0; double delay = 0.0; #ifdef DEBUG fprintf(stderr, "%d - %s: received a REPLY\n", index, __FUNCTION__); #endif // DEBUG /* * Got a reply. So reset the "soft state" maintained for * route requests in the request table. We don't really have * have a separate request table. It is just a part of the * routing table itself. */ // Note that rp_dst is the dest of the data pac ets, not the // the dest of the reply, which is the src of the data pac ets. rt = rtable.rt_loo up(rp->rp_dst); /* * If I don't have a rt entry to this host... adding */ if(rt == 0) { rt = rtable.rt_add(rp->rp_dst); } /* * Add a forward route table entry... here I am following * Per ins-Royer AODV paper almost literally - SRD 5/99 */ if ( (rt->rt_seqno rp->rp_dst_seqno) || // newer route ((rt->rt_seqno == rp->rp_dst_seqno) && (rt->rt_hops > rp->rp_hop_count)) ) { // shorter or better route

// Update the rt entry rt_update(rt, rp->rp_dst_seqno, rp->rp_hop_count, rp->rp_src, CURRENT_TIME + rp->rp_lifetime); // reset the soft state rt->rt_req_cnt = 0; rt->rt_req_timeout = 0.0; rt->rt_req_last_ttl = rp->rp_hop_count; 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->rt_disc_latency[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; } /* * Send all pac ets queued in the sendbuffer destined for * this destination. * XXX - observe the "second" use of p. */ Pac et *buf_p t; while((buf_p t = rqueue.deque(rt->rt_dst))) { if(rt->rt_hops != INFINITY2) { assert (rt->rt_flags == RTF_UP); // Delay them a little to help ARP. Otherwise ARP // may drop pac ets. -SRD 5/23/99 forward(rt, buf_p t, delay); delay += ARP_DELAY; } } } else { suppress_reply = 1; } /* * If reply is for me, discard it. */ if(ih->daddr() == index || suppress_reply) { Pac et::free(p); } /* * Otherwise, forward the Route Reply. */ else { // Find the rt entry aodv_rt_entry *rt0 = rtable.rt_loo up(ih->daddr()); // If the rt is up, forward if(rt0 && (rt0->rt_hops != INFINITY2)) { assert (rt0->rt_flags == RTF_UP); rp->rp_hop_count += 1; rp->rp_src = index; forward(rt0, p, NO_DELAY); // Insert the nexthop towards the RREQ source to

// the precursor list of the RREQ destination rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source } else { // I don't now how to forward .. drop the reply. #ifdef DEBUG fprintf(stderr, "%s: dropping Route Reply\n", __FUNCTION__); #endif // DEBUG drop(p, DROP_RTR_NO_ROUTE); } } } void AODV::recvError(Pac et *p) { struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_error *re = HDR_AODV_ERROR(p); aodv_rt_entry *rt; u_int8_t i; Pac et *rerr = Pac et::alloc(); struct hdr_aodv_error *nre = HDR_AODV_ERROR(rerr); nre->DestCount = 0; for (i=0; i<re->DestCount; i++) { // For each unreachable destination rt = rtable.rt_loo up(re->unreachable_dst[i]); if ( rt && (rt->rt_hops != INFINITY2) && (rt->rt_nexthop == ih->saddr()) && (rt->rt_seqno = re->unreachable_dst_seqno[i]) ) { assert(rt->rt_flags == RTF_UP); assert((rt->rt_seqno%2) == 0); // is the seqno even? #ifdef DEBUG fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\t(%d\t%u\t%d)\n", __FUNCTION__,CU RRENT_TIME, index, rt->rt_dst, rt->rt_seqno, rt->rt_nexthop, re->unreachable_dst[i],re->unreachable_dst_seqno[i], ih->saddr()); #endif // DEBUG rt->rt_seqno = re->unreachable_dst_seqno[i]; rt_down(rt); // Not sure whether this is the right thing to do Pac et *p t; while((p t = ifqueue->filter(ih->saddr()))) { drop(p t, DROP_RTR_MAC_CALLBACK); } // if precursor list non-empty add to RERR and delete the precursor list if (!rt->pc_empty()) { nre->unreachable_dst[nre->DestCount] = rt->rt_dst; nre->unreachable_dst_seqno[nre->DestCount] = rt->rt_seqno; nre->DestCount += 1; rt->pc_delete(); } } }

if (nre->DestCount > 0) { #ifdef DEBUG fprintf(stderr, "%s(%f): %d\t sending RERR...\n", __FUNCTION__, CURRENT_TIME, index); #endif // DEBUG sendError(rerr); } else { Pac et::free(rerr); } Pac et::free(p); }

/* Pac et Transmission Routines */ void AODV::forward(aodv_rt_entry *rt, Pac et *p, double delay) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); if(ih->ttl_ == 0) { #ifdef DEBUG fprintf(stderr, "%s: calling drop()\n", __PRETTY_FUNCTION__); #endif // DEBUG drop(p, DROP_RTR_TTL); return; } if (rt) { assert(rt->rt_flags == RTF_UP); rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT; ch->next_hop_ = rt->rt_nexthop; ch->addr_type() = NS_AF_INET; ch->direction() = hdr_cmn::DOWN; //important: change the pac et's direc tion } else { // if it is a broadcast pac et // assert(ch->ptype() == PT_AODV); // maybe a diff p t type li e gaf assert(ih->daddr() == (nsaddr_t) IP_BROADCAST); ch->addr_type() = NS_AF_NONE; ch->direction() = hdr_cmn::DOWN; //important: change the pac et's direc tion } if (ih->daddr() == (nsaddr_t) IP_BROADCAST) { // If it is a broadcast pac et assert(rt == 0); /* * Jitter the sending of broadcast pac ets by 10ms

*/ Scheduler::instance().schedule(target_, p, 0.01 * Random::uniform()); } else { // Not a broadcast pac et if(delay > 0.0) { Scheduler::instance().schedule(target_, p, delay); } else { // Not a broadcast pac et, no delay, send immediately Scheduler::instance().schedule(target_, p, 0.); } } } void AODV::sendRequest(nsaddr_t dst) { // Allocate a RREQ pac et Pac et *p = Pac et::alloc(); struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p); aodv_rt_entry *rt = rtable.rt_loo up(dst); assert(rt); /* * Rate limit sending of Route Requests. We are very conservative * about sending out route requests. */ if (rt->rt_flags == RTF_UP) { assert(rt->rt_hops != INFINITY2); Pac et::free((Pac et *)p); return; } if (rt->rt_req_timeout > CURRENT_TIME) { Pac et::free((Pac et *)p); return; } // rt_req_cnt is the no. of times we did networ -wide broadcast // RREQ_RETRIES is the maximum number we will allow before // going to a long timeout. if (rt->rt_req_cnt > RREQ_RETRIES) { rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT; rt->rt_req_cnt = 0; Pac et *buf_p t; while ((buf_p t = rqueue.deque(rt->rt_dst))) { drop(buf_p t, DROP_RTR_NO_ROUTE); } Pac et::free((Pac et *)p); return; } #ifdef DEBUG

fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d\n", ++route_request, index, rt->rt_dst); #endif // DEBUG // Determine the TTL to be used this time. // Dynamic TTL evaluation - SRD rt->rt_req_last_ttl = max(rt->rt_req_last_ttl,rt->rt_last_hop_count); if (0 == rt->rt_req_last_ttl) { // first time query broadcast ih->ttl_ = TTL_START; } else { // Expanding ring search. if (rt->rt_req_last_ttl TTL_THRESHOLD) ih->ttl_ = rt->rt_req_last_ttl + TTL_INCREMENT; else { // networ -wide broadcast ih->ttl_ = NETWORK_DIAMETER; rt->rt_req_cnt += 1; } } // remember the TTL used for the next time rt->rt_req_last_ttl = ih->ttl_; // // // // PerHopTime is the The factor 2.0 is Also note that we done networ wide roundtrip time per hop for route requests. just to be safe .. SRD 5/22/99 are ma ing timeouts to be larger if we have broadcast before.

rt->rt_req_timeout = 2.0 * (double) ih->ttl_ * PerHopTime(rt); if (rt->rt_req_cnt > 0) rt->rt_req_timeout *= rt->rt_req_cnt; rt->rt_req_timeout += CURRENT_TIME; // Don't let the timeout to be too large, however .. SRD 6/8/99 if (rt->rt_req_timeout > CURRENT_TIME + MAX_RREQ_TIMEOUT) rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT; rt->rt_expire = 0; #ifdef DEBUG fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d, tout %f ms\n", ++route_request, index, rt->rt_dst, rt->rt_req_timeout - CURRENT_TIME); #endif // DEBUG // Fill out the RREQ pac et // ch->uid() = 0; ch->ptype() = PT_AODV; ch->size() = IP_HDR_LEN + rq->size(); ch->iface() = -2; ch->error() = 0; ch->addr_type() = NS_AF_NONE; ch->prev_hop_ = index; // AODV hac ih->saddr() = index;

ih->daddr() = IP_BROADCAST; ih->sport() = RT_PORT; ih->dport() = RT_PORT; // Fill up some more fields. rq->rq_type = AODVTYPE_RREQ; rq->rq_hop_count = 1; rq->rq_bcast_id = bid++; rq->rq_dst = dst; rq->rq_dst_seqno = (rt ? rt->rt_seqno : 0); rq->rq_src = index; seqno += 2; assert ((seqno%2) == 0); rq->rq_src_seqno = seqno; rq->rq_timestamp = CURRENT_TIME; Scheduler::instance().schedule(target_, p, 0.); } void AODV::sendReply(nsaddr_t ipdst, u_int32_t hop_count, nsaddr_t rpdst, u_int32_t rpseq, u_int32_t lifetime, double timestamp) { Pac et *p = Pac et::alloc(); struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p); aodv_rt_entry *rt = rtable.rt_loo up(ipdst); #ifdef DEBUG fprintf(stderr, "sending Reply from %d at %.2f\n", index, Scheduler::instance(). cloc ()); #endif // DEBUG assert(rt); rp->rp_type = AODVTYPE_RREP; //rp->rp_flags = 0x00; rp->rp_hop_count = hop_count; rp->rp_dst = rpdst; rp->rp_dst_seqno = rpseq; rp->rp_src = index; rp->rp_lifetime = lifetime; rp->rp_timestamp = timestamp; // ch->uid() = 0; ch->ptype() = PT_AODV; ch->size() = IP_HDR_LEN + rp->size(); ch->iface() = -2; ch->error() = 0; ch->addr_type() = NS_AF_INET; ch->next_hop_ = rt->rt_nexthop; ch->prev_hop_ = index; // AODV hac ch->direction() = hdr_cmn::DOWN; ih->saddr() = index; ih->daddr() = ipdst; ih->sport() = RT_PORT; ih->dport() = RT_PORT; ih->ttl_ = NETWORK_DIAMETER;

Scheduler::instance().schedule(target_, p, 0.); } void AODV::sendError(Pac et *p, bool jitter) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_error *re = HDR_AODV_ERROR(p); #ifdef ERROR fprintf(stderr, "sending Error from %d at %.2f\n", index, Scheduler::instance(). cloc ()); #endif // DEBUG re->re_type = AODVTYPE_RERR; //re->reserved[0] = 0x00; re->reserved[1] = 0x00; // DestCount and list of unreachable destinations are already filled // ch->uid() = 0; ch->ptype() = PT_AODV; ch->size() = IP_HDR_LEN + re->size(); ch->iface() = -2; ch->error() = 0; ch->addr_type() = NS_AF_NONE; ch->next_hop_ = 0; ch->prev_hop_ = index; // AODV hac ch->direction() = hdr_cmn::DOWN;//important: change the pac et's direction ih->saddr() = ih->daddr() = ih->sport() = ih->dport() = ih->ttl_ = 1; index; IP_BROADCAST; RT_PORT; RT_PORT;

// Do we need any jitter? Yes if (jitter) Scheduler::instance().schedule(target_, p, 0.01*Random::uniform()); else Scheduler::instance().schedule(target_, p, 0.0); } /* Neighbor Management Functions */ void AODV::sendHello() { Pac et *p = Pac et::alloc(); struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_reply *rh = HDR_AODV_REPLY(p); #ifdef DEBUG fprintf(stderr, "sending Hello from %d at %.2f\n", index, Scheduler::instance(). cloc ()); #endif // DEBUG

rh->rp_type = AODVTYPE_HELLO; //rh->rp_flags = 0x00; rh->rp_hop_count = 1; rh->rp_dst = index; rh->rp_dst_seqno = seqno; rh->rp_lifetime = (1 + ALLOWED_HELLO_LOSS) * HELLO_INTERVAL; // ch->uid() = 0; ch->ptype() = PT_AODV; ch->size() = IP_HDR_LEN + rh->size(); ch->iface() = -2; ch->error() = 0; ch->addr_type() = NS_AF_NONE; ch->prev_hop_ = index; // AODV hac ih->saddr() = ih->daddr() = ih->sport() = ih->dport() = ih->ttl_ = 1; } void AODV::recvHello(Pac et *p) { //struct hdr_ip *ih = HDR_IP(p); struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p); AODV_Neighbor *nb; nb = nb_loo up(rp->rp_dst); if(nb == 0) { nb_insert(rp->rp_dst); } else { nb->nb_expire = CURRENT_TIME + (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL); } Pac et::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_lin ); seqno += 2; // set of neighbors changed assert ((seqno%2) == 0); } AODV_Neighbor* AODV::nb_loo up(nsaddr_t id) { AODV_Neighbor *nb = nbhead.lh_first; index; IP_BROADCAST; RT_PORT; RT_PORT;

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

for(; nb; nb = nb->nb_lin .le_next) { if(nb->nb_addr == id) brea ; } 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_lin _del(id); seqno += 2; // Set of neighbors changed assert ((seqno%2) == 0); for(; nb; nb = nb->nb_lin .le_next) { if(nb->nb_addr == id) { LIST_REMOVE(nb,nb_lin ); delete nb; brea ; } } handle_lin _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_lin .le_next; if(nb->nb_expire = now) { nb_delete(nb->nb_addr); } } }

S-ar putea să vă placă și