mobicache.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * mobicache.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: mobicache.cc,v 1.6 2005/08/25 18:58:05 johnh 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 /* mobicache.cc
00051    cache used in the mobicom 98 submission.  see the paper for a description
00052    Ported from CMU/Monarch's code, appropriate copyright applies.  
00053 */
00054 
00055 //#ifdef DSR_MOBICACHE
00056 
00057 extern "C" {
00058 #include <stdio.h>
00059 #include <stdarg.h>
00060 };
00061 
00062 #undef DEBUG
00063 
00064 #include <god.h>
00065 #include "path.h"
00066 #include "routecache.h"
00067 #ifdef DSR_CACHE_STATS
00068 #include "cache_stats.h"
00069 #endif
00070 
00071 
00072 /* invariants
00073 
00074    - no path contains an id more than once
00075    - all paths start with the id of our node (MAC_id or net_id)
00076 */
00077 
00078 #define fout stdout
00079 
00080 static const int verbose = 0;
00081 static const int verbose_debug = 0;
00082 
00083 /*===============================================================
00084   function selectors
00085 ----------------------------------------------------------------*/
00086 bool cache_ignore_hints = false;     // ignore all hints?
00087 bool cache_use_overheard_routes = true; 
00088 // if we are A, and we over hear a rt Z Y (X) W V U, do we add route
00089 // A X W V U to the cache?
00090 
00091 
00092 /*===============================================================
00093   Class declaration
00094 ----------------------------------------------------------------*/
00095 class MobiCache;
00096 
00097 class Cache {
00098 friend class MobiCache;
00099 
00100 public:
00101   Cache(char *name, int size, MobiCache *rtcache);
00102   ~Cache();
00103 
00104   int pickVictim(int exclude = -1);
00105   // returns the index of a suitable victim in the cache
00106   // will spare the life of exclude
00107   bool searchRoute(const ID& dest, int& i, Path &path, int &index);
00108   // look for dest in cache, starting at index, 
00109   //if found, rtn true with path s.t. cache[index] == path && path[i] == dest
00110   Path* addRoute(Path &route, int &prefix_len);
00111   // rtns a pointer the path in the cache that we added
00112   void noticeDeadLink(const ID&from, const ID& to);
00113   // the link from->to isn't working anymore, purge routes containing
00114   // it from the cache
00115 
00116 private:
00117   Path *cache;
00118   int size;
00119   int victim_ptr;       // next victim for eviction
00120   MobiCache *routecache;
00121   char *name;
00122 };
00123 
00125 
00126 class MobiCache : public RouteCache {
00127 friend class Cache;
00128 friend class MobiHandler;
00129 
00130 public:
00131   MobiCache(const ID& MAC_id, const ID& net_id,int psize = 30,int ssize = 34 );
00132   MobiCache();
00133   ~MobiCache();
00134   void noticeDeadLink(const ID&from, const ID& to, Time t);
00135   // the link from->to isn't working anymore, purge routes containing
00136   // it from the cache
00137   void noticeRouteUsed(const Path& route, Time t,
00138                const ID& who_from);
00139   // tell the cache about a route we saw being used
00140   void addRoute(const Path& route, Time t, const ID& who_from);
00141   // add this route to the cache (presumably we did a route request
00142   // to find this route and don't want to lose it)
00143   bool findRoute(ID dest, Path& route, int for_use = 0);
00144   // if there is a cached path from us to dest returns true and fills in
00145   // the route accordingly. returns false otherwise
00146   // if for_use, then we assume that the node really wants to keep 
00147   // the returned route so it will be promoted to primary storage if not there
00148   // already
00149   int command(int argc, const char*const* argv);
00150 
00151 protected:
00152   Cache *primary_cache;   /* routes that we are using, or that we have reason
00153                  to believe we really want to hold on to */
00154   Cache *secondary_cache; /* routes we've learned via a speculative process
00155                  that might not pan out */
00156 
00157 #ifdef DSR_CACHE_STATS
00158   void periodic_checkCache(void);
00159   void checkRoute(Path *p, int action, int prefix_len);
00160   void checkRoute(Path &p, int&, int&, double&, int&, int&, double &);
00161 #endif
00162 };
00163 
00164 
00165 RouteCache *
00166 makeRouteCache()
00167 {
00168   return new MobiCache();
00169 }
00170 
00171 
00172 /*===============================================================
00173   OTcl definition
00174 ----------------------------------------------------------------*/
00175 static class MobiCacheClass : public TclClass {
00176 public:
00177         MobiCacheClass() : TclClass("MobiCache") {}
00178         TclObject* create(int, const char*const*) {
00179                 return (new MobiCache);
00180         }
00181 } class_MobiCache;
00182 
00183 /*===============================================================
00184  Constructors
00185 ----------------------------------------------------------------*/
00186 MobiCache::MobiCache(): RouteCache()
00187 {
00188   primary_cache = new Cache("primary", 30, this);
00189   secondary_cache = new Cache("secondary", 64, this);
00190   //secondary_cache = new Cache("secondary", 10000, this);
00191   assert(primary_cache != NULL && secondary_cache != NULL);
00192 #ifdef DSR_CACHE_STATS
00193     stat.reset();
00194 #endif
00195 }
00196 
00197 MobiCache::~MobiCache()
00198 {
00199   delete primary_cache;
00200   delete secondary_cache;
00201 }
00202 
00203 int
00204 MobiCache::command(int argc, const char*const* argv)
00205 {
00206   if(argc == 2 && strcasecmp(argv[1], "startdsr") == 0)
00207     { 
00208       if (ID(1,::IP) == net_id) 
00209     trace("Sconfig %.5f using MOBICACHE", Scheduler::instance().clock());
00210       // FALL-THROUGH
00211     }
00212   return RouteCache::command(argc, argv);
00213 }
00214 
00215 #ifdef DSR_CACHE_STATS
00216 
00217 void
00218 MobiCache::periodic_checkCache()
00219 {
00220   int c;
00221   int route_count = 0;
00222   int route_bad_count = 0;
00223   int subroute_count = 0;
00224   int subroute_bad_count = 0;
00225   int link_bad_count = 0;
00226   double link_bad_time = 0.0;
00227   int link_bad_tested = 0;
00228   int link_good_tested = 0;
00229 
00230   for(c = 0; c < primary_cache->size; c++)
00231     {
00232       int x = 0;
00233 
00234       if (primary_cache->cache[c].length() == 0) continue;
00235 
00236       checkRoute(primary_cache->cache[c],
00237                  x,
00238                  link_bad_count,
00239                  link_bad_time,
00240                  link_bad_tested,
00241                  link_good_tested,
00242          stat.link_good_time);
00243 
00244       route_count += 1;
00245       route_bad_count += x ? 1 : 0;
00246       
00247       subroute_count += primary_cache->cache[c].length() - 1;
00248       subroute_bad_count += x;
00249     }
00250   for(c = 0; c < secondary_cache->size; c++)
00251     {
00252       int x = 0;
00253 
00254       if (secondary_cache->cache[c].length() == 0) continue;
00255 
00256       checkRoute(secondary_cache->cache[c],
00257                  x,
00258                  link_bad_count,
00259                  link_bad_time,
00260                  link_bad_tested,
00261                  link_good_tested,
00262          stat.link_good_time);
00263 
00264       route_count += 1;
00265       route_bad_count += x ? 1 : 0;
00266 
00267       subroute_count += secondary_cache->cache[c].length() - 1;
00268       subroute_bad_count += x;
00269     }
00270 
00271   // lifetime of good link is (total time) / (total num links - num bad links)
00272   stat.link_good_time = stat.link_good_time / (subroute_count - link_bad_count);
00273 
00274   trace("SRC %.9f _%s_ cache-summary %d %d %d %d | %d %.9f %d %d | %d %d %d %d %d | %d %d %d %d %d | %d %d %d %d %d %d %.9f",
00275     Scheduler::instance().clock(), net_id.dump(),
00276         route_count,
00277         route_bad_count,
00278         subroute_count,
00279         subroute_bad_count,
00280 
00281         link_bad_count,
00282         link_bad_count ? link_bad_time/link_bad_count : 0.0,
00283         link_bad_tested,
00284         link_good_tested,
00285 
00286         stat.route_add_count,
00287         stat.route_add_bad_count,
00288         stat.subroute_add_count,
00289         stat.subroute_add_bad_count,
00290         stat.link_add_tested,
00291              
00292         stat.route_notice_count,
00293         stat.route_notice_bad_count,
00294         stat.subroute_notice_count,
00295         stat.subroute_notice_bad_count,
00296         stat.link_notice_tested,
00297              
00298         stat.route_find_count,
00299     stat.route_find_for_me,
00300         stat.route_find_bad_count,
00301         stat.route_find_miss_count,
00302         stat.subroute_find_count,
00303         stat.subroute_find_bad_count,
00304 
00305     stat.link_good_time);
00306   stat.reset();
00307 }
00308 
00309 #endif /* DSR_CACHE_STATS */
00310 
00311 /*===============================================================
00312   member functions
00313 ----------------------------------------------------------------*/
00314 
00315 void
00316 MobiCache::addRoute(const Path& route, Time t, const ID& who_from)
00317 // add this route to the cache (presumably we did a route request
00318 // to find this route and don't want to lose it)
00319 // who_from is the id of the routes provider
00320 {
00321   Path rt;
00322 
00323   if(pre_addRoute(route, rt, t, who_from) == 0)
00324     return;
00325 
00326   // must call addRoute before checkRoute
00327   int prefix_len = 0;
00328 
00329 #ifdef DSR_CACHE_STATS
00330   Path *p = primary_cache->addRoute(rt, prefix_len);
00331   checkRoute(p, ACTION_ADD_ROUTE, prefix_len);
00332 #else
00333   (void) primary_cache->addRoute(rt, prefix_len);
00334 #endif
00335 }
00336 
00337 void
00338 MobiCache::noticeDeadLink(const ID&from, const ID& to, Time)
00339   // the link from->to isn't working anymore, purge routes containing
00340   // it from the cache
00341 {
00342   if(verbose_debug)
00343     trace("SRC %.9f _%s_ dead link %s->%s",
00344       Scheduler::instance().clock(), net_id.dump(),
00345       from.dump(), to.dump());
00346   
00347   primary_cache->noticeDeadLink(from, to);
00348   secondary_cache->noticeDeadLink(from, to);
00349   return;
00350 }
00351 
00352 
00353 void
00354 MobiCache::noticeRouteUsed(const Path& p, Time t, const ID& who_from)
00355 // tell the cache about a route we saw being used
00356 {
00357   Path stub;
00358   if(pre_noticeRouteUsed(p, stub, t, who_from) == 0)
00359     return;
00360 
00361   int prefix_len = 0;
00362 
00363 #ifdef DSR_CACHE_STATS
00364   Path *p0 = secondary_cache->addRoute(stub, prefix_len);
00365   checkRoute(p0, ACTION_NOTICE_ROUTE, prefix_len);
00366 #else
00367   (void) secondary_cache->addRoute(stub, prefix_len);
00368 #endif
00369 }
00370 
00371 bool
00372 MobiCache::findRoute(ID dest, Path& route, int for_me)
00373 // if there is a cached path from us to dest returns true and fills in
00374 // the route accordingly. returns false otherwise
00375 // if for_me, then we assume that the node really wants to keep 
00376 // the returned route so it will be promoted to primary storage if not there
00377 // already
00378 {
00379   Path path;
00380   int min_index = -1;
00381   int min_length = MAX_SR_LEN + 1;
00382   int min_cache = 0;        // 2 == primary, 1 = secondary
00383   int index;
00384   int len;
00385 
00386   assert(!(net_id == invalid_addr));
00387 
00388   index = 0;
00389   while (primary_cache->searchRoute(dest, len, path, index))
00390     {
00391       min_cache = 2;
00392       if (len < min_length)
00393     {
00394       min_length = len;
00395       route = path;
00396     }
00397       index++;
00398     }
00399   
00400   index = 0;
00401   while (secondary_cache->searchRoute(dest, len, path, index))
00402     {
00403       if (len < min_length)
00404     {
00405       min_index = index;
00406       min_cache = 1;
00407       min_length = len;
00408       route = path;
00409     }
00410       index++;
00411     }
00412 
00413   if (min_cache == 1 && for_me)
00414     { // promote the found route to the primary cache
00415       int prefix_len;
00416  
00417       primary_cache->addRoute(secondary_cache->cache[min_index], prefix_len);
00418 
00419       // no need to run checkRoute over the Path* returned from
00420       // addRoute() because whatever was added was already in
00421       // the cache.
00422 
00423       //   prefix_len = 0
00424       //        - victim was selected in primary cache
00425       //        - data should be "silently" migrated from primary to the
00426       //          secondary cache
00427       //   prefix_len > 0
00428       //        - there were two copies of the first prefix_len routes
00429       //          in the cache, but after the migration, there will be
00430       //          only one.
00431       //        - log the first prefix_len bytes of the secondary cache
00432       //          entry as "evicted"
00433       if(prefix_len > 0)
00434         {
00435           secondary_cache->cache[min_index].setLength(prefix_len);
00436 #ifdef DSR_CACHE_STATS
00437           checkRoute_logall(&secondary_cache->cache[min_index], 
00438                             ACTION_EVICT, 0);
00439 #endif
00440         }
00441       secondary_cache->cache[min_index].setLength(0); // kill route
00442     }
00443 
00444   if (min_cache) 
00445     {
00446       route.setLength(min_length + 1);
00447       if (verbose_debug)
00448     trace("SRC %.9f _%s_ $hit for %s in %s %s",
00449           Scheduler::instance().clock(), net_id.dump(),
00450           dest.dump(), min_cache == 1 ? "secondary" : "primary",
00451           route.dump());    
00452 #ifdef DSR_CACHE_STATS
00453       int bad = checkRoute_logall(&route, ACTION_FIND_ROUTE, 0);      
00454       stat.route_find_count += 1;
00455       if (for_me) stat.route_find_for_me += 1;
00456       stat.route_find_bad_count += bad ? 1 : 0;
00457       stat.subroute_find_count += route.length() - 1;
00458       stat.subroute_find_bad_count += bad;
00459 #endif
00460       return true;
00461     }
00462   else
00463     {
00464       if (verbose_debug)
00465         trace("SRC %.9f _%s_ find-route [%d] %s->%s miss %d %.9f",
00466               Scheduler::instance().clock(), net_id.dump(),
00467               0, net_id.dump(), dest.dump(), 0, 0.0);
00468 #ifdef DSR_CACHE_STATS
00469       stat.route_find_count += 1;
00470       if (for_me) stat.route_find_for_me += 1;
00471       stat.route_find_miss_count += 1;
00472 #endif
00473       return false;
00474     }
00475 }
00476 
00477 /*===========================================================================
00478   class Cache routines
00479 ---------------------------------------------------------------------------*/
00480 
00481 Cache::Cache(char *name, int size, MobiCache *rtcache)
00482 {
00483   this->name = name;
00484   this->size = size;
00485   cache = new Path[size];
00486   routecache = rtcache;
00487   victim_ptr = 0;
00488 }
00489 
00490 Cache::~Cache() 
00491 {
00492   delete[] cache;
00493 }
00494 
00495 bool 
00496 Cache::searchRoute(const ID& dest, int& i, Path &path, int &index)
00497   // look for dest in cache, starting at index, 
00498   //if found, return true with path s.t. cache[index] == path && path[i] == dest
00499 {
00500   for (; index < size; index++)
00501     for (int n = 0 ; n < cache[index].length(); n++)
00502       if (cache[index][n] == dest) 
00503     {
00504       i = n;
00505       path = cache[index];
00506       return true;
00507     }
00508   return false;
00509 }
00510 
00511 Path*
00512 Cache::addRoute(Path & path, int &common_prefix_len)
00513 {
00514   int index, m, n;
00515   int victim;
00516 
00517   // see if this route is already in the cache
00518   for (index = 0 ; index < size ; index++)
00519     { // for all paths in the cache
00520       for (n = 0 ; n < cache[index].length() ; n ++)
00521     { // for all nodes in the path
00522       if (n >= path.length()) break;
00523       if (cache[index][n] != path[n]) break;
00524     }
00525       if (n == cache[index].length()) 
00526     { // new rt completely contains cache[index] (or cache[index] is empty)
00527           common_prefix_len = n;
00528           for ( ; n < path.length() ; n++)
00529             cache[index].appendToPath(path[n]);
00530       if (verbose_debug)
00531         routecache->trace("SRC %.9f _%s_ %s suffix-rule (len %d/%d) %s",
00532           Scheduler::instance().clock(), routecache->net_id.dump(),
00533               name, n, path.length(), path.dump()); 
00534       goto done;
00535     }
00536       else if (n == path.length())
00537     { // new route already contained in the cache
00538           common_prefix_len = n;
00539       if (verbose_debug)
00540         routecache->trace("SRC %.9f _%s_ %s prefix-rule (len %d/%d) %s",
00541           Scheduler::instance().clock(), routecache->net_id.dump(),
00542           name, n, cache[index].length(), cache[index].dump()); 
00543       goto done;
00544     }
00545       else 
00546     { // keep looking at the rest of the cache 
00547     }
00548     } 
00549 
00550   // there are some new goodies in the new route
00551   victim = pickVictim();
00552   if(verbose_debug) {
00553     routecache->trace("SRC %.9f _%s_ %s evicting %s",
00554               Scheduler::instance().clock(), routecache->net_id.dump(),
00555               name, cache[victim].dump());  
00556     routecache->trace("SRC %.9f _%s_ while adding %s",
00557               Scheduler::instance().clock(), routecache->net_id.dump(),
00558               path.dump()); 
00559   }
00560   cache[victim].reset();
00561   CopyIntoPath(cache[victim], path, 0, path.length() - 1);
00562   common_prefix_len = 0;
00563   index = victim; // remember which cache line we stuck the path into
00564 
00565 done:
00566 
00567 #ifdef DEBUG
00568   {
00569     Path &p = path;
00570     int c;
00571     char buf[1000];
00572     char *ptr = buf;
00573     ptr += sprintf(buf,"Sdebug %.9f _%s_ adding ", 
00574            Scheduler::instance().clock(), routecache->net_id.dump());
00575     for (c = 0 ; c < p.length(); c++)
00576       ptr += sprintf(ptr,"%s [%d %.9f] ",p[c].dump(), p[c].link_type, p[c].t);
00577     routecache->trace(buf);
00578   }
00579 #endif //DEBUG
00580 
00581   // freshen all the timestamps on the links in the cache
00582   for (m = 0 ; m < size ; m++)
00583     { // for all paths in the cache
00584 
00585 #ifdef DEBUG
00586   {
00587     if (cache[m].length() == 0) continue;
00588 
00589     Path &p = cache[m];
00590     int c;
00591     char buf[1000];
00592     char *ptr = buf;
00593     ptr += sprintf(buf,"Sdebug %.9f _%s_ checking ", 
00594            Scheduler::instance().clock(), routecache->net_id.dump());
00595     for (c = 0 ; c < p.length(); c++)
00596       ptr += sprintf(ptr,"%s [%d %.9f] ",p[c].dump(), p[c].link_type, p[c].t);
00597     routecache->trace(buf);
00598   }
00599 #endif //DEBUG
00600       
00601       for (n = 0 ; n < cache[m].length() - 1 ; n ++)
00602     { // for all nodes in the path
00603       if (n >= path.length() - 1) break;
00604       if (cache[m][n] != path[n]) break;
00605       if (cache[m][n+1] == path[n+1])
00606         { // freshen the timestamps and type of the link          
00607 
00608 #ifdef DEBUG
00609 routecache->trace("Sdebug %.9f _%s_ freshening %s->%s to %d %.9f",
00610           Scheduler::instance().clock(), routecache->net_id.dump(),
00611           path[n].dump(), path[n+1].dump(), path[n].link_type,
00612           path[n].t);
00613 #endif //DEBUG
00614 
00615           cache[m][n].t = path[n].t;
00616           cache[m][n].link_type = path[n].link_type;
00617           /* NOTE: we don't check to see if we're turning a TESTED
00618          into an UNTESTED link.  Last change made rules -dam 5/19/98 */
00619         }
00620     }
00621     }
00622   return &cache[index];
00623 }
00624 
00625 
00626 void
00627 Cache::noticeDeadLink(const ID&from, const ID& to)
00628   // the link from->to isn't working anymore, purge routes containing
00629   // it from the cache
00630 {  
00631   for (int p = 0 ; p < size ; p++)
00632     { // for all paths in the cache
00633       for (int n = 0 ; n < (cache[p].length()-1) ; n ++)
00634     { // for all nodes in the path
00635       if (cache[p][n] == from && cache[p][n+1] == to)
00636         {
00637           if(verbose_debug)
00638         routecache->trace("SRC %.9f _%s_ %s truncating %s %s",
00639                                   Scheduler::instance().clock(),
00640                                   routecache->net_id.dump(),
00641                                   name, cache[p].dump(),
00642                                   cache[p].owner().dump());
00643 #ifdef DSR_CACHE_STATS
00644               routecache->checkRoute(&cache[p], ACTION_CHECK_CACHE, 0);
00645               routecache->checkRoute_logall(&cache[p], ACTION_DEAD_LINK, n);
00646 #endif        
00647           if (n == 0)
00648         cache[p].reset();        // kill the whole path
00649           else {
00650         cache[p].setLength(n+1); // truncate the path here
00651                 cache[p][n].log_stat = LS_UNLOGGED;
00652               }
00653 
00654           if(verbose_debug)
00655         routecache->trace("SRC %.9f _%s_ to %s %s",
00656               Scheduler::instance().clock(), routecache->net_id.dump(),
00657               cache[p].dump(), cache[p].owner().dump());
00658 
00659           break;
00660         } // end if this is a dead link
00661     } // end for all nodes
00662     } // end for all paths
00663   return;
00664 }
00665 
00666 int
00667 Cache::pickVictim(int exclude)
00668 // returns the index of a suitable victim in the cache
00669 // never return exclude as the victim, but rather spare their life
00670 {
00671   for(int c = 0; c < size ; c++)
00672     if (cache[c].length() == 0) return c;
00673   
00674   int victim = victim_ptr;
00675   while (victim == exclude)
00676     {
00677       victim_ptr = (victim_ptr+1 == size) ? 0 : victim_ptr+1;
00678       victim = victim_ptr;
00679     }
00680   victim_ptr = (victim_ptr+1 == size) ? 0 : victim_ptr+1;
00681 
00682 #ifdef DSR_CACHE_STATS
00683   routecache->checkRoute(&cache[victim], ACTION_CHECK_CACHE, 0);
00684   int bad = routecache->checkRoute_logall(&cache[victim], ACTION_EVICT, 0);
00685   routecache->trace("SRC %.9f _%s_ evicting %d %d %s",
00686                     Scheduler::instance().clock(), routecache->net_id.dump(),
00687                     cache[victim].length() - 1, bad, name);
00688 #endif
00689   return victim;
00690 }
00691 
00692 #ifdef DSR_CACHE_STATS
00693 
00694 /*
00695  * Called only for the once-per-second cache check.
00696  */
00697 void
00698 MobiCache::checkRoute(Path & p,
00699                       int & subroute_bad_count,
00700                       int & link_bad_count,
00701                       double & link_bad_time,
00702                       int & link_bad_tested,
00703                       int & link_good_tested,
00704               double & link_good_time)
00705 {
00706   int c;
00707   int flag = 0;
00708 
00709   if(p.length() == 0)
00710     return;
00711   assert(p.length() >= 2);
00712 
00713   for (c = 0; c < p.length() - 1; c++)
00714     {
00715       assert(LS_UNLOGGED == p[c].log_stat || LS_LOGGED == p[c].log_stat );
00716       if (God::instance()->hops(p[c].getNSAddr_t(), p[c+1].getNSAddr_t()) != 1)
00717     { // the link's dead
00718           if(p[c].log_stat == LS_UNLOGGED)
00719         {
00720           trace("SRC %.9f _%s_ check-cache [%d %d] %s->%s dead %d %.9f",
00721             Scheduler::instance().clock(), net_id.dump(),
00722             p.length(), c, p[c].dump(), p[c+1].dump(),
00723                     p[c].link_type, p[c].t);
00724           p[c].log_stat = LS_LOGGED;
00725         }
00726           if(flag == 0)
00727             {
00728               subroute_bad_count += p.length() - c - 1;
00729               flag = 1;
00730             }
00731           link_bad_count += 1;
00732           link_bad_time += Scheduler::instance().clock() - p[c].t;
00733           link_bad_tested += (p[c].link_type == LT_TESTED) ? 1 : 0;
00734     }
00735       else
00736         {
00737       
00738       link_good_time += Scheduler::instance().clock() - p[c].t;
00739       
00740           if(p[c].log_stat == LS_LOGGED)
00741             {
00742               trace("SRC %.9f _%s_ resurrected-link [%d %d] %s->%s dead %d %.9f",
00743                     Scheduler::instance().clock(), net_id.dump(),
00744                     p.length(), c, p[c].dump(), p[c+1].dump(),
00745                     p[c].link_type, p[c].t);
00746               p[c].log_stat = LS_UNLOGGED;
00747             }
00748           link_good_tested += (p[c].link_type == LT_TESTED) ? 1 : 0;
00749         }
00750     }
00751 }
00752 
00753 void
00754 MobiCache::checkRoute(Path *p, int action, int prefix_len)
00755 {
00756   int c;
00757   int subroute_bad_count = 0;
00758   int tested = 0;
00759 
00760   if(p->length() == 0)
00761     return;
00762   assert(p->length() >= 2);
00763 
00764   assert(action == ACTION_ADD_ROUTE ||
00765          action == ACTION_CHECK_CACHE ||
00766          action == ACTION_NOTICE_ROUTE);
00767 
00768   for (c = 0; c < p->length() - 1; c++)
00769     {
00770       if (God::instance()->hops((*p)[c].getNSAddr_t(),
00771                                 (*p)[c+1].getNSAddr_t()) != 1)
00772     { // the link's dead
00773           if((*p)[c].log_stat == LS_UNLOGGED)
00774             {
00775               trace("SRC %.9f _%s_ %s [%d %d] %s->%s dead %d %.9f",
00776                     Scheduler::instance().clock(), net_id.dump(),
00777                     action_name[action], p->length(), c,
00778                     (*p)[c].dump(), (*p)[c+1].dump(),
00779                     (*p)[c].link_type, (*p)[c].t);
00780 
00781               (*p)[c].log_stat = LS_LOGGED;
00782             }
00783 
00784           if(subroute_bad_count == 0)
00785             subroute_bad_count = p->length() - c - 1;
00786     }
00787       else
00788         {
00789           if((*p)[c].log_stat == LS_LOGGED)
00790             {
00791               trace("SRC %.9f _%s_ resurrected-link [%d %d] %s->%s dead %d %.9f",
00792                     Scheduler::instance().clock(), net_id.dump(),
00793                     p->length(), c, (*p)[c].dump(), (*p)[c+1].dump(),
00794                     (*p)[c].link_type, (*p)[c].t);
00795               (*p)[c].log_stat = LS_UNLOGGED;
00796             }
00797         }
00798       tested += (*p)[c].link_type == LT_TESTED ? 1 : 0;
00799     }
00800 
00801   /*
00802    * Add Route or Notice Route actually did something
00803    */
00804   if(prefix_len < p->length())
00805     {
00806       switch(action)
00807         {
00808         case ACTION_ADD_ROUTE:
00809           stat.route_add_count += 1;
00810           stat.route_add_bad_count += subroute_bad_count ? 1 : 0;
00811           stat.subroute_add_count += p->length() - prefix_len - 1;
00812           stat.subroute_add_bad_count += subroute_bad_count;
00813           stat.link_add_tested += tested;
00814           break;
00815 
00816         case ACTION_NOTICE_ROUTE:
00817           stat.route_notice_count += 1;
00818           stat.route_notice_bad_count += subroute_bad_count ? 1 : 0;
00819           stat.subroute_notice_count += p->length() - prefix_len - 1;
00820           stat.subroute_notice_bad_count += subroute_bad_count;
00821           stat.link_notice_tested += tested;
00822           break;
00823         }
00824     }
00825 }
00826 #endif /* DSR_CACHE_STATS */
00827 
00828 //#endif /* DSR_MOBICACHE */

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