00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
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
00073
00074
00075
00076
00077
00078 #define fout stdout
00079
00080 static const int verbose = 0;
00081 static const int verbose_debug = 0;
00082
00083
00084
00085
00086 bool cache_ignore_hints = false;
00087 bool cache_use_overheard_routes = true;
00088
00089
00090
00091
00092
00093
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
00106
00107 bool searchRoute(const ID& dest, int& i, Path &path, int &index);
00108
00109
00110 Path* addRoute(Path &route, int &prefix_len);
00111
00112 void noticeDeadLink(const ID&from, const ID& to);
00113
00114
00115
00116 private:
00117 Path *cache;
00118 int size;
00119 int victim_ptr;
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
00136
00137 void noticeRouteUsed(const Path& route, Time t,
00138 const ID& who_from);
00139
00140 void addRoute(const Path& route, Time t, const ID& who_from);
00141
00142
00143 bool findRoute(ID dest, Path& route, int for_use = 0);
00144
00145
00146
00147
00148
00149 int command(int argc, const char*const* argv);
00150
00151 protected:
00152 Cache *primary_cache;
00153
00154 Cache *secondary_cache;
00155
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
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
00185
00186 MobiCache::MobiCache(): RouteCache()
00187 {
00188 primary_cache = new Cache("primary", 30, this);
00189 secondary_cache = new Cache("secondary", 64, this);
00190
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
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
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
00310
00311
00312
00313
00314
00315 void
00316 MobiCache::addRoute(const Path& route, Time t, const ID& who_from)
00317
00318
00319
00320 {
00321 Path rt;
00322
00323 if(pre_addRoute(route, rt, t, who_from) == 0)
00324 return;
00325
00326
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
00340
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
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
00374
00375
00376
00377
00378 {
00379 Path path;
00380 int min_index = -1;
00381 int min_length = MAX_SR_LEN + 1;
00382 int min_cache = 0;
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 {
00415 int prefix_len;
00416
00417 primary_cache->addRoute(secondary_cache->cache[min_index], prefix_len);
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
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);
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
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
00498
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
00518 for (index = 0 ; index < size ; index++)
00519 {
00520 for (n = 0 ; n < cache[index].length() ; n ++)
00521 {
00522 if (n >= path.length()) break;
00523 if (cache[index][n] != path[n]) break;
00524 }
00525 if (n == cache[index].length())
00526 {
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 {
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 {
00547 }
00548 }
00549
00550
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;
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
00582 for (m = 0 ; m < size ; m++)
00583 {
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 {
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 {
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
00618
00619 }
00620 }
00621 }
00622 return &cache[index];
00623 }
00624
00625
00626 void
00627 Cache::noticeDeadLink(const ID&from, const ID& to)
00628
00629
00630 {
00631 for (int p = 0 ; p < size ; p++)
00632 {
00633 for (int n = 0 ; n < (cache[p].length()-1) ; n ++)
00634 {
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();
00649 else {
00650 cache[p].setLength(n+1);
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 }
00661 }
00662 }
00663 return;
00664 }
00665
00666 int
00667 Cache::pickVictim(int exclude)
00668
00669
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
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 {
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 {
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
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
00827
00828