Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

aodv.cc

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

Generated on Tue Apr 20 12:14:10 2004 for NS2.26SourcesOriginal by doxygen 1.3.3