aodv.cc

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 1997, 1998 Carnegie Mellon University.  All Rights
00003 Reserved. 
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007 
00008 1. Redistributions of source code must retain the above copyright notice,
00009 this list of conditions and the following disclaimer.
00010 2. Redistributions in binary form must reproduce the above copyright notice,
00011 this list of conditions and the following disclaimer in the documentation
00012 and/or other materials provided with the distribution.
00013 3. The name of the author may not be used to endorse or promote products
00014 derived from this software without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00020 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00021 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00022 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00023 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00025 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 The AODV code developed by the CMU/MONARCH group was optimized and tuned by Samir Das and Mahesh Marina, University of Cincinnati. The work was partially done in Sun Microsystems. Modified for gratuitous replies by Anant Utgikar, 09/16/02.
00028 
00029 */
00030 
00031 //#include <ip.h>
00032 
00033 #include <aodv/aodv.h>
00034 #include <aodv/aodv_packet.h>
00035 #include <random.h>
00036 #include <cmu-trace.h>
00037 //#include <energy-model.h>
00038 
00039 #define max(a,b)        ( (a) > (b) ? (a) : (b) )
00040 #define CURRENT_TIME    Scheduler::instance().clock()
00041 
00042 //#define DEBUG
00043 //#define ERROR
00044 
00045 #ifdef DEBUG
00046 static int extra_route_reply = 0;
00047 static int limit_route_request = 0;
00048 static int route_request = 0;
00049 #endif
00050 
00051 
00052 /*
00053   TCL Hooks
00054 */
00055 
00056 
00057 int hdr_aodv::offset_;
00058 static class AODVHeaderClass : public PacketHeaderClass {
00059 public:
00060         AODVHeaderClass() : PacketHeaderClass("PacketHeader/AODV",
00061                                               sizeof(hdr_all_aodv)) {
00062       bind_offset(&hdr_aodv::offset_);
00063     } 
00064 } class_rtProtoAODV_hdr;
00065 
00066 static class AODVclass : public TclClass {
00067 public:
00068         AODVclass() : TclClass("Agent/AODV") {}
00069         TclObject* create(int argc, const char*const* argv) {
00070           assert(argc == 5);
00071           //return (new AODV((nsaddr_t) atoi(argv[4])));
00072       return (new AODV((nsaddr_t) Address::instance().str2addr(argv[4])));
00073         }
00074 } class_rtProtoAODV;
00075 
00076 
00077 int
00078 AODV::command(int argc, const char*const* argv) {
00079   if(argc == 2) {
00080   Tcl& tcl = Tcl::instance();
00081     
00082     if(strncasecmp(argv[1], "id", 2) == 0) {
00083       tcl.resultf("%d", index);
00084       return TCL_OK;
00085     }
00086     
00087     if(strncasecmp(argv[1], "start", 2) == 0) {
00088       btimer.handle((Event*) 0);
00089 
00090 #ifndef AODV_LINK_LAYER_DETECTION
00091       htimer.handle((Event*) 0);
00092       ntimer.handle((Event*) 0);
00093 #endif // LINK LAYER DETECTION
00094 
00095       rtimer.handle((Event*) 0);
00096       return TCL_OK;
00097      }               
00098   }
00099   else if(argc == 3) {
00100     if(strcmp(argv[1], "index") == 0) {
00101       index = atoi(argv[2]);
00102       return TCL_OK;
00103     }
00104 
00105     else if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "tracetarget") == 0) {
00106       logtarget = (Trace*) TclObject::lookup(argv[2]);
00107       if(logtarget == 0)
00108     return TCL_ERROR;
00109       return TCL_OK;
00110     }
00111     else if(strcmp(argv[1], "drop-target") == 0) {
00112     int stat = rqueue.command(argc,argv);
00113       if (stat != TCL_OK) return stat;
00114       return Agent::command(argc, argv);
00115     }
00116     else if(strcmp(argv[1], "if-queue") == 0) {
00117     ifqueue = (PriQueue*) TclObject::lookup(argv[2]);
00118       
00119       if(ifqueue == 0)
00120     return TCL_ERROR;
00121       return TCL_OK;
00122     }
00123     else if (strcmp(argv[1], "port-dmux") == 0) {
00124         dmux_ = (PortClassifier *)TclObject::lookup(argv[2]);
00125     if (dmux_ == 0) {
00126         fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__,
00127         argv[1], argv[2]);
00128         return TCL_ERROR;
00129     }
00130     return TCL_OK;
00131     }
00132   }
00133   return Agent::command(argc, argv);
00134 }
00135 
00136 /* 
00137    Constructor
00138 */
00139 
00140 AODV::AODV(nsaddr_t id) : Agent(PT_AODV),
00141               btimer(this), htimer(this), ntimer(this), 
00142               rtimer(this), lrtimer(this), rqueue() {
00143  
00144                 
00145   index = id;
00146   seqno = 2;
00147   bid = 1;
00148 
00149   LIST_INIT(&nbhead);
00150   LIST_INIT(&bihead);
00151 
00152   logtarget = 0;
00153   ifqueue = 0;
00154 }
00155 
00156 /*
00157   Timers
00158 */
00159 
00160 void
00161 BroadcastTimer::handle(Event*) {
00162   agent->id_purge();
00163   Scheduler::instance().schedule(this, &intr, BCAST_ID_SAVE);
00164 }
00165 
00166 void
00167 HelloTimer::handle(Event*) {
00168    agent->sendHello();
00169    double interval = MinHelloInterval + 
00170                  ((MaxHelloInterval - MinHelloInterval) * Random::uniform());
00171    assert(interval >= 0);
00172    Scheduler::instance().schedule(this, &intr, interval);
00173 }
00174 
00175 void
00176 NeighborTimer::handle(Event*) {
00177   agent->nb_purge();
00178   Scheduler::instance().schedule(this, &intr, HELLO_INTERVAL);
00179 }
00180 
00181 void
00182 RouteCacheTimer::handle(Event*) {
00183   agent->rt_purge();
00184 #define FREQUENCY 0.5 // sec
00185   Scheduler::instance().schedule(this, &intr, FREQUENCY);
00186 }
00187 
00188 void
00189 LocalRepairTimer::handle(Event* p)  {  // SRD: 5/4/99
00190 aodv_rt_entry *rt;
00191 struct hdr_ip *ih = HDR_IP( (Packet *)p);
00192 
00193    /* you get here after the timeout in a local repair attempt */
00194    /*   fprintf(stderr, "%s\n", __FUNCTION__); */
00195 
00196 
00197     rt = agent->rtable.rt_lookup(ih->daddr());
00198     
00199     if (rt && rt->rt_flags != RTF_UP) {
00200     // route is yet to be repaired
00201     // I will be conservative and bring down the route
00202     // and send route errors upstream.
00203     /* The following assert fails, not sure why */
00204     /* assert (rt->rt_flags == RTF_IN_REPAIR); */
00205         
00206       //rt->rt_seqno++;
00207       agent->rt_down(rt);
00208       // send RERR
00209 #ifdef DEBUG
00210       fprintf(stderr,"Node %d: Dst - %d, failed local repair\n",index, rt->rt_dst);
00211 #endif      
00212     }
00213     Packet::free((Packet *)p);
00214 }
00215 
00216 
00217 /*
00218    Broadcast ID Management  Functions
00219 */
00220 
00221 
00222 void
00223 AODV::id_insert(nsaddr_t id, u_int32_t bid) {
00224 BroadcastID *b = new BroadcastID(id, bid);
00225 
00226  assert(b);
00227  b->expire = CURRENT_TIME + BCAST_ID_SAVE;
00228  LIST_INSERT_HEAD(&bihead, b, link);
00229 }
00230 
00231 /* SRD */
00232 bool
00233 AODV::id_lookup(nsaddr_t id, u_int32_t bid) {
00234 BroadcastID *b = bihead.lh_first;
00235  
00236  // Search the list for a match of source and bid
00237  for( ; b; b = b->link.le_next) {
00238    if ((b->src == id) && (b->id == bid))
00239      return true;     
00240  }
00241  return false;
00242 }
00243 
00244 void
00245 AODV::id_purge() {
00246 BroadcastID *b = bihead.lh_first;
00247 BroadcastID *bn;
00248 double now = CURRENT_TIME;
00249 
00250  for(; b; b = bn) {
00251    bn = b->link.le_next;
00252    if(b->expire <= now) {
00253      LIST_REMOVE(b,link);
00254      delete b;
00255    }
00256  }
00257 }
00258 
00259 /*
00260   Helper Functions
00261 */
00262 
00263 double
00264 AODV::PerHopTime(aodv_rt_entry *rt) {
00265 int num_non_zero = 0, i;
00266 double total_latency = 0.0;
00267 
00268  if (!rt)
00269    return ((double) NODE_TRAVERSAL_TIME );
00270     
00271  for (i=0; i < MAX_HISTORY; i++) {
00272    if (rt->rt_disc_latency[i] > 0.0) {
00273       num_non_zero++;
00274       total_latency += rt->rt_disc_latency[i];
00275    }
00276  }
00277  if (num_non_zero > 0)
00278    return(total_latency / (double) num_non_zero);
00279  else
00280    return((double) NODE_TRAVERSAL_TIME);
00281 
00282 }
00283 
00284 /*
00285   Link Failure Management Functions
00286 */
00287 
00288 static void
00289 aodv_rt_failed_callback(Packet *p, void *arg) {
00290   ((AODV*) arg)->rt_ll_failed(p);
00291 }
00292 
00293 /*
00294  * This routine is invoked when the link-layer reports a route failed.
00295  */
00296 void
00297 AODV::rt_ll_failed(Packet *p) {
00298 struct hdr_cmn *ch = HDR_CMN(p);
00299 struct hdr_ip *ih = HDR_IP(p);
00300 aodv_rt_entry *rt;
00301 nsaddr_t broken_nbr = ch->next_hop_;
00302 
00303 #ifndef AODV_LINK_LAYER_DETECTION
00304  drop(p, DROP_RTR_MAC_CALLBACK);
00305 #else 
00306 
00307  /*
00308   * Non-data packets and Broadcast Packets can be dropped.
00309   */
00310   if(! DATA_PACKET(ch->ptype()) ||
00311      (u_int32_t) ih->daddr() == IP_BROADCAST) {
00312     drop(p, DROP_RTR_MAC_CALLBACK);
00313     return;
00314   }
00315   log_link_broke(p);
00316     if((rt = rtable.rt_lookup(ih->daddr())) == 0) {
00317     drop(p, DROP_RTR_MAC_CALLBACK);
00318     return;
00319   }
00320   log_link_del(ch->next_hop_);
00321 
00322 #ifdef AODV_LOCAL_REPAIR
00323   /* if the broken link is closer to the dest than source, 
00324      attempt a local repair. Otherwise, bring down the route. */
00325 
00326 
00327   if (ch->num_forwards() > rt->rt_hops) {
00328     local_rt_repair(rt, p); // local repair
00329     // retrieve all the packets in the ifq using this link,
00330     // queue the packets for which local repair is done, 
00331     return;
00332   }
00333   else  
00334 #endif // LOCAL REPAIR  
00335 
00336   {
00337     drop(p, DROP_RTR_MAC_CALLBACK);
00338     // Do the same thing for other packets in the interface queue using the
00339     // broken link -Mahesh
00340 while((p = ifqueue->filter(broken_nbr))) {
00341      drop(p, DROP_RTR_MAC_CALLBACK);
00342     }   
00343     nb_delete(broken_nbr);
00344   }
00345 
00346 #endif // LINK LAYER DETECTION
00347 }
00348 
00349 void
00350 AODV::handle_link_failure(nsaddr_t id) {
00351 aodv_rt_entry *rt, *rtn;
00352 Packet *rerr = Packet::alloc();
00353 struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr);
00354 
00355  re->DestCount = 0;
00356  for(rt = rtable.head(); rt; rt = rtn) {  // for each rt entry
00357    rtn = rt->rt_link.le_next; 
00358    if ((rt->rt_hops != INFINITY2) && (rt->rt_nexthop == id) ) {
00359      assert (rt->rt_flags == RTF_UP);
00360      assert((rt->rt_seqno%2) == 0);
00361      rt->rt_seqno++;
00362      re->unreachable_dst[re->DestCount] = rt->rt_dst;
00363      re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno;
00364 #ifdef DEBUG
00365      fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\n", __FUNCTION__, CURRENT_TIME,
00366              index, re->unreachable_dst[re->DestCount],
00367              re->unreachable_dst_seqno[re->DestCount], rt->rt_nexthop);
00368 #endif // DEBUG
00369      re->DestCount += 1;
00370      rt_down(rt);
00371    }
00372    // remove the lost neighbor from all the precursor lists
00373    rt->pc_delete(id);
00374  }   
00375 
00376  if (re->DestCount > 0) {
00377 #ifdef DEBUG
00378    fprintf(stderr, "%s(%f): %d\tsending RERR...\n", __FUNCTION__, CURRENT_TIME, index);
00379 #endif // DEBUG
00380    sendError(rerr, false);
00381  }
00382  else {
00383    Packet::free(rerr);
00384  }
00385 }
00386 
00387 void
00388 AODV::local_rt_repair(aodv_rt_entry *rt, Packet *p) {
00389 #ifdef DEBUG
00390   fprintf(stderr,"%s: Dst - %d\n", __FUNCTION__, rt->rt_dst); 
00391 #endif  
00392   // Buffer the packet 
00393   rqueue.enque(p);
00394 
00395   // mark the route as under repair 
00396   rt->rt_flags = RTF_IN_REPAIR;
00397 
00398   sendRequest(rt->rt_dst);
00399 
00400   // set up a timer interrupt
00401   Scheduler::instance().schedule(&lrtimer, p->copy(), rt->rt_req_timeout);
00402 }
00403 
00404 void
00405 AODV::rt_update(aodv_rt_entry *rt, u_int32_t seqnum, u_int16_t metric,
00406             nsaddr_t nexthop, double expire_time) {
00407 
00408      rt->rt_seqno = seqnum;
00409      rt->rt_hops = metric;
00410      rt->rt_flags = RTF_UP;
00411      rt->rt_nexthop = nexthop;
00412      rt->rt_expire = expire_time;
00413 }
00414 
00415 void
00416 AODV::rt_down(aodv_rt_entry *rt) {
00417   /*
00418    *  Make sure that you don't "down" a route more than once.
00419    */
00420 
00421   if(rt->rt_flags == RTF_DOWN) {
00422     return;
00423   }
00424 
00425   // assert (rt->rt_seqno%2); // is the seqno odd?
00426   rt->rt_last_hop_count = rt->rt_hops;
00427   rt->rt_hops = INFINITY2;
00428   rt->rt_flags = RTF_DOWN;
00429   rt->rt_nexthop = 0;
00430   rt->rt_expire = 0;
00431 
00432 } /* rt_down function */
00433 
00434 /*
00435   Route Handling Functions
00436 */
00437 
00438 void
00439 AODV::rt_resolve(Packet *p) {
00440 struct hdr_cmn *ch = HDR_CMN(p);
00441 struct hdr_ip *ih = HDR_IP(p);
00442 aodv_rt_entry *rt;
00443 
00444  /*
00445   *  Set the transmit failure callback.  That
00446   *  won't change.
00447   */
00448  ch->xmit_failure_ = aodv_rt_failed_callback;
00449  ch->xmit_failure_data_ = (void*) this;
00450     rt = rtable.rt_lookup(ih->daddr());
00451  if(rt == 0) {
00452       rt = rtable.rt_add(ih->daddr());
00453  }
00454 
00455  /*
00456   * If the route is up, forward the packet 
00457   */
00458     
00459  if(rt->rt_flags == RTF_UP) {
00460    assert(rt->rt_hops != INFINITY2);
00461    forward(rt, p, NO_DELAY);
00462  }
00463  /*
00464   *  if I am the source of the packet, then do a Route Request.
00465   */
00466     else if(ih->saddr() == index) {
00467    rqueue.enque(p);
00468    sendRequest(rt->rt_dst);
00469  }
00470  /*
00471   * A local repair is in progress. Buffer the packet. 
00472   */
00473  else if (rt->rt_flags == RTF_IN_REPAIR) {
00474    rqueue.enque(p);
00475  }
00476 
00477  /*
00478   * I am trying to forward a packet for someone else to which
00479   * I don't have a route.
00480   */
00481  else {
00482  Packet *rerr = Packet::alloc();
00483  struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr);
00484  /* 
00485   * For now, drop the packet and send error upstream.
00486   * Now the route errors are broadcast to upstream
00487   * neighbors - Mahesh 09/11/99
00488   */    
00489  
00490    assert (rt->rt_flags == RTF_DOWN);
00491    re->DestCount = 0;
00492    re->unreachable_dst[re->DestCount] = rt->rt_dst;
00493    re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno;
00494    re->DestCount += 1;
00495 #ifdef DEBUG
00496    fprintf(stderr, "%s: sending RERR...\n", __FUNCTION__);
00497 #endif
00498    sendError(rerr, false);
00499 
00500    drop(p, DROP_RTR_NO_ROUTE);
00501  }
00502 
00503 }
00504 
00505 void
00506 AODV::rt_purge() {
00507 aodv_rt_entry *rt, *rtn;
00508 double now = CURRENT_TIME;
00509 double delay = 0.0;
00510 Packet *p;
00511 
00512  for(rt = rtable.head(); rt; rt = rtn) {  // for each rt entry
00513    rtn = rt->rt_link.le_next;
00514    if ((rt->rt_flags == RTF_UP) && (rt->rt_expire < now)) {
00515    // if a valid route has expired, purge all packets from 
00516    // send buffer and invalidate the route.                    
00517     assert(rt->rt_hops != INFINITY2);
00518      while((p = rqueue.deque(rt->rt_dst))) {
00519 #ifdef DEBUG
00520        fprintf(stderr, "%s: calling drop()\n",
00521                        __FUNCTION__);
00522 #endif // DEBUG
00523        drop(p, DROP_RTR_NO_ROUTE);
00524      }
00525      rt->rt_seqno++;
00526      assert (rt->rt_seqno%2);
00527      rt_down(rt);
00528    }
00529    else if (rt->rt_flags == RTF_UP) {
00530    // If the route is not expired,
00531    // and there are packets in the sendbuffer waiting,
00532    // forward them. This should not be needed, but this extra 
00533    // check does no harm.
00534      assert(rt->rt_hops != INFINITY2);
00535      while((p = rqueue.deque(rt->rt_dst))) {
00536        forward (rt, p, delay);
00537        delay += ARP_DELAY;
00538      }
00539    } 
00540    else if (rqueue.find(rt->rt_dst))
00541    // If the route is down and 
00542    // if there is a packet for this destination waiting in
00543    // the sendbuffer, then send out route request. sendRequest
00544    // will check whether it is time to really send out request
00545    // or not.
00546    // This may not be crucial to do it here, as each generated 
00547    // packet will do a sendRequest anyway.
00548 
00549      sendRequest(rt->rt_dst); 
00550    }
00551 
00552 }
00553 
00554 /*
00555   Packet Reception Routines
00556 */
00557 
00558 void
00559 AODV::recv(Packet *p, Handler*) {
00560 struct hdr_cmn *ch = HDR_CMN(p);
00561 struct hdr_ip *ih = HDR_IP(p);
00562 
00563  assert(initialized());
00564  //assert(p->incoming == 0);
00565  // XXXXX NOTE: use of incoming flag has been depracated; In order to track direction of pkt flow, direction_ in hdr_cmn is used instead. see packet.h for details.
00566 
00567  if(ch->ptype() == PT_AODV) {
00568    ih->ttl_ -= 1;
00569    recvAODV(p);
00570    return;
00571  }
00572 
00573 
00574  /*
00575   *  Must be a packet I'm originating...
00576   */
00577 if((ih->saddr() == index) && (ch->num_forwards() == 0)) {
00578  /*
00579   * Add the IP Header
00580   */
00581    ch->size() += IP_HDR_LEN;
00582    // Added by Parag Dadhania && John Novatnack to handle broadcasting
00583    if ( (u_int32_t)ih->daddr() != IP_BROADCAST)
00584      ih->ttl_ = NETWORK_DIAMETER;
00585 }
00586  /*
00587   *  I received a packet that I sent.  Probably
00588   *  a routing loop.
00589   */
00590 else if(ih->saddr() == index) {
00591    drop(p, DROP_RTR_ROUTE_LOOP);
00592    return;
00593  }
00594  /*
00595   *  Packet I'm forwarding...
00596   */
00597  else {
00598  /*
00599   *  Check the TTL.  If it is zero, then discard.
00600   */
00601    if(--ih->ttl_ == 0) {
00602      drop(p, DROP_RTR_TTL);
00603      return;
00604    }
00605  }
00606 // Added by Parag Dadhania && John Novatnack to handle broadcasting
00607  if ( (u_int32_t)ih->daddr() != IP_BROADCAST)
00608    rt_resolve(p);
00609  else
00610    forward((aodv_rt_entry*) 0, p, NO_DELAY);
00611 }
00612 
00613 
00614 void
00615 AODV::recvAODV(Packet *p) {
00616  struct hdr_aodv *ah = HDR_AODV(p);
00617 
00618  assert(HDR_IP (p)->sport() == RT_PORT);
00619  assert(HDR_IP (p)->dport() == RT_PORT);
00620 
00621  /*
00622   * Incoming Packets.
00623   */
00624  switch(ah->ah_type) {
00625 
00626  case AODVTYPE_RREQ:
00627    recvRequest(p);
00628    break;
00629 
00630  case AODVTYPE_RREP:
00631    recvReply(p);
00632    break;
00633 
00634  case AODVTYPE_RERR:
00635    recvError(p);
00636    break;
00637 
00638  case AODVTYPE_HELLO:
00639    recvHello(p);
00640    break;
00641         
00642  default:
00643    fprintf(stderr, "Invalid AODV type (%x)\n", ah->ah_type);
00644    exit(1);
00645  }
00646 
00647 }
00648 
00649 
00650 void
00651 AODV::recvRequest(Packet *p) {
00652 struct hdr_ip *ih = HDR_IP(p);
00653 struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p);
00654 aodv_rt_entry *rt;
00655 
00656   /*
00657    * Drop if:
00658    *      - I'm the source
00659    *      - I recently heard this request.
00660    */
00661 
00662   if(rq->rq_src == index) {
00663 #ifdef DEBUG
00664     fprintf(stderr, "%s: got my own REQUEST\n", __FUNCTION__);
00665 #endif // DEBUG
00666     Packet::free(p);
00667     return;
00668   } 
00669 
00670  if (id_lookup(rq->rq_src, rq->rq_bcast_id)) {
00671 
00672 #ifdef DEBUG
00673    fprintf(stderr, "%s: discarding request\n", __FUNCTION__);
00674 #endif // DEBUG
00675  
00676    Packet::free(p);
00677    return;
00678  }
00679 
00680  /*
00681   * Cache the broadcast ID
00682   */
00683  id_insert(rq->rq_src, rq->rq_bcast_id);
00684 
00685 
00686 
00687  /* 
00688   * We are either going to forward the REQUEST or generate a
00689   * REPLY. Before we do anything, we make sure that the REVERSE
00690   * route is in the route table.
00691   */
00692  aodv_rt_entry *rt0; // rt0 is the reverse route 
00693    
00694    rt0 = rtable.rt_lookup(rq->rq_src);
00695    if(rt0 == 0) { /* if not in the route table */
00696    // create an entry for the reverse route.
00697      rt0 = rtable.rt_add(rq->rq_src);
00698    }
00699   
00700    rt0->rt_expire = max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE));
00701 
00702    if ( (rq->rq_src_seqno > rt0->rt_seqno ) ||
00703         ((rq->rq_src_seqno == rt0->rt_seqno) && 
00704      (rq->rq_hop_count < rt0->rt_hops)) ) {
00705    // If we have a fresher seq no. or lesser #hops for the 
00706    // same seq no., update the rt entry. Else don't bother.
00707 rt_update(rt0, rq->rq_src_seqno, rq->rq_hop_count, ih->saddr(),
00708                max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE)) );
00709      if (rt0->rt_req_timeout > 0.0) {
00710      // Reset the soft state and 
00711      // Set expiry time to CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT
00712      // This is because route is used in the forward direction,
00713      // but only sources get benefited by this change
00714        rt0->rt_req_cnt = 0;
00715        rt0->rt_req_timeout = 0.0; 
00716        rt0->rt_req_last_ttl = rq->rq_hop_count;
00717        rt0->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
00718      }
00719 
00720      /* Find out whether any buffered packet can benefit from the 
00721       * reverse route.
00722       * May need some change in the following code - Mahesh 09/11/99
00723       */
00724      assert (rt0->rt_flags == RTF_UP);
00725      Packet *buffered_pkt;
00726      while ((buffered_pkt = rqueue.deque(rt0->rt_dst))) {
00727        if (rt0 && (rt0->rt_flags == RTF_UP)) {
00728     assert(rt0->rt_hops != INFINITY2);
00729          forward(rt0, buffered_pkt, NO_DELAY);
00730        }
00731      }
00732    } 
00733    // End for putting reverse route in rt table
00734 
00735 
00736  /*
00737   * We have taken care of the reverse route stuff.
00738   * Now see whether we can send a route reply. 
00739   */
00740 
00741  rt = rtable.rt_lookup(rq->rq_dst);
00742 
00743  // First check if I am the destination ..
00744 
00745  if(rq->rq_dst == index) {
00746 
00747 #ifdef DEBUG
00748    fprintf(stderr, "%d - %s: destination sending reply\n",
00749                    index, __FUNCTION__);
00750 #endif // DEBUG
00751 
00752                
00753    // Just to be safe, I use the max. Somebody may have
00754    // incremented the dst seqno.
00755    seqno = max(seqno, rq->rq_dst_seqno)+1;
00756    if (seqno%2) seqno++;
00757 
00758    sendReply(rq->rq_src,           // IP Destination
00759              1,                    // Hop Count
00760              index,                // Dest IP Address
00761              seqno,                // Dest Sequence Num
00762              MY_ROUTE_TIMEOUT,     // Lifetime
00763              rq->rq_timestamp);    // timestamp
00764  
00765    Packet::free(p);
00766  }
00767 
00768  // I am not the destination, but I may have a fresh enough route.
00769 
00770  else if (rt && (rt->rt_hops != INFINITY2) && 
00771         (rt->rt_seqno >= rq->rq_dst_seqno) ) {
00772 
00773    //assert (rt->rt_flags == RTF_UP);
00774    assert(rq->rq_dst == rt->rt_dst);
00775    //assert ((rt->rt_seqno%2) == 0);    // is the seqno even?
00776    sendReply(rq->rq_src,
00777              rt->rt_hops + 1,
00778              rq->rq_dst,
00779              rt->rt_seqno,
00780          (u_int32_t) (rt->rt_expire - CURRENT_TIME),
00781          //             rt->rt_expire - CURRENT_TIME,
00782              rq->rq_timestamp);
00783    // Insert nexthops to RREQ source and RREQ destination in the
00784    // precursor lists of destination and source respectively
00785    rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source
00786    rt0->pc_insert(rt->rt_nexthop); // nexthop to RREQ destination
00787 
00788 #ifdef RREQ_GRAT_RREP  
00789 
00790    sendReply(rq->rq_dst,
00791              rq->rq_hop_count,
00792              rq->rq_src,
00793              rq->rq_src_seqno,
00794          (u_int32_t) (rt->rt_expire - CURRENT_TIME),
00795          //             rt->rt_expire - CURRENT_TIME,
00796              rq->rq_timestamp);
00797 #endif
00798    
00799 // TODO: send grat RREP to dst if G flag set in RREQ using rq->rq_src_seqno, rq->rq_hop_counT
00800    
00801 // DONE: Included gratuitous replies to be sent as per IETF aodv draft specification. As of now, G flag has not been dynamically used and is always set or reset in aodv-packet.h --- Anant Utgikar, 09/16/02.
00802 
00803     Packet::free(p);
00804  }
00805  /*
00806   * Can't reply. So forward the  Route Request
00807   */
00808  else {
00809    ih->saddr() = index;
00810    ih->daddr() = IP_BROADCAST;
00811    rq->rq_hop_count += 1;
00812    // Maximum sequence number seen en route
00813    if (rt) rq->rq_dst_seqno = max(rt->rt_seqno, rq->rq_dst_seqno);
00814    forward((aodv_rt_entry*) 0, p, DELAY);
00815  }
00816 
00817 }
00818 
00819 
00820 void
00821 AODV::recvReply(Packet *p) {
00822 //struct hdr_cmn *ch = HDR_CMN(p);
00823 struct hdr_ip *ih = HDR_IP(p);
00824 struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);
00825 aodv_rt_entry *rt;
00826 char suppress_reply = 0;
00827 double delay = 0.0;
00828     
00829 #ifdef DEBUG
00830  fprintf(stderr, "%d - %s: received a REPLY\n", index, __FUNCTION__);
00831 #endif // DEBUG
00832 
00833 
00834  /*
00835   *  Got a reply. So reset the "soft state" maintained for 
00836   *  route requests in the request table. We don't really have
00837   *  have a separate request table. It is just a part of the
00838   *  routing table itself. 
00839   */
00840  // Note that rp_dst is the dest of the data packets, not the
00841  // the dest of the reply, which is the src of the data packets.
00842 
00843  rt = rtable.rt_lookup(rp->rp_dst);
00844         
00845  /*
00846   *  If I don't have a rt entry to this host... adding
00847   */
00848  if(rt == 0) {
00849    rt = rtable.rt_add(rp->rp_dst);
00850  }
00851 
00852  /*
00853   * Add a forward route table entry... here I am following 
00854   * Perkins-Royer AODV paper almost literally - SRD 5/99
00855   */
00856 
00857  if ( (rt->rt_seqno < rp->rp_dst_seqno) ||   // newer route 
00858       ((rt->rt_seqno == rp->rp_dst_seqno) &&  
00859        (rt->rt_hops > rp->rp_hop_count)) ) { // shorter or better route
00860     
00861   // Update the rt entry 
00862   rt_update(rt, rp->rp_dst_seqno, rp->rp_hop_count,
00863         rp->rp_src, CURRENT_TIME + rp->rp_lifetime);
00864 
00865   // reset the soft state
00866   rt->rt_req_cnt = 0;
00867   rt->rt_req_timeout = 0.0; 
00868   rt->rt_req_last_ttl = rp->rp_hop_count;
00869   
00870 if (ih->daddr() == index) { // If I am the original source
00871   // Update the route discovery latency statistics
00872   // rp->rp_timestamp is the time of request origination
00873         
00874     rt->rt_disc_latency[(unsigned char)rt->hist_indx] = (CURRENT_TIME - rp->rp_timestamp)
00875                                          / (double) rp->rp_hop_count;
00876     // increment indx for next time
00877     rt->hist_indx = (rt->hist_indx + 1) % MAX_HISTORY;
00878   } 
00879 
00880   /*
00881    * Send all packets queued in the sendbuffer destined for
00882    * this destination. 
00883    * XXX - observe the "second" use of p.
00884    */
00885   Packet *buf_pkt;
00886   while((buf_pkt = rqueue.deque(rt->rt_dst))) {
00887     if(rt->rt_hops != INFINITY2) {
00888           assert (rt->rt_flags == RTF_UP);
00889     // Delay them a little to help ARP. Otherwise ARP 
00890     // may drop packets. -SRD 5/23/99
00891       forward(rt, buf_pkt, delay);
00892       delay += ARP_DELAY;
00893     }
00894   }
00895  }
00896  else {
00897   suppress_reply = 1;
00898  }
00899 
00900  /*
00901   * If reply is for me, discard it.
00902   */
00903 
00904 if(ih->daddr() == index || suppress_reply) {
00905    Packet::free(p);
00906  }
00907  /*
00908   * Otherwise, forward the Route Reply.
00909   */
00910  else {
00911  // Find the rt entry
00912 aodv_rt_entry *rt0 = rtable.rt_lookup(ih->daddr());
00913    // If the rt is up, forward
00914    if(rt0 && (rt0->rt_hops != INFINITY2)) {
00915         assert (rt0->rt_flags == RTF_UP);
00916      rp->rp_hop_count += 1;
00917      rp->rp_src = index;
00918      forward(rt0, p, NO_DELAY);
00919      // Insert the nexthop towards the RREQ source to 
00920      // the precursor list of the RREQ destination
00921      rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source
00922      
00923    }
00924    else {
00925    // I don't know how to forward .. drop the reply. 
00926 #ifdef DEBUG
00927      fprintf(stderr, "%s: dropping Route Reply\n", __FUNCTION__);
00928 #endif // DEBUG
00929      drop(p, DROP_RTR_NO_ROUTE);
00930    }
00931  }
00932 }
00933 
00934 
00935 void
00936 AODV::recvError(Packet *p) {
00937 struct hdr_ip *ih = HDR_IP(p);
00938 struct hdr_aodv_error *re = HDR_AODV_ERROR(p);
00939 aodv_rt_entry *rt;
00940 u_int8_t i;
00941 Packet *rerr = Packet::alloc();
00942 struct hdr_aodv_error *nre = HDR_AODV_ERROR(rerr);
00943 
00944  nre->DestCount = 0;
00945 
00946  for (i=0; i<re->DestCount; i++) {
00947  // For each unreachable destination
00948    rt = rtable.rt_lookup(re->unreachable_dst[i]);
00949    if ( rt && (rt->rt_hops != INFINITY2) &&
00950     (rt->rt_nexthop == ih->saddr()) &&
00951         (rt->rt_seqno <= re->unreachable_dst_seqno[i]) ) {
00952     assert(rt->rt_flags == RTF_UP);
00953     assert((rt->rt_seqno%2) == 0); // is the seqno even?
00954 #ifdef DEBUG
00955      fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\t(%d\t%u\t%d)\n", __FUNCTION__,CURRENT_TIME,
00956              index, rt->rt_dst, rt->rt_seqno, rt->rt_nexthop,
00957              re->unreachable_dst[i],re->unreachable_dst_seqno[i],
00958                  ih->saddr());
00959 #endif // DEBUG
00960         rt->rt_seqno = re->unreachable_dst_seqno[i];
00961         rt_down(rt);
00962 
00963    // Not sure whether this is the right thing to do
00964    Packet *pkt;
00965     while((pkt = ifqueue->filter(ih->saddr()))) {
00966             drop(pkt, DROP_RTR_MAC_CALLBACK);
00967         }
00968 
00969      // if precursor list non-empty add to RERR and delete the precursor list
00970         if (!rt->pc_empty()) {
00971             nre->unreachable_dst[nre->DestCount] = rt->rt_dst;
00972             nre->unreachable_dst_seqno[nre->DestCount] = rt->rt_seqno;
00973             nre->DestCount += 1;
00974         rt->pc_delete();
00975         }
00976    }
00977  } 
00978 
00979  if (nre->DestCount > 0) {
00980 #ifdef DEBUG
00981    fprintf(stderr, "%s(%f): %d\t sending RERR...\n", __FUNCTION__, CURRENT_TIME, index);
00982 #endif // DEBUG
00983    sendError(rerr);
00984  }
00985  else {
00986    Packet::free(rerr);
00987  }
00988 
00989  Packet::free(p);
00990 }
00991 
00992 
00993 /*
00994    Packet Transmission Routines
00995 */
00996 
00997 void
00998 AODV::forward(aodv_rt_entry *rt, Packet *p, double delay) {
00999 struct hdr_cmn *ch = HDR_CMN(p);
01000 struct hdr_ip *ih = HDR_IP(p);
01001 
01002  if(ih->ttl_ == 0) {
01003 
01004 #ifdef DEBUG
01005   fprintf(stderr, "%s: calling drop()\n", __PRETTY_FUNCTION__);
01006 #endif // DEBUG
01007  
01008   drop(p, DROP_RTR_TTL);
01009   return;
01010  }
01011 
01012  if (ch->ptype() != PT_AODV && ch->direction() == hdr_cmn::UP &&
01013     ((u_int32_t)ih->daddr() == IP_BROADCAST)
01014         || (ih->daddr() == here_.addr_)) {
01015     dmux_->recv(p,0);
01016     return;
01017  }
01018 
01019  if (rt) {
01020    assert(rt->rt_flags == RTF_UP);
01021    rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
01022    ch->next_hop_ = rt->rt_nexthop;
01023    ch->addr_type() = NS_AF_INET;
01024    ch->direction() = hdr_cmn::DOWN;       //important: change the packet's direction
01025  }
01026  else { // if it is a broadcast packet
01027    // assert(ch->ptype() == PT_AODV); // maybe a diff pkt type like gaf
01028    assert(ih->daddr() == (nsaddr_t) IP_BROADCAST);
01029    ch->addr_type() = NS_AF_NONE;
01030    ch->direction() = hdr_cmn::DOWN;       //important: change the packet's direction
01031  }
01032 
01033 if (ih->daddr() == (nsaddr_t) IP_BROADCAST) {
01034  // If it is a broadcast packet
01035    assert(rt == 0);
01036    /*
01037     *  Jitter the sending of broadcast packets by 10ms
01038     */
01039    Scheduler::instance().schedule(target_, p,
01040                        0.01 * Random::uniform());
01041  }
01042  else { // Not a broadcast packet 
01043    if(delay > 0.0) {
01044      Scheduler::instance().schedule(target_, p, delay);
01045    }
01046    else {
01047    // Not a broadcast packet, no delay, send immediately
01048      Scheduler::instance().schedule(target_, p, 0.);
01049    }
01050  }
01051 
01052 }
01053 
01054 
01055 void
01056 AODV::sendRequest(nsaddr_t dst) {
01057 // Allocate a RREQ packet 
01058 Packet *p = Packet::alloc();
01059 struct hdr_cmn *ch = HDR_CMN(p);
01060 struct hdr_ip *ih = HDR_IP(p);
01061 struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p);
01062 aodv_rt_entry *rt = rtable.rt_lookup(dst);
01063 
01064  assert(rt);
01065 
01066  /*
01067   *  Rate limit sending of Route Requests. We are very conservative
01068   *  about sending out route requests. 
01069   */
01070 
01071  if (rt->rt_flags == RTF_UP) {
01072    assert(rt->rt_hops != INFINITY2);
01073    Packet::free((Packet *)p);
01074    return;
01075  }
01076 
01077  if (rt->rt_req_timeout > CURRENT_TIME) {
01078    Packet::free((Packet *)p);
01079    return;
01080  }
01081 
01082  // rt_req_cnt is the no. of times we did network-wide broadcast
01083  // RREQ_RETRIES is the maximum number we will allow before 
01084  // going to a long timeout.
01085 
01086  if (rt->rt_req_cnt > RREQ_RETRIES) {
01087    rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
01088    rt->rt_req_cnt = 0;
01089  Packet *buf_pkt;
01090    while ((buf_pkt = rqueue.deque(rt->rt_dst))) {
01091        drop(buf_pkt, DROP_RTR_NO_ROUTE);
01092    }
01093    Packet::free((Packet *)p);
01094    return;
01095  }
01096 
01097 #ifdef DEBUG
01098    fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d\n",
01099                     ++route_request, index, rt->rt_dst);
01100 #endif // DEBUG
01101 
01102  // Determine the TTL to be used this time. 
01103  // Dynamic TTL evaluation - SRD
01104 
01105  rt->rt_req_last_ttl = max(rt->rt_req_last_ttl,rt->rt_last_hop_count);
01106 
01107  if (0 == rt->rt_req_last_ttl) {
01108  // first time query broadcast
01109    ih->ttl_ = TTL_START;
01110  }
01111  else {
01112  // Expanding ring search.
01113    if (rt->rt_req_last_ttl < TTL_THRESHOLD)
01114      ih->ttl_ = rt->rt_req_last_ttl + TTL_INCREMENT;
01115    else {
01116    // network-wide broadcast
01117      ih->ttl_ = NETWORK_DIAMETER;
01118      rt->rt_req_cnt += 1;
01119    }
01120  }
01121 
01122  // remember the TTL used  for the next time
01123  rt->rt_req_last_ttl = ih->ttl_;
01124 
01125  // PerHopTime is the roundtrip time per hop for route requests.
01126  // The factor 2.0 is just to be safe .. SRD 5/22/99
01127  // Also note that we are making timeouts to be larger if we have 
01128  // done network wide broadcast before. 
01129 
01130  rt->rt_req_timeout = 2.0 * (double) ih->ttl_ * PerHopTime(rt); 
01131  if (rt->rt_req_cnt > 0)
01132    rt->rt_req_timeout *= rt->rt_req_cnt;
01133  rt->rt_req_timeout += CURRENT_TIME;
01134 
01135  // Don't let the timeout to be too large, however .. SRD 6/8/99
01136  if (rt->rt_req_timeout > CURRENT_TIME + MAX_RREQ_TIMEOUT)
01137    rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
01138  rt->rt_expire = 0;
01139 
01140 #ifdef DEBUG
01141  fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d, tout %f ms\n",
01142              ++route_request, 
01143          index, rt->rt_dst, 
01144          rt->rt_req_timeout - CURRENT_TIME);
01145 #endif  // DEBUG
01146     
01147 
01148  // Fill out the RREQ packet 
01149  // ch->uid() = 0;
01150  ch->ptype() = PT_AODV;
01151  ch->size() = IP_HDR_LEN + rq->size();
01152  ch->iface() = -2;
01153  ch->error() = 0;
01154  ch->addr_type() = NS_AF_NONE;
01155  ch->prev_hop_ = index;          // AODV hack
01156 
01157  ih->saddr() = index;
01158  ih->daddr() = IP_BROADCAST;
01159  ih->sport() = RT_PORT;
01160  ih->dport() = RT_PORT;
01161 
01162  // Fill up some more fields. 
01163  rq->rq_type = AODVTYPE_RREQ;
01164  rq->rq_hop_count = 1;
01165  rq->rq_bcast_id = bid++;
01166  rq->rq_dst = dst;
01167  rq->rq_dst_seqno = (rt ? rt->rt_seqno : 0);
01168  rq->rq_src = index;
01169  seqno += 2;
01170  assert ((seqno%2) == 0);
01171  rq->rq_src_seqno = seqno;
01172  rq->rq_timestamp = CURRENT_TIME;
01173 
01174  Scheduler::instance().schedule(target_, p, 0.);
01175 
01176 }
01177 
01178 void
01179 AODV::sendReply(nsaddr_t ipdst, u_int32_t hop_count, nsaddr_t rpdst,
01180                 u_int32_t rpseq, u_int32_t lifetime, double timestamp) {
01181 Packet *p = Packet::alloc();
01182 struct hdr_cmn *ch = HDR_CMN(p);
01183 struct hdr_ip *ih = HDR_IP(p);
01184 struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);
01185 aodv_rt_entry *rt = rtable.rt_lookup(ipdst);
01186 
01187 #ifdef DEBUG
01188 fprintf(stderr, "sending Reply from %d at %.2f\n", index, Scheduler::instance().clock());
01189 #endif // DEBUG
01190  assert(rt);
01191 
01192  rp->rp_type = AODVTYPE_RREP;
01193  //rp->rp_flags = 0x00;
01194  rp->rp_hop_count = hop_count;
01195  rp->rp_dst = rpdst;
01196  rp->rp_dst_seqno = rpseq;
01197  rp->rp_src = index;
01198  rp->rp_lifetime = lifetime;
01199  rp->rp_timestamp = timestamp;
01200    
01201  // ch->uid() = 0;
01202  ch->ptype() = PT_AODV;
01203  ch->size() = IP_HDR_LEN + rp->size();
01204  ch->iface() = -2;
01205  ch->error() = 0;
01206  ch->addr_type() = NS_AF_INET;
01207  ch->next_hop_ = rt->rt_nexthop;
01208  ch->prev_hop_ = index;          // AODV hack
01209  ch->direction() = hdr_cmn::DOWN;
01210 
01211  ih->saddr() = index;
01212  ih->daddr() = ipdst;
01213  ih->sport() = RT_PORT;
01214  ih->dport() = RT_PORT;
01215  ih->ttl_ = NETWORK_DIAMETER;
01216 
01217  Scheduler::instance().schedule(target_, p, 0.);
01218 
01219 }
01220 
01221 void
01222 AODV::sendError(Packet *p, bool jitter) {
01223 struct hdr_cmn *ch = HDR_CMN(p);
01224 struct hdr_ip *ih = HDR_IP(p);
01225 struct hdr_aodv_error *re = HDR_AODV_ERROR(p);
01226     
01227 #ifdef ERROR
01228 fprintf(stderr, "sending Error from %d at %.2f\n", index, Scheduler::instance().clock());
01229 #endif // DEBUG
01230 
01231  re->re_type = AODVTYPE_RERR;
01232  //re->reserved[0] = 0x00; re->reserved[1] = 0x00;
01233  // DestCount and list of unreachable destinations are already filled
01234 
01235  // ch->uid() = 0;
01236  ch->ptype() = PT_AODV;
01237  ch->size() = IP_HDR_LEN + re->size();
01238  ch->iface() = -2;
01239  ch->error() = 0;
01240  ch->addr_type() = NS_AF_NONE;
01241  ch->next_hop_ = 0;
01242  ch->prev_hop_ = index;          // AODV hack
01243  ch->direction() = hdr_cmn::DOWN;       //important: change the packet's direction
01244 
01245  ih->saddr() = index;
01246  ih->daddr() = IP_BROADCAST;
01247  ih->sport() = RT_PORT;
01248  ih->dport() = RT_PORT;
01249  ih->ttl_ = 1;
01250 
01251  // Do we need any jitter? Yes
01252  if (jitter)
01253     Scheduler::instance().schedule(target_, p, 0.01*Random::uniform());
01254  else
01255     Scheduler::instance().schedule(target_, p, 0.0);
01256 
01257 }
01258 
01259 
01260 /*
01261    Neighbor Management Functions
01262 */
01263 
01264 void
01265 AODV::sendHello() {
01266 Packet *p = Packet::alloc();
01267 struct hdr_cmn *ch = HDR_CMN(p);
01268 struct hdr_ip *ih = HDR_IP(p);
01269 struct hdr_aodv_reply *rh = HDR_AODV_REPLY(p);
01270 
01271 #ifdef DEBUG
01272 fprintf(stderr, "sending Hello from %d at %.2f\n", index, Scheduler::instance().clock());
01273 #endif // DEBUG
01274 
01275  rh->rp_type = AODVTYPE_HELLO;
01276  //rh->rp_flags = 0x00;
01277  rh->rp_hop_count = 1;
01278  rh->rp_dst = index;
01279  rh->rp_dst_seqno = seqno;
01280  rh->rp_lifetime = (1 + ALLOWED_HELLO_LOSS) * HELLO_INTERVAL;
01281 
01282  // ch->uid() = 0;
01283  ch->ptype() = PT_AODV;
01284  ch->size() = IP_HDR_LEN + rh->size();
01285  ch->iface() = -2;
01286  ch->error() = 0;
01287  ch->addr_type() = NS_AF_NONE;
01288  ch->prev_hop_ = index;          // AODV hack
01289 
01290  ih->saddr() = index;
01291  ih->daddr() = IP_BROADCAST;
01292  ih->sport() = RT_PORT;
01293  ih->dport() = RT_PORT;
01294  ih->ttl_ = 1;
01295 
01296  Scheduler::instance().schedule(target_, p, 0.0);
01297 }
01298 
01299 
01300 void
01301 AODV::recvHello(Packet *p) {
01302 //struct hdr_ip *ih = HDR_IP(p);
01303 struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);
01304 AODV_Neighbor *nb;
01305 
01306  nb = nb_lookup(rp->rp_dst);
01307  if(nb == 0) {
01308    nb_insert(rp->rp_dst);
01309  }
01310  else {
01311    nb->nb_expire = CURRENT_TIME +
01312                    (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
01313  }
01314 
01315  Packet::free(p);
01316 }
01317 
01318 void
01319 AODV::nb_insert(nsaddr_t id) {
01320 AODV_Neighbor *nb = new AODV_Neighbor(id);
01321 
01322  assert(nb);
01323  nb->nb_expire = CURRENT_TIME +
01324                 (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
01325  LIST_INSERT_HEAD(&nbhead, nb, nb_link);
01326  seqno += 2;             // set of neighbors changed
01327  assert ((seqno%2) == 0);
01328 }
01329 
01330 
01331 AODV_Neighbor*
01332 AODV::nb_lookup(nsaddr_t id) {
01333 AODV_Neighbor *nb = nbhead.lh_first;
01334 
01335  for(; nb; nb = nb->nb_link.le_next) {
01336    if(nb->nb_addr == id) break;
01337  }
01338  return nb;
01339 }
01340 
01341 
01342 /*
01343  * Called when we receive *explicit* notification that a Neighbor
01344  * is no longer reachable.
01345  */
01346 void
01347 AODV::nb_delete(nsaddr_t id) {
01348 AODV_Neighbor *nb = nbhead.lh_first;
01349 
01350  log_link_del(id);
01351  seqno += 2;     // Set of neighbors changed
01352  assert ((seqno%2) == 0);
01353 
01354  for(; nb; nb = nb->nb_link.le_next) {
01355    if(nb->nb_addr == id) {
01356      LIST_REMOVE(nb,nb_link);
01357      delete nb;
01358      break;
01359    }
01360  }
01361 
01362  handle_link_failure(id);
01363 
01364 }
01365 
01366 
01367 /*
01368  * Purges all timed-out Neighbor Entries - runs every
01369  * HELLO_INTERVAL * 1.5 seconds.
01370  */
01371 void
01372 AODV::nb_purge() {
01373 AODV_Neighbor *nb = nbhead.lh_first;
01374 AODV_Neighbor *nbn;
01375 double now = CURRENT_TIME;
01376 
01377  for(; nb; nb = nbn) {
01378    nbn = nb->nb_link.le_next;
01379    if(nb->nb_expire <= now) {
01380      nb_delete(nb->nb_addr);
01381    }
01382  }
01383 
01384 }

Generated on Tue Mar 6 16:47:43 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6