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 #ifdef DSR_SIMPLECACHE
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 *secondary_cache;
00153
00154
00155 #ifdef DSR_CACHE_STATS
00156 void periodic_checkCache(void);
00157 void checkRoute(Path *p, int action, int prefix_len);
00158 void checkRoute(Path &p, int&, int&, double&, int&, int&, double &);
00159 #endif
00160 };
00161
00162
00163 RouteCache *
00164 makeRouteCache()
00165 {
00166 return new MobiCache();
00167 }
00168
00169
00170
00171
00172
00173 static class MobiCacheClass : public TclClass {
00174 public:
00175 MobiCacheClass() : TclClass("MobiCache") {}
00176 TclObject* create(int, const char*const*) {
00177 return (new MobiCache);
00178 }
00179 } class_MobiCache;
00180
00181
00182
00183
00184 MobiCache::MobiCache(): RouteCache()
00185 {
00186 secondary_cache = new Cache("secondary", 10000, this);
00187 assert(secondary_cache != NULL);
00188 #ifdef DSR_CACHE_STATS
00189 stat.reset();
00190 #endif
00191 }
00192
00193 MobiCache::~MobiCache()
00194 {
00195 delete secondary_cache;
00196 }
00197
00198 int
00199 MobiCache::command(int argc, const char*const* argv)
00200 {
00201 if(argc == 2 && strcasecmp(argv[1], "startdsr") == 0)
00202 {
00203 if (ID(1,::IP) == net_id)
00204 trace("Sconfig %.5f using MOBICACHE", Scheduler::instance().clock());
00205
00206 }
00207 return RouteCache::command(argc, argv);
00208 }
00209
00210 #ifdef DSR_CACHE_STATS
00211
00212 void
00213 MobiCache::periodic_checkCache()
00214 {
00215 int c;
00216 int route_count = 0;
00217 int route_bad_count = 0;
00218 int subroute_count = 0;
00219 int subroute_bad_count = 0;
00220 int link_bad_count = 0;
00221 double link_bad_time = 0.0;
00222 int link_bad_tested = 0;
00223 int link_good_tested = 0;
00224
00225 for(c = 0; c < secondary_cache->size; c++)
00226 {
00227 int x = 0;
00228
00229 if (secondary_cache->cache[c].length() == 0) continue;
00230
00231 checkRoute(secondary_cache->cache[c],
00232 x,
00233 link_bad_count,
00234 link_bad_time,
00235 link_bad_tested,
00236 link_good_tested,
00237 stat.link_good_time);
00238
00239 route_count += 1;
00240 route_bad_count += x ? 1 : 0;
00241
00242 subroute_count += secondary_cache->cache[c].length() - 1;
00243 subroute_bad_count += x;
00244 }
00245
00246
00247 stat.link_good_time = stat.link_good_time / (subroute_count - link_bad_count);
00248
00249 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",
00250 Scheduler::instance().clock(), net_id.dump(),
00251 route_count,
00252 route_bad_count,
00253 subroute_count,
00254 subroute_bad_count,
00255
00256 link_bad_count,
00257 link_bad_count ? link_bad_time/link_bad_count : 0.0,
00258 link_bad_tested,
00259 link_good_tested,
00260
00261 stat.route_add_count,
00262 stat.route_add_bad_count,
00263 stat.subroute_add_count,
00264 stat.subroute_add_bad_count,
00265 stat.link_add_tested,
00266
00267 stat.route_notice_count,
00268 stat.route_notice_bad_count,
00269 stat.subroute_notice_count,
00270 stat.subroute_notice_bad_count,
00271 stat.link_notice_tested,
00272
00273 stat.route_find_count,
00274 stat.route_find_for_me,
00275 stat.route_find_bad_count,
00276 stat.route_find_miss_count,
00277 stat.subroute_find_count,
00278 stat.subroute_find_bad_count,
00279
00280 stat.link_good_time);
00281 stat.reset();
00282 }
00283
00284 #endif
00285
00286
00287
00288
00289
00290 void
00291 MobiCache::addRoute(const Path& route, Time t, const ID& who_from)
00292
00293
00294
00295 {
00296 Path rt;
00297
00298 if(pre_addRoute(route, rt, t, who_from) == 0)
00299 return;
00300
00301
00302 int prefix_len = 0;
00303
00304 #ifdef DSR_CACHE_STATS
00305 Path *p = secondary_cache->addRoute(rt, prefix_len);
00306 checkRoute(p, ACTION_ADD_ROUTE, prefix_len);
00307 #else
00308 (void) secondary_cache->addRoute(rt, prefix_len);
00309 #endif
00310 }
00311
00312 void
00313 MobiCache::noticeDeadLink(const ID&from, const ID& to, Time)
00314
00315
00316 {
00317 if(verbose_debug)
00318 trace("SRC %.9f _%s_ dead link %s->%s",
00319 Scheduler::instance().clock(), net_id.dump(),
00320 from.dump(), to.dump());
00321
00322 secondary_cache->noticeDeadLink(from, to);
00323 return;
00324 }
00325
00326
00327 void
00328 MobiCache::noticeRouteUsed(const Path& p, Time t, const ID& who_from)
00329
00330 {
00331 Path stub;
00332 if(pre_noticeRouteUsed(p, stub, t, who_from) == 0)
00333 return;
00334
00335 int prefix_len = 0;
00336
00337 #ifdef DSR_CACHE_STATS
00338 Path *p0 = secondary_cache->addRoute(stub, prefix_len);
00339 checkRoute(p0, ACTION_NOTICE_ROUTE, prefix_len);
00340 #else
00341 (void) secondary_cache->addRoute(stub, prefix_len);
00342 #endif
00343 }
00344
00345 bool
00346 MobiCache::findRoute(ID dest, Path& route, int for_me)
00347
00348
00349
00350
00351
00352 {
00353 Path path;
00354 int min_index = -1;
00355 int min_length = MAX_SR_LEN + 1;
00356 int min_cache = 0;
00357 int index;
00358 int len;
00359
00360 assert(!(net_id == invalid_addr));
00361
00362 index = 0;
00363 while (secondary_cache->searchRoute(dest, len, path, index))
00364 {
00365 if (len < min_length)
00366 {
00367 min_index = index;
00368 min_cache = 1;
00369 min_length = len;
00370 route = path;
00371 }
00372 index++;
00373 }
00374
00375 if (min_cache)
00376 {
00377 route.setLength(min_length + 1);
00378 if (verbose_debug)
00379 trace("SRC %.9f _%s_ $hit for %s in %s %s",
00380 Scheduler::instance().clock(), net_id.dump(),
00381 dest.dump(), min_cache == 1 ? "secondary" : "primary",
00382 route.dump());
00383 #ifdef DSR_CACHE_STATS
00384 int bad = checkRoute_logall(&route, ACTION_FIND_ROUTE, 0);
00385 stat.route_find_count += 1;
00386 if (for_me) stat.route_find_for_me += 1;
00387 stat.route_find_bad_count += bad ? 1 : 0;
00388 stat.subroute_find_count += route.length() - 1;
00389 stat.subroute_find_bad_count += bad;
00390 #endif
00391 return true;
00392 }
00393 else
00394 {
00395 if (verbose_debug)
00396 trace("SRC %.9f _%s_ find-route [%d] %s->%s miss %d %.9f",
00397 Scheduler::instance().clock(), net_id.dump(),
00398 0, net_id.dump(), dest.dump(), 0, 0.0);
00399 #ifdef DSR_CACHE_STATS
00400 stat.route_find_count += 1;
00401 if (for_me) stat.route_find_for_me += 1;
00402 stat.route_find_miss_count += 1;
00403 #endif
00404 return false;
00405 }
00406 }
00407
00408
00409
00410
00411
00412 Cache::Cache(char *name, int size, MobiCache *rtcache)
00413 {
00414 this->name = name;
00415 this->size = size;
00416 cache = new Path[size];
00417 routecache = rtcache;
00418 victim_ptr = 0;
00419 }
00420
00421 Cache::~Cache()
00422 {
00423 delete[] cache;
00424 }
00425
00426 bool
00427 Cache::searchRoute(const ID& dest, int& i, Path &path, int &index)
00428
00429
00430 {
00431 for (; index < size; index++)
00432 for (int n = 0 ; n < cache[index].length(); n++)
00433 if (cache[index][n] == dest)
00434 {
00435 i = n;
00436 path = cache[index];
00437 return true;
00438 }
00439 return false;
00440 }
00441
00442 Path*
00443 Cache::addRoute(Path & path, int &common_prefix_len)
00444 {
00445 int index, m, n;
00446 int victim;
00447
00448
00449 for (index = 0 ; index < size ; index++)
00450 {
00451 for (n = 0 ; n < cache[index].length() ; n ++)
00452 {
00453 if (n >= path.length()) break;
00454 if (cache[index][n] != path[n]) break;
00455 }
00456 if (n == cache[index].length())
00457 {
00458 common_prefix_len = n;
00459 for ( ; n < path.length() ; n++)
00460 cache[index].appendToPath(path[n]);
00461 if (verbose_debug)
00462 routecache->trace("SRC %.9f _%s_ %s suffix-rule (len %d/%d) %s",
00463 Scheduler::instance().clock(), routecache->net_id.dump(),
00464 name, n, path.length(), path.dump());
00465 goto done;
00466 }
00467 else if (n == path.length())
00468 {
00469 common_prefix_len = n;
00470 if (verbose_debug)
00471 routecache->trace("SRC %.9f _%s_ %s prefix-rule (len %d/%d) %s",
00472 Scheduler::instance().clock(), routecache->net_id.dump(),
00473 name, n, cache[index].length(), cache[index].dump());
00474 goto done;
00475 }
00476 else
00477 {
00478 }
00479 }
00480
00481
00482 victim = pickVictim();
00483 if(verbose_debug) {
00484 routecache->trace("SRC %.9f _%s_ %s evicting %s",
00485 Scheduler::instance().clock(), routecache->net_id.dump(),
00486 name, cache[victim].dump());
00487 routecache->trace("SRC %.9f _%s_ while adding %s",
00488 Scheduler::instance().clock(), routecache->net_id.dump(),
00489 path.dump());
00490 }
00491 cache[victim].reset();
00492 CopyIntoPath(cache[victim], path, 0, path.length() - 1);
00493 common_prefix_len = 0;
00494 index = victim;
00495
00496 done:
00497
00498 #ifdef DEBUG
00499 {
00500 Path &p = path;
00501 int c;
00502 char buf[1000];
00503 char *ptr = buf;
00504 ptr += sprintf(buf,"Sdebug %.9f _%s_ adding ",
00505 Scheduler::instance().clock(), routecache->net_id.dump());
00506 for (c = 0 ; c < p.length(); c++)
00507 ptr += sprintf(ptr,"%s [%d %.9f] ",p[c].dump(), p[c].link_type, p[c].t);
00508 routecache->trace(buf);
00509 }
00510 #endif //DEBUG
00511
00512
00513 for (m = 0 ; m < size ; m++)
00514 {
00515
00516 #ifdef DEBUG
00517 {
00518 if (cache[m].length() == 0) continue;
00519
00520 Path &p = cache[m];
00521 int c;
00522 char buf[1000];
00523 char *ptr = buf;
00524 ptr += sprintf(buf,"Sdebug %.9f _%s_ checking ",
00525 Scheduler::instance().clock(), routecache->net_id.dump());
00526 for (c = 0 ; c < p.length(); c++)
00527 ptr += sprintf(ptr,"%s [%d %.9f] ",p[c].dump(), p[c].link_type, p[c].t);
00528 routecache->trace(buf);
00529 }
00530 #endif //DEBUG
00531
00532 for (n = 0 ; n < cache[m].length() - 1 ; n ++)
00533 {
00534 if (n >= path.length() - 1) break;
00535 if (cache[m][n] != path[n]) break;
00536 if (cache[m][n+1] == path[n+1])
00537 {
00538
00539 #ifdef DEBUG
00540 routecache->trace("Sdebug %.9f _%s_ freshening %s->%s to %d %.9f",
00541 Scheduler::instance().clock(), routecache->net_id.dump(),
00542 path[n].dump(), path[n+1].dump(), path[n].link_type,
00543 path[n].t);
00544 #endif //DEBUG
00545
00546 cache[m][n].t = path[n].t;
00547 cache[m][n].link_type = path[n].link_type;
00548
00549
00550 }
00551 }
00552 }
00553 return &cache[index];
00554 }
00555
00556
00557 void
00558 Cache::noticeDeadLink(const ID&from, const ID& to)
00559
00560
00561 {
00562 for (int p = 0 ; p < size ; p++)
00563 {
00564 for (int n = 0 ; n < (cache[p].length()-1) ; n ++)
00565 {
00566 if (cache[p][n] == from && cache[p][n+1] == to)
00567 {
00568 if(verbose_debug)
00569 routecache->trace("SRC %.9f _%s_ %s truncating %s %s",
00570 Scheduler::instance().clock(),
00571 routecache->net_id.dump(),
00572 name, cache[p].dump(),
00573 cache[p].owner().dump());
00574 #ifdef DSR_CACHE_STATS
00575 routecache->checkRoute(&cache[p], ACTION_CHECK_CACHE, 0);
00576 routecache->checkRoute_logall(&cache[p], ACTION_DEAD_LINK, n);
00577 #endif
00578 if (n == 0)
00579 cache[p].reset();
00580 else {
00581 cache[p].setLength(n+1);
00582 cache[p][n].log_stat = LS_UNLOGGED;
00583 }
00584
00585 if(verbose_debug)
00586 routecache->trace("SRC %.9f _%s_ to %s %s",
00587 Scheduler::instance().clock(), routecache->net_id.dump(),
00588 cache[p].dump(), cache[p].owner().dump());
00589
00590 break;
00591 }
00592 }
00593 }
00594 return;
00595 }
00596
00597 int
00598 Cache::pickVictim(int exclude)
00599
00600
00601 {
00602 for(int c = 0; c < size ; c++)
00603 if (cache[c].length() == 0) return c;
00604
00605 int victim = victim_ptr;
00606 while (victim == exclude)
00607 {
00608 victim_ptr = (victim_ptr+1 == size) ? 0 : victim_ptr+1;
00609 victim = victim_ptr;
00610 }
00611 victim_ptr = (victim_ptr+1 == size) ? 0 : victim_ptr+1;
00612
00613 #ifdef DSR_CACHE_STATS
00614 routecache->checkRoute(&cache[victim], ACTION_CHECK_CACHE, 0);
00615 int bad = routecache->checkRoute_logall(&cache[victim], ACTION_EVICT, 0);
00616 routecache->trace("SRC %.9f _%s_ evicting %d %d %s",
00617 Scheduler::instance().clock(), routecache->net_id.dump(),
00618 cache[victim].length() - 1, bad, name);
00619 #endif
00620 return victim;
00621 }
00622
00623 #ifdef DSR_CACHE_STATS
00624
00625
00626
00627
00628 void
00629 MobiCache::checkRoute(Path & p,
00630 int & subroute_bad_count,
00631 int & link_bad_count,
00632 double & link_bad_time,
00633 int & link_bad_tested,
00634 int & link_good_tested,
00635 double & link_good_time)
00636 {
00637 int c;
00638 int flag = 0;
00639
00640 if(p.length() == 0)
00641 return;
00642 assert(p.length() >= 2);
00643
00644 for (c = 0; c < p.length() - 1; c++)
00645 {
00646 assert(LS_UNLOGGED == p[c].log_stat || LS_LOGGED == p[c].log_stat );
00647 if (God::instance()->hops(p[c].getNSAddr_t(), p[c+1].getNSAddr_t()) != 1)
00648 {
00649 if(p[c].log_stat == LS_UNLOGGED)
00650 {
00651 trace("SRC %.9f _%s_ check-cache [%d %d] %s->%s dead %d %.9f",
00652 Scheduler::instance().clock(), net_id.dump(),
00653 p.length(), c, p[c].dump(), p[c+1].dump(),
00654 p[c].link_type, p[c].t);
00655 p[c].log_stat = LS_LOGGED;
00656 }
00657 if(flag == 0)
00658 {
00659 subroute_bad_count += p.length() - c - 1;
00660 flag = 1;
00661 }
00662 link_bad_count += 1;
00663 link_bad_time += Scheduler::instance().clock() - p[c].t;
00664 link_bad_tested += (p[c].link_type == LT_TESTED) ? 1 : 0;
00665 }
00666 else
00667 {
00668
00669 link_good_time += Scheduler::instance().clock() - p[c].t;
00670
00671 if(p[c].log_stat == LS_LOGGED)
00672 {
00673 trace("SRC %.9f _%s_ resurrected-link [%d %d] %s->%s dead %d %.9f",
00674 Scheduler::instance().clock(), net_id.dump(),
00675 p.length(), c, p[c].dump(), p[c+1].dump(),
00676 p[c].link_type, p[c].t);
00677 p[c].log_stat = LS_UNLOGGED;
00678 }
00679 link_good_tested += (p[c].link_type == LT_TESTED) ? 1 : 0;
00680 }
00681 }
00682 }
00683
00684 void
00685 MobiCache::checkRoute(Path *p, int action, int prefix_len)
00686 {
00687 int c;
00688 int subroute_bad_count = 0;
00689 int tested = 0;
00690
00691 if(p->length() == 0)
00692 return;
00693 assert(p->length() >= 2);
00694
00695 assert(action == ACTION_ADD_ROUTE ||
00696 action == ACTION_CHECK_CACHE ||
00697 action == ACTION_NOTICE_ROUTE);
00698
00699 for (c = 0; c < p->length() - 1; c++)
00700 {
00701 if (God::instance()->hops((*p)[c].getNSAddr_t(),
00702 (*p)[c+1].getNSAddr_t()) != 1)
00703 {
00704 if((*p)[c].log_stat == LS_UNLOGGED)
00705 {
00706 trace("SRC %.9f _%s_ %s [%d %d] %s->%s dead %d %.9f",
00707 Scheduler::instance().clock(), net_id.dump(),
00708 action_name[action], p->length(), c,
00709 (*p)[c].dump(), (*p)[c+1].dump(),
00710 (*p)[c].link_type, (*p)[c].t);
00711
00712 (*p)[c].log_stat = LS_LOGGED;
00713 }
00714
00715 if(subroute_bad_count == 0)
00716 subroute_bad_count = p->length() - c - 1;
00717 }
00718 else
00719 {
00720 if((*p)[c].log_stat == LS_LOGGED)
00721 {
00722 trace("SRC %.9f _%s_ resurrected-link [%d %d] %s->%s dead %d %.9f",
00723 Scheduler::instance().clock(), net_id.dump(),
00724 p->length(), c, (*p)[c].dump(), (*p)[c+1].dump(),
00725 (*p)[c].link_type, (*p)[c].t);
00726 (*p)[c].log_stat = LS_UNLOGGED;
00727 }
00728 }
00729 tested += (*p)[c].link_type == LT_TESTED ? 1 : 0;
00730 }
00731
00732
00733
00734
00735 if(prefix_len < p->length())
00736 {
00737 switch(action)
00738 {
00739 case ACTION_ADD_ROUTE:
00740 stat.route_add_count += 1;
00741 stat.route_add_bad_count += subroute_bad_count ? 1 : 0;
00742 stat.subroute_add_count += p->length() - prefix_len - 1;
00743 stat.subroute_add_bad_count += subroute_bad_count;
00744 stat.link_add_tested += tested;
00745 break;
00746
00747 case ACTION_NOTICE_ROUTE:
00748 stat.route_notice_count += 1;
00749 stat.route_notice_bad_count += subroute_bad_count ? 1 : 0;
00750 stat.subroute_notice_count += p->length() - prefix_len - 1;
00751 stat.subroute_notice_bad_count += subroute_bad_count;
00752 stat.link_notice_tested += tested;
00753 break;
00754 }
00755 }
00756 }
00757 #endif
00758
00759 #endif