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

dsragent.cc

Go to the documentation of this file.
00001 // Copyright (c) 2000 by the University of Southern California
00002 // All rights reserved.
00003 //
00004 // Permission to use, copy, modify, and distribute this software and its
00005 // documentation in source and binary forms for non-commercial purposes
00006 // and without fee is hereby granted, provided that the above copyright
00007 // notice appear in all copies and that both the copyright notice and
00008 // this permission notice appear in supporting documentation. and that
00009 // any documentation, advertising materials, and other materials related
00010 // to such distribution and use acknowledge that the software was
00011 // developed by the University of Southern California, Information
00012 // Sciences Institute.  The name of the University may not be used to
00013 // endorse or promote products derived from this software without
00014 // specific prior written permission.
00015 //
00016 // THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
00017 // the suitability of this software for any purpose.  THIS SOFTWARE IS
00018 // PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
00019 // INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00020 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 //
00022 // Other copyrights might apply to parts of this software and are so
00023 // noted when applicable.
00024 //
00025 /* 
00026    dsragent.cc
00027 
00028    requires a radio model such that sendPacket returns true
00029    iff the packet is recieved by the destination node.
00030    
00031    Ported from CMU/Monarch's code, appropriate copyright applies.  
00032 */
00033 
00034 extern "C" {
00035 #include <assert.h>
00036 #include <math.h>
00037 #include <stdio.h>
00038 #include <signal.h>
00039 #include <float.h>
00040 }
00041 
00042 #include <object.h>
00043 #include <agent.h>
00044 #include <trace.h>
00045 #include <packet.h>
00046 #include <scheduler.h>
00047 #include <random.h>
00048 
00049 #include <mac.h>
00050 #include <ll.h>
00051 #include <cmu-trace.h>
00052 
00053 #include "path.h"
00054 #include "srpacket.h"
00055 #include "routecache.h"
00056 #include "requesttable.h"
00057 #include "dsragent.h"
00058 
00059 
00060 /*==============================================================
00061   Declarations and global defintions
00062 ------------------------------------------------------------*/
00063 // #define NEW_IFQ_LOGIC
00064 // #define NEW_REQUEST_LOGIC
00065 #define NEW_SALVAGE_LOGIC
00066 
00067 #ifdef NEW_SALVAGE_LOGIC
00068 /*
00069  *  Maximum number of times that a packet may be salvaged.
00070  */
00071 static int dsr_salvage_max_attempts = 15;
00072 /*
00073  *  Maximum number of Route Requests that can be sent for a salvaged
00074  *  packets that was originated at another node.
00075  */
00076 static int dsr_salvage_max_requests = 1;
00077 /*
00078  *  May an intermediate node send a propagating Route Request for
00079  *  a salvaged packet that was originated elsewhere.
00080  */
00081 static bool dsr_salvage_allow_propagating = 0;
00082 
00083 #endif
00084 
00085 /* couple of flowstate constants... */
00086 static const bool dsragent_enable_flowstate = true;
00087 static const bool dsragent_prefer_default_flow = true;
00088 static const bool dsragent_prefer_shorter_over_default = true;
00089 static const bool dsragent_always_reestablish = true;
00090 static const int min_adv_interval = 5;
00091 static const int default_flow_timeout = 60;
00092 //#define DSRFLOW_VERBOSE
00093 
00094 static const int verbose = 0;
00095 static const int verbose_srr = 0;
00096 static const int verbose_ssalv = 1;
00097 
00098 DSRAgent_List DSRAgent::agthead = { 0 };
00099 
00100 Time arp_timeout = 30.0e-3;     // (sec) arp request timeout
00101 Time rt_rq_period = 0.5;        // (sec) length of one backoff period
00102 Time rt_rq_max_period = 10.0;   // (sec) maximum time between rt reqs
00103 
00104 #if 0
00105 /* used in route reply holdoffs, which are currently disabled -dam 5/98 */
00106 Time rt_rep_holdoff_period = 3.0e-3; // secs (about 2*process_time)
00107 // to determine how long to sit on our rt reply we pick a number
00108 // U(O.0,rt_rep_holdoff_period) + (our route length-1)*rt_rep_holdoff
00109 #endif //0
00110 
00111 Time grat_hold_down_time = 1.0; // (sec) min time between grat replies for
00112                                 // same route
00113 
00114 Time max_err_hold = 1.0;        // (sec) 
00115 // maximum time between when we recv a route error told to us, and when we
00116 // transmit a propagating route request that can carry that data.  used to
00117 // keep us from propagating stale route error data
00118 
00119 
00120 /*************** selectors ******************/
00121 bool dsragent_snoop_forwarded_errors = true;
00122 // give errors we forward to our cache?
00123 bool dsragent_snoop_source_routes = true;
00124 // should we snoop on any source routes we see?
00125 bool dsragent_reply_only_to_first_rtreq = false;
00126 // should we only respond to the first route request we receive from a host?
00127 bool dsragent_propagate_last_error = true;
00128 // should we take the data from the last route error msg sent to us
00129 // and propagate it around on the next propagating route request we do?
00130 // this is aka grat route error propagation
00131 bool dsragent_send_grat_replies = true;
00132 // should we send gratuitous replies to effect route shortening?
00133 bool dsragent_salvage_with_cache = true;
00134 // should we consult our cache for a route if we get a xmitfailure
00135 // and salvage the packet using the route if possible
00136 bool dsragent_use_tap = true;
00137 // should we listen to a promiscuous tap?
00138 bool dsragent_reply_from_cache_on_propagating = true;
00139 // should we consult the route cache before propagating rt req's and
00140 // answer if possible?
00141 bool dsragent_ring_zero_search = true;
00142 // should we send a non-propagating route request as the first action
00143 // in each route discovery action?
00144 
00145 // NOTE: to completely turn off replying from cache, you should
00146 // set both dsragent_ring_zero_search and 
00147 // dsragent_reply_from_cache_on_propagating to false
00148 
00149 bool dsragent_dont_salvage_bad_replies = true;
00150 // if we have an xmit failure on a packet, and the packet contains a 
00151 // route reply, should we scan the reply to see if contains the dead link?
00152 // if it does, we won't salvage the packet unless there's something aside
00153 // from a reply in it (in which case we salvage, but cut out the rt reply)
00154 bool dsragent_require_bi_routes = true;
00155 // do we need to have bidirectional source routes? 
00156 // [XXX this flag doesn't control all the behaviors and code that assume
00157 // bidirectional links -dam 5/14/98]
00158 
00159 #if 0
00160 bool lsnode_holdoff_rt_reply = true;
00161 // if we have a cached route to reply to route_request with, should we
00162 // hold off and not send it for a while?
00163 bool lsnode_require_use = true;
00164 // do we require ourselves to hear a route requestor use a route
00165 // before we withold our route, or is merely hearing another (better)
00166 // route reply enough?
00167 #endif
00168 
00169 /*
00170 
00171 
00172 Our strategy is as follows:
00173 
00174  - it's only worth discovering bidirectional routes, since all data
00175  paths will have to have to be bidirectional for 802.11 ACKs to work
00176 
00177  - reply to all route requests for us that we recv (not just the first one)
00178  but reply to them by reversing the route and unicasting.  don't do
00179  a route request (since that will end up returning the requestor lots of
00180  routes that are potentially unidirectional). By reversing the discovered 
00181  route for the route reply, only routes that are bidirectional will make it
00182  back the original requestor
00183 
00184  - once a packet goes into the sendbuffer, it can't be piggybacked on a 
00185  route request.  the code assumes that the only thing that removes
00186  packets from the send buff is the StickPktIn routine, or the route reply
00187  arrives routine
00188 
00189 */
00190 
00191 /*===========================================================================
00192   SendBuf management and helpers
00193 ---------------------------------------------------------------------------*/
00194 void
00195 SendBufferTimer::expire(Event *) 
00196 { 
00197   a_->sendBufferCheck(); 
00198   resched(BUFFER_CHECK + BUFFER_CHECK * Random::uniform(1.0));
00199 }
00200 
00201 void
00202 DSRAgent::dropSendBuff(SRPacket &p)
00203   // log p as being dropped by the sendbuffer in DSR agent
00204 {
00205   trace("Ssb %.5f _%s_ dropped %s -> %s", Scheduler::instance().clock(), 
00206         net_id.dump(), p.src.dump(), p.dest.dump());
00207   drop(p.pkt, DROP_RTR_QTIMEOUT);
00208   p.pkt = 0;
00209   p.route.reset();
00210 }
00211 
00212 void
00213 DSRAgent::stickPacketInSendBuffer(SRPacket& p)
00214 {
00215   Time min = DBL_MAX;
00216   int min_index = 0;
00217   int c;
00218 
00219   if (verbose)
00220     trace("Sdebug %.5f _%s_ stuck into send buff %s -> %s",
00221           Scheduler::instance().clock(), 
00222           net_id.dump(), p.src.dump(), p.dest.dump());
00223 
00224   for (c = 0 ; c < SEND_BUF_SIZE ; c ++)
00225     if (send_buf[c].p.pkt == NULL)
00226       {
00227         send_buf[c].t = Scheduler::instance().clock();
00228         send_buf[c].p = p;
00229         return;
00230       }
00231     else if (send_buf[c].t < min)
00232       {
00233         min = send_buf[c].t;
00234         min_index = c;
00235       }
00236   
00237   // kill somebody
00238   dropSendBuff(send_buf[min_index].p);
00239   send_buf[min_index].t = Scheduler::instance().clock();
00240   send_buf[min_index].p = p;
00241 }
00242 
00243 void
00244 DSRAgent::sendBufferCheck()
00245   // see if any packets in send buffer need route requests sent out
00246   // for them, or need to be expired
00247 { // this is called about once a second.  run everybody through the
00248   // get route for pkt routine to see if it's time to do another 
00249   // route request or what not
00250   int c;
00251 
00252   for (c  = 0 ; c <SEND_BUF_SIZE ; c++) {
00253           if (send_buf[c].p.pkt == NULL)
00254                   continue;
00255           if (Scheduler::instance().clock() - send_buf[c].t > SEND_TIMEOUT) {
00256                   dropSendBuff(send_buf[c].p);
00257                   send_buf[c].p.pkt = 0;
00258                   continue;
00259           }
00260 #ifdef DEBUG
00261           trace("Sdebug %.5f _%s_ checking for route for dst %s",
00262                 Scheduler::instance().clock(), net_id.dump(), 
00263                 send_buf[c].p.dest.dump());
00264 #endif
00265 
00266           handlePktWithoutSR(send_buf[c].p, true);
00267 #ifdef DEBUG
00268           if (send_buf[c].p.pkt == NULL) 
00269                   trace("Sdebug %.5f _%s_ sendbuf pkt to %s liberated by handlePktWOSR",
00270                         Scheduler::instance().clock(), net_id.dump(), 
00271                         send_buf[c].p.dest.dump());
00272 #endif
00273   }
00274 }
00275 
00276 /*==============================================================
00277   Route Request backoff
00278 ------------------------------------------------------------*/
00279 static bool
00280 BackOffTest(Entry *e, Time time)
00281 // look at the entry and decide if we can send another route
00282 // request or not.  update entry as well
00283 {
00284   Time next = ((Time) (0x1 << (e->rt_reqs_outstanding * 2))) * rt_rq_period;
00285 
00286   if (next > rt_rq_max_period)
00287           next = rt_rq_max_period;
00288 
00289   if (next + e->last_rt_req > time)
00290           return false;
00291 
00292   // don't let rt_reqs_outstanding overflow next on the LogicalShiftsLeft's
00293   if (e->rt_reqs_outstanding < 15)
00294           e->rt_reqs_outstanding++;
00295 
00296   e->last_rt_req = time;
00297 
00298   return true;
00299 }
00300 
00301 /*===========================================================================
00302   DSRAgent OTcl linkage
00303 ---------------------------------------------------------------------------*/
00304 static class DSRAgentClass : public TclClass {
00305 public:
00306   DSRAgentClass() : TclClass("Agent/DSRAgent") {}
00307   TclObject* create(int, const char*const*) {
00308     return (new DSRAgent);
00309   }
00310 } class_DSRAgent;
00311 
00312 /*===========================================================================
00313   DSRAgent methods
00314 ---------------------------------------------------------------------------*/
00315 DSRAgent::DSRAgent(): Agent(PT_DSR), request_table(128), route_cache(NULL),
00316 send_buf_timer(this), flow_table(), ars_table()
00317 {
00318   int c;
00319   route_request_num = 1;
00320 
00321   route_cache = makeRouteCache();
00322 
00323   for (c = 0 ; c < RTREP_HOLDOFF_SIZE ; c++)
00324           rtrep_holdoff[c].requested_dest = invalid_addr;
00325   num_heldoff_rt_replies = 0;
00326 
00327   target_ = 0;
00328   logtarget = 0;
00329 
00330   grat_hold_victim = 0;
00331   for (c = 0; c < RTREP_HOLDOFF_SIZE ; c++) {
00332     grat_hold[c].t = 0;
00333     grat_hold[c].p.reset();
00334   }
00335 
00336   //bind("off_SR_", &off_sr_);
00337   //bind("off_ll_", &off_ll_);
00338   //bind("off_mac_", &off_mac_);
00339   //bind("off_ip_", &off_ip_);
00340 
00341   ll = 0;
00342   ifq = 0;
00343   mac_ = 0;
00344 
00345   LIST_INSERT_HEAD(&agthead, this, link);
00346 #ifdef DSR_FILTER_TAP
00347   bzero(tap_uid_cache, sizeof(tap_uid_cache));
00348 #endif
00349   route_error_held = false;
00350 }
00351 
00352 DSRAgent::~DSRAgent()
00353 {
00354   fprintf(stderr,"DFU: Don't do this! I haven't figured out ~DSRAgent\n");
00355   exit(-1);
00356 }
00357 
00358 void
00359 DSRAgent::Terminate()
00360 {
00361         int c;
00362         for (c  = 0 ; c < SEND_BUF_SIZE ; c++) {
00363                 if (send_buf[c].p.pkt) {
00364                         drop(send_buf[c].p.pkt, DROP_END_OF_SIMULATION);
00365                         send_buf[c].p.pkt = 0;
00366                 }
00367         }
00368 }
00369 
00370 void
00371 DSRAgent::testinit()
00372 {
00373   struct hdr_sr hsr;
00374   
00375   if (net_id == ID(1,::IP))
00376     {
00377       printf("adding route to 1\n");
00378       hsr.init();
00379       hsr.append_addr( 1, NS_AF_INET );
00380       hsr.append_addr( 2, NS_AF_INET );
00381       hsr.append_addr( 3, NS_AF_INET );
00382       hsr.append_addr( 4, NS_AF_INET );
00383       
00384       route_cache->addRoute(Path(hsr.addrs(),
00385                                  hsr.num_addrs()), 0.0, ID(1,::IP));
00386     }
00387   
00388   if (net_id == ID(3,::IP))
00389     {
00390       printf("adding route to 3\n");
00391       hsr.init();
00392       hsr.append_addr( 3, NS_AF_INET );
00393       hsr.append_addr( 2, NS_AF_INET );
00394       hsr.append_addr( 1, NS_AF_INET );
00395       
00396       route_cache->addRoute(Path(hsr.addrs(),
00397                                  hsr.num_addrs()), 0.0, ID(3,::IP));
00398     }
00399 }
00400 
00401 
00402 int
00403 DSRAgent::command(int argc, const char*const* argv)
00404 {
00405   TclObject *obj;  
00406 
00407   if (argc == 2) 
00408     {
00409       if (strcasecmp(argv[1], "testinit") == 0)
00410         {
00411           testinit();
00412           return TCL_OK;
00413         }
00414       if (strcasecmp(argv[1], "reset") == 0)
00415         {
00416           Terminate();
00417           return Agent::command(argc, argv);
00418         }
00419       if (strcasecmp(argv[1], "check-cache") == 0)
00420         {
00421           return route_cache->command(argc, argv);
00422         }
00423       if (strcasecmp(argv[1], "startdsr") == 0)
00424         {
00425           if (ID(1,::IP) == net_id) 
00426             { // log the configuration parameters of the dsragent
00427   trace("Sconfig %.5f tap: %s snoop: rts? %s errs? %s",
00428                     Scheduler::instance().clock(),
00429                     dsragent_use_tap ? "on" : "off",
00430                     dsragent_snoop_source_routes ? "on" : "off",
00431                     dsragent_snoop_forwarded_errors ? "on" : "off");
00432   trace("Sconfig %.5f salvage: %s !bd replies? %s",
00433                     Scheduler::instance().clock(),
00434                     dsragent_salvage_with_cache ? "on" : "off",
00435                     dsragent_dont_salvage_bad_replies ? "on" : "off");
00436   trace("Sconfig %.5f grat error: %s grat reply: %s",
00437                     Scheduler::instance().clock(),
00438                     dsragent_propagate_last_error ? "on" : "off",
00439                     dsragent_send_grat_replies ? "on" : "off");
00440   trace("Sconfig %.5f $reply for props: %s ring 0 search: %s",
00441                     Scheduler::instance().clock(),
00442                     dsragent_reply_from_cache_on_propagating ? "on" : "off",
00443                     dsragent_ring_zero_search ? "on" : "off");
00444             }
00445           // cheap source of jitter
00446           send_buf_timer.sched(BUFFER_CHECK 
00447                                + BUFFER_CHECK * Random::uniform(1.0));    
00448           return route_cache->command(argc,argv);
00449         }
00450     }
00451   else if(argc == 3) 
00452     {
00453       if (strcasecmp(argv[1], "addr") == 0) 
00454         {
00455           int temp;
00456           temp = Address::instance().str2addr(argv[2]);
00457          net_id = ID(temp, ::IP);
00458          flow_table.setNetAddr(net_id.addr);
00459          route_cache->net_id = net_id;
00460          return TCL_OK;
00461         } 
00462       else if(strcasecmp(argv[1], "mac-addr") == 0) 
00463         {
00464           MAC_id = ID(atoi(argv[2]), ::MAC);
00465           route_cache->MAC_id = MAC_id;
00466           return TCL_OK;
00467         }
00468       
00469       if( (obj = TclObject::lookup(argv[2])) == 0) 
00470         {
00471           fprintf(stderr, "DSRAgent: %s lookup of %s failed\n", argv[1],
00472                   argv[2]);
00473           return TCL_ERROR;
00474         }
00475 
00476       if (strcasecmp(argv[1], "log-target") == 0)  {
00477               logtarget = (Trace*) obj;
00478               return route_cache->command(argc, argv);
00479       }
00480       else if (strcasecmp(argv[1], "tracetarget") == 0 )
00481         {
00482           logtarget = (Trace*) obj;
00483           return route_cache->command(argc, argv);
00484         }
00485       else if (strcasecmp(argv[1], "install-tap") == 0)  
00486         {
00487           mac_ = (Mac*) obj;
00488           mac_->installTap(this);
00489           return TCL_OK;
00490         }
00491       else if (strcasecmp(argv[1], "node") == 0)
00492         {
00493           node_ = (MobileNode *) obj;
00494           return TCL_OK;
00495         }
00496       else if (strcasecmp (argv[1], "port-dmux") == 0) 
00497         {
00498           port_dmux_ = (NsObject *) obj;
00499           return TCL_OK;
00500         }
00501     }
00502   else if (argc == 4)
00503     {
00504       if (strcasecmp(argv[1], "add-ll") == 0) 
00505         {
00506           if( (obj = TclObject::lookup(argv[2])) == 0) {
00507             fprintf(stderr, "DSRAgent: %s lookup of %s failed\n", argv[1],
00508                     argv[2]);
00509             return TCL_ERROR;
00510           }
00511           ll = (NsObject*) obj;
00512           if( (obj = TclObject::lookup(argv[3])) == 0) {
00513             fprintf(stderr, "DSRAgent: %s lookup of %s failed\n", argv[1],
00514                     argv[3]);
00515             return TCL_ERROR;
00516           }
00517           ifq = (CMUPriQueue *) obj;
00518           return TCL_OK;
00519 
00520         }
00521 
00522 
00523     }
00524   return Agent::command(argc, argv);
00525 }
00526 
00527 void
00528 DSRAgent::sendOutBCastPkt(Packet *p)
00529 {
00530   hdr_cmn *cmh =  hdr_cmn::access(p);
00531   if(cmh->direction() == hdr_cmn::UP)
00532     cmh->direction() = hdr_cmn::DOWN;
00533   // no jitter required
00534   Scheduler::instance().schedule(ll, p, 0.0);
00535 }
00536 
00537 
00538 
00539 void
00540 DSRAgent::recv(Packet* packet, Handler*)
00541   /* handle packets with a MAC destination address of this host, or
00542      the MAC broadcast addr */
00543 {
00544   hdr_sr *srh =  hdr_sr::access(packet);
00545   hdr_ip *iph =  hdr_ip::access(packet);
00546   hdr_cmn *cmh =  hdr_cmn::access(packet);
00547 
00548   // special process for GAF
00549   if (cmh->ptype() == PT_GAF) {
00550     if (iph->daddr() == (int)IP_BROADCAST) { 
00551       if(cmh->direction() == hdr_cmn::UP)
00552         cmh->direction() = hdr_cmn::DOWN;
00553       Scheduler::instance().schedule(ll,packet,0);
00554       return;
00555     } else {
00556       target_->recv(packet, (Handler*)0);
00557       return;     
00558     }
00559   }
00560 
00561   assert(cmh->size() >= 0);
00562 
00563   SRPacket p(packet, srh);
00564   //p.dest = ID(iph->dst(),::IP);
00565   //p.src = ID(iph->src(),::IP);
00566   p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
00567   p.src = ID((Address::instance().get_nodeaddr(iph->saddr())),::IP);
00568 
00569   assert(logtarget != 0);
00570 
00571   if (srh->valid() != 1) {
00572     unsigned int dst = cmh->next_hop();
00573     if (dst == IP_BROADCAST) {
00574       // extensions for mobileIP --Padma, 04/99.
00575       // Brdcast pkt - treat differently
00576       if (p.src == net_id)
00577         // I have originated this pkt
00578         sendOutBCastPkt(packet);
00579       else 
00580         //hand it over to port-dmux
00581         port_dmux_->recv(packet, (Handler*)0);
00582       
00583     } else {
00584       // this must be an outgoing packet, it doesn't have a SR header on it
00585       
00586       srh->init();               // give packet an SR header now
00587       cmh->size() += IP_HDR_LEN; // add on IP header size
00588       if (verbose)
00589         trace("S %.9f _%s_ originating %s -> %s",
00590               Scheduler::instance().clock(), net_id.dump(), p.src.dump(), 
00591               p.dest.dump());
00592       handlePktWithoutSR(p, false);
00593       goto done;
00594     }
00595   }
00596   else if (srh->valid() == 1) 
00597     {
00598       if (p.dest == net_id || p.dest == IP_broadcast)
00599         { // this packet is intended for us
00600           handlePacketReceipt(p);
00601           goto done;
00602         }
00603       
00604       // should we check to see if it's an error packet we're handling
00605       // and if so call processBrokenRouteError to snoop
00606       if (dsragent_snoop_forwarded_errors && srh->route_error())
00607         {
00608           processBrokenRouteError(p);
00609         }
00610 
00611       if (srh->route_request())
00612         { // propagate a route_request that's not for us
00613           handleRouteRequest(p);
00614         }
00615       else
00616         { // we're not the intended final recpt, but we're a hop
00617           handleForwarding(p);
00618         }
00619     }
00620   else {
00621     // some invalid pkt has reached here
00622     fprintf(stderr,"dsragent: Error-received Invalid pkt!\n");
00623     Packet::free(p.pkt);
00624     p.pkt =0; // drop silently
00625   }
00626 
00627  done:
00628   assert(p.pkt == 0);
00629   
00630   p.pkt = 0;
00631   return;
00632 }
00633 
00634 
00635 /*===========================================================================
00636   handlers for each class of packet
00637 ---------------------------------------------------------------------------*/
00638 void
00639 DSRAgent::handlePktWithoutSR(SRPacket& p, bool retry)
00640   /* obtain a source route to p's destination and send it off.
00641      this should be a retry if the packet is already in the sendbuffer */
00642 {
00643   hdr_sr *srh =  hdr_sr::access(p.pkt);
00644   assert(srh->valid());
00645 
00646   if (p.dest == net_id)
00647     { // it doesn't need a source route, 'cause it's for us
00648       handlePacketReceipt(p);
00649       return;
00650     }
00651 
00652   // Extensions for wired cum wireless simulation mode
00653   //if pkt dst outside my subnet, route to base_stn
00654 
00655   ID dest;
00656   if (diff_subnet(p.dest,net_id)) {
00657   dest = ID(node_->base_stn(),::IP);
00658   p.dest = dest;
00659   }
00660 
00661   if (route_cache->findRoute(p.dest, p.route, 1))
00662     { // we've got a route...
00663       if (verbose)
00664         trace("S$hit %.5f _%s_ %s -> %s %s",
00665               Scheduler::instance().clock(), net_id.dump(),
00666               p.src.dump(), p.dest.dump(), p.route.dump());      
00667       sendOutPacketWithRoute(p, true);
00668       return;
00669     } // end if we have a route
00670   else
00671     { // we don't have a route...
00672       if (verbose) 
00673         trace("S$miss %.5f _%s_ %s -> %s", 
00674               Scheduler::instance().clock(), net_id.dump(), 
00675               net_id.dump(), p.dest.dump());
00676 
00677       getRouteForPacket(p, retry);
00678       return;
00679     } // end of we don't have a route
00680 }
00681 
00682 void
00683 DSRAgent::handlePacketReceipt(SRPacket& p)
00684   /* Handle a packet destined to us */
00685 {
00686   hdr_cmn *cmh =  hdr_cmn::access(p.pkt);
00687   hdr_sr *srh =  hdr_sr::access(p.pkt);
00688 
00689   if (srh->route_reply())
00690     { // we got a route_reply piggybacked on a route_request
00691       // accept the new source route before we do anything else
00692       // (we'll send off any packet's we have queued and waiting)
00693       acceptRouteReply(p);
00694     }
00695   
00696   if (srh->route_request())
00697     {
00698       if (dsragent_reply_only_to_first_rtreq  && ignoreRouteRequestp(p)) 
00699         { //we only respond to the first route request
00700           // we receive from a host 
00701           Packet::free(p.pkt);     // drop silently
00702           p.pkt = 0;
00703           return;
00704         }
00705       else
00706         { // we're going to process this request now, so record the req_num
00707           request_table.insert(p.src, p.src, srh->rtreq_seq());
00708           returnSrcRouteToRequestor(p);
00709         }
00710     }
00711 
00712   if (srh->route_error())
00713     { // register the dead route      
00714       processBrokenRouteError(p);
00715     }
00716 
00717   if (srh->flow_unknown())
00718     processUnknownFlowError(p, false);
00719 
00720   if (srh->flow_default_unknown())
00721     processUnknownFlowError(p, true);
00722 
00723   /* give the data in the packet to our higher layer (our port dmuxer, most 
00724    likely) */
00725   //handPktToDmux(p);
00726   assert(p.dest == net_id || p.dest == MAC_id);
00727   
00728 #if 0
00729   if (iph->dport() == 255) {
00730     int mask = Address::instance().portmask();
00731     int shift = Address::instance().portshift();  
00732     iph->daddr() = ((iph->dport() & mask) << shift) | ((~(mask) << shift) & iph->dst());
00733   }
00734 #endif
00735   
00736   cmh->size() -= srh->size();   // cut off the SR header 4/7/99 -dam
00737   srh->valid() = 0;
00738   cmh->size() -= IP_HDR_LEN;    // cut off IP header size 4/7/99 -dam
00739   target_->recv(p.pkt, (Handler*)0);
00740   p.pkt = 0;
00741 
00742 }
00743 
00744 
00745 void
00746 DSRAgent::handleDefaultForwarding(SRPacket &p) {
00747   hdr_ip *iph = hdr_ip::access(p.pkt);
00748   u_int16_t flowid;
00749   int       flowidx;
00750 
00751   if (!flow_table.defaultFlow(p.src.addr, p.dest.addr, flowid)) {
00752     sendUnknownFlow(p, true);
00753     assert(p.pkt == 0);
00754     return;
00755   }
00756 
00757   if ((flowidx = flow_table.find(p.src.addr, p.dest.addr, flowid)) == -1) {
00758     sendUnknownFlow(p, false, flowid);
00759     assert(p.pkt == 0);
00760     return;
00761   }
00762 
00763   if (iph->ttl() != flow_table[flowidx].expectedTTL) {
00764     sendUnknownFlow(p, true);
00765     assert(p.pkt == 0);
00766     return;
00767   }
00768 
00769   // XXX should also check prevhop
00770 
00771   handleFlowForwarding(p, flowidx);
00772 }
00773 
00774 void
00775 DSRAgent::handleFlowForwarding(SRPacket &p, int flowidx) {
00776   hdr_sr *srh = hdr_sr::access(p.pkt);
00777   hdr_ip *iph = hdr_ip::access(p.pkt);
00778   hdr_cmn *cmnh =  hdr_cmn::access(p.pkt);
00779   int amt;
00780 
00781   assert(flowidx >= 0);
00782   assert(!srh->num_addrs());
00783 
00784   cmnh->next_hop() = flow_table[flowidx].nextHop;
00785   cmnh->addr_type() = ::IP;
00786 
00787   cmnh->xmit_failure_ = XmitFlowFailureCallback;
00788   cmnh->xmit_failure_data_ = (void *) this;
00789 
00790   // make sure we aren't cycling packets
00791   //assert(p.pkt->incoming == 0); // this is an outgoing packet
00792   assert(cmnh->direction() == hdr_cmn::UP);
00793 
00794   if (!iph->ttl()--) {
00795     drop(p.pkt, DROP_RTR_TTL);
00796     p.pkt = 0;
00797     return;
00798   }
00799 
00800   trace("SFf %.9f _%s_ %d [%s -> %s] %d to %d", 
00801         Scheduler::instance().clock(), net_id.dump(), cmnh->uid(),
00802         p.src.dump(), p.dest.dump(), flow_table[flowidx].flowId,
00803         flow_table[flowidx].nextHop);
00804 
00805   // XXX ych 5/8/01 ARS also should check previous hop
00806   if (!srh->salvaged() && 
00807       (amt = ars_table.findAndClear(cmnh->uid(), flow_table[flowidx].flowId)) &&
00808       p.route.index() - amt > 0) {
00809     trace("SFARS %.9f _%s_ %d [%s -> %s] %d %d", 
00810           Scheduler::instance().clock(), net_id.dump(), cmnh->uid(),
00811           p.src.dump(), p.dest.dump(), flow_table[flowidx].flowId, amt);
00812 
00813     // stamp a route in the packet...
00814     p.route = flow_table[flowidx].sourceRoute;
00815     p.route.index() -= amt;
00816     sendRouteShortening(p, p.route.index(), 
00817                         flow_table[flowidx].sourceRoute.index());
00818   }
00819 
00820   if (dsragent_always_reestablish) {
00821     // XXX this is an utter hack. the flow_table needs to remember the original
00822     // timeout value specified, as well as the original time to timeout. No
00823     // establishment packets are allowed after the original time. Must make sure
00824     // flowids assigned do not overlap. ych 5/8/01
00825     flow_table[flowidx].timeout = Scheduler::instance().clock() + 
00826                                   default_flow_timeout;
00827   }
00828   // set the direction pkt to be down
00829   cmnh->direction() = hdr_cmn::DOWN;
00830   Scheduler::instance().schedule(ll, p.pkt, 0);
00831   p.pkt = 0;
00832 }
00833 
00834 void
00835 DSRAgent::handleFlowForwarding(SRPacket &p) {
00836   hdr_sr *srh = hdr_sr::access(p.pkt);
00837   hdr_ip *iph = hdr_ip::access(p.pkt);
00838   int flowidx = flow_table.find(p.src.addr, p.dest.addr, srh->flow_id());
00839 
00840   assert(srh->flow_header());
00841 
00842   if (srh->num_addrs()) {
00843     assert(srh->flow_timeout());
00844 
00845     if (flowidx == -1) {
00846       flow_table.cleanup();
00847       flowidx = flow_table.createEntry(p.src.addr, p.dest.addr, srh->flow_id());
00848 
00849       assert(flowidx != -1);
00850 
00851       flow_table[flowidx].timeout = Scheduler::instance().clock() + 
00852                                     srh->flow_timeout_time();
00853       flow_table[flowidx].hopCount = srh->hopCount();
00854       flow_table[flowidx].expectedTTL = iph->ttl();
00855       flow_table[flowidx].sourceRoute = p.route;
00856       flow_table[flowidx].nextHop = srh->get_next_addr();
00857       assert(srh->hopCount() == srh->cur_addr());
00858       assert(srh->get_next_type() == ::IP);
00859       assert(flow_table[flowidx].sourceRoute[flow_table[flowidx].hopCount] == 
00860              net_id);
00861 
00862       flow_table[flowidx].count = 0;            // shouldn't be used
00863       flow_table[flowidx].allowDefault = false; // shouldn't be used
00864     }
00865 
00866     assert(flowidx != -1);
00867     //assert(flow_table[flowidx].hopCount == srh->hopCount());
00868     
00869     srh->hopCount()++;
00870     return;
00871   }
00872 
00873   if (flowidx == -1) {
00874     // return an error
00875     sendUnknownFlow(p, false, srh->flow_id());
00876     assert(p.pkt == 0);
00877     return;
00878   }
00879 
00880   //assert(flow_table[flowidx].hopCount == srh->hopCount());
00881 
00882   srh->hopCount()++;
00883 
00884   // forward the packet
00885   handleFlowForwarding(p, flowidx);
00886 }
00887 
00888 void
00889 DSRAgent::handleForwarding(SRPacket &p)
00890   /* forward packet on to next host in source route,
00891    snooping as appropriate */
00892 {
00893   hdr_sr *srh =  hdr_sr::access(p.pkt);
00894   hdr_ip *iph = hdr_ip::access(p.pkt);
00895   hdr_cmn *ch =  hdr_cmn::access(p.pkt);
00896   bool flowOnly = !srh->num_addrs();
00897 
00898   if (srh->flow_header())
00899     handleFlowForwarding(p);
00900   else if (!srh->num_addrs())
00901     handleDefaultForwarding(p);
00902 
00903   if (flowOnly)
00904     return;
00905 
00906   assert(p.pkt); // make sure flow state didn't eat the pkt
00907 
00908   // first make sure we are the ``current'' host along the source route.
00909   // if we're not, the previous node set up the source route incorrectly.
00910   assert(p.route[p.route.index()] == net_id
00911          || p.route[p.route.index()] == MAC_id);
00912 
00913   if (p.route.index() >= p.route.length())
00914     {
00915       fprintf(stderr,"dfu: ran off the end of a source route\n");
00916       trace("SDFU:  ran off the end of a source route\n");
00917       drop(p.pkt, DROP_RTR_ROUTE_LOOP);
00918       p.pkt = 0;
00919       // maybe we should send this packet back as an error...
00920       return;
00921     }
00922 
00923   // if there's a source route, maybe we should snoop it too
00924   if (dsragent_snoop_source_routes)
00925     route_cache->noticeRouteUsed(p.route, Scheduler::instance().clock(), 
00926                                  net_id);
00927 
00928   // sendOutPacketWithRoute will add in the size of the src hdr, so
00929   // we have to subtract it out here
00930   ch->size() -= srh->size();
00931 
00932   // we need to manually decr this, since nothing else does.
00933   if (!iph->ttl()--) {
00934     drop(p.pkt, DROP_RTR_TTL);
00935     p.pkt = 0;
00936     return;
00937   }
00938 
00939   // now forward the packet...
00940   sendOutPacketWithRoute(p, false);
00941 }
00942 
00943 void
00944 DSRAgent::handleRouteRequest(SRPacket &p)
00945   /* process a route request that isn't targeted at us */
00946 {
00947   hdr_sr *srh =  hdr_sr::access(p.pkt);
00948   assert (srh->route_request());
00949 
00950 #ifdef notdef
00951   {
00952           int src = mac_->hdr_src(HDR_MAC(p.pkt));
00953 
00954           if(mac_->is_neighbor(src) == 0) {
00955                   Packet::free(p.pkt);
00956                   p.pkt = 0;
00957                   return;
00958           }
00959   }
00960 #endif
00961 
00962   if (ignoreRouteRequestp(p)) 
00963     {
00964       if (verbose_srr) 
00965         trace("SRR %.5f _%s_ dropped %s #%d (ignored)",
00966               Scheduler::instance().clock(), net_id.dump(), p.src.dump(),
00967               srh->rtreq_seq());
00968       Packet::free(p.pkt);  // pkt is a route request we've already processed
00969       p.pkt = 0;
00970       return; // drop silently
00971     }
00972 
00973   // we're going to process this request now, so record the req_num
00974   request_table.insert(p.src, p.src, srh->rtreq_seq());
00975 
00976   /*  - if it's a Ring 0 search, check the rt$ for a reply and use it if
00977      possible.  There's not much point in doing Ring 0 search if you're 
00978      not going to check the cache.  See the comment about turning off all
00979      reply from cache behavior near the definition of d_r_f_c_o_p (if your 
00980      workload had really good spatial locality, it might still make 
00981      sense 'cause your target is probably sitting next to you)
00982       - if reply from cache is on, check the cache and reply if possible
00983       - otherwise, just propagate if possible. */
00984   if ((srh->max_propagation() == 0 || dsragent_reply_from_cache_on_propagating)
00985       && replyFromRouteCache(p))
00986           return;                       // all done
00987 
00988 #ifdef NEW_REQUEST_LOGIC
00989   /*
00990    * If we are congested, don't forward or answer the Route Reply
00991    */
00992   if(ifq->prq_length() > 10) {
00993           trace("SRR %.9f _%s_ discarding %s #%d (ifq length %d)",
00994                 Scheduler::instance().clock(),
00995                 net_id.dump(),
00996                 p.src.dump(),
00997                 srh->rtreq_seq(),
00998                 ifq->prq_length());
00999           Packet::free(p.pkt);
01000           p.pkt = 0;
01001           return;
01002   }
01003 
01004   /*
01005    *  If "free air time" < 15%, don't forward or answer the Route Reply
01006    */
01007   {
01008           double atime = mac_->air_time_free(10);
01009 
01010           if(atime > 0.0 && atime < 0.15) {
01011                   trace("SRR %.9f _%s_ discarding %s #%d (free air time %f)",
01012                         Scheduler::instance().clock(),
01013                         net_id.dump(),
01014                         p.src.dump(),
01015                         srh->rtreq_seq(),
01016                         atime);
01017                   Packet::free(p.pkt);
01018                   p.pkt = 0;
01019                   return;
01020           }
01021   }  
01022 #endif /* NEW_REQUEST_LOGIC */
01023 
01024   // does the orginator want us to propagate?
01025   if (p.route.length() > srh->max_propagation())
01026     {   // no propagation
01027       if (verbose_srr) 
01028         trace("SRR %.5f _%s_ dropped %s #%d (prop limit exceeded)",
01029               Scheduler::instance().clock(), net_id.dump(), p.src.dump(),
01030               srh->rtreq_seq());
01031       Packet::free(p.pkt); // pkt isn't for us, and isn't data carrying
01032       p.pkt = 0;
01033       return;           
01034     }
01035 
01036   // can we propagate?
01037   if (p.route.full())
01038     {   // no propagation
01039       trace("SRR %.5f _%s_ dropped %s #%d (SR full)",
01040             Scheduler::instance().clock(), net_id.dump(), p.src.dump(),
01041             srh->rtreq_seq());
01042       /* pkt is a rt req, even if data carrying, we don't want to log 
01043          the drop using drop() since many nodes could be dropping the 
01044          packet in this fashion */
01045       Packet::free(p.pkt);
01046       p.pkt = 0;
01047       return;           
01048     }
01049 
01050   // add ourselves to the source route
01051   p.route.appendToPath(net_id);
01052 
01053   if (verbose_srr)
01054     trace("SRR %.5f _%s_ rebroadcast %s #%d ->%s %s",
01055           Scheduler::instance().clock(), net_id.dump(), p.src.dump(),
01056           srh->rtreq_seq(), p.dest.dump(), p.route.dump());
01057 
01058   sendOutPacketWithRoute(p, false);
01059   return;      
01060 }
01061 
01062 /*===========================================================================
01063   Helpers
01064 ---------------------------------------------------------------------------*/
01065 bool
01066 DSRAgent::ignoreRouteRequestp(SRPacket &p)
01067 // should we ignore this route request?
01068 {
01069   hdr_sr *srh =  hdr_sr::access(p.pkt);
01070 
01071   if (request_table.get(p.src) >= srh->rtreq_seq())
01072     { // we've already processed a copy of this reqest so
01073       // we should drop the request silently
01074       return true;
01075     }
01076   if (p.route.member(net_id,MAC_id))
01077     { // we're already on the route, drop silently
01078       return true;
01079     }
01080 
01081   if (p.route.full())
01082     { // there won't be room for us to put our address into
01083       // the route
01084       // so drop silently - sigh, so close, and yet so far...
01085       // Note that since we don't record the req_id of this message yet,
01086       // we'll process the request if it gets to us on a shorter path
01087       return true;
01088     }
01089   return false;
01090 }
01091 
01092 
01093 bool
01094 DSRAgent::replyFromRouteCache(SRPacket &p)
01095   /* - see if can reply to this route request from our cache
01096      if so, do it and return true, otherwise, return false 
01097      - frees or hands off p iff returns true */
01098 {
01099   Path rest_of_route;
01100   Path complete_route = p.route;
01101 
01102   /* we shouldn't yet be on on the pkt's current source route */
01103   assert(!p.route.member(net_id, MAC_id));
01104 
01105   // do we have a cached route the target?
01106   /* XXX what if we have more than 1?  (and one is legal for reply from
01107      cache and one isn't?) 1/28/97 -dam */
01108   if (!route_cache->findRoute(p.dest, rest_of_route, 0))
01109     { // no route => we're done
01110       return false;
01111     }
01112 
01113   /* but we should be on on the remainder of the route (and should be at
01114    the start of the route */
01115   assert(rest_of_route[0] == net_id || rest_of_route[0] == MAC_id);
01116 
01117   if (rest_of_route.length() + p.route.length() > MAX_SR_LEN)
01118     return false; // too long to work with...
01119 
01120   // add our suggested completion to the route so far
01121   complete_route.appendPath(rest_of_route);
01122 
01123   // call compressPath to remove any double backs
01124   ::compressPath(complete_route);
01125 
01126   if (!complete_route.member(net_id, MAC_id))
01127     { // we're not on the suggested route, so we can't return it
01128       return false;
01129     }
01130 
01131   // if there is any other information piggybacked into the
01132   // route request pkt, we need to forward it on to the dst
01133   hdr_cmn *cmh =  hdr_cmn::access(p.pkt);
01134   hdr_sr *srh =  hdr_sr::access(p.pkt);
01135   int request_seqnum = srh->rtreq_seq();
01136   
01137   if (PT_DSR != cmh->ptype()    // there's data
01138       || srh->route_reply()
01139       || (srh->route_error() && 
01140           srh->down_links()[srh->num_route_errors()-1].tell_addr 
01141           != GRAT_ROUTE_ERROR))
01142     { // must forward the packet on
01143       SRPacket p_copy = p;
01144       p.pkt = 0;
01145       srh->route_request() = 0;
01146 
01147       p_copy.route = complete_route;
01148       p_copy.route.setIterator(p.route.length());
01149 
01150       assert(p.route[p.route.index()] == net_id);
01151       
01152       if (verbose) trace("Sdebug %.9f _%s_ splitting %s to %s",
01153                          Scheduler::instance().clock(), net_id.dump(),
01154                          p.route.dump(), p_copy.route.dump());
01155 
01156       sendOutPacketWithRoute(p_copy,false);
01157     }
01158   else 
01159     {
01160       Packet::free(p.pkt);  // free the rcvd rt req before making rt reply
01161       p.pkt = 0;
01162     }
01163 
01164   // make up and send out a route reply
01165   p.route.appendToPath(net_id);
01166   p.route.reverseInPlace();
01167   route_cache->addRoute(p.route, Scheduler::instance().clock(), net_id);
01168   p.dest = p.src;
01169   p.src = net_id;
01170   p.pkt = allocpkt();
01171 
01172   hdr_ip *iph =  hdr_ip::access(p.pkt);
01173   iph->saddr() = Address::instance().create_ipaddr(p.src.addr, RT_PORT);
01174   iph->sport() = RT_PORT;
01175   iph->daddr() = Address::instance().create_ipaddr(p.dest.addr, RT_PORT);
01176   iph->dport() = RT_PORT;
01177   iph->ttl() = 255;
01178 
01179   srh = hdr_sr::access(p.pkt);
01180   srh->init();
01181   for (int i = 0 ; i < complete_route.length() ; i++)
01182     complete_route[i].fillSRAddr(srh->reply_addrs()[i]);
01183   srh->route_reply_len() = complete_route.length();
01184   srh->route_reply() = 1;
01185 
01186   // propagate the request sequence number in the reply for analysis purposes
01187   srh->rtreq_seq() = request_seqnum;
01188 
01189   hdr_cmn *cmnh =  hdr_cmn::access(p.pkt);
01190   cmnh->ptype() = PT_DSR;
01191   cmnh->size() = IP_HDR_LEN;
01192 
01193   if (verbose_srr)
01194     trace("SRR %.9f _%s_ cache-reply-sent %s -> %s #%d (len %d) %s",
01195           Scheduler::instance().clock(), net_id.dump(),
01196           p.src.dump(), p.dest.dump(), request_seqnum, complete_route.length(),
01197           complete_route.dump());
01198   sendOutPacketWithRoute(p, true);
01199   return true;
01200 }
01201 
01202 
01203 void
01204 DSRAgent::sendOutPacketWithRoute(SRPacket& p, bool fresh, Time delay)
01205      // take packet and send it out, packet must a have a route in it
01206      // return value is not very meaningful
01207      // if fresh is true then reset the path before using it, if fresh
01208      //  is false then our caller wants us use a path with the index
01209      //  set as it currently is
01210 {
01211   hdr_sr *srh =  hdr_sr::access(p.pkt);
01212   hdr_cmn *cmnh = hdr_cmn::access(p.pkt);
01213 
01214   assert(srh->valid());
01215   assert(cmnh->size() > 0);
01216 
01217   ID dest;
01218   if (diff_subnet(p.dest,net_id)) {
01219   dest = ID(node_->base_stn(),::IP);
01220   p.dest = dest;
01221   }
01222 
01223   if (p.dest == net_id)
01224     { // it doesn't need to go on the wire, 'cause it's for us
01225       recv(p.pkt, (Handler *) 0);
01226       p.pkt = 0;
01227       return;
01228     }
01229 
01230   if (fresh)
01231     {
01232       p.route.resetIterator();
01233       if (verbose && !srh->route_request())
01234         {
01235           trace("SO %.9f _%s_ originating %s %s", 
01236                 Scheduler::instance().clock(), 
01237                 net_id.dump(), packet_info.name(cmnh->ptype()), p.route.dump());
01238         }
01239     }
01240 
01241   p.route.fillSR(srh);
01242 
01243   // set direction of pkt to DOWN , i.e downward
01244   cmnh->direction() = hdr_cmn::DOWN;
01245 
01246   // let's see if we can snag this packet for flow state... ych 5/2/01
01247   if (dsragent_enable_flowstate &&
01248       p.src == net_id && !srh->route_request() && !srh->cur_addr() &&
01249       // can't yet decode flow errors and route errors/replies together
01250       // so don't tempt the system... ych 5/7/01
01251       !srh->route_error() && !srh->route_reply()) {
01252     hdr_ip *iph =  hdr_ip::access(p.pkt);
01253     int flowidx;
01254     u_int16_t flowid, default_flowid;
01255     double now = Scheduler::instance().clock();
01256 
01257     // hmmm, let's see if we can save us some overhead...
01258     if (dsragent_prefer_default_flow &&
01259         flow_table.defaultFlow(p.src.addr, p.dest.addr, flowid) &&
01260         -1 != (flowidx = flow_table.find(p.src.addr, p.dest.addr, flowid)) &&
01261         flow_table[flowidx].timeout >= now &&
01262         (!dsragent_prefer_shorter_over_default || 
01263           flow_table[flowidx].sourceRoute.length() <= p.route.length()) &&
01264         !(p.route == flow_table[flowidx].sourceRoute)) {
01265 
01266       p.route = flow_table[flowidx].sourceRoute;
01267       p.route.fillSR(srh);
01268     }
01269 
01270     flowidx = flow_table.find(p.src.addr, p.dest.addr, p.route);
01271 
01272     if (flowidx == -1 || flow_table[flowidx].timeout < now) {
01273       // I guess we don't know about this flow; allocate it.
01274       flow_table.cleanup();
01275       flowid = flow_table.generateNextFlowId(p.dest.addr, true);
01276       flowidx = flow_table.createEntry(p.src.addr, p.dest.addr, flowid);
01277       assert(flowidx != -1);
01278 
01279       // fill out the table
01280       flow_table[flowidx].count = 1;
01281       flow_table[flowidx].lastAdvRt = Scheduler::instance().clock();
01282       flow_table[flowidx].timeout = now + default_flow_timeout;
01283       flow_table[flowidx].hopCount = 0;
01284       flow_table[flowidx].expectedTTL = iph->ttl();
01285       flow_table[flowidx].allowDefault = true;
01286       flow_table[flowidx].sourceRoute = p.route;
01287       flow_table[flowidx].nextHop = srh->get_next_addr();
01288       assert(srh->get_next_type() == ::IP);
01289 
01290       // fix up the srh for the timeout
01291       srh->flow_timeout() = 1;
01292       srh->flow_timeout_time() = default_flow_timeout;
01293       srh->cur_addr() = srh->cur_addr() + 1;
01294     } else if (flow_table[flowidx].count <= END_TO_END_COUNT ||
01295                 flow_table[flowidx].lastAdvRt < 
01296                    (Scheduler::instance().clock() - min_adv_interval)) {
01297       // I've got it, but maybe someone else doesn't
01298       if (flow_table[flowidx].expectedTTL != iph->ttl())
01299         flow_table[flowidx].allowDefault = false;
01300 
01301       flow_table[flowidx].count++;
01302       flow_table[flowidx].lastAdvRt = Scheduler::instance().clock();
01303 
01304       srh->flow_timeout() = 1;
01305       if (dsragent_always_reestablish)
01306         srh->flow_timeout_time() = default_flow_timeout;
01307       else
01308         srh->flow_timeout_time() = (int)(flow_table[flowidx].timeout - now);
01309       srh->cur_addr() = srh->cur_addr() + 1;
01310     } else {
01311       // flow is established end to end
01312       assert (flow_table[flowidx].sourceRoute == p.route);
01313       srh->flow_timeout() = srh->cur_addr() = srh->num_addrs() = 0;
01314     }
01315 
01316     if (dsragent_always_reestablish) {
01317       // XXX see major problems detailed above (search for dsragent_always_re..)
01318       flow_table[flowidx].timeout = now + default_flow_timeout;
01319     }
01320 
01321     cmnh->next_hop() = flow_table[flowidx].nextHop;
01322     cmnh->addr_type() = ::IP;
01323 
01324     if (flow_table.defaultFlow(p.src.addr, p.dest.addr, default_flowid) &&
01325         flow_table[flowidx].flowId == default_flowid &&
01326         !srh->num_addrs() && iph->ttl() == flow_table[flowidx].expectedTTL &&
01327         flow_table[flowidx].allowDefault) {
01328       // we can go without anything... woo hoo!
01329       assert(!srh->flow_header());
01330     } else {
01331       srh->flow_header() = 1;
01332       srh->flow_id() = flow_table[flowidx].flowId;
01333       srh->hopCount() = 1;
01334     }
01335 
01336     trace("SF%ss %.9f _%s_ %d [%s -> %s] %d(%d) to %d %s", 
01337         srh->num_addrs() ? "EST" : "",
01338         Scheduler::instance().clock(), net_id.dump(), cmnh->uid(),
01339         p.src.dump(), p.dest.dump(), flow_table[flowidx].flowId,
01340         srh->flow_header(), flow_table[flowidx].nextHop,
01341         srh->num_addrs() ? srh->dump() : "");
01342 
01343     cmnh->size() += srh->size();
01344     cmnh->xmit_failure_ = srh->num_addrs() ? XmitFailureCallback : 
01345                                              XmitFlowFailureCallback;
01346     cmnh->xmit_failure_data_ = (void *) this;
01347 
01348     assert(!srh->num_addrs() || srh->flow_timeout());
01349   } else {
01350     // old non-flowstate stuff...
01351     assert(p.src != net_id || !srh->flow_header());
01352     cmnh->size() += srh->size();
01353 
01354     if (srh->route_request())
01355       { // broadcast forward
01356         cmnh->xmit_failure_ = 0;
01357         cmnh->next_hop() = MAC_BROADCAST;
01358         cmnh->addr_type() = NS_AF_ILINK;
01359       }
01360     else
01361       { // forward according to source route
01362         cmnh->xmit_failure_ = XmitFailureCallback;
01363         cmnh->xmit_failure_data_ = (void *) this;
01364 
01365         cmnh->next_hop() = srh->get_next_addr();
01366         cmnh->addr_type() = srh->get_next_type();
01367         srh->cur_addr() = srh->cur_addr() + 1;
01368       } /* route_request() */
01369   } /* can snag for path state */
01370 
01371   /* put route errors at the head of the ifq somehow? -dam 4/13/98 */
01372 
01373   // make sure we aren't cycling packets
01374   
01375 #ifdef notdef
01376   if (ifq->prq_length() > 25)
01377           trace("SIFQ %.5f _%s_ len %d",
01378                 Scheduler::instance().clock(),
01379                 net_id.dump(), ifq->prq_length());
01380 #endif
01381 #ifdef NEW_IFQ_LOGIC
01382   /*
01383    *  If the interface queue is full, there's no sense in sending
01384    *  the packet.  Drop it and generate a Route Error?
01385    */
01386   /* question for the author: this seems rife with congestion/infinite loop
01387    * possibilities. you're responding to an ifq full by sending a rt err.
01388    * sounds like the source quench problem. ych 5/5/01
01389    */
01390   if(ifq->prq_isfull(p.pkt)) {
01391           xmitFailed(p.pkt, DROP_IFQ_QFULL);
01392           p.pkt = 0;
01393           return;
01394   }
01395 #endif /* NEW_IFQ_LOGIC */
01396 
01397   // ych debugging
01398   assert(!srh->flow_header() || !srh->num_addrs() || srh->flow_timeout());
01399 
01400   // off it goes!
01401   if (srh->route_request())
01402     { // route requests need to be jittered a bit
01403       Scheduler::instance().schedule(ll, p.pkt, 
01404                                      Random::uniform(RREQ_JITTER) + delay);
01405     }
01406   else
01407     { // no jitter required 
01408       Scheduler::instance().schedule(ll, p.pkt, delay);
01409     }
01410   p.pkt = NULL; /* packet sent off */
01411 }
01412 
01413 void
01414 DSRAgent::getRouteForPacket(SRPacket &p, bool retry)
01415   /* try to obtain a route for packet
01416      pkt is freed or handed off as needed, unless retry == true
01417      in which case it is not touched */
01418 {
01419   // since we'll commonly be only one hop away, we should
01420   // arp first before route discovery as an optimization...
01421 
01422   Entry *e = request_table.getEntry(p.dest);
01423   Time time = Scheduler::instance().clock();
01424 
01425 #if 0
01426   /* pre 4/13/98 logic -dam removed b/c it seemed more complicated than
01427      needed since we're not doing piggybacking and we're returning
01428      route replies via a reversed route (the copy in this code is
01429      critical if we need to piggyback route replies on the route request to
01430      discover the return path) */
01431 
01432   /* make the route request packet */
01433   SRPacket rrp = p;
01434   rrp.pkt = p.pkt->copy();
01435   hdr_sr *srh = hdr_sr::access(rrp.pkt);
01436   hdr_ip *iph = hdr_ip::access(rrp.pkt);
01437   hdr_cmn *cmh =  hdr_cmn::access(rrp.pkt);
01438   //iph->daddr() = p.dest.getNSAddr_t();
01439   iph->daddr() = Address::instance().create_ipaddr(p.dest.getNSAddr_t(),RT_PORT);
01440   iph->dport() = RT_PORT;
01441   //iph->saddr() = net_id.getNSAddr_t();
01442   iph->saddr() = Address::instance().create_ipaddr(net_id.getNSAddr_t(),RT_PORT);
01443   iph->sport() = RT_PORT;
01444   cmnh->ptype() = PT_DSR;
01445   cmnh->size() = size_;
01446   cmnh->num_forwards() = 0;
01447 #endif
01448 
01449   /* make the route request packet */
01450   SRPacket rrp;
01451   rrp.dest = p.dest;
01452   rrp.src = net_id;
01453   rrp.pkt = allocpkt();
01454 
01455   hdr_sr *srh = hdr_sr::access(rrp.pkt); 
01456   hdr_ip *iph = hdr_ip::access(rrp.pkt);
01457   hdr_cmn *cmnh =  hdr_cmn::access(rrp.pkt);
01458   
01459   iph->daddr() = Address::instance().create_ipaddr(p.dest.getNSAddr_t(),RT_PORT);
01460   iph->dport() = RT_PORT;
01461   iph->saddr() = Address::instance().create_ipaddr(net_id.getNSAddr_t(),RT_PORT);
01462   iph->sport() = RT_PORT;
01463   cmnh->ptype() = PT_DSR;
01464   cmnh->size() = size_ + IP_HDR_LEN; // add in IP header
01465   cmnh->num_forwards() = 0;
01466   
01467   srh->init();
01468 
01469 
01470   if (BackOffTest(e, time)) {
01471           // it's time to start another route request cycle
01472 
01473 #ifdef NEW_SALVAGE_LOGIC
01474           if(p.src != net_id) {
01475 
01476                   assert(dsr_salvage_max_requests > 0);
01477                   assert(p.pkt);
01478 
01479                   if(e->rt_reqs_outstanding > dsr_salvage_max_requests) {
01480                           drop(p.pkt, DROP_RTR_NO_ROUTE);
01481                           p.pkt = 0;
01482 
01483                           // dump the route request packet we made up
01484                           Packet::free(rrp.pkt);
01485                           rrp.pkt = 0;
01486 
01487                           return;
01488                   }
01489           }
01490 #endif /* NEW_SALVAGE_LOGIC */
01491 
01492           if (dsragent_ring_zero_search) {
01493                   // do a ring zero search
01494                   e->last_type = LIMIT0;
01495                   sendOutRtReq(rrp, 0);
01496           } else {
01497                   // do a propagating route request right now
01498                   e->last_type = UNLIMIT;
01499                   sendOutRtReq(rrp, MAX_SR_LEN);
01500           }
01501 
01502           e->last_arp = time;
01503   }  else if (LIMIT0 == e->last_type &&
01504 #ifdef NEW_SALVAGE_LOGIC
01505               (dsr_salvage_allow_propagating || p.src == net_id) &&
01506 #endif
01507            (time - e->last_arp) > arp_timeout) {
01508           // try propagating rt req since we haven't heard back
01509           // from limited one
01510 
01511           e->last_type = UNLIMIT;
01512           sendOutRtReq(rrp, MAX_SR_LEN);
01513   }
01514   else {
01515           // it's not time to send another route request...
01516           if (!retry && verbose_srr)
01517                   trace("SRR %.5f _%s_ RR-not-sent %s -> %s", 
01518                         Scheduler::instance().clock(), 
01519                         net_id.dump(), rrp.src.dump(), rrp.dest.dump());
01520           Packet::free(rrp.pkt); // dump the route request packet we made up
01521           rrp.pkt = 0;
01522   }
01523 
01524   /* for now, no piggybacking at all, queue all pkts */
01525   if (!retry) {
01526           stickPacketInSendBuffer(p);
01527           p.pkt = 0; // pkt is handled for now (it's in sendbuffer)
01528   }
01529 
01530 }
01531 
01532 void
01533 DSRAgent::sendOutRtReq(SRPacket &p, int max_prop)
01534   // turn p into a route request and launch it, max_prop of request is
01535   // set as specified
01536   // p.pkt is freed or handed off
01537 {
01538   hdr_sr *srh =  hdr_sr::access(p.pkt);
01539   assert(srh->valid());
01540 
01541   srh->route_request() = 1;
01542   srh->rtreq_seq() = route_request_num++;
01543   srh->max_propagation() = max_prop;
01544   p.route.reset();
01545   p.route.appendToPath(net_id);
01546 
01547   if (dsragent_propagate_last_error && route_error_held 
01548       && Scheduler::instance().clock() - route_error_data_time  < max_err_hold)
01549     {
01550       assert(srh->num_route_errors() < MAX_ROUTE_ERRORS);
01551       srh->route_error() = 1;
01552       link_down *deadlink = &(srh->down_links()[srh->num_route_errors()]);
01553       deadlink->addr_type = NS_AF_INET;
01554       deadlink->from_addr = err_from.getNSAddr_t();
01555       deadlink->to_addr = err_to.getNSAddr_t();
01556       deadlink->tell_addr = GRAT_ROUTE_ERROR;
01557       srh->num_route_errors() += 1;
01558       /*
01559        * Make sure that the Route Error gets on a propagating request.
01560        */
01561       if(max_prop > 0) route_error_held = false;
01562     }
01563 
01564   if (verbose_srr)
01565     trace("SRR %.5f _%s_ new-request %d %s #%d -> %s", 
01566           Scheduler::instance().clock(), net_id.dump(), 
01567           max_prop, p.src.dump(), srh->rtreq_seq(), p.dest.dump());
01568   sendOutPacketWithRoute(p, false);
01569 }
01570 
01571 void
01572 DSRAgent::returnSrcRouteToRequestor(SRPacket &p)
01573   // take the route in p, add us to the end of it and return the
01574   // route to the sender of p
01575   // doesn't free p.pkt
01576 {
01577   hdr_sr *old_srh = hdr_sr::access(p.pkt);
01578 
01579   if (p.route.full()) 
01580     return; // alas, the route would be to long once we add ourselves
01581 
01582   SRPacket p_copy = p;
01583   p_copy.pkt = allocpkt();
01584   p_copy.dest = p.src;
01585   p_copy.src = net_id;
01586 
01587   p_copy.route.appendToPath(net_id);
01588 
01589   hdr_ip *new_iph =  hdr_ip::access(p_copy.pkt);
01590   //new_iph->daddr() = p_copy.dest.addr;
01591   new_iph->daddr() = Address::instance().create_ipaddr(p_copy.dest.getNSAddr_t(),RT_PORT);
01592   new_iph->dport() = RT_PORT;
01593   //new_iph->saddr() = p_copy.src.addr;
01594   new_iph->saddr() =
01595     Address::instance().create_ipaddr(p_copy.src.getNSAddr_t(),RT_PORT); 
01596   new_iph->sport() = RT_PORT;
01597   new_iph->ttl() = 255;
01598 
01599   hdr_sr *new_srh =  hdr_sr::access(p_copy.pkt);
01600   new_srh->init();
01601   for (int i = 0 ; i < p_copy.route.length() ; i++)
01602     p_copy.route[i].fillSRAddr(new_srh->reply_addrs()[i]);
01603   new_srh->route_reply_len() = p_copy.route.length();
01604   new_srh->route_reply() = 1;
01605 
01606   // propagate the request sequence number in the reply for analysis purposes
01607   new_srh->rtreq_seq() = old_srh->rtreq_seq();
01608   
01609   hdr_cmn *new_cmnh =  hdr_cmn::access(p_copy.pkt);
01610   new_cmnh->ptype() = PT_DSR;
01611   new_cmnh->size() = IP_HDR_LEN;
01612 
01613   if (verbose_srr)
01614     trace("SRR %.9f _%s_ reply-sent %s -> %s #%d (len %d) %s",
01615           Scheduler::instance().clock(), net_id.dump(),
01616           p_copy.src.dump(), p_copy.dest.dump(), old_srh->rtreq_seq(),
01617           p_copy.route.length(), p_copy.route.dump());
01618 
01619   // flip the route around for the return to the requestor, and 
01620   // cache the route for future use
01621   p_copy.route.reverseInPlace();
01622   route_cache->addRoute(p_copy.route, Scheduler::instance().clock(), net_id);
01623 
01624   p_copy.route.resetIterator();
01625   p_copy.route.fillSR(new_srh);
01626   new_cmnh->size() += new_srh->size();
01627   
01628   /* we now want to jitter when we first originate route replies, since
01629      they are a transmission we make in response to a broadcast packet 
01630      -dam 4/23/98
01631      sendOutPacketWithRoute(p_copy, true); */
01632   {
01633           double d = Random::uniform(RREQ_JITTER);
01634 #if 0
01635           fprintf(stderr, "Random Delay: %f\n", d);
01636 #endif
01637           Scheduler::instance().schedule(this, p_copy.pkt, d);
01638   }
01639 }
01640 
01641 int
01642 DSRAgent::diff_subnet(ID dest, ID myid) 
01643 {
01644         int dst = dest.addr;
01645         int id = myid.addr;
01646         char* dstnet = Address::instance().get_subnetaddr(dst);
01647         char * subnet = Address::instance().get_subnetaddr(id);
01648         if (subnet != NULL) {
01649                 if (dstnet != NULL) {
01650                         if (strcmp(dstnet, subnet) != 0) {
01651                                 delete [] dstnet;
01652                                 return 1;
01653                         }
01654                         delete [] dstnet;
01655                 }
01656                 delete [] subnet;
01657         }
01658         assert(dstnet == NULL);
01659         return 0;
01660 }
01661 
01662 
01663 void
01664 DSRAgent::acceptRouteReply(SRPacket &p)
01665   /* - enter the packet's source route into our cache
01666      - see if any packets are waiting to be sent out with this source route
01667      - doesn't free the pkt */
01668 {
01669   hdr_sr *srh =  hdr_sr::access(p.pkt);
01670   Path reply_route(srh->reply_addrs(), srh->route_reply_len());
01671 
01672   if (!srh->route_reply())
01673     { // somethings wrong...
01674       trace("SDFU non route containing packet given to acceptRouteReply");
01675       fprintf(stderr,
01676               "dfu: non route containing packet given to acceptRouteReply\n");
01677     }
01678 
01679   bool good_reply = true;  
01680   //#ifdef USE_GOD_FEEDBACK
01681   /* check to see if this reply is valid or not using god info */
01682   int i;
01683   
01684   for (i = 0; i < reply_route.length()-1 ; i++) 
01685     if (God::instance()->hops(reply_route[i].getNSAddr_t(), 
01686                               reply_route[i+1].getNSAddr_t()) != 1)
01687       {
01688         good_reply = false;
01689         break;
01690       }
01691   //#endif //GOD_FEEDBACK
01692 
01693   if (verbose_srr)
01694     trace("SRR %.9f _%s_ reply-received %d from %s  %s #%d -> %s %s",
01695           Scheduler::instance().clock(), net_id.dump(),
01696           good_reply ? 1 : 0,
01697           p.src.dump(), reply_route[0].dump(), srh->rtreq_seq(),
01698           reply_route[reply_route.length()-1].dump(),
01699           reply_route.dump());
01700 
01701   // add the new route into our cache
01702   route_cache->addRoute(reply_route, Scheduler::instance().clock(), p.src);
01703 
01704   // back down the route request counters
01705   Entry *e = request_table.getEntry(reply_route[reply_route.length()-1]);
01706   e->rt_reqs_outstanding = 0;
01707   e->last_rt_req = 0.0;  
01708 
01709   // see if the addtion of this route allows us to send out
01710   // any of the packets we have waiting
01711   Time delay = 0.0;
01712   ID dest;
01713   for (int c = 0; c < SEND_BUF_SIZE; c++)
01714     {
01715       if (send_buf[c].p.pkt == NULL) continue;
01716 
01717       // check if pkt is destined to outside domain
01718       if (diff_subnet(send_buf[c].p.dest,net_id)) {
01719         dest = ID(node_->base_stn(),::IP);
01720         send_buf[c].p.dest = dest;
01721       }
01722 
01723       if (route_cache->findRoute(send_buf[c].p.dest, send_buf[c].p.route, 1))
01724         { // we have a route!
01725 #ifdef DEBUG
01726           struct hdr_cmn *ch = HDR_CMN(send_buf[c].p.pkt);
01727           if(ch->size() < 0) {
01728                 drop(send_buf[c].p.pkt, "XXX");
01729                 abort();
01730           }
01731 #endif
01732           if (verbose)
01733             trace("Sdebug %.9f _%s_ liberated from sendbuf %s->%s %s",
01734                   Scheduler::instance().clock(), net_id.dump(),
01735                   send_buf[c].p.src.dump(), send_buf[c].p.dest.dump(), 
01736                   send_buf[c].p.route.dump());
01737           /* we need to spread out the rate at which we send packets
01738              in to the link layer to give ARP time to complete.  If we
01739              dump all the packets in at once, all but the last one will
01740              be dropped.  XXX THIS IS A MASSIVE HACK -dam 4/14/98 */
01741           sendOutPacketWithRoute(send_buf[c].p, true, delay);
01742           delay += arp_timeout; 
01743           send_buf[c].p.pkt = NULL;
01744         }
01745     }
01746 }
01747 
01748 void
01749 DSRAgent::processUnknownFlowError(SRPacket &p, bool asDefault) {
01750   hdr_sr *srh = hdr_sr::access(p.pkt);
01751   int flowidx = -1;
01752   struct flow_error *fe;
01753   u_int16_t flowid;
01754 
01755   if (asDefault) {
01756     assert (srh->flow_default_unknown() && srh->num_default_unknown());
01757     fe = &srh->unknown_defaults()[srh->num_default_unknown()-1];
01758   } else {
01759     assert (srh->flow_unknown() && srh->num_flow_unknown());
01760     fe = &srh->unknown_flows()[srh->num_flow_unknown()-1];
01761     if (!flow_table.defaultFlow(fe->flow_src, fe->flow_dst, flowid))
01762       goto skip_proc;
01763   }
01764 
01765   /* not for us; hope it gets the right place... */
01766   if (fe->flow_src != (int) net_id.addr)
01767     return;
01768 
01769   if (-1 != (flowidx = flow_table.find(fe->flow_src, fe->flow_dst, 
01770                                        asDefault ? flowid : fe->flow_id)))
01771     flow_table[flowidx].count = 0;
01772 
01773 skip_proc:
01774   trace("SFEr %.9f _%s_ from %d re %d : %d [%d]",
01775         Scheduler::instance().clock(), net_id.dump(), p.src.addr, fe->flow_dst,
01776         asDefault ? -1 : fe->flow_id, 
01777         flowidx != -1 ? flow_table[flowidx].count : -1);
01778 
01779   if ((asDefault ? srh->num_default_unknown() : srh->num_flow_unknown()) == 1)
01780     return;
01781 
01782   SRPacket p_copy = p;
01783   p_copy.pkt = p.pkt->copy();
01784 
01785   hdr_sr *new_srh = hdr_sr::access(p_copy.pkt);
01786   hdr_ip *new_iph = hdr_ip::access(p_copy.pkt);
01787   
01788   // remove us from the list of errors
01789   if (asDefault)
01790     new_srh->num_default_unknown()--;
01791   else
01792     new_srh->num_flow_unknown()--;
01793   
01794   // send the packet to the person listed in what's now the last entry
01795   p_copy.dest = ID(fe[-1].flow_src, ::IP);
01796   p_copy.src = net_id;
01797 
01798   //new_iph->daddr() = p_copy.dest.addr;
01799   new_iph->daddr() = Address::instance().create_ipaddr(p_copy.dest.getNSAddr_t(),RT_PORT);
01800   new_iph->dport() = RT_PORT;
01801   //new_iph->saddr() = p_copy.src.addr;
01802   new_iph->saddr() = Address::instance().create_ipaddr(p_copy.src.getNSAddr_t(),RT_PORT);
01803   new_iph->sport() = RT_PORT;
01804   new_iph->ttl() = 255;
01805 
01806   new_srh->flow_header() = 0;
01807   new_srh->flow_timeout() = 0;
01808 
01809   // an error packet is a first class citizen, so we'll
01810   // use handlePktWOSR to obtain a route if needed
01811   handlePktWithoutSR(p_copy, false);
01812 }
01813 
01814 void
01815 DSRAgent::processBrokenRouteError(SRPacket& p)
01816 // take the error packet and proccess our part of it.
01817 // if needed, send the remainder of the errors to the next person
01818 // doesn't free p.pkt
01819 {
01820   hdr_sr *srh = hdr_sr::access(p.pkt);
01821 
01822   if (!srh->route_error())
01823     return; // what happened??
01824   
01825   /* if we hear A->B is dead, should we also run the link B->A through the
01826      cache as being dead, since 802.11 requires bidirectional links 
01827       XXX -dam 4/23/98 */
01828 
01829   // since CPU time is cheaper than network time, we'll process
01830   // all the dead links in the error packet
01831   assert(srh->num_route_errors() > 0);
01832   for (int c = 0 ; c < srh->num_route_errors() ; c++)
01833     {
01834       assert(srh->down_links()[c].addr_type == NS_AF_INET);
01835       route_cache->noticeDeadLink(ID(srh->down_links()[c].from_addr,::IP),
01836                                  ID(srh->down_links()[c].to_addr,::IP),
01837                                  Scheduler::instance().clock());
01838       flow_table.noticeDeadLink(ID(srh->down_links()[c].from_addr,::IP),
01839                                  ID(srh->down_links()[c].to_addr,::IP));
01840       // I'll assume everything's of type NS_AF_INET for the printout... XXX
01841       if (verbose_srr)
01842         trace("SRR %.9f _%s_ dead-link tell %d  %d -> %d",
01843               Scheduler::instance().clock(), net_id.dump(),
01844               srh->down_links()[c].tell_addr,
01845               srh->down_links()[c].from_addr,
01846               srh->down_links()[c].to_addr);
01847     }
01848 
01849   ID who = ID(srh->down_links()[srh->num_route_errors()-1].tell_addr, ::IP);
01850   if (who != net_id && who != MAC_id)
01851     { // this error packet wasn't meant for us to deal with
01852       // since the outer entry doesn't list our name
01853       return;
01854     }
01855 
01856   // record this route error data for possible propagation on our next
01857   // route request
01858   route_error_held = true;
01859   err_from = ID(srh->down_links()[srh->num_route_errors()-1].from_addr,::IP);
01860   err_to = ID(srh->down_links()[srh->num_route_errors()-1].to_addr,::IP);
01861   route_error_data_time = Scheduler::instance().clock();
01862 
01863   if (1 == srh->num_route_errors())
01864     { // this error packet has done its job
01865       // it's either for us, in which case we've done what it sez
01866       // or it's not for us, in which case we still don't have to forward
01867       // it to whoever it is for
01868       return;
01869     }
01870 
01871   /* make a copy of the packet and send it to the next tell_addr on the
01872      error list.  the copy is needed in case there is other data in the
01873      packet (such as nested route errors) that need to be delivered */
01874   if (verbose) 
01875     trace("Sdebug %.5f _%s_ unwrapping nested route error",
01876           Scheduler::instance().clock(), net_id.dump());
01877   
01878   SRPacket p_copy = p;
01879   p_copy.pkt = p.pkt->copy();
01880 
01881   hdr_sr *new_srh = hdr_sr::access(p_copy.pkt);
01882   hdr_ip *new_iph = hdr_ip::access(p_copy.pkt);
01883   
01884   // remove us from the list of errors
01885   new_srh->num_route_errors() -= 1;
01886   
01887   // send the packet to the person listed in what's now the last entry
01888   p_copy.dest = ID(new_srh->down_links()[new_srh->num_route_errors()-1].tell_addr, ::IP);
01889   p_copy.src = net_id;
01890 
01891   //new_iph->daddr() = p_copy.dest.addr;
01892   new_iph->daddr() = Address::instance().create_ipaddr(p_copy.dest.getNSAddr_t(),RT_PORT);
01893   new_iph->dport() = RT_PORT;
01894   //new_iph->saddr() = p_copy.src.addr;
01895   new_iph->saddr() = Address::instance().create_ipaddr(p_copy.src.getNSAddr_t(),RT_PORT);
01896   new_iph->sport() = RT_PORT;
01897   new_iph->ttl() = 255;
01898 
01899   new_srh->flow_header() = 0;
01900   new_srh->flow_timeout() = 0;
01901       
01902   // an error packet is a first class citizen, so we'll
01903   // use handlePktWOSR to obtain a route if needed
01904   handlePktWithoutSR(p_copy, false);
01905 }
01906 
01907 #ifdef DSR_FILTER_TAP
01908 int64_t dsr_tap = 0;
01909 int64_t dsr_tap_skip = 0;
01910 #endif
01911 
01912 // Process flow state Automatic Route Shortening
01913 void
01914 DSRAgent::processFlowARS(const Packet *packet) {
01915   
01916   hdr_sr *srh = hdr_sr::access(packet);
01917   hdr_ip *iph = hdr_ip::access(packet);
01918   hdr_cmn *cmh = hdr_cmn::access(packet);
01919   //hdr_sr  *srh = (hdr_sr*) ((Packet *)packet)->access(off_sr_);
01920   //hdr_ip  *iph = (hdr_ip*) ((Packet *)packet)->access(off_ip_);
01921   //hdr_cmn *cmh =  (hdr_cmn*)((Packet *)packet)->access(off_cmn_);
01922   u_int16_t flowid;
01923   int flowidx;
01924   int shortamt;
01925 
01926   assert(!srh->num_addrs());
01927 
01928   if (srh->flow_header()) {
01929     flowid = srh->flow_id();
01930 
01931     // do I know about this flow?
01932     if (-1 == (flowidx = flow_table.find(iph->saddr(), iph->daddr(), flowid)))
01933       return;
01934 
01935     shortamt = flow_table[flowidx].hopCount - srh->hopCount();
01936   } else {
01937     // do I know which flow is default?
01938     if (!flow_table.defaultFlow(iph->saddr(), iph->daddr(), flowid))
01939       return;
01940 
01941     // do I know about this flow?
01942     if (-1 == (flowidx = flow_table.find(iph->saddr(), iph->daddr(), flowid)))
01943       return;
01944 
01945     shortamt = iph->ttl() - flow_table[flowidx].expectedTTL;
01946   }
01947 
01948   // transmitter downstream from us
01949   if (shortamt <= 0)
01950     return;
01951 
01952   // this is a _MAJOR_ problem!!!
01953   if (flow_table[flowidx].sourceRoute.length() < shortamt)
01954     return;
01955 
01956   ars_table.insert(cmh->uid(), flowid, shortamt);
01957 }
01958 
01959 void 
01960 DSRAgent::tap(const Packet *packet)
01961   /* process packets that are promiscously listened to from the MAC layer tap
01962   *** do not change or free packet *** */
01963 {
01964   hdr_sr *srh = hdr_sr::access(packet);
01965   hdr_ip *iph = hdr_ip::access(packet);
01966   hdr_cmn *cmh =  hdr_cmn::access(packet);
01967   
01968   if (!dsragent_use_tap) return;
01969 
01970   if (!srh->valid()) return;    // can't do anything with it
01971 
01972   if (!srh->num_addrs()) {
01973     processFlowARS(packet);
01974     return;
01975   }
01976 
01977   // don't trouble me with packets I'm about to receive anyway
01978   /* this change added 5/13/98 -dam */
01979   ID next_hop(srh->addrs()[srh->cur_addr()]);
01980   if (next_hop == net_id || next_hop == MAC_id) return;
01981 
01982   SRPacket p((Packet *) packet, srh);
01983   //p.dest = ID(iph->dst(),::IP);
01984   //p.src = ID(iph->src(),::IP);
01985   p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
01986   p.src = ID((Address::instance().get_nodeaddr(iph->saddr())),::IP);
01987 
01988   // don't trouble me with my own packets
01989   if (p.src == net_id) return; 
01990 
01991 #ifdef DSR_FILTER_TAP
01992   /* 
01993    * Don't process packets more than once.  In real implementations
01994    * this can be done with the (IP Source, IP ID) pair, but it is
01995    * simpler to implement it with the global "uid" in simulation.
01996    */
01997   {
01998           int uid = cmh->uid();
01999           if(tap_uid_cache[(uid & TAP_BITMASK)] == uid) {
02000                   dsr_tap_skip++;
02001                   return;
02002           }
02003           dsr_tap++;
02004           tap_uid_cache[(uid & TAP_BITMASK)] = uid;
02005   }
02006 #endif
02007 
02008   /* snoop on the SR data */
02009   if (srh->route_error())
02010     {
02011       if (verbose)
02012         trace("Sdebug _%s_ tap saw error %d",  net_id.dump(), cmh->uid());
02013       processBrokenRouteError(p);
02014     }
02015 
02016   if (srh->route_reply())
02017     {
02018       Path reply_path(srh->reply_addrs(), srh->route_reply_len());
02019       if(verbose)
02020         trace("Sdebug _%s_ tap saw route reply %d  %s",
02021                net_id.dump(), cmh->uid(), reply_path.dump());
02022       route_cache->noticeRouteUsed(reply_path, Scheduler::instance().clock(), 
02023                                    p.src);
02024     }
02025 
02026   /* we can't decide whether we should snoop on the src routes in 
02027      route requests.  We've seen cases where we hear a route req from a
02028      node, but can't complete an arp with that node (and so can't actually
02029      deliver packets through it if called on to do so) -dam 4/16/98 */
02030 
02031   if (srh->route_request()) return; // don't path shorten route requests
02032   // the logic is wrong for shortening rtreq's anyway, cur_addr always = 0
02033 
02034   if (dsragent_snoop_source_routes)
02035     {
02036       if (verbose)
02037         trace("Sdebug _%s_ tap saw route use %d %s", net_id.dump(), 
02038               cmh->uid(), p.route.dump());
02039       route_cache->noticeRouteUsed(p.route, Scheduler::instance().clock(), 
02040                                    net_id);
02041     }
02042 
02043   if (PT_DSR == cmh->ptype()) return; //  no route shortening on any
02044   // DSR packet
02045 
02046   /* I think we ended up sending grat route replies for source routes on 
02047      route replies for route requests that were answered by someone else's
02048      cache, resulting in the wrong node receiving the route.  For now, I 
02049      outlaw it.
02050 
02051      The root of the problem is that when we salvage a pkt from a failed
02052      link using a route from our cache, we break what had been an invariant
02053      that the IP src of a packet was also the first machine listed on the
02054      source route.  Here's the route of the problem that results in the 
02055      simulator crashing at 8.56135 when 44 recieves a route reply that
02056      has 24 listed as the first node in the route.
02057 
02058 SSendFailure 8.52432 24 [10 |24 46 45 1 40 ]
02059 S$hit 8.52432 salvaging 10 -> 40 with [(24) 44 50 9 40 ]
02060 S$hit 8.52432 salvaging 44 -> 40 with [(24) 44 50 9 40 ]
02061 D 8.52432 [20 42 2e 18 800] 24 DSR 156 -- 10->40 6 [0] [1 9 39] [0 0 0->0]
02062 s 8.52438 [1b 45e 2c 18 0] 24 MAC 20
02063 r 8.52446 [1b 45e 2c 18 0] 44 MAC 20
02064 s 8.52454 [101b 27e 23 1b 0] 27 MAC 20
02065 s 8.52564 [101b 27e 23 1b 0] 27 MAC 20
02066 s 8.52580 [101b 45e 2c 18 0] 24 MAC 20
02067 r 8.52588 [101b 45e 2c 18 0] 44 MAC 20
02068 s 8.52589 [1c 41c 18 0 0] 44 MAC 14
02069 r 8.52595 [1c 41c 18 0 0] 24 MAC 14
02070 s 8.52600 [20 42 2c 18 800] 24 DSR 244 -- 10->40 5 [0] [1 9 39] [0 0 24->46]
02071 r 8.52698 [20 42 2c 18 800] 44 DSR 216 -- 10->40 5 [0] [1 9 39] [0 0 24->46]
02072 
02073 s 8.53947 [20 42 2c 18 800] 24 DSR 204 -- 44->40 5 [0] [1 8 39] [0 0 0->0]
02074 r 8.54029 [20 42 2c 18 800] 44 DSR 176 -- 44->40 5 [0] [1 8 39] [0 0 0->0]
02075 Sdebug 50 consider grat arp for [24 (44) 50 9 40 ]
02076 SRR 8.54029 50 gratuitous-reply-sent 50 -> 44 [24 (50) 9 40 ]
02077 SF 8.54029 44 [44 -> 40] via 0x3200 [24 |44 50 9 40 ]
02078 s 8.54030 [1d 0 18 0 0] 44 MAC 14
02079 r 8.54036 [1d 0 18 0 0] 24 MAC 14
02080 s 8.54044 [101b 54f 32 2c 0] 44 MAC 20
02081 r 8.54053 [101b 54f 32 2c 0] 50 MAC 20
02082 s 8.54054 [1c 50d 2c 0 0] 50 MAC 14
02083 r 8.54059 [1c 50d 2c 0 0] 44 MAC 14
02084 s 8.54064 [20 42 32 2c 800] 44 DSR 304 -- 10->40 5 [0] [1 9 39] [0 0 24->46]
02085 r 8.54186 [20 42 32 2c 800] 50 DSR 276 -- 10->40 5 [0] [1 9 39] [0 0 24->46]
02086 SF 8.54186 50 [10 -> 40] via 0x900 [24 44 |50 9 40 ]
02087 
02088 s 8.56101 [20 42 2c 18 800] 24 DSR 84 -- 50->44 2 [0] [1 4 40] [0 0 0->0]
02089 r 8.56135 [20 42 2c 18 800] 44 DSR 56 -- 50->44 2 [0] [1 4 40] [0 0 0->0]
02090 
02091 */
02092 
02093 
02094   /* check to see if we can shorten the route being used */
02095   if (p.route[p.route.index()] != net_id
02096       && p.route[p.route.index()] != MAC_id)
02097     { // it's not immeadiately to us
02098       for (int i = p.route.index() + 1; i < p.route.length(); i++)
02099         if (p.route[i] == net_id || p.route[i] == MAC_id)
02100           { // but it'll get here eventually...
02101             sendRouteShortening(p, p.route.index(), i);
02102           }
02103     }
02104 }
02105 
02106 static GratReplyHoldDown *
02107 FindGratHoldDown(GratReplyHoldDown *hd, int sz, Path& query)
02108 {
02109   int c;
02110   for (c = 0; c < sz; c++)
02111     if (query == hd[c].p) return &hd[c];
02112   return NULL;
02113 }
02114 
02115 void
02116 DSRAgent::sendRouteShortening(SRPacket &p, int heard_at, int xmit_at)
02117   // p was overheard at heard_at in it's SR, but we aren't supposed to
02118   // get it till xmit_at, so all the nodes between heard_at and xmit_at
02119   // can be elided.  Send originator of p a gratuitous route reply to 
02120   // tell them this.
02121 {
02122   // this shares code with returnSrcRouteToRequestor - factor them -dam */
02123 
02124   if (!dsragent_send_grat_replies) return;
02125 
02126   if (verbose)
02127     trace("Sdebug %s consider grat arp for %s", net_id.dump(), p.route.dump());
02128   GratReplyHoldDown *g = FindGratHoldDown(grat_hold, RTREP_HOLDOFF_SIZE, 
02129                                           p.route);
02130   if (!g)
02131     { 
02132       grat_hold[grat_hold_victim].p = p.route;
02133       grat_hold_victim = (grat_hold_victim + 1) % RTREP_HOLDOFF_SIZE;
02134       g = &grat_hold[grat_hold_victim];      
02135     }
02136   else if (Scheduler::instance().clock() - g->t < grat_hold_down_time) return;
02137   g->t = Scheduler::instance().clock();
02138 
02139   SRPacket p_copy = p;
02140   p_copy.pkt = allocpkt();
02141   p_copy.dest = p.route[0];   // tell the originator of this long source route
02142   p_copy.src = net_id;
02143 
02144   // reverse the route to get the packet back
02145   p_copy.route[p_copy.route.index()] = net_id;
02146   p_copy.route.reverseInPlace();
02147   p_copy.route.removeSection(0,p_copy.route.index());
02148 
02149   hdr_ip *new_iph =  hdr_ip::access(p_copy.pkt);
02150   //new_iph->daddr() = p_copy.dest.addr;
02151   new_iph->daddr() = Address::instance().create_ipaddr(p_copy.dest.getNSAddr_t(),RT_PORT);
02152   new_iph->dport() = RT_PORT;
02153   //new_iph->saddr() = p_copy.src.addr;
02154   new_iph->saddr() = Address::instance().create_ipaddr(p_copy.src.getNSAddr_t(),RT_PORT);
02155   new_iph->sport() = RT_PORT;
02156   new_iph->ttl() = 255;
02157 
02158   // shorten's p's route
02159   p.route.removeSection(heard_at, xmit_at);
02160   hdr_sr *new_srh =  hdr_sr::access(p_copy.pkt);
02161   new_srh->init();
02162   for (int i = 0 ; i < p.route.length() ; i++)
02163     p.route[i].fillSRAddr(new_srh->reply_addrs()[i]);
02164   new_srh->route_reply_len() = p.route.length();
02165   new_srh->route_reply() = 1;
02166   // grat replies will have a 0 seq num (it's only for trace analysis anyway)
02167   new_srh->rtreq_seq() = 0;
02168 
02169   hdr_cmn *new_cmnh =  hdr_cmn::access(p_copy.pkt);
02170   new_cmnh->ptype() = PT_DSR;
02171   new_cmnh->size() += IP_HDR_LEN;
02172 
02173   if (verbose_srr)
02174     trace("SRR %.9f _%s_ gratuitous-reply-sent %s -> %s (len %d) %s",
02175           Scheduler::instance().clock(), net_id.dump(),
02176           p_copy.src.dump(), p_copy.dest.dump(), p.route.length(), 
02177           p.route.dump());
02178 
02179   // cache the route for future use (we learned the route from p)
02180   route_cache->addRoute(p_copy.route, Scheduler::instance().clock(), p.src);
02181   sendOutPacketWithRoute(p_copy, true);
02182 }
02183 
02184 /*==============================================================
02185   debug and trace output
02186 ------------------------------------------------------------*/
02187 void
02188 DSRAgent::trace(char* fmt, ...)
02189 {
02190   va_list ap;
02191   
02192   if (!logtarget) return;
02193 
02194   va_start(ap, fmt);
02195   vsprintf(logtarget->pt_->buffer(), fmt, ap);
02196   logtarget->pt_->dump();
02197   va_end(ap);
02198 }
02199 
02200 
02201 /*==============================================================
02202   Callback for link layer transmission failures
02203 ------------------------------------------------------------*/
02204 // XXX Obviously this structure and FilterFailure() is not used anywhere, 
02205 // because off_cmn_ in this structure cannot be populated at all!
02206 // Instead of deleting, I'm simply commenting them out, perhaps they'll be 
02207 // salvaged sometime in the future. - haoboy
02208 
02209 //  struct filterfailuredata {
02210 //    nsaddr_t dead_next_hop;
02211 //    int off_cmn_;
02212 //    DSRAgent *agent;
02213 //  };
02214 
02215 //  int
02216 //  FilterFailure(Packet *p, void *data)
02217 //  {
02218 //    struct filterfailuredata *ffd = (filterfailuredata *) data;
02219 //    hdr_cmn *cmh = (hdr_cmn*)p->access(ffd->off_cmn_);
02220 //    int remove = cmh->next_hop() == ffd->dead_next_hop;
02221 
02222 //    if (remove)
02223 //        ffd->agent->undeliverablePkt(p,1);
02224 //    return remove;
02225 //  }
02226 
02227 void
02228 DSRAgent::undeliverablePkt(Packet *pkt, int mine)
02229   /* when we've got a packet we can't deliver, what to do with it? 
02230      frees or hands off p if mine = 1, doesn't hurt it otherwise */
02231 {
02232   hdr_sr *srh = hdr_sr::access(pkt);
02233   hdr_ip *iph = hdr_ip::access(pkt);
02234   hdr_cmn *cmh;
02235 
02236   SRPacket p(pkt,srh);
02237   //p.dest = ID(iph->dst(),::IP);
02238   //p.src = ID(iph->src(),::IP);
02239   p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
02240   p.src = ID((Address::instance().get_nodeaddr(iph->saddr())),::IP);
02241   p.pkt = mine ? pkt : pkt->copy();
02242 
02243   srh = hdr_sr::access(p.pkt);
02244   iph = hdr_ip::access(p.pkt);
02245   cmh = hdr_cmn::access(p.pkt);
02246 
02247   // we're about to salvage. flowstate rules say we must strip all flow
02248   // state info out of this packet. ych 5/5/01
02249   cmh->size() -= srh->size(); // changes affect size of header...
02250   srh->flow_timeout() = 0;
02251   srh->flow_header() = 0;
02252   cmh->size() += srh->size(); // done fixing flow state headers
02253 
02254   if (ID((Address::instance().get_nodeaddr(iph->saddr())),::IP) == net_id) {
02255     // it's our packet we couldn't send
02256     cmh->size() -= srh->size(); // remove size of SR header
02257     assert(cmh->size() >= 0);
02258     
02259     handlePktWithoutSR(p, false);
02260     
02261     return;
02262   }
02263 
02264   /*
02265    * Am I allowed to salvage?
02266    */
02267   if(dsragent_salvage_with_cache == 0) {
02268           assert(mine);
02269           drop(pkt, DROP_RTR_NO_ROUTE);  
02270           return;
02271   }
02272 
02273 #ifdef NEW_SALVAGE_LOGIC
02274   if(srh->salvaged() >= dsr_salvage_max_attempts) {
02275           assert(mine);
02276           drop(pkt, DROP_RTR_SALVAGE);
02277           return;
02278   }
02279 #endif /* NEW_SALVAGE_LOGIC */
02280 
02281   // it's a packet we're forwarding for someone, save it if we can...
02282   Path salvage_route;
02283       
02284   if (route_cache->findRoute(p.dest, salvage_route, 0)) {
02285           // be nice and send the packet out
02286 #if 0
02287           /* we'd like to create a ``proper'' source route with the
02288              IP src of the packet as the first node, but we can't actually 
02289              just append the salvage route onto the route used so far, 
02290              since the append creates routes with loops in them 
02291              like  1 2 3 4 3 5 
02292              If we were to squish the route to remove the loop, then we'd be
02293              removing ourselves from the route, which is verboten.
02294              If we did remove ourselves, and our salvage route contained
02295              a stale link, we might never hear the route error.
02296              -dam 5/13/98
02297 
02298              Could we perhaps allow SRs with loops in them on the air?
02299              Since it's still a finite length SR, the pkt can't loop
02300              forever... -dam 8/5/98 */
02301 
02302           // truncate the route at the bad link and append good bit
02303           int our_index = p.route.index();
02304 
02305           p.route.setLength(our_index);
02306           // yes this cuts us off the route,
02307 
02308           p.route.appendPath(salvage_route);
02309           // but we're at the front of s_r
02310           p.route.setIterator(our_index);
02311 #else
02312           p.route = salvage_route;
02313           p.route.resetIterator();
02314 #endif
02315 
02316           if (dsragent_dont_salvage_bad_replies && srh->route_reply()) {
02317                   // check to see if we'd be salvaging a packet
02318                   // with the dead link in it
02319 
02320                   ID to_id(srh->addrs()[srh->cur_addr()+1].addr,
02321                            (ID_Type) srh->addrs()[srh->cur_addr()].addr_type);
02322                   bool bad_reply = false;
02323 
02324                   for (int i = 0 ; i < srh->route_reply_len()-1; i++) {
02325 
02326                           if (net_id == ID(srh->reply_addrs()[i]) &&
02327                               to_id == ID(srh->reply_addrs()[i+1]) ||
02328                               (dsragent_require_bi_routes &&
02329                                to_id == ID(srh->reply_addrs()[i]) &&
02330                                net_id == ID(srh->reply_addrs()[i+1]))) {
02331                                           
02332                                   bad_reply = true;
02333                                   break;
02334                           }
02335                   }
02336                   if (bad_reply) {
02337                           // think about killing this packet
02338                           srh->route_reply() = 0;
02339                           if (PT_DSR == cmh->ptype() &&
02340                               ! srh->route_request() &&
02341                               ! srh->route_error()) {
02342                                   // this packet has no reason to live
02343                                   if (verbose_srr)
02344                                           trace("SRR %.5f _%s_ --- %d dropping bad-reply %s -> %s", 
02345                                                 Scheduler::instance().clock(), net_id.dump(), 
02346                                                 cmh->uid(), p.src.dump(), p.dest.dump());
02347                                   if (mine)
02348                                           drop(pkt, DROP_RTR_MAC_CALLBACK);
02349                                   return;
02350                           }
02351                   }
02352           }
02353 
02354           if (verbose_ssalv) 
02355                   trace("Ssalv %.5f _%s_ salvaging %s -> %s --- %d with %s",
02356                         Scheduler::instance().clock(), net_id.dump(),
02357                         p.src.dump(), p.dest.dump(),
02358                         cmh->uid(), p.route.dump());
02359 
02360           // remove size of SR header, added back in sendOutPacketWithRoute
02361           cmh->size() -= srh->size(); 
02362           assert(cmh->size() >= 0);
02363 #ifdef NEW_SALVAGE_LOGIC
02364           srh->salvaged() += 1;
02365 #endif
02366           sendOutPacketWithRoute(p, false);
02367   }
02368 #ifdef NEW_SALVAGE_LOGIC
02369   else if(dsr_salvage_max_requests > 0) {
02370           /*
02371            * Allow the node to perform route discovery for an
02372            * intermediate hop.
02373            */
02374           if (verbose_ssalv) 
02375                   trace("Ssalv %.5f _%s_ adding to SB --- %d %s -> %s [%d]", 
02376                         Scheduler::instance().clock(), 
02377                         net_id.dump(),
02378                         cmh->uid(),
02379                         p.src.dump(), p.dest.dump(),
02380                         srh->salvaged());
02381           stickPacketInSendBuffer(p);
02382   }
02383 #endif
02384   else {
02385           // we don't have a route, and it's not worth us doing a
02386           // route request to try to help the originator out, since
02387           // it might be counter productive
02388           if (verbose_ssalv) 
02389                   trace("Ssalv %.5f _%s_ dropping --- %d %s -> %s [%d]", 
02390                         Scheduler::instance().clock(), 
02391                         net_id.dump(), cmh->uid(),
02392                         p.src.dump(), p.dest.dump(),
02393                         srh->salvaged());
02394           if (mine)
02395                   drop(pkt, DROP_RTR_NO_ROUTE);
02396   }
02397 }
02398 
02399 #ifdef USE_GOD_FEEDBACK
02400 static int linkerr_is_wrong = 0;
02401 #endif
02402 
02403 void
02404 DSRAgent::sendUnknownFlow(SRPacket &p, bool asDefault, u_int16_t flowid) {
02405   hdr_sr *srh = hdr_sr::access(p.pkt);
02406   hdr_ip *iph = hdr_ip::access(p.pkt);
02407   hdr_cmn *cmh = hdr_cmn::access(p.pkt);
02408   struct flow_error *fe;
02409 
02410   assert(!srh->num_addrs()); // flow forwarding basis only.
02411 #if 0
02412   // this doesn't always hold true; if an xmit fails, we'll dump the
02413   // thing from our flow table, possibly before we even get here (though how
02414   // we found out, other than from this packet, is anyone's guess, considering
02415   // that underliverablePkt() should have been called in any other circumstance,
02416   // so we shouldn't go through the failed stuff.
02417   assert(p.src != net_id); // how'd it get here if it were?
02418 
02419   // this doesn't always hold true; I may be sending it default, fail,
02420   // the flow times out, but I still know the flowid (whacked paths through
02421   // the code, I know... ych 5/7/01
02422   assert(srh->flow_header() ^ asDefault); // one or the other, not both
02423 #endif
02424 
02425   if (p.src == net_id) {
02426     Packet::free(p.pkt);
02427     p.pkt = 0;
02428     return; // gimme a break, we already know!
02429   }
02430 
02431   undeliverablePkt(p.pkt, false); // salvage, but don't molest.
02432  
02433   /* warp into an error... */
02434   if (asDefault) {
02435     if (!srh->flow_default_unknown()) {
02436       srh->num_default_unknown() = 1;
02437       srh->flow_default_unknown() = 1;
02438       fe = srh->unknown_defaults();
02439     } else if (srh->num_default_unknown() < MAX_ROUTE_ERRORS) {
02440       fe = srh->unknown_defaults() + srh->num_default_unknown();
02441       srh->num_default_unknown()++;
02442     } else {
02443       trace("SYFU  %.5f _%s_ dumping maximally nested Flow error %d -> %d",
02444       Scheduler::instance().clock(), net_id.dump(), p.src.addr, p.dest.addr);
02445 
02446       Packet::free(p.pkt);        // no drop needed
02447       p.pkt = 0;
02448       return;
02449     }
02450   } else {
02451     if (!srh->flow_unknown()) {
02452       srh->num_flow_unknown() = 1;
02453       srh->flow_unknown() = 1;
02454       fe = srh->unknown_flows();
02455     } else if (srh->num_default_unknown() < MAX_ROUTE_ERRORS) {
02456       fe = srh->unknown_flows() + srh->num_flow_unknown();
02457       srh->num_flow_unknown()++;
02458     } else {
02459       trace("SYFU  %.5f _%s_ dumping maximally nested Flow error %d -> %d",
02460       Scheduler::instance().clock(), net_id.dump(), p.src.addr, p.dest.addr);
02461 
02462       Packet::free(p.pkt);        // no drop needed
02463       p.pkt = 0;
02464       return;
02465     }
02466   }
02467 
02468   trace("SFErr %.5f _%s_ %d -> %d : %d",
02469         Scheduler::instance().clock(), net_id.dump(), p.src.addr, p.dest.addr,
02470         flowid);
02471 
02472   srh->route_reply() = 0;
02473   srh->route_request() = 0;
02474   srh->flow_header() = 0;
02475   srh->flow_timeout() = 0;
02476 
02477   //iph->daddr() = p.src.addr;
02478   iph->daddr() = Address::instance().create_ipaddr(p.src.getNSAddr_t(),RT_PORT);
02479   iph->dport() = RT_PORT;
02480   //iph->saddr() = net_id.addr;
02481   iph->saddr() = Address::instance().create_ipaddr(net_id.getNSAddr_t(),RT_PORT);
02482   iph->sport() = RT_PORT;
02483   iph->ttl() = 255;
02484 
02485   //fe->flow_src = p.src.addr;
02486   fe->flow_src = p.src.getNSAddr_t();
02487   //fe->flow_dst = p.dest.addr;
02488   fe->flow_dst = p.dest.getNSAddr_t();
02489   fe->flow_id  = flowid;
02490 
02491   //p.src = ID(iph->src(), ::IP);
02492   //p.dest = ID(iph->dst(), ::IP);
02493   p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
02494   p.src = ID((Address::instance().get_nodeaddr(iph->saddr())),::IP);
02495 
02496 
02497   cmh->ptype() = PT_DSR;                // cut off data
02498   cmh->size() = IP_HDR_LEN;
02499   cmh->num_forwards() = 0;
02500   // assign this packet a new uid, since we're sending it
02501   cmh->uid() = uidcnt_++;
02502 
02503   handlePktWithoutSR(p, false);
02504   assert(p.pkt == 0);
02505 }
02506 
02507 void 
02508 DSRAgent::xmitFlowFailed(Packet *pkt, const char* reason)
02509 {
02510   hdr_sr *srh = hdr_sr::access(pkt);
02511   hdr_ip *iph = hdr_ip::access(pkt);
02512   hdr_cmn *cmh = hdr_cmn::access(pkt);
02513   int flowidx = flow_table.find(iph->saddr(), iph->daddr(), srh->flow_id());
02514   u_int16_t default_flow;
02515 
02516   assert(!srh->num_addrs());
02517 
02518   if (!srh->flow_header()) {
02519     if (!flow_table.defaultFlow(iph->saddr(), iph->daddr(), default_flow)) {
02520       SRPacket p(pkt, srh);
02521       //p.src = ID(iph->src(), ::IP);
02522       //p.dest = ID(iph->dst(), ::IP);
02523       p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
02524       p.src = ID((Address::instance().get_nodeaddr(iph->saddr())),::IP);
02525 
02526 
02527       sendUnknownFlow(p, true);
02528       return;
02529     }
02530     flowidx = flow_table.find(iph->saddr(), iph->daddr(), default_flow);
02531   }
02532 
02533   if (flowidx == -1 || 
02534       flow_table[flowidx].timeout < Scheduler::instance().clock()) {
02535     // blah, the flow has expired, or been forgotten.
02536     SRPacket p(pkt, srh);
02537     //p.src = ID(iph->src(), ::IP);
02538     //p.dest = ID(iph->dst(), ::IP);
02539     p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP);
02540     p.src = ID((Address::instance().get_nodeaddr(iph->saddr())),::IP);
02541 
02542 
02543     return;
02544   }
02545 
02546   cmh->size() -= srh->size(); // gonna change the source route size
02547   assert(cmh->size() >= 0);
02548   
02549   flow_table[flowidx].sourceRoute.fillSR(srh);
02550   srh->cur_addr() = flow_table[flowidx].hopCount;
02551   assert(srh->addrs()[srh->cur_addr()].addr == (nsaddr_t) net_id.addr);
02552   cmh->size() += srh->size();
02553 
02554   // xmitFailed is going to assume this was incr'ed for send
02555   srh->cur_addr()++;
02556   xmitFailed(pkt, reason);
02557 }
02558 
02559 void 
02560 DSRAgent::xmitFailed(Packet *pkt, const char* reason)
02561   /* mark our route cache reflect the failure of the link between
02562      srh[cur_addr] and srh[next_addr], and then create a route err
02563      message to send to the orginator of the pkt (srh[0])
02564      p.pkt freed or handed off */
02565 {
02566   hdr_sr *srh = hdr_sr::access(pkt);
02567   hdr_ip *iph = hdr_ip::access(pkt);
02568   hdr_cmn *cmh = hdr_cmn::access(pkt);
02569 
02570   assert(cmh->size() >= 0);
02571 
02572   srh->cur_addr() -= 1;         // correct for inc already done on sending
02573   
02574   if (srh->cur_addr() >= srh->num_addrs() - 1)
02575     {
02576       trace("SDFU: route error beyond end of source route????");
02577       fprintf(stderr,"SDFU: route error beyond end of source route????\n");
02578       Packet::free(pkt);
02579       return;
02580     }
02581 
02582   if (srh->route_request())
02583     {
02584       trace("SDFU: route error forwarding route request????");
02585       fprintf(stderr,"SDFU: route error forwarding route request????\n");
02586       Packet::free(pkt);
02587       return;
02588     }
02589 
02590 
02591   ID tell_id(srh->addrs()[0].addr,
02592              (ID_Type) srh->addrs()[srh->cur_addr()].addr_type);
02593   ID from_id(srh->addrs()[srh->cur_addr()].addr,
02594              (ID_Type) srh->addrs()[srh->cur_addr()].addr_type);
02595   ID to_id(srh->addrs()[srh->cur_addr()+1].addr,
02596              (ID_Type) srh->addrs()[srh->cur_addr()].addr_type);
02597   assert(from_id == net_id || from_id == MAC_id);
02598 
02599   trace("SSendFailure %.9f _%s_ %d %d %d:%d %d:%d %s->%s %d %d %d %d %s",
02600         Scheduler::instance().clock(), net_id.dump(), 
02601         cmh->uid(), cmh->ptype(),
02602         iph->saddr(), iph->sport(),
02603         iph->daddr(), iph->dport(),
02604         from_id.dump(),to_id.dump(),
02605         God::instance()->hops(from_id.getNSAddr_t(), to_id.getNSAddr_t()),
02606         God::instance()->hops(iph->saddr(),iph->daddr()),
02607         God::instance()->hops(from_id.getNSAddr_t(), iph->daddr()),
02608         srh->num_addrs(), srh->dump());
02609 
02610 #ifdef USE_GOD_FEEDBACK
02611   if (God::instance()->hops(from_id.getNSAddr_t(), to_id.getNSAddr_t()) == 1)
02612     { /* god thinks this link is still valid */
02613       linkerr_is_wrong++;
02614       trace("SxmitFailed %.5f _%s_  %d->%d god okays #%d",
02615             Scheduler::instance().clock(), net_id.dump(),
02616             from_id.getNSAddr_t(), to_id.getNSAddr_t(), linkerr_is_wrong);
02617       fprintf(stderr,
02618               "xmitFailed on link %d->%d god okays - ignoring & recycling #%d\n",
02619               from_id.getNSAddr_t(), to_id.getNSAddr_t(), linkerr_is_wrong);
02620       /* put packet back on end of ifq for xmission */
02621       srh->cur_addr() += 1;     // correct for decrement earlier in proc 
02622       // make sure we aren't cycling packets
02623       // also change direction in pkt hdr
02624       cmh->direction() = hdr_cmn::DOWN;
02625       ll->recv(pkt, (Handler*) 0);
02626       return;
02627     }
02628 #endif
02629 
02630   if(strcmp(reason, "DROP_IFQ_QFULL") != 0) {
02631           assert(strcmp(reason, "DROP_RTR_MAC_CALLBACK") == 0);
02632 
02633           /* kill any routes we have using this link */
02634           route_cache->noticeDeadLink(from_id, to_id,
02635                                       Scheduler::instance().clock());
02636           flow_table.noticeDeadLink(from_id, to_id);
02637 
02638           /* give ourselves a chance to save the packet */
02639           undeliverablePkt(pkt->copy(), 1);
02640 
02641           /* now kill all the other packets in the output queue that would
02642              use the same next hop.  This is reasonable, since 802.11 has
02643              already retried the xmission multiple times => a persistent
02644              failure. */
02645 
02646           /* XXX YCH 5/4/01 shouldn't each of these packets get Route Errors
02647            * if one hasn't already been sent? ie if two different routes
02648            * are using this link?
02649            */
02650           {
02651             Packet *r, *nr, *queue1 = 0, *queue2 = 0;
02652             // pkts to be recycled
02653             
02654             while((r = ifq->prq_get_nexthop(to_id.getNSAddr_t()))) {
02655               r->next_ = queue1;
02656               queue1 = r; 
02657             }
02658 
02659             // the packets are now in the reverse order of how they
02660             // appeared in the IFQ so reverse them again
02661             for(r = queue1; r; r = nr) {
02662               nr = r->next_;
02663               r->next_ = queue2;
02664               queue2 = r;
02665             }
02666 
02667             // now process them in order
02668             for(r = queue2; r; r = nr) {
02669               nr = r->next_;
02670               undeliverablePkt(r, 1);
02671             }
02672           }
02673   }
02674   
02675   /* warp pkt into a route error message */
02676   if (tell_id == net_id || tell_id == MAC_id)
02677     { // no need to send the route error if it's for us
02678       if (verbose) 
02679         trace("Sdebug _%s_ not bothering to send route error to ourselves", 
02680               tell_id.dump());
02681       Packet::free(pkt);        // no drop needed
02682       pkt = 0;
02683       return;
02684     }
02685 
02686   if (srh->num_route_errors() >= MAX_ROUTE_ERRORS)
02687     { // no more room in the error packet to nest an additional error.
02688       // this pkt's been bouncing around so much, let's just drop and let
02689       // the originator retry
02690       // Another possibility is to just strip off the outer error, and
02691       // launch a Route discovey for the inner error XXX -dam 6/5/98
02692       trace("SDFU  %.5f _%s_ dumping maximally nested error %s  %d -> %d",
02693             Scheduler::instance().clock(), net_id.dump(),
02694             tell_id.dump(),
02695             from_id.dump(),
02696             to_id.dump());
02697       Packet::free(pkt);        // no drop needed
02698       pkt = 0;
02699       return;
02700     }
02701 
02702   link_down *deadlink = &(srh->down_links()[srh->num_route_errors()]);
02703   deadlink->addr_type = srh->addrs()[srh->cur_addr()].addr_type;
02704   deadlink->from_addr = srh->addrs()[srh->cur_addr()].addr;
02705   deadlink->to_addr = srh->addrs()[srh->cur_addr()+1].addr;
02706   deadlink->tell_addr = srh->addrs()[0].addr;
02707   srh->num_route_errors() += 1;
02708 
02709   if (verbose)
02710     trace("Sdebug %.5f _%s_ sending into dead-link (nest %d) tell %d  %d -> %d",
02711           Scheduler::instance().clock(), net_id.dump(),
02712           srh->num_route_errors(),
02713           deadlink->tell_addr,
02714           deadlink->from_addr,
02715           deadlink->to_addr);
02716 
02717   srh->route_error() = 1;
02718   srh->route_reply() = 0;
02719   srh->route_request() = 0;
02720   srh->flow_header() = 0;
02721   srh->flow_timeout() = 0;
02722 
02723   //iph->daddr() = deadlink->tell_addr;
02724   iph->daddr() = Address::instance().create_ipaddr(deadlink->tell_addr,RT_PORT);
02725   iph->dport() = RT_PORT;
02726   //iph->saddr() = net_id.addr;
02727   iph->saddr() = Address::instance().create_ipaddr(net_id.addr,RT_PORT);
02728   iph->sport() = RT_PORT;
02729   iph->ttl() = 255;
02730 
02731   cmh->ptype() = PT_DSR;                // cut off data
02732   cmh->size() = IP_HDR_LEN;
02733   cmh->num_forwards() = 0;
02734   // assign this packet a new uid, since we're sending it
02735   cmh->uid() = uidcnt_++;
02736 
02737   SRPacket p(pkt, srh);
02738   p.route.setLength(p.route.index()+1);
02739   p.route.reverseInPlace();
02740   p.dest = tell_id;
02741   p.src = net_id;
02742 
02743   /* send out the Route Error message */
02744   sendOutPacketWithRoute(p, true);
02745 }
02746 
02747 void
02748 XmitFailureCallback(Packet *pkt, void *data)
02749 {
02750   DSRAgent *agent = (DSRAgent *)data; // cast of trust
02751   agent->xmitFailed(pkt);
02752 }
02753 
02754 void
02755 XmitFlowFailureCallback(Packet *pkt, void *data)
02756 {
02757   DSRAgent *agent = (DSRAgent *)data;
02758   agent->xmitFlowFailed(pkt);
02759 }
02760 
02761 #if 0
02762 
02763 /* this is code that implements Route Reply holdoff to prevent route 
02764    reply storms.  It's described in the kluwer paper and was used in 
02765    those simulations, but isn't currently used.  -dam 8/5/98 */
02766 
02767 /*==============================================================
02768   Callback Timers to deal with holding off  route replies
02769 
02770   Basic theory: if we see a node S that has requested a route to D
02771   send a packet to D via a route of length <= ours then don't send
02772   our route.  We record that S has used a good route to D by setting
02773   the best_length to -1, meaning that our route can't possibly do
02774   S any good (unless S has been lied to, but we probably can't know
02775   that).
02776   
02777   NOTE: there is confusion in this code as to whether the requestor
02778   and requested_dest ID's are MAC or IP... It doesn't matter for now
02779   but will later when they are not the same.
02780 
02781 ------------------------------------------------------------*/
02782 struct RtHoldoffData: public EventData {
02783   RtHoldoffData(DSRAgent *th, Packet *pa, int ind):t(th), p(pa), index(ind)
02784   {}
02785   DSRAgent *t;
02786   Packet *p;
02787   int index;
02788 };
02789 
02790 void
02791 RouteReplyHoldoffCallback(Node *node, Time time, EventData *data)
02792 // see if the packet inside the data is still in the
02793 // send buffer and expire it if it is
02794 {
02795   Packet *p = ((RtHoldoffData *)data)->p;
02796   DSRAgent *t = ((RtHoldoffData *)data)->t;
02797   int index = ((RtHoldoffData *)data)->index;
02798 
02799   RtRepHoldoff *entry = &(t->rtrep_holdoff[index]);
02800   assert((entry->requestor == p->dest));
02801 
02802   // if we haven't heard the requestor use a route equal or better
02803   // than ours then send our reply.
02804   if ((lsnode_require_use && entry->best_length != -1)
02805       || (!lsnode_require_use && entry->best_length > entry->our_length))
02806     { // we send
02807       world_statistics.sendingSrcRtFromCache(t,time,p);
02808       t->sendPacket(t,time,p);
02809     }
02810   else
02811     { // dump our packet
02812       delete p;
02813     }
02814   entry->requestor = invalid_addr;
02815   entry->requested_dest = invalid_addr;
02816   delete data;
02817   t->num_heldoff_rt_replies--;
02818 }
02819 
02820 void
02821 DSRAgent::scheduleRouteReply(Time t, Packet *new_p)
02822   // schedule a time to send new_p if we haven't heard a better
02823   // answer in the mean time.  Do not modify new_p after calling this
02824 {
02825   for (int c = 0; c < RTREP_HOLDOFF_SIZE; c ++)
02826     if (rtrep_holdoff[c].requested_dest == invalid_addr) break;
02827   assert(c < RTREP_HOLDOFF_SIZE);
02828 
02829   Path *our_route = &(new_p->data.getRoute().source_route);
02830   rtrep_holdoff[c].requested_dest = (*our_route)[our_route->length() - 1];
02831   rtrep_holdoff[c].requestor = new_p->dest;
02832   rtrep_holdoff[c].best_length = MAX_ROUTE_LEN + 1;
02833   rtrep_holdoff[c].our_length = our_route->length();
02834 
02835   Time send_time = t +
02836     (Time) (our_route->length() - 1) * rt_rep_holdoff_period
02837     + U(0.0, rt_rep_holdoff_period);
02838   RegisterCallback(this,&RouteReplyHoldoffCallback, send_time,
02839                    new RtHoldoffData(this,new_p,c));
02840   num_heldoff_rt_replies++;
02841 }
02842 
02843 void
02844 DSRAgent::snoopForRouteReplies(Time t, Packet *p)
02845   // see if p is a route reply that we're watching for
02846   // or if it was sent off using a route reply we're watching for
02847 {
02848   for (int c = 0 ; c <RTREP_HOLDOFF_SIZE ; c ++)
02849     {
02850       RtRepHoldoff *entry = &(rtrep_holdoff[c]);
02851 
02852       // there is no point in doing this first check if we're always
02853       // going to send our route reply unless we hear the requester use one
02854       // better or equal to ours
02855       if (entry->requestor == p->dest
02856           && (p->type == ::route_reply || p->data.sourceRoutep()))
02857         { // see if this route reply is one we're watching for
02858           Path *srcrt = &(p->data.getRoute().source_route);
02859           if (!(entry->requested_dest == (*srcrt)[srcrt->length()-1]))
02860             continue;           // it's not ours
02861           if (entry->best_length > srcrt->length())
02862             entry->best_length = srcrt->length();
02863         } // end if we heard a route reply being sent
02864       else if (entry->requestor == p->src
02865                && entry->requested_dest == p->dest)
02866         { // they're using a route  reply! see if ours is better
02867           if (p->route.length() <= entry->our_length)
02868             { // Oh no! they've used a better path than ours!
02869               entry->best_length = -1; //there's no point in replying.
02870             }
02871         } // end if they used used route reply
02872       else
02873         continue;
02874     }
02875 }
02876 
02877 #endif //0
02878 
02879 
02880 
02881 
02882 
02883 
02884 
02885 

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