dsragent.cc

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

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