module-aodv.cc

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 
00037 #include <random.h>
00038 #include<float.h>
00039 #include<node-core.h>
00040 #include "aodv-pkt.h"
00041 #include "module-aodv.h"
00042 
00043 
00044 #define CURRENT_TIME (Scheduler::instance().clock())
00045 #define max(a,b)        ( (a) > (b) ? (a) : (b) )
00046 
00047 extern packet_t PT_MCBR;
00048 
00049 packet_t PT_MRCL_AODV;
00050 
00051 static class AodvModuleClass : public TclClass {
00052 public:
00053         AodvModuleClass() : TclClass("Routing/AODV") {}
00054         TclObject* create(int, const char*const*) {
00055                 return (new AodvModule());
00056         }
00057 } class_aodv_module;
00058 
00059 
00060 /*------------------------------------------------------------
00061                                 TIMERS
00062 --------------------------------------------------------------*/
00063 
00064 void MrclBroadcastTimer::handle(Event*)
00065 {
00066         module->id_purge();
00067         Scheduler::instance().schedule(this, &intr, BCAST_ID_SAVE);
00068 }
00069 
00070 void MrclHelloTimer::handle(Event*)
00071 {
00072         module->sendHello();
00073         double interval = module->minHelloInterval() + 
00074                                 ((module->maxHelloInterval() - module->minHelloInterval()) * Random::uniform());
00075         assert(interval >= 0);
00076         Scheduler::instance().schedule(this, &intr, interval);
00077 }
00078 
00079 
00080 void MrclNeighborTimer::handle(Event*)
00081 {
00082         module->nb_purge();
00083         Scheduler::instance().schedule(this, &intr, HELLO_INTERVAL);
00084 }
00085 
00086 void MrclRouteCacheTimer::handle(Event*)
00087 {
00088         module->rt_purge();
00089         Scheduler::instance().schedule(this, &intr, module->routeCacheFrequency());
00090 }
00091 
00092 
00093 void MrclLocalRepairTimer::handle(Event* p)
00094 {
00095         // SRD: 5/4/99
00096         RoutingHdr *rhdr = HDR_ROUTING((Packet *)p);
00097         Aodv_rt_entry *rt = module->rtable_lookup(rhdr->daddr());
00098 
00099         /* you get here after the timeout in a local repair attempt */
00100         /*      fprintf(stderr, "%s\n", __FUNCTION__); */
00101 
00102         if (rt && rt->getFlags() != RTF_UP) {
00103                 // route is yet to be repaired
00104                 // I will be conservative and bring down the route
00105                 // and send route errors upstream.
00106                 /* The following assert fails, not sure why */
00107                 /* assert (rt->rt_flags == RTF_IN_REPAIR); */
00108                 
00109                 //rt->rt_seqno++;
00110                 module->rt_down(rt);
00111                 // send RERR
00112                 if (module->debug())
00113                         fprintf(stderr,"Node %d: Dst - %s, failed local repair\n",index, rt->getDst());
00114         
00115         }
00116         Packet::free((Packet *)p);
00117 }
00118 
00119 AodvModule::AodvModule() : 
00120         bcache_(0),
00121         ncache_(0),
00122         rqueue_(this),
00123         bid_(1),
00124         btimer(this),
00125         htimer(this),
00126         ntimer(this),
00127         rtimer(this),
00128         lrtimer(this),
00129         AODV_LINK_LAYER_DETECTION(TRUE),                // standardly disabled in ns2 (actived thanks to "AodvLinkLayerDetection" Tcl command)
00130         AODV_LOCAL_REPAIR(TRUE),
00131         AODV_MIRACLE_ROUTING(TRUE),
00132         ifqueue_(0),
00133         debugout(1),
00134         broadcastAddr_(0)
00135 {
00136         seqno_ = 2;
00137         bind_bool("RREQ_GRAT_RREP", &RREQ_GRAT_RREP);
00138         bind("minHelloIntervalRatio_",&minHelloIntervalRatio_);
00139         bind("maxHelloIntervalRatio_",&maxHelloIntervalRatio_);
00140         bind("helloInterval_",&helloInterval_);
00141         bind("routeCacheFrequency_",&routeCacheFrequency_);
00142         m_ = new HopCountMetric*;
00143         m_[0] = new HopCountMetric();
00144 }
00145 
00146 AodvModule::~AodvModule()
00147 {
00148         delete m_[0];
00149         delete m_;
00150 }
00151 
00152 int AodvModule::command(int argc, const char *const *argv)
00153 {
00154 //      Tcl& tcl = Tcl::instance();
00155         if (argc==2)
00156         {
00157                 if(strcmp(argv[1], "start") == 0)
00158                 {
00159                         btimer.handle((Event*) 0);
00160                         if (!AODV_LINK_LAYER_DETECTION)
00161                         {
00162                                 htimer.handle((Event*) 0);
00163                                 ntimer.handle((Event*) 0);
00164                         }
00165                         rtimer.handle((Event*) 0);
00166                         return TCL_OK;
00167                 }
00168                 else if(strcmp(argv[1], "AodvLinkLayerDetection") == 0)
00169                 {
00170                         AODV_LINK_LAYER_DETECTION = FALSE;
00171                         return TCL_OK;
00172                 }
00173                 else if(strcmp(argv[1], "AodvMiracleRouting") == 0)
00174                 {
00175                         AODV_MIRACLE_ROUTING = TRUE;
00176                         return TCL_OK;
00177                 }
00178                 else if(strcmp(argv[1], "AodvStandardNs2") == 0)
00179                 {
00180                         AODV_MIRACLE_ROUTING = FALSE;
00181                         return TCL_OK;
00182                 }
00183         }
00184         else if (argc==3)
00185         {
00186                 if (strcmp(argv[1],"setBroadcastAddr")==0)
00187                 {
00188                         MrclAddress *addr = (MrclAddress *)(TclObject::lookup(argv[2]));
00189                         if (addr==0)
00190                         {
00191                                 printf("AodvModule::command(%s), error in address lookup\n", argv[1]);
00192                                 return TCL_ERROR;
00193                         }
00194                         broadcastAddr_ = addr;
00195                         int len = addr->strlen() + 2;
00196                         char *str = new char[len];
00197                         addr->toString(str, len);
00198                         if(debug_>5)
00199                         {
00200                                 printf("AodvModule::command(%s) -- setBroadcastAddr(%d) = %s\n", argv[1], nAddresses(), str);
00201                         }
00202                         return TCL_OK;
00203                 }
00204                 else if(strcmp(argv[1], "if_queue") == 0)
00205                 {
00206                         ifqueue_ = (PriQueue*) TclObject::lookup(argv[2]);
00207                         if(ifqueue_ == 0)
00208                                 return TCL_ERROR;
00209                         return TCL_OK;
00210                 }
00211         }
00212         return MrclRouting::command(argc, argv);
00213 }
00214 
00215 
00216 /*
00217   Link Failure Management Functions
00218 */
00219 
00220 static void aodv_rt_failed_callback(Packet *p, void *arg)
00221 {
00222         ((AodvModule*) arg)->rt_ll_failed(p);
00223 }
00224 
00225 /*
00226  * This routine is invoked when the link-layer reports a route failed.
00227  */
00228 void AodvModule::rt_ll_failed(Packet *p)
00229 {
00230         struct hdr_cmn *ch = HDR_CMN(p);
00231         RoutingHdr *rhdr = HDR_ROUTING(p);
00232 
00233         Aodv_rt_entry *rt;
00234         char* broken_nbr = rhdr->nexthop();
00235 
00236         if (debug_>5)
00237         {
00238                 char addr[20];
00239                 char saddr[20];
00240                 int ip;
00241                 memcpy(&ip, rhdr->nexthop() + sizeof(int), sizeof(int));
00242                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00243                 memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
00244                 sprintf(saddr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00245                 printf("[AodvModule::rt_ll_failed] Node %s  %s failed pkt %d\n", saddr, addr, ch->uid());
00246         }
00247 
00248         if (!AODV_LINK_LAYER_DETECTION)
00249         {
00250                 drop(p, DROP_RTR_MAC_CALLBACK_VERBOSITY, DROP_RTR_MAC_CALLBACK);
00251                 return;
00252         }
00253         /*
00254         * Non-data packets and Broadcast Packets can be dropped.
00255         */
00256         if(! (DATA_PACKET(ch->ptype())||(ch->ptype()==PT_MCBR)) || MrclAddress::areEqual(rhdr->daddr(), broadcastAddr_->getAddr()) )
00257         {
00258                 drop(p, DROP_RTR_MAC_CALLBACK_VERBOSITY, DROP_RTR_MAC_CALLBACK);
00259                 return;
00260         }
00261 //      log_link_broke(p);
00262         if((rt = rtable_.rt_lookup(rhdr->daddr())) == 0)
00263         {
00264                 drop(p, DROP_RTR_MAC_CALLBACK_VERBOSITY, DROP_RTR_MAC_CALLBACK);
00265                 return;
00266         }
00267 //      log_link_del(ch->next_hop_);
00268 
00269         if (AODV_LOCAL_REPAIR)
00270         {
00271                 /* if the broken link is closer to the dest than source, 
00272                 attempt a local repair. Otherwise, bring down the route. */
00273                 if (ch->num_forwards() > rt->getHops())
00274                 {
00275                         local_rt_repair(rt, p); // local repair
00276                         // retrieve all the packets in the ifq using this link,
00277                         // queue the packets for which local repair is done, 
00278                         return;
00279                 }else if (rt->getFlags()==RTF_IN_REPAIR) return;                // broken link is in repairing phase
00280         }
00281         nb_delete(broken_nbr);
00282         drop(p, DROP_RTR_MAC_CALLBACK_VERBOSITY, DROP_RTR_MAC_CALLBACK);
00283         // Do the same thing for other packets in the interface queue using the
00284         // broken link -Mahesh
00285         if (ifqueue_)
00286         {
00287                 while((p = ifqueue_->filter((nsaddr_t)(*(broken_nbr+sizeof(int))))))
00288                 {
00289                         drop(p, DROP_RTR_MAC_CALLBACK_VERBOSITY, DROP_RTR_MAC_CALLBACK);
00290                 }
00291         }
00292 //      nb_delete(broken_nbr);
00293 }
00294 
00295 
00296 void AodvModule::handle_link_failure(char* id)
00297 {
00298         if (debug_>5)
00299         {
00300                 char addr[20];
00301                 int ip;
00302                 memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
00303                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00304                 char addr2[20];
00305                 memcpy(&ip, id + sizeof(int), sizeof(int));
00306                 sprintf(addr2,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00307                 printf("[AodvModule::handle_link_failure] Node %s link failure %s\n", addr, addr2);
00308         }
00309         Aodv_rt_entry *rt, *rtn;
00310         Packet *rerr = Packet::alloc();
00311 //      hdr_mrcl_aodv *ah = HDR_MRCL_AODV(rerr);
00312 //      hdr_mrcl_aodv_error *re = (hdr_mrcl_aodv_error *)(ah->body);
00313         hdr_mrcl_aodv_error *re = HDR_MRCL_AODV_ERROR(rerr);
00314 
00315         re->DestCount = 0;
00316         for(rt = rtable_.head(); rt; rt = rtn)
00317         {
00318                 // for each rt entry
00319                 rtn = rtable_.next(rt);
00320         if ((rt->getHops() != INFINITY2) && (MrclAddress::areEqual(rt->getNexthop(),id) ) )
00321         {
00322                 assert (rt->getFlags() == RTF_UP);
00323                 assert((rt->getSeqno()%2) == 0);
00324                 rt->incrSeqno();
00325                 MrclAddress::storeAddr(&(re->unreachable_dst[re->DestCount * MRCL_ADDRESS_MAX_LEN]), rt->getDst());
00326                 re->unreachable_dst_seqno[re->DestCount] = rt->getSeqno();
00327         if (debug_)
00328         {
00329                 fprintf(stderr, "[AodvModule::handle_link_failure] %s(%f): %d\t(%d\t%u\t%d)\n", __FUNCTION__, CURRENT_TIME,
00330                                 index, re->unreachable_dst[re->DestCount],
00331                                 re->unreachable_dst_seqno[re->DestCount], (char *)(rt->getNexthop()+ sizeof(int)));
00332         }
00333 
00334         re->DestCount += 1;
00335         rt_down(rt);
00336         }
00337         // remove the lost neighbor from all the precursor lists
00338         rt->pc_delete(id);
00339         }
00340         
00341         if (re->DestCount > 0) {
00342 #ifdef DEBUG
00343                 fprintf(stderr, "%s(%f): %d\tsending RERR...\n", __FUNCTION__, CURRENT_TIME, index);
00344 #endif // DEBUG
00345                 sendError(rerr, false);
00346         }
00347         else
00348         {
00349                 Packet::free(rerr);
00350         }
00351 }
00352 
00353 void AodvModule::local_rt_repair(Aodv_rt_entry *rt, Packet *p)
00354 {
00355         if (debug_)
00356         {
00357                 fprintf(stderr,"[AodvModule::local_rt_repair] %s: Dst - %d\n", __FUNCTION__, (char *)(rt->getDst()+ sizeof(int)));
00358         }
00359   // Buffer the packet 
00360   rqueue_.enque(p);
00361 
00362   // mark the route as under repair 
00363   rt->setFlags(RTF_IN_REPAIR);
00364 
00365   sendRequest(rt->getDst());
00366 
00367   // set up a timer interrupt
00368   Scheduler::instance().schedule(&lrtimer, p->copy(), rt->rt_req_timeout);
00369 }
00370 
00371 
00372 
00373 /*
00374   Route Handling Functions
00375 */
00376 
00377 
00378 void AodvModule::rt_update(Aodv_rt_entry *rt, int seqnum, int metric, char *nexthop, double expire_time)
00379 {
00380         rt->setSeqno(seqnum);
00381         rt->setHops(metric);
00382         rt->setFlags(RTF_UP);
00383         rt->setNexthop(nexthop);
00384         rt->setExpire(expire_time);
00385 }
00386 
00387 void AodvModule::rt_down(Aodv_rt_entry *rt)
00388 {
00389         /*
00390         *  Make sure that you don't "down" a route more than once.
00391         */
00392 
00393         if(rt->getFlags() == RTF_DOWN) 
00394         {
00395                 return;
00396         }
00397 
00398         // assert (rt->rt_seqno%2); // is the seqno odd?
00399         rt->setLastHopCount(rt->getHops());
00400         rt->setHops(INFINITY2);
00401         rt->setFlags(RTF_DOWN);
00402         rt->resetNexthop();
00403         rt->setExpire(0);
00404 }
00405 
00406 
00407 void AodvModule::rt_purge()
00408 {
00409         Aodv_rt_entry *rt, *rtn;
00410         double now = CURRENT_TIME;
00411         double delay = 0.0;
00412         Packet *p;
00413 
00414         char addr[20];
00415         int ip;
00416         if (debug_>5)
00417         {       memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
00418                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00419                 printf("Node %s check route table at %f\n", addr, CURRENT_TIME);
00420         }
00421         for(rt = rtable_.head(); rt; rt = rtn)
00422         {  // for each rt entry
00423 //              rtn = rt->rt_link.le_next;                      // standard ns version: not used
00424                 rtn = rtable_.next(rt);
00425                 if (debug_>5)
00426                 {
00427                         memcpy(&ip, rt->getDst() + sizeof(int), sizeof(int));
00428                         sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00429                         printf("\tdst %s expire at %f\n", addr, rt->getExpire());
00430                 }
00431                 if ((rt->getFlags() == RTF_UP) && (rt->getExpire() < now))
00432                 {
00433                         // if a valid route has expired, purge all packets from 
00434                         // send buffer and invalidate the route.                    
00435                         assert(rt->getHops() != INFINITY2);
00436                         while((p = rqueue_.deque(rt->getDst())))
00437                         {
00438                                 if (debug_)
00439                                         fprintf(stderr, "%s: calling drop()\n", __FUNCTION__);
00440                                 drop(p, AODV_DROP_RTR_NO_ROUTE_VERBOSITY, AODV_DROP_RTR_NO_ROUTE);
00441                         }
00442                         rt->incrSeqno();
00443                         assert (rt->getSeqno()%2);
00444                         rt_down(rt);
00445                 }
00446                 else if (rt->getFlags() == RTF_UP)
00447                 {
00448                         // If the route is not expired,
00449                         // and there are packets in the sendbuffer waiting,
00450                         // forward them. This should not be needed, but this extra 
00451                         // check does no harm.
00452                         assert(rt->getHops() != INFINITY2);
00453                         while((p = rqueue_.deque(rt->getDst())))
00454                         {
00455                                 forward (p, rt, delay);
00456                                 delay += ARP_DELAY;
00457                         }
00458                 }
00459                 else if (rqueue_.find(rt->getDst()))
00460                         // If the route is down and 
00461                         // if there is a packet for this destination waiting in
00462                         // the sendbuffer, then send out route request. sendRequest
00463                         // will check whether it is time to really send out request or not.
00464                         // This may not be crucial to do it here, as each generated 
00465                         // packet will do a sendRequest anyway.
00466                         sendRequest(rt->getDst()); 
00467         }
00468 
00469 }
00470 
00471 
00472 
00473 int AodvModule::controlPacket(Packet *p)
00474 {
00475         hdr_cmn *ch = HDR_CMN(p);
00476 
00477         if(ch->ptype() != PT_AODV)
00478                 return 0;
00479         
00480         recvAodv(p);
00481         return 1;
00482 }
00483 
00484 
00485 void AodvModule::forward(Packet *p)
00486 {
00487 
00488         struct hdr_cmn *ch = HDR_CMN(p);
00489         RoutingHdr *rhdr = HDR_ROUTING(p);
00490 
00491         // check destination
00492         assert(nAddresses() > 0);
00493         assert(broadcastAddr_);
00494                 
00495         if (ch->ptype() != PT_AODV && ch->direction() == hdr_cmn::UP &&
00496                 (broadcastAddr_->isEqual(rhdr->daddr()))
00497                 || isMyAddress(rhdr->daddr())) 
00498         {
00499                 // packet for me (unicast or broadcast)
00500                 //dmux_->recv(p,0);
00501                 if (debug_>5)
00502                 {
00503                         char addr[20];
00504                         int ip;
00505                         memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
00506                         sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00507                         Position* pos = getPosition();
00508                         printf("[AodvModule::forward1] %s My packet %d -> send up (%f,%f) at %f ttl %d\n", addr, ch->uid(), pos->getX(), pos->getY(), CURRENT_TIME, rhdr->ttl());
00509                 }
00510                 sendUp(p);
00511                 return;
00512         }
00513         // packet not for me -> try to solve the address
00514         if ((MrclAddress::areEqual(rhdr->daddr(),rhdr->nexthop()))&&!(isMyAddress(rhdr->daddr())))
00515         {
00516                 return;
00517         }
00518         int nRoute = getRoute(rhdr->daddr(), p, 0);
00519         if (debug_>5)
00520         {
00521                 char addr[20];
00522                 char saddr[20];
00523                 int ip;
00524                 memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
00525                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00526                 memcpy(&ip, rhdr->saddr() + sizeof(int), sizeof(int));
00527                 sprintf(saddr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00528                 printf("[AodvModule] Node %s Try to solve new packet from %s at %.10f\n", addr, saddr, CURRENT_TIME);
00529                 printf("[AodvModule] find %d route(s)\n", nRoute);
00530         }
00531         if (nRoute != 0)
00532         {
00533                 if (rhdr->getModuleRoute(rhdr->moduleRouteCount() - 1) == getId())
00534                 {
00535                         if ((isMyAddress(rhdr->saddr()))&&(ch->num_forwards()==0))
00536                                 rhdr->ttl_ = NETWORK_DIAMETER;
00537                         else
00538                                 rhdr->ttl_--;
00539 
00540                         if (nRoute > 0)
00541                         {
00542                                 if (AODV_MIRACLE_ROUTING==FALSE)
00543                                 {
00544                                         // standard AODV working -> try to forward directly the packet despite possible better paths via others routing module
00545                                         int i = 0;
00546                                         while((rhdr->getModuleRoute(rhdr->moduleRouteCount() - 1)!=getId())||(i<nRoute-1))
00547                                         {
00548                                                 getRoute(rhdr->daddr(), p, ++i);
00549                                         }
00550                                         if (rhdr->getModuleRoute(rhdr->moduleRouteCount() - 1)==getId())
00551                                         {
00552                                                 // route known by this module
00553                                                 Aodv_rt_entry *rt = rtable_.rt_lookup(rhdr->daddr());
00554                                                 if (debug_>5)
00555                                                 {
00556                                                         char saddr[20];
00557                                                         int ip;
00558                                                         memcpy(&ip, rt->getNexthop() + sizeof(int), sizeof(int));
00559                                                         sprintf(saddr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00560                                                         printf("[AodvModule::forward1] forward to %s\n", saddr);
00561                                                 }
00562                                                 forward(p, rt,0);
00563                                         }
00564                                         else
00565                                         {
00566                                                 // route does not known by this module -> try ro solve it
00567                                                 resolve(p);
00568                                                 return;
00569                                         }
00570                                 }
00571                                 else
00572                                 {
00573                                         if (rhdr->getModuleRoute(rhdr->moduleRouteCount() - 1)==getId())
00574                                         {
00575                                                 // this AODV module has the better metric to forward this packet
00576                                                 Aodv_rt_entry *rt = rtable_.rt_lookup(rhdr->daddr());
00577                                                 forward(p, rt,0);
00578                                         }
00579                                         else
00580                                         {
00581                                                 // route known by another routing module
00582                                                 // this packet has to be forwarded to other routing module
00583                                                 getRoute(rhdr->daddr(), p, 0);
00584                                                 if (debug_>5)
00585                                                         printf("[AodvModule::forward2] sendUp to another routing module %d %d \n", rhdr->moduleRouteCount(), getId());
00586                                                 sendUp(p);
00587                                         }
00588                                 }
00589                         }
00590                         else
00591                         {
00592                                 resolve(p);
00593                                 return;
00594                         }
00595                 }
00596                 else
00597                 {
00598                         // this packet has to be forwarded to another routing module
00599                         if (debug_)
00600                                 printf("[AodvModule::forward1] sendUp to another routing module \n");
00601 //              mrhdr->setSendup();
00602                         sendUp(p);
00603                 }
00604         }
00605         else
00606         {
00607                 // packet can not be forwarded
00608                 if (debug_>5)
00609                         printf("[AodvModule::forward1]  NO ROUTE to HOST %s -> DROP packet\n", rhdr->daddr());
00610                 drop(p, AODV_DROP_RTR_NO_ROUTE_VERBOSITY, DROP_RTR_NO_ROUTE);
00611         }
00612 }
00613 
00614 
00615 
00616 void AodvModule::resolve(Packet *p)
00617 {
00618         RoutingHdr *rhdr = HDR_ROUTING(p);
00619 
00620         if (debug_>5)
00621         {
00622                 char addr[20];
00623                 int ip;
00624                 memcpy(&ip, rhdr->daddr() + sizeof(int), sizeof(int));
00625                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00626                 printf("[AodvModule::resolve] route unknown to %s -> start Route Discovery and put the packet in queue\n", addr);
00627         }
00628         Aodv_rt_entry *rt = rtable_.rt_lookup(rhdr->daddr());
00629         if(rt == 0)
00630         {
00631                 rt = rtable_.rt_add(rhdr->daddr());
00632         }
00633         /*
00634         *  if I am the source of the packet, then do a Route Request.
00635         */
00636         if(isMyAddress(rhdr->saddr()))
00637         {
00638                 rqueue_.enque(p);
00639                 sendRequest(rt->getDst());
00640         }
00641         else
00642         {
00643                 if (rt->getFlags() == RTF_IN_REPAIR)
00644                 {
00645                         /*
00646                         *       A local repair is in progress. Buffer the packet. 
00647                         */
00648                         rqueue_.enque(p);
00649                 }
00650                 else
00651                 {
00652                         Packet *rerr = Packet::alloc();
00653 //                      hdr_mrcl_aodv *ah = HDR_MRCL_AODV(rerr);
00654 //                      hdr_mrcl_aodv_error *re = (hdr_mrcl_aodv_error *)(ah->body);
00655                         hdr_mrcl_aodv_error *re = HDR_MRCL_AODV_ERROR(rerr);
00656                         /* 
00657                         * For now, drop the packet and send error upstream.
00658                         * Now the route errors are broadcast to upstream
00659                         * neighbors - Mahesh 09/11/99
00660                         */
00661         
00662                         assert(rt->getFlags() == RTF_DOWN);
00663                         re->DestCount = 0;
00664                         MrclAddress::storeAddr(&(re->unreachable_dst[re->DestCount * MRCL_ADDRESS_MAX_LEN]), rt->getDst());
00665                         re->unreachable_dst_seqno[re->DestCount] = rt->getSeqno();
00666                         re->DestCount += 1;
00667                         if (debug_)
00668                         {
00669                                 fprintf(stderr, "[AodvModule::resolve] %s: sending RERR...\n", __FUNCTION__);
00670                         }
00671                         sendError(rerr, false);
00672                         drop(p, AODV_DROP_RTR_NO_ROUTE_VEROSITY, AODV_DROP_RTR_NO_ROUTE);
00673                 }
00674         }
00675 }
00676 
00677 void AodvModule::recvAodv(Packet *p)
00678 {
00679         hdr_mrcl_aodv *ah = HDR_MRCL_AODV(p);
00680 
00681         switch(ah->ah_type)
00682         {
00683                 case AODVTYPE_RREQ:
00684                         recvRequest(p);
00685                         break;
00686                 case AODVTYPE_RREP:
00687                         recvReply(p);
00688                         break;
00689                 case AODVTYPE_RERR:
00690                         recvError(p);
00691                         break;
00692                 case AODVTYPE_HELLO:
00693                         recvHello(p);
00694                         break;
00695                 default:
00696                         fprintf(stderr, "Invalid AODV type (%x)\n", ah->ah_type);
00697                         exit(1);
00698         }
00699 }
00700 
00701 int AodvModule::id_lookup(char *addr, int bid)
00702 {
00703         for(AddrList *cur = bcache_; cur; cur = cur->next)
00704         {
00705                 if(MrclAddress::areEqual(cur->addr,addr) && bid == cur->id)
00706                 {
00707                         return 1;
00708                 }
00709         }
00710         return 0;
00711 }
00712 
00713 
00714 void AodvModule::id_delete(AddrList *a)
00715 {
00716         if(a == bcache_)
00717         {
00718                 bcache_ = a->next;
00719                 if(bcache_)
00720                         bcache_->prev = 0;
00721         }
00722         else
00723         {
00724                 a->prev->next = a->next;
00725                 if(a->next)
00726                         a->next->prev = a->prev;
00727         }
00728         delete a;
00729 }
00730 
00731 void AodvModule::id_purge()
00732 {
00733         double now = CURRENT_TIME;
00734         AddrList *cur = bcache_;
00735         while(cur)
00736         {
00737                 if(cur->expire <= now)
00738                 {
00739                         if(cur != bcache_)
00740                         {
00741                                 cur = cur->prev;
00742                                 id_delete(cur->next);
00743                                 cur = cur->next;
00744                         }
00745                         else
00746                         {
00747                                 id_delete(cur);
00748                                 cur = ncache_;
00749                         }
00750                 }
00751                 else
00752                         cur = cur->next;
00753         }
00754 }
00755 
00756 
00757 void AodvModule::id_insert(char *addr, int bid)
00758 {
00759         AddrList *a = new AddrList;
00760         MrclAddress::storeAddr(a->addr, addr);
00761         a->id = bid;
00762         a->expire = Scheduler::instance().clock() + BCAST_ID_SAVE;
00763         a->next = bcache_;
00764         a->prev = 0;
00765         if(bcache_)
00766                 bcache_->prev = a;
00767         bcache_ = a;
00768 }
00769 
00770 void AodvModule::recvRequest(Packet *p)
00771 {
00772         if (debugout)
00773         {
00774                 char addr[20];
00775                 int ip;
00776                 memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
00777                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00778                 char saddr[20];
00779                 RoutingHdr* mrhdr = HDR_ROUTING(p);
00780                 memcpy(&ip, mrhdr->saddr() + sizeof(int), sizeof(int));
00781                 sprintf(saddr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
00782                 printf("[AodvModule::recvRequest] Node %s recv REQ from %s\n", addr, saddr);
00783         }
00784 //      hdr_mrcl_aodv *ah = HDR_MRCL_AODV(p);
00785 //      hdr_mrcl_aodv_request *rq = (hdr_mrcl_aodv_request *)(ah->body);
00786         hdr_mrcl_aodv_request *rq = HDR_MRCL_AODV_REQUEST(p);
00787         RoutingHdr *rhdr = HDR_ROUTING(p);
00788         /*
00789         * Drop if:
00790         *      - I'm the source
00791         *      - I recently heard this request.
00792         */
00793         if(isMyAddress(rq->rq_src))
00794         {
00795                 drop(p, AODV_GOT_MY_REQUEST_VERBOSITY, AODV_GOT_MY_REQUEST);
00796                 return;
00797         }
00798 
00799         if(id_lookup(rq->rq_src, rq->rq_bcast_id))
00800         {
00801                 drop(p, AODV_DISCARD_REQUEST_VERBOSITY, AODV_DISCARD_REQUEST);
00802                 return;
00803         }
00804         /*
00805         * Cache the broadcast ID
00806         */
00807         id_insert(rq->rq_src, rq->rq_bcast_id);
00808         /* 
00809         * We are either going to forward the REQUEST or generate a
00810         * REPLY. Before we do anything, we make sure that the REVERSE
00811         * route is in the route table.
00812         */
00813         Aodv_rt_entry *rt0 = rtable_.rt_lookup(rq->rq_src); //rt0 is the reverse route
00814         if(rt0 == 0) 
00815         { /* if not in the route table */
00816                 // create an entry for the reverse route.
00817                 rt0 = rtable_.rt_add(rq->rq_src);
00818         }
00819   
00820         rt0->setExpire(max(rt0->getExpire(), (CURRENT_TIME + REV_ROUTE_LIFE)));
00821 
00822         if ( (rq->rq_src_seqno > rt0->getSeqno() ) || ((rq->rq_src_seqno == rt0->getSeqno()) && (rq->rq_hop_count < rt0->getHops())) ) 
00823         {
00824                 // If we have a fresher seq no. or lesser #hops for the 
00825                 // same seq no., update the rt entry. Else don't bother.
00826                 rt_update(rt0, rq->rq_src_seqno, rq->rq_hop_count, rhdr->saddr(),
00827                         max(rt0->getExpire(), (CURRENT_TIME + REV_ROUTE_LIFE)) );
00828                 if (rt0->rt_req_timeout > 0.0) 
00829                 {
00830                         // Reset the soft state and 
00831                         // Set expiry time to CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT
00832                         // This is because route is used in the forward direction,
00833                         // but only sources get benefited by this change
00834                         rt0->rt_req_cnt = 0;
00835                         rt0->rt_req_timeout = 0.0; 
00836                         rt0->setReqLastTtl(rq->rq_hop_count);
00837                         rt0->setExpire(CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT);
00838                 }
00839                 /* Find out whether any buffered packet can benefit from the 
00840                 * reverse route.
00841                 * May need some change in the following code - Mahesh 09/11/99
00842                 */
00843                 assert (rt0->getFlags() == RTF_UP);
00844                 Packet *buffered_pkt;
00845                 while ((buffered_pkt = rqueue_.deque(rt0->getDst()))) 
00846                 {
00847                         if (rt0 && (rt0->getFlags() == RTF_UP)) 
00848                         {
00849                                 assert(rt0->getHops() != INFINITY2);
00850                                 forward(buffered_pkt, rt0);
00851                         }
00852                 }
00853         }
00854         // End for putting reverse route in rt table
00855 
00856         /*
00857         * We have taken care of the reverse route stuff.
00858         * Now see whether we can send a route reply. 
00859         */
00860         Aodv_rt_entry *rt = rtable_.rt_lookup(rq->rq_dst);
00861         
00862         // First check if I am the destination ..
00863         if(isMyAddress(rq->rq_dst)) 
00864         {
00865 
00866                 if(debug_)
00867                         fprintf(stderr, "%s: destination sending reply\n",
00868                                  __FUNCTION__);
00869                 // Just to be safe, I use the max. Somebody may have
00870                 // incremented the dst seqno.
00871                 seqno_ = max(seqno_, rq->rq_dst_seqno)+1;
00872                 if (seqno_ % 2) 
00873                         seqno_++;
00874 
00875                 assert(nAddresses() > 0);
00876                 sendReply(rq->rq_src,                   // IP Destination
00877                                 1,                      // Hop Count
00878                                 getAddress(0)->getAddr(),                       // Dest IP Address
00879                                 seqno_,                 // Dest Sequence Num
00880                                 MY_ROUTE_TIMEOUT,       // Lifetime
00881                                 rq->rq_timestamp);      // timestamp
00882  
00883                 drop(p, AODV_RECEIVED_REQUEST_VERBOSITY, AODV_RECEIVED_REQUEST);
00884         }
00885         // I am not the destination, but I may have a fresh enough route.
00886         else
00887         {
00888                 if (AODV_MIRACLE_ROUTING==FALSE)
00889                 {
00890                         // standard ns2 behaviour -> answer with the info only of the local routing table
00891                         if (rt && (rt->getHops() != INFINITY2) && 
00892                                 (rt->getSeqno() >= rq->rq_dst_seqno) ) 
00893                         {
00894                                 //assert (rt->rt_flags == RTF_UP);
00895                                 assert(MrclAddress::areEqual(rq->rq_dst, rt->getDst()));
00896                                 //assert ((rt->rt_seqno%2) == 0);       // is the seqno even?
00897                                 sendReply(rq->rq_src,
00898                                         rt->getHops() + 1,
00899                                         rq->rq_dst,
00900                                         rt->getSeqno(),
00901                                         (int)(rt->getExpire() - CURRENT_TIME),
00902                                         rq->rq_timestamp);
00903                                 // Insert nexthops to RREQ source and RREQ destination in the
00904                                 // precursor lists of destination and source respectively
00905                                 rt->pc_insert(rt0->getNexthop()); // nexthop to RREQ source
00906                                 rt0->pc_insert(rt->getNexthop()); // nexthop to RREQ destination
00907                 
00908                                 if(RREQ_GRAT_RREP)
00909                                         sendReply(rq->rq_dst,
00910                                                 rq->rq_hop_count,
00911                                                 rq->rq_src,
00912                                                 rq->rq_src_seqno,
00913                                                 (int)(rt->getExpire() - CURRENT_TIME),
00914                                                 rq->rq_timestamp);
00915                 
00916                         
00917                                 // TODO: send grat RREP to dst if G flag set in RREQ using rq->rq_src_seqno, rq->rq_hop_counT
00918                         
00919                                 // 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.
00920                                 
00921                                 drop(p, AODV_RECEIVED_REQUEST_VERBOSITY, AODV_RECEIVED_REQUEST_RESOLVED);
00922                         }
00923                         /*
00924                         * Can't reply. So forward the  Route Request
00925                         */
00926                         else 
00927                         {
00928                                 assert(nAddresses() > 0);
00929                                 assert(broadcastAddr_);
00930                                 MrclAddress::storeAddr(rhdr->saddr(), getAddress(0)->getAddr());
00931                                 MrclAddress::storeAddr(rhdr->daddr(), broadcastAddr_->getAddr());
00932                                 rq->rq_hop_count += 1;
00933                                 // Maximum sequence number seen en route
00934                                 if (rt) 
00935                                         rq->rq_dst_seqno = max(rt->getSeqno(), rq->rq_dst_seqno);
00936                                 forward(p, (Aodv_rt_entry *)0);
00937                         }
00938                 }
00939                 else
00940                 {
00941                         // enhanced beahviour mode -> test all the routing modules within the MIRACLE routing framework
00942                         int nRoute = getRoute(rhdr->daddr(), p, 0);
00943                         if (nRoute>0)
00944                         {
00945                                 if (rhdr->getModuleRoute(rhdr->moduleRouteCount() - 1)==getId())
00946                                 {
00947                                         Aodv_rt_entry *rt0 = rtable_.rt_lookup(rhdr->daddr());
00948                                         if(rt0 && (rt0->getHops() != INFINITY2)&& (rt->getSeqno() >= rq->rq_dst_seqno) )
00949                                         {
00950                                                 // Directly
00951                                                 //assert (rt->rt_flags == RTF_UP);
00952                                                 assert(MrclAddress::areEqual(rq->rq_dst, rt->getDst()));
00953                                                 //assert ((rt->rt_seqno%2) == 0);       // is the seqno even?
00954                                                 sendReply(rq->rq_src,
00955                                                         rq->rq_hop_count + 1,
00956                                                         rq->rq_dst,
00957                                                         rq->rq_dst_seqno,
00958                                                         ACTIVE_ROUTE_TIMEOUT,
00959                                                         rq->rq_timestamp);
00960                                         }
00961                                 }
00962                                 else
00963                                 {
00964                                         // via another routing module within this miracle routing framework
00965 //                                              if (rt)
00966 //                                              printf("rt %p\n", rt);
00967 //                                              sendReply(rq->rq_src,
00968 //                                              rt->getHops() + 1,
00969 //                                              rq->rq_dst,
00970 //                                              rt->getSeqno(),
00971 //                                              (int)(rt->getExpire() - CURRENT_TIME),
00972 //                                              rq->rq_timestamp);
00973 //                                      // Insert nexthops to RREQ source and RREQ destination in the
00974 //                                      // precursor lists of destination and source respectively
00975 //                                      rt->pc_insert(rt0->getNexthop()); // nexthop to RREQ source
00976 //                                      rt0->pc_insert(rt->getNexthop()); // nexthop to RREQ destination
00977                         
00978                                         if(RREQ_GRAT_RREP)
00979                                                 sendReply(rq->rq_src,
00980                                                         rq->rq_hop_count,
00981                                                         rq->rq_dst,
00982                                                         rq->rq_dst_seqno,
00983                                                         ACTIVE_ROUTE_TIMEOUT,
00984                                                         rq->rq_timestamp);
00985                                 }
00986                                 drop(p, AODV_RECEIVED_REQUEST_VERBOSITY, AODV_RECEIVED_REQUEST_RESOLVED);
00987 
00988                         }
00989                         else
00990                         {
00991                                 assert(nAddresses() > 0);
00992                                 assert(broadcastAddr_);
00993                                 MrclAddress::storeAddr(rhdr->saddr(), getAddress(0)->getAddr());
00994                                 MrclAddress::storeAddr(rhdr->daddr(), broadcastAddr_->getAddr());
00995                                 rq->rq_hop_count += 1;
00996                                 // Maximum sequence number seen en route
00997                                 if (rt) 
00998                                         rq->rq_dst_seqno = max(rt->getSeqno(), rq->rq_dst_seqno);
00999                                 forward(p, (Aodv_rt_entry *)0);
01000                         }
01001                 }
01002         }
01003 }
01004 
01005 void AodvModule::recvReply(Packet *p)
01006 {
01007         RoutingHdr *rhdr = HDR_ROUTING(p);
01008 //      hdr_mrcl_aodv *ah = HDR_MRCL_AODV(p);
01009 //      hdr_mrcl_aodv_reply *rp = (hdr_mrcl_aodv_reply *)(ah->body);
01010         hdr_mrcl_aodv_reply *rp = HDR_MRCL_AODV_REPLY(p);
01011         char suppress_reply = 0;
01012         double delay = 0.0;
01013         
01014         if(debug_)
01015                 fprintf(stderr, "%d - %s: received a REPLY\n", index, __FUNCTION__);
01016         
01017         /*
01018         *  Got a reply. So reset the "soft state" maintained for 
01019         *  route requests in the request table. We don't really have
01020         *  have a separate request table. It is just a part of the
01021         *  routing table itself. 
01022         */
01023         // Note that rp_dst is the dest of the data packets, not the
01024         // the dest of the reply, which is the src of the data packets.
01025 
01026         Aodv_rt_entry *rt = rtable_.rt_lookup(rp->rp_dst);
01027         
01028         /*
01029         *  If I don't have a rt entry to this host... adding
01030         */
01031         if(rt == 0) 
01032         {
01033                 rt = rtable_.rt_add(rp->rp_dst);
01034         }
01035         /*
01036         * Add a forward route table entry... here I am following 
01037         * Perkins-Royer AODV paper almost literally - SRD 5/99
01038         */
01039 
01040         if ( (rt->getSeqno() < rp->rp_dst_seqno) ||   // newer route 
01041                 ((rt->getSeqno() == rp->rp_dst_seqno) &&  (rt->getHops() > rp->rp_hop_count)) ) 
01042         { // shorter or better route
01043         
01044                 // Update the rt entry 
01045                 rt_update(rt, rp->rp_dst_seqno, rp->rp_hop_count,
01046                         rp->rp_src, CURRENT_TIME + rp->rp_lifetime);
01047                 // reset the soft state
01048                 rt->rt_req_cnt = 0;
01049                 rt->rt_req_timeout = 0.0; 
01050                 rt->setReqLastTtl(rp->rp_hop_count);
01051   
01052                 if (isMyAddress(rhdr->daddr())) 
01053                 { // If I am the original source
01054                         // Update the route discovery latency statistics
01055                         // rp->rp_timestamp is the time of request origination
01056                 
01057                         rt->setDiscLatency((unsigned char)rt->getHistIndx(), (CURRENT_TIME - rp->rp_timestamp)
01058                                          / (double) rp->rp_hop_count);
01059                         // increment indx for next time
01060                         rt->setHistIndx((char)((rt->getHistIndx() + 1) % MAX_HISTORY));
01061                 }       
01062 
01063                 /*
01064                 * Send all packets queued in the sendbuffer destined for
01065                 * this destination. 
01066                 * XXX - observe the "second" use of p.
01067                 */
01068                 Packet *buf_pkt;
01069                 while((buf_pkt = rqueue_.deque(rt->getDst()))) 
01070                 {
01071                         if(rt->getHops() != INFINITY2) 
01072                         {
01073                                 assert (rt->getFlags() == RTF_UP);
01074                                 // Delay them a little to help ARP. Otherwise ARP 
01075                                 // may drop packets. -SRD 5/23/99
01076                                 forward(buf_pkt, rt, delay);
01077                                 delay += ARP_DELAY;
01078                         }
01079                 }
01080         }
01081         else 
01082         {
01083                 suppress_reply = 1;
01084         }
01085 
01086         /*
01087         * If reply is for me, discard it.
01088         */
01089         if(isMyAddress(rhdr->daddr())) 
01090         {
01091 //              char addr[20];
01092 //              int ip;
01093 //              memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
01094 //              sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01095 //              printf("[AodvModule::recvReply] %s recv my RREP -> discard it\n", addr);
01096                 drop(p, AODV_REPLY_FOR_ME_VERBOSITY, AODV_REPLY_FOR_ME);
01097         }
01098         else if(suppress_reply) 
01099         {
01100 //              char addr[20];
01101 //              int ip;
01102 //              memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
01103 //              sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01104 //              printf("[AodvModule::recvReply] %s <suppress_reply> -> discard it\n", addr);
01105                 drop(p, AODV_SUPPRESS_REPLY_VERBOSITY, AODV_SUPPRESS_REPLY);
01106         }
01107         /*
01108         * Otherwise, forward the Route Reply.
01109         */
01110         else 
01111         {
01112         /*      char addr[20];
01113                 int ip;
01114                 memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
01115                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01116                 printf("[AodvModule::recvReply] %s forward RREP\n", addr);
01117         */      // Find the rt entry
01118                 Aodv_rt_entry *rt0 = rtable_.rt_lookup(rhdr->daddr());
01119                 // If the rt is up, forward
01120                 if(rt0 && (rt0->getHops() != INFINITY2)) 
01121                 {
01122                         assert (rt0->getFlags() == RTF_UP);
01123                         rp->rp_hop_count += 1;
01124                         assert(nAddresses() > 0);
01125                         MrclAddress::storeAddr(rp->rp_src, getAddress(0)->getAddr());
01126                         forward(p, rt0);
01127                         // Insert the nexthop towards the RREQ source to 
01128                         // the precursor list of the RREQ destination
01129                         rt->pc_insert(rt0->getNexthop()); // nexthop to RREQ source
01130       
01131                 }
01132                 else 
01133                 {
01134                         // I don't know how to forward .. drop the reply. 
01135                         if(debug_)
01136                                 fprintf(stderr, "%s: dropping Route Reply\n", __FUNCTION__);
01137                         drop(p, AODV_DROP_RTR_NO_ROUTE_VERBOSITY, DROP_RTR_NO_ROUTE);
01138                 }
01139         }
01140 }
01141 
01142 void AodvModule::recvError(Packet *p)
01143 {
01144         RoutingHdr *rhdr = HDR_ROUTING(p);
01145 //      hdr_mrcl_aodv *ah = HDR_MRCL_AODV(p);
01146 //      hdr_mrcl_aodv_error *re = (hdr_mrcl_aodv_error *)(ah->body);
01147         hdr_mrcl_aodv_error *re = HDR_MRCL_AODV_ERROR(p);
01148 
01149         Aodv_rt_entry *rt;
01150         int i;
01151         Packet *rerr = Packet::alloc();
01152 //      hdr_mrcl_aodv *ah_err = HDR_MRCL_AODV(rerr);
01153 //      hdr_mrcl_aodv_error *nre = (hdr_mrcl_aodv_error *)(ah_err->body);
01154         hdr_mrcl_aodv_error *nre = HDR_MRCL_AODV_ERROR(rerr);
01155 
01156         if (debugout)
01157         {
01158                 char addr[20];
01159                 int ip;
01160                 memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
01161                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01162                 char saddr[20];
01163                 RoutingHdr* mrhdr = HDR_ROUTING(p);
01164                 memcpy(&ip, mrhdr->saddr() + sizeof(int), sizeof(int));
01165                 sprintf(saddr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01166                 printf("[AodvModule::recvError] Node %s recv RERR from %s\n", addr, saddr);
01167         }
01168                 
01169         nre->DestCount = 0;
01170 
01171         for (i=0; i<re->DestCount; i++) 
01172         {
01173                 // For each unreachable destination
01174                 rt = rtable_.rt_lookup(&(re->unreachable_dst[i]));
01175                 if ( rt && (rt->getHops() != INFINITY2) &&
01176                         (MrclAddress::areEqual(rt->getNexthop(), rhdr->saddr())) &&
01177                         (rt->getSeqno() <= re->unreachable_dst_seqno[i]) ) 
01178                 {
01179                         if (rt->getFlags() == RTF_IN_REPAIR) continue; // this node has just recognized the link failure and it's trying to repair the link
01180                         assert(rt->getFlags() == RTF_UP);
01181                         assert((rt->getSeqno()%2) == 0); // is the seqno even?
01182                         rt->setSeqno(re->unreachable_dst_seqno[i]);
01183                         rt_down(rt);
01184 
01185                         // Not sure whether this is the right thing to do
01186                         if (ifqueue_)
01187                         {
01188                                 Packet *pkt;
01189                                 struct hdr_ip *ih = HDR_IP(p);
01190                                 while((pkt = ifqueue_->filter(ih->saddr()))) 
01191                                 {
01192                                         drop(pkt, DROP_RTR_MAC_CALLBACK_VERBOSITY, DROP_RTR_MAC_CALLBACK);
01193                                 }
01194                         }
01195 
01196                         // if precursor list non-empty add to RERR and delete the precursor list
01197                         if (!rt->pc_empty()) 
01198                         {
01199                                 MrclAddress::storeAddr(&(nre->unreachable_dst[nre->DestCount * MRCL_ADDRESS_MAX_LEN]), rt->getDst());
01200                                 nre->unreachable_dst_seqno[nre->DestCount] = rt->getSeqno();
01201                                 nre->DestCount += 1;
01202                                 rt->pc_delete();
01203                         }
01204                 }
01205         } 
01206 
01207         if (nre->DestCount > 0) 
01208         {
01209                 if(debug_)
01210                         fprintf(stderr, "%s(%f)\t sending RERR...\n", __FUNCTION__, CURRENT_TIME);
01211         sendError(rerr);
01212         }
01213         else 
01214         {
01215                 Packet::free(rerr);
01216         }
01217         drop(p, AODV_RECV_ERROR_VERBOSITY, AODV_RECV_ERROR);
01218 }
01219 
01220 void AodvModule::recvHello(Packet *p)
01221 {
01222         hdr_mrcl_aodv_reply *rp = HDR_MRCL_AODV_REPLY(p);
01223         AddrList *nb = nb_lookup(rp->rp_dst);
01224         if(nb == 0) 
01225         {
01226                 nb_insert(rp->rp_dst);
01227         }
01228         else 
01229         {
01230                 nb->expire = CURRENT_TIME + (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
01231         }
01232 
01233         drop(p, AODV_RECV_HELLO_VERBOSITY, AODV_RECV_HELLO);
01234 }
01235 
01236 
01237 void AodvModule::sendReply(char *dst, int hop_count, char *rp_dst, int rpseq, int lifetime, double timestamp)
01238 {
01239         Packet *p = Packet::alloc();
01240         struct hdr_cmn *ch = HDR_CMN(p);
01241         RoutingHdr *rhdr = HDR_ROUTING(p);
01242 //      hdr_mrcl_aodv *ah = HDR_MRCL_AODV(p);
01243 //      hdr_mrcl_aodv_reply *rp =(hdr_mrcl_aodv_reply *)(ah->body);
01244         hdr_mrcl_aodv_reply *rp = HDR_MRCL_AODV_REPLY(p);
01245         Aodv_rt_entry *rt = rtable_.rt_lookup(dst);
01246 
01247         if(debug_)
01248                 fprintf(stderr, "sending Reply from %d at %.2f\n", index, Scheduler::instance().clock());
01249 
01250         assert(rt);
01251 
01252         rp->rp_type = AODVTYPE_RREP;
01253         rp->rp_hop_count = hop_count;
01254         MrclAddress::storeAddr(rp->rp_dst, rp_dst);
01255         rp->rp_dst_seqno = rpseq;
01256         assert(nAddresses() > 0);
01257 //      getAddress(0)->getAddr(rp->rp_src);
01258         MrclAddress::storeAddr(rp->rp_src, getAddress(0)->getAddr());
01259         rp->rp_lifetime = lifetime;
01260         rp->rp_timestamp = timestamp;
01261    
01262         // ch->uid() = 0;
01263         ch->ptype() = PT_AODV;
01264         ch->size() = overheadLength_ + rp->size();
01265         // [Ali Hamidian bug solve] check for PT_TCP and PT_ACK packet types, they do not need to include IP header length (just addedd by TCP Agent) and overheadLenght_ just include it by default
01266         if((ch->ptype() == PT_TCP || ch->ptype() == PT_ACK) && (ch->size()>= IP_HDR_LEN)) ch->size()-=IP_HDR_LEN;
01267         ch->iface() = -2;
01268         ch->error() = 0;
01269         ch->addr_type() = NS_AF_INET;
01270         ch->next_hop_ = *((int *)(rt->getNexthop()) + 1);
01271         int a;
01272         getAddress(0)->getAddr(&a, sizeof(int), sizeof(int));
01273         ch->prev_hop_ = a;          // AODV hack
01274 
01275         MrclAddress::storeAddr(rhdr->saddr(), getAddress(0)->getAddr());
01276         MrclAddress::storeAddr(rhdr->daddr(), dst);
01277         rhdr->ttl() = NETWORK_DIAMETER;
01278 
01279 //      setOldAddresses(p);
01280         sendDown(p);
01281 }
01282 
01283 
01284 void AodvModule::sendRequest(char *dst)
01285 {
01286 
01287         if (debugout)
01288         {
01289                 char addr[20];
01290                 int ip;
01291                 memcpy(&ip, dst + sizeof(int), sizeof(int));
01292                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01293                 Position *pos = getPosition();
01294                 printf("[AodvModule::sendRequest] to %s pos(%f,%f)\n", addr, pos->getX(), pos->getY());
01295         }
01296         // Allocate a RREQ packet 
01297         Packet *p = Packet::alloc();
01298         struct hdr_cmn *ch = HDR_CMN(p);
01299         RoutingHdr *rhdr = HDR_ROUTING(p);
01300 //      hdr_mrcl_aodv *ah = HDR_MRCL_AODV(p);
01301 //      hdr_mrcl_aodv_request *rq =(hdr_mrcl_aodv_request *)(ah->body);
01302         hdr_mrcl_aodv_request *rq = HDR_MRCL_AODV_REQUEST(p);
01303         Aodv_rt_entry *rt = rtable_.rt_lookup(dst);
01304 
01305         assert(rt);
01306 
01307         /*
01308         *  Rate limit sending of Route Requests. We are very conservative
01309         *  about sending out route requests. 
01310         */
01311 
01312         if (rt->getFlags() == RTF_UP) 
01313         {
01314                 assert(rt->getHops() != INFINITY2);
01315                 Packet::free(p);
01316                 return;
01317         }
01318 
01319         if (rt->rt_req_timeout > CURRENT_TIME) 
01320         {
01321                 Packet::free(p);
01322                 return;
01323         }
01324 
01325         // rt_req_cnt is the no. of times we did network-wide broadcast
01326         // RREQ_RETRIES is the maximum number we will allow before 
01327         // going to a long timeout.
01328 
01329         if (rt->rt_req_cnt > RREQ_RETRIES) 
01330         {
01331                 rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
01332                 rt->rt_req_cnt = 0;
01333                 Packet *buf_pkt;
01334                 while ((buf_pkt = rqueue_.deque(rt->getDst()))) 
01335                 {
01336                         drop(buf_pkt, AODV_DROP_RTR_NO_ROUTE_VERBOSITY, DROP_RTR_NO_ROUTE);
01337                 }
01338                 Packet::free(p);
01339                 return;
01340         }
01341 
01342         if(debug_)
01343                 fprintf(stderr, "(%d) Sending Route Request, dst\n", getId());
01344 
01345         // Determine the TTL to be used this time. 
01346         // Dynamic TTL evaluation - SRD
01347 
01348         rt->setReqLastTtl(max(rt->getReqLastTtl(),rt->getLastHopCount()));
01349 
01350         if (rt->getReqLastTtl() == 0)
01351         {
01352                 // first time query broadcast
01353                 rhdr->ttl() = TTL_START;
01354         }
01355         else 
01356         {
01357                 // Expanding ring search.
01358                 if (rt->getReqLastTtl() < TTL_THRESHOLD)
01359                         rhdr->ttl() = rt->getReqLastTtl() + TTL_INCREMENT;
01360                 else 
01361                 {
01362                         // network-wide broadcast
01363                         rhdr->ttl() = NETWORK_DIAMETER;
01364                         rt->rt_req_cnt += 1;
01365                 }
01366         }
01367 
01368         // remember the TTL used  for the next time
01369         rt->setReqLastTtl(rhdr->ttl());
01370 
01371         // PerHopTime is the roundtrip time per hop for route requests.
01372         // The factor 2.0 is just to be safe .. SRD 5/22/99
01373         // Also note that we are making timeouts to be larger if we have 
01374         // done network wide broadcast before. 
01375         rt->rt_req_timeout = 2.0 * (double) rhdr->ttl() * perHopTime(rt); 
01376         if (rt->rt_req_cnt > 0)
01377                 rt->rt_req_timeout *= rt->rt_req_cnt;
01378         rt->rt_req_timeout += CURRENT_TIME;
01379 
01380         // Don't let the timeout to be too large, however .. SRD 6/8/99
01381         if (rt->rt_req_timeout > CURRENT_TIME + MAX_RREQ_TIMEOUT)
01382                 rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
01383         rt->setExpire(0);
01384 
01385         // Fill out the RREQ packet 
01386         // ch->uid() = 0;
01387         ch->ptype() = PT_AODV;
01388         ch->size() = overheadLength_ + rq->size();
01389         // [Ali Hamidian bug solve] check for PT_TCP and PT_ACK packet types, they do not need to include IP header length (just addedd by TCP Agent) and overheadLenght_ just include it by default
01390         if((ch->ptype() == PT_TCP || ch->ptype() == PT_ACK) && (ch->size()>= IP_HDR_LEN)) ch->size()-=IP_HDR_LEN;
01391         ch->iface() = -2;
01392         ch->error() = 0;
01393         ch->addr_type() = NS_AF_NONE;
01394         ch->prev_hop_ = *((int *)(getAddress(0)->getAddr()) + 1);          // AODV hack
01395         assert(nAddresses()>0);
01396         MrclAddress::storeAddr(rhdr->saddr(), getAddress(0)->getAddr());
01397         assert(broadcastAddr_!=0);
01398         MrclAddress::storeAddr(rhdr->daddr(), broadcastAddr_->getAddr());
01399         // Fill up some more fields. 
01400         rq->rq_type = AODVTYPE_RREQ;
01401         rq->rq_hop_count = 1;
01402         rq->rq_bcast_id = bid_++;
01403         MrclAddress::storeAddr(rq->rq_dst, dst);
01404         rq->rq_dst_seqno = (rt ? rt->getSeqno() : 0);
01405         MrclAddress::storeAddr(rq->rq_src, getAddress(0)->getAddr());
01406         seqno_ += 2;
01407         assert ((seqno_%2) == 0);
01408         rq->rq_src_seqno = seqno_;
01409         rq->rq_timestamp = CURRENT_TIME;
01410 
01411         //  Scheduler::instance().schedule(target_, p, 0.);
01412         sendDown(p);
01413 
01414 }
01415 
01416 void AodvModule::sendError(Packet *p, int jitter)
01417 {
01418         hdr_cmn *ch = HDR_CMN(p);
01419         RoutingHdr *rhdr = HDR_ROUTING(p);
01420 //      hdr_mrcl_aodv *ah = HDR_MRCL_AODV(p);
01421 //      hdr_mrcl_aodv_error *re = ((hdr_mrcl_aodv_error *)ah->body);
01422         hdr_mrcl_aodv_error *re = HDR_MRCL_AODV_ERROR(p);
01423     
01424         if(debug_)
01425                 fprintf(stderr, "sending Error from at %.2f\n", Scheduler::instance().clock());
01426 
01427         re->re_type = AODVTYPE_RERR;
01428         //re->reserved[0] = 0x00; re->reserved[1] = 0x00;
01429         // DestCount and list of unreachable destinations are already filled
01430 
01431         // ch->uid() = 0;
01432         ch->ptype() = PT_AODV;
01433         ch->size() = overheadLength_ + re->size();
01434         // [Ali Hamidian bug solve] check for PT_TCP and PT_ACK packet types, they do not need to include IP header length (just addedd by TCP Agent) and overheadLenght_ just include it by default
01435         if((ch->ptype() == PT_TCP || ch->ptype() == PT_ACK) && (ch->size()>= IP_HDR_LEN)) ch->size()-=IP_HDR_LEN;
01436         ch->iface() = -2;
01437         ch->error() = 0;
01438         ch->addr_type() = NS_AF_NONE;
01439         ch->next_hop_ = 0;
01440         ch->prev_hop_ = *((int *)(getAddress(0)->getAddr()) + 1);          // AODV hack
01441 
01442         MrclAddress::storeAddr(rhdr->saddr(), getAddress(0)->getAddr());
01443         MrclAddress::storeAddr(rhdr->daddr(), broadcastAddr_->getAddr());
01444 
01445         rhdr->ttl() = 1;
01446         /*setOldAddresses(p);*/
01447 
01448         // Do we need any jitter? Yes
01449         if (jitter)
01450                 sendDown(p, 0.01*Random::uniform());
01451         else
01452                 sendDown(p);
01453 
01454 }
01455 
01456 
01457 
01458 void AodvModule::forward(Packet *p, Aodv_rt_entry *re, double delay)
01459 {
01460         struct hdr_cmn *ch = HDR_CMN(p);
01461         RoutingHdr *rhdr = HDR_ROUTING(p);
01462 
01463         if(rhdr->ttl_ == 0) 
01464         {
01465 
01466                 if(debug_)
01467                         fprintf(stderr, "%s: calling drop()\n", __PRETTY_FUNCTION__);
01468                 drop(p, AODV_DROP_RTR_TTL_VERBOSITY, AODV_DROP_RTR_TTL);
01469                 return;
01470         }
01471         /*
01472         if (ch->ptype() != PT_AODV && ch->direction() == hdr_cmn::UP &&
01473                 broadcastAddr_->isEqual(rhdr->daddr()) || isMyAddress(re->getDst())) 
01474         {
01475                 printf("ATTENTION!!! forward is sending up a packet!!!!\n");
01476                 sendUp(p);
01477                 return;
01478         }*/
01479         if (re) 
01480         {
01481                 assert(re->getFlags() == RTF_UP);
01482                 re->setExpire(CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT);
01483                 MrclAddress::storeAddr(rhdr->nexthop(), re->getNexthop());
01484                 ch->next_hop_ = *((int *)(re->getNexthop()) + 1);
01485                 ch->addr_type() = NS_AF_INET;
01486         }
01487         else 
01488         { // if it is a broadcast packet
01489                 // assert(ch->ptype() == PT_AODV); // maybe a diff pkt type like gaf
01490                 assert(broadcastAddr_->isEqual(rhdr->daddr()));
01491                 ch->addr_type() = NS_AF_NONE;
01492         }
01493         ch->xmit_failure_ = aodv_rt_failed_callback;
01494         ch->xmit_failure_data_ = (void*) this;
01495         rhdr->clearModuleRoute();
01496         if (broadcastAddr_->isEqual(rhdr->daddr())) 
01497         {// If it is a broadcast packet
01498                 assert(re == 0);
01499                  // According to Marco Fiore proposal: this avoids random jitter on non-AODV broadcasts
01500                 if(ch->ptype() == PT_AODV) {
01501                         /*
01502                         *  Jitter the sending of broadcast packets by 10ms
01503                         */
01504                         sendDown(p, 0.01 * Random::uniform());
01505                 }
01506                 else
01507                 {
01508                         sendDown(p);
01509                 }
01510         }
01511         else 
01512         { // Not a broadcast packet 
01513                 if (debug_>5)
01514                 {
01515                         char addr[20];
01516                         char nexthop[20];
01517                         int ip;
01518                         memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
01519                         sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01520                         memcpy(&ip, rhdr->nexthop() + sizeof(int), sizeof(int));
01521                         sprintf(nexthop,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01522                         Position* pos = getPosition();
01523                         printf("[AodvModule::forward] node %s send down to %s pkt %d ttl %d num_forwards %d (%f,%f)\n", 
01524                                                 addr, nexthop, ch->uid(), rhdr->ttl(), ch->num_forwards(), pos->getX(), pos->getY());
01525                 }
01526                 sendDown(p, delay);
01527    }
01528 }
01529 
01530 
01531 void AodvModule::nb_insert(char *id)
01532 {
01533         AddrList *nb = new AddrList;
01534         MrclAddress::storeAddr(nb->addr, id);
01535 
01536         //assert(nb);
01537         nb->expire = CURRENT_TIME + (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
01538         nb->prev = 0;
01539         if(!ncache_)
01540         {
01541                 nb->next = 0;
01542                 ncache_ = nb;
01543         }
01544         else
01545         {
01546                 nb->next = ncache_;
01547                 ncache_->prev = nb;
01548                 ncache_ = nb;
01549         }
01550         
01551         seqno_ += 2;             // set of neighbors changed
01552         assert ((seqno_%2) == 0);
01553 }
01554 
01555 AddrList *AodvModule::nb_lookup(char *id)
01556 {
01557         for(AddrList *cur = ncache_; cur; cur = cur->next)
01558         {
01559                 if(MrclAddress::areEqual(id, cur->addr))
01560                         return cur;
01561         }
01562         return 0;
01563 }
01564 
01565 void AodvModule::nb_delete(char *id)
01566 {
01567         if (debug_>5)
01568         {
01569                 char addr[20];
01570                 int ip;
01571                 memcpy(&ip, id + sizeof(int), sizeof(int));
01572                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01573                 printf("[AodvModule::nb_delete] delete id %s at %.2f (triggered from LL)\n", addr, Scheduler::instance().clock());
01574         }
01575         AddrList *nb = nb_lookup(id);
01576         if(nb)
01577                 nb_delete(nb);
01578         handle_link_failure(id);
01579 }
01580 
01581 void AodvModule::nb_delete(AddrList *a)
01582 {
01583         if (debug_>5)
01584         {
01585                 char addr[20];
01586                 int ip;
01587                 memcpy(&ip, a->addr + sizeof(int), sizeof(int));
01588                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01589                 printf("[AodvModule::nb_delete] delete id %s at %.2f (triggered from HELLO)\n", addr, Scheduler::instance().clock());
01590         }
01591         if(a == ncache_)
01592         {
01593                 ncache_ = a->next;
01594                 if(ncache_)
01595                         ncache_->prev = 0;
01596         }
01597         else
01598         {
01599                 a->prev->next = a->next;
01600                 if(a->next)
01601                         a->next->prev = a->prev;
01602         }
01603         handle_link_failure(a->addr);
01604         delete a;
01605 }
01606 
01607 void AodvModule::nb_purge()
01608 {
01609         double now = CURRENT_TIME;
01610         AddrList *cur = ncache_;
01611         while(cur)
01612         {
01613                 if (debug_>5)
01614                 {
01615                         char addr[20];
01616                         int ip;
01617                         memcpy(&ip, cur->addr + sizeof(int), sizeof(int));
01618                         sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01619                         char saddr[20];
01620                         memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
01621                         sprintf(saddr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01622                         printf("Node %s checking %s expire %f (now%f)\n", saddr, addr, cur->expire, CURRENT_TIME);
01623                 }
01624                 if(cur->expire <= now)
01625                 {
01626                         if(cur != ncache_)
01627                         {
01628                                 cur = cur->prev;
01629                                 nb_delete(cur->next);
01630                                 cur = cur->next;
01631                         }
01632                         else
01633                         {
01634                                 nb_delete(cur);
01635                                 cur = ncache_;
01636                         }
01637                 }
01638                 else
01639                         cur = cur->next;
01640         }
01641 }
01642 
01643 double AodvModule::perHopTime(Aodv_rt_entry *rt) 
01644 {
01645         int num_non_zero = 0;
01646         int i;
01647         double total_latency = 0.0;
01648 
01649         if (!rt)
01650                 return ((double) NODE_TRAVERSAL_TIME );
01651 
01652         for (i=0; i < MAX_HISTORY; i++) 
01653         {
01654                 if (rt->getDiscLatency(i) > 0.0) 
01655                 {
01656                         num_non_zero++;
01657                         total_latency += rt->getDiscLatency(i);
01658                 }
01659         }
01660         if (num_non_zero > 0)
01661                 return(total_latency / (double) num_non_zero);
01662         else
01663         return((double) NODE_TRAVERSAL_TIME);
01664 }
01665 
01666 char *AodvModule::getNextHop(Packet *p)
01667 {
01668         hdr_cmn *ch = HDR_CMN(p);
01669         RoutingHdr *rhdr = HDR_ROUTING(p);
01670         Aodv_rt_entry *rt = rtable_.rt_lookup(rhdr->daddr());
01671         if ((debug_>5)&&(rt==0))
01672         {
01673                 printf("[AodvModule::getNextHop]  no nexthop\n");
01674         }
01675         else
01676         {
01677                 char addr[20];
01678                 int ip;
01679                 memcpy(&ip, rt->getNexthop() + sizeof(int), sizeof(int));
01680                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01681                 printf("[AodvModule::getNextHop] forward to %s, path will expire at %f\n", addr, rt->getExpire());
01682         }
01683         return rt->getNexthop();
01684 }
01685 
01686 int AodvModule::canIReach(char *a, Metric ***m)
01687 {
01688         Aodv_rt_entry *rt = rtable_.rt_lookup(a);
01689         if(!rt)
01690         {
01691                 // return a fake metric, in order maintain RoutingModule specific
01692                 HopCountMetric **fake = new HopCountMetric*;
01693                 fake[0] = new HopCountMetric();
01694                 fake[0]->setHopCount(DBL_MAX);
01695                 *m = (Metric **) fake;
01696                 Packet* p;
01697                 return -1;
01698         }
01699         if ((rt->getFlags() == RTF_DOWN) || (rt->getFlags() == RTF_IN_REPAIR))
01700         {
01701                 // return a fake metric, in order maintain RoutingModule specific
01702                 HopCountMetric **fake = new HopCountMetric*;
01703                 fake[0] = new HopCountMetric();
01704                 fake[0]->setHopCount(DBL_MAX);
01705                 *m = (Metric **) fake;
01706                 Packet* p;
01707                 return -1;
01708         }       
01709         m_[0]->setHopCount(rt->getHops());
01710 //      Packet* p;
01711         *m = (Metric **)m_;
01712         if (debug_>5)
01713         {
01714                 char addr[20];
01715                 int ip;
01716                 memcpy(&ip, a + sizeof(int), sizeof(int));
01717                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01718                 printf("[AodvModule::canIReach] reachability to %s, path will expire at %f\n", addr, rt->getExpire());
01719         }
01720         return 1;
01721 }
01722 
01723 
01724 /*
01725    Neighbor Management Functions
01726 */
01727 
01728 void AodvModule::sendHello()
01729 {
01730 //      if ((debug_==9)&&(CURRENT_TIME>2.0)) return;                    // used in link failure debug
01731         Packet *p = Packet::alloc();
01732         struct hdr_cmn *ch = HDR_CMN(p);
01733         RoutingHdr *rhdr = HDR_ROUTING(p);
01734 //      hdr_mrcl_aodv *ah = HDR_MRCL_AODV(p);
01735 //      hdr_mrcl_aodv_reply *rp =(hdr_mrcl_aodv_reply *)(ah->body);
01736         hdr_mrcl_aodv_reply *rp = HDR_MRCL_AODV_REPLY(p);
01737         
01738         if (debug_)
01739         {
01740                 char addr[20];
01741                 int ip;
01742                 memcpy(&ip, getAddress(0)->getAddr() + sizeof(int), sizeof(int));
01743                 sprintf(addr,"%d.%d.%d.%d", (ip & 0xff000000)>>24,(ip & 0x00ff0000)>>16, (ip & 0x0000ff00)>>8, (ip & 0x000000ff));
01744                 printf("[AodvModule::sendHello] sending Hello from %s at %.2f\n", addr, Scheduler::instance().clock());
01745         }
01746         
01747         
01748         rp->rp_type = AODVTYPE_HELLO;
01749         //rh->rp_flags = 0x00;
01750         rp->rp_hop_count = 1;
01751 //      rp->rp_dst = index;
01752         rp->rp_dst_seqno = seqno_;
01753         rp->rp_lifetime = (1 + ALLOWED_HELLO_LOSS) * HELLO_INTERVAL;
01754         MrclAddress::storeAddr(rp->rp_src, getAddress(0)->getAddr());
01755         MrclAddress::storeAddr(rp->rp_dst, getAddress(0)->getAddr());
01756         
01757         // ch->uid() = 0;
01758         ch->ptype() = PT_AODV;
01759         ch->size() = overheadLength_ + rp->size();
01760         // [Ali Hamidian bug solve] check for PT_TCP and PT_ACK packet types, they do not need to include IP header length (just addedd by TCP Agent) and overheadLenght_ just include it by default
01761         if((ch->ptype() == PT_TCP || ch->ptype() == PT_ACK) && (ch->size()>= IP_HDR_LEN)) ch->size()-=IP_HDR_LEN;
01762         ch->iface() = -2;                               // WHY???
01763         ch->error() = 0;
01764         ch->addr_type() = NS_AF_NONE;
01765         int a;
01766         getAddress(0)->getAddr(&a, sizeof(int), sizeof(int));
01767         ch->prev_hop_ = a;          // AODV hack
01768         
01769         MrclAddress::storeAddr(rhdr->saddr(), getAddress(0)->getAddr());
01770         MrclAddress::storeAddr(rhdr->daddr(), broadcastAddr_->getAddr());
01771         rhdr->ttl() = NETWORK_DIAMETER;
01772         sendDown(p);
01773 }
01774 

Generated on Wed Nov 26 15:47:27 2008 for NS-MIRACLE library by  doxygen 1.5.2