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 #ifdef DSR_LINKCACHE
00052
00053 #include <god.h>
00054 #include "path.h"
00055 #include "routecache.h"
00056 #include <list.h>
00057 #ifdef DSR_CACHE_STATS
00058 #include "cache_stats.h"
00059 #endif
00060
00061 #define CURRENT_TIME Scheduler::instance().clock()
00062 #define MAX_SIMTIME 86400
00063
00064 bool cache_ignore_hints = false;
00065 bool cache_use_overheard_routes = true;
00066
00067
00068
00069 static const bool lc_cache_negative_links = false;
00070 static const double lc_neg_cache_life = 1.0;
00071
00072
00073 static const bool lc_bidirectional_links = true;
00074
00075
00076 static const bool lc_evict_unreachable_links = false;
00077
00078
00079
00080
00081
00082 #define LC_MAX_NODES 200
00083
00084
00085 static const double lc_gen_use_bonus = 300;
00086
00087
00088 static const double lc_static_discover_life = 5.0;
00089 static const double lc_static_overhear_life = 5.0;
00090
00091
00092 static const double lc_table_init_val = 50.0;
00093 static const double lc_table_mult_by = 0.5;
00094 static const double lc_linear_alpha = 1.0/8.0;
00095 static const double lc_exp_add_amt = 2.0;
00096 static const double lc_exp_div_amt = 2.0;
00097 static const double lc_minlifetime = 2.0;
00098
00099
00100 #define EXPPOLICY_INFINITE 0
00101 #define EXPPOLICY_STATIC 1
00102 #define EXPPOLICY_LINEAR 2
00103 #define EXPPOLICY_EXP 3
00104 #ifdef GOD_STABILITY
00105 #define EXPPOLICY_GOD_OMNI 4
00106 #define EXPPOLICY_GOD_TABLE 5
00107 #endif
00108 #define LONGEST_LIVED_ROUTE
00109
00110 static const int lc_exppolicy = EXPPOLICY_EXP;
00111
00112 #ifdef GOD_STABILITY
00113 extern double *godavglife;
00114 #endif
00115
00116 #ifndef REALTIME_EXPIRE
00117
00118 #define IS_GOOD 0
00119 #define IS_BAD 1
00120 #define CALLED_GOOD 0
00121 #define CALLED_BAD 2
00122 static int expirestats[4];
00123 #endif
00124
00125 static int verbose_debug = 0;
00126
00127
00128
00129 class Link {
00130 public:
00131 Link(nsaddr_t dst) {
00132 ln_dst = dst;
00133 ln_flags = ln_cost = 0;
00134 ln_timeout = 0.0;
00135 ln_insert = 0.0;
00136 ln_t = 0.0;
00137 ln_linktype = LT_NONE;
00138 ln_logstat = LS_UNLOGGED;
00139 }
00140
00141 inline bool expired() {
00142 return (ln_timeout <= CURRENT_TIME);
00143 }
00144
00145 LIST_ENTRY(Link) ln_link;
00146 nsaddr_t ln_dst;
00147 int ln_flags;
00148 #define LINK_FLAG_UP 0x01
00149
00150
00151
00152
00153 int ln_cost;
00154
00155
00156
00157
00158
00159
00160 double ln_timeout;
00161 double ln_insert;
00162
00163 #define LINK_TIMEOUT MAX_SIMTIME
00164
00165
00166 Time ln_t;
00167 Link_Type ln_linktype;
00168 Log_Status ln_logstat;
00169 };
00170
00171 LIST_HEAD(dsrLinkHead, Link);
00172
00173 class LinkCache : public RouteCache {
00174 friend class MobiHandler;
00175
00176 public:
00177 LinkCache();
00178
00179 void noticeDeadLink(const ID&from, const ID& to, Time t);
00180
00181
00182
00183 void noticeRouteUsed(const Path& route, Time t,
00184 const ID& who_from);
00185
00186
00187 void addRoute(const Path& route, Time t, const ID& who_from);
00188
00189
00190
00191 bool findRoute(ID dest, Path& route, int for_me = 0);
00192
00193
00194
00195
00196
00197 int command(int argc, const char*const* argv);
00198
00199 protected:
00200 dsrLinkHead lcache[LC_MAX_NODES + 1];
00201
00202
00203 int addLink(const ID& from, const ID& to,
00204 int flags, double timeout = LINK_TIMEOUT, int cost = 1);
00205 int delLink(const ID& from, const ID& to);
00206 Link* findLink(int from, int to);
00207 void purgeLink(void);
00208 void dumpLink(void);
00209
00210 void Link_to_ID(Link* l, ID& id);
00211
00212 #ifdef DSR_CACHE_STATS
00213 void checkLink_logall(const ID& from, const ID& to, int action);
00214 void checkLink(const ID& from, const ID& to, int action);
00215 void periodic_checkCache();
00216
00217 struct cache_stats stat;
00218 #endif
00219 private:
00221
00222
00223 double dirty;
00224 #ifdef LONGEST_LIVED_ROUTE
00225 double dl[LC_MAX_NODES + 1];
00226 #endif
00227 u_int32_t d[LC_MAX_NODES + 1];
00228 u_int32_t pi[LC_MAX_NODES + 1];
00229 bool S[LC_MAX_NODES + 1];
00230 double exptable[LC_MAX_NODES + 1];
00231 #define INFINITY 0x7fffffff
00232
00233 void init_single_source(int s);
00234 #ifdef LONGEST_LIVED_ROUTE
00235 void relax(u_int32_t u, u_int32_t v, u_int32_t w, double);
00236 #else
00237 void relax(u_int32_t u, u_int32_t v, u_int32_t w);
00238 #endif
00239 int extract_min_q(void);
00240 void dijkstra(void);
00241 void dump_dijkstra(int dst);
00242 double find_timeout(ID a, ID b, bool discovered);
00243 };
00244
00246
00247 double LinkCache::find_timeout(ID a, ID b, bool discovered) {
00248 double lifetime = 0.0;
00249 switch (lc_exppolicy) {
00250 case EXPPOLICY_INFINITE:
00251 #ifdef GOD_STABILITY
00252 case EXPPOLICY_GOD_OMNI:
00253 #endif
00254 return MAX_SIMTIME;
00255 case EXPPOLICY_LINEAR: case EXPPOLICY_EXP:
00256 lifetime = exptable[a.addr] > exptable[b.addr] ?
00257 exptable[b.addr] : exptable[a.addr];
00258 lifetime *= lc_table_mult_by;
00259 break;
00260 #ifdef GOD_STABILITY
00261 case EXPPOLICY_GOD_TABLE:
00262 lifetime = godavglife[a.addr] > godavglife[b.addr] ?
00263 godavglife[b.addr] : godavglife[a.addr];
00264 lifetime *= lc_table_mult_by;
00265 break;
00266 #endif
00267 case EXPPOLICY_STATIC:
00268 lifetime = discovered ? lc_static_discover_life :
00269 lc_static_overhear_life;
00270 break;
00271 default:
00272 assert(0);
00273 }
00274
00275 if (lifetime < lc_minlifetime)
00276 lifetime = lc_minlifetime;
00277
00278 return CURRENT_TIME + lifetime;
00279 }
00280
00281 RouteCache *
00282 makeRouteCache()
00283 {
00284 return new LinkCache();
00285 }
00286
00287 LinkCache::LinkCache() : RouteCache()
00288 {
00289 int i = 0;
00290
00291 for(i = 0; i <= LC_MAX_NODES; i++) {
00292 LIST_INIT(&lcache[i]);
00293 exptable[i] = lc_table_init_val;
00294 }
00295
00296 #ifdef DSR_CACHE_STATS
00297 stat.reset();
00298 #endif
00299 dirty = -1;
00300 }
00301
00302
00303 int
00304 LinkCache::command(int argc, const char*const* argv)
00305 {
00306 if(argc == 2 && strcasecmp(argv[1], "startdsr") == 0)
00307 {
00308 if (ID(1,::IP) == net_id)
00309 trace("Sconfig %.5f using LINKCACHE %d", Scheduler::instance().clock(),
00310 lc_exppolicy);
00311
00312 }
00313
00314 if(argc == 3)
00315 {
00316 if (strcasecmp(argv[1], "ip-addr") == 0)
00317 {
00318 assert(atoi(argv[2]) <= LC_MAX_NODES);
00319
00320 #ifndef REALTIME_EXPIRE
00321 if (atoi(argv[2]) == 1)
00322 bzero(expirestats, sizeof(expirestats));
00323 #endif
00324
00325
00326 }
00327 }
00328 return RouteCache::command(argc, argv);
00329 }
00330
00331
00332 void
00333 LinkCache::noticeDeadLink(const ID& from, const ID& to, Time)
00334 {
00335 Link *l = findLink(from.addr, to.addr);
00336
00337 if (l && (l->ln_flags & LINK_FLAG_UP) &&
00338 (lc_exppolicy == EXPPOLICY_LINEAR ||
00339 lc_exppolicy == EXPPOLICY_EXP)) {
00340 if (lc_exppolicy == EXPPOLICY_LINEAR) {
00341 exptable[from.addr]=lc_linear_alpha*exptable[from.addr]
00342 +(CURRENT_TIME-l->ln_insert)*(1-lc_linear_alpha);
00343 exptable[to.addr]=lc_linear_alpha*exptable[to.addr]
00344 +(CURRENT_TIME-l->ln_insert)*(1-lc_linear_alpha);
00345 } else {
00346 exptable[from.addr] /= lc_exp_div_amt;
00347 exptable[to.addr] /= lc_exp_div_amt;
00348 }
00349 }
00350
00351 if(lc_cache_negative_links == true) {
00352 if(l) {
00353 l->ln_flags &= ~LINK_FLAG_UP;
00354 l->ln_insert = CURRENT_TIME;
00355 l->ln_timeout = CURRENT_TIME + lc_neg_cache_life;
00356 dirty = CURRENT_TIME;
00357 } else {
00358 addLink(from, to, 0, CURRENT_TIME + lc_neg_cache_life);
00359 }
00360 }
00361 else {
00362 if(l) {
00363 #ifdef DSR_CACHE_STATS
00364 checkLink(from, to, ACTION_DEAD_LINK);
00365 #endif
00366 (void) delLink(from, to);
00367 }
00368 }
00369 }
00370
00371 void
00372 LinkCache::noticeRouteUsed(const Path& p, Time t, const ID& who_from)
00373 {
00374 Path stub;
00375 int c;
00376
00377 if(pre_noticeRouteUsed(p, stub, t, who_from) == 0)
00378 return;
00379
00380 #ifdef DSR_CACHE_STATS
00381 int link_notice_count = stat.link_notice_count;
00382 int link_notice_bad_count = stat.link_notice_bad_count;
00383 #endif
00384
00385
00386
00387
00388 for(c = 0; c < stub.length() - 1; c++) {
00389 if(addLink(stub[c], stub[c+1], LINK_FLAG_UP,
00390 find_timeout(stub[c], stub[c+1], false))) {
00391 #ifdef DSR_CACHE_STATS
00392 checkLink(stub[c], stub[c+1], ACTION_NOTICE_ROUTE);
00393 #endif
00394 }
00395 }
00396
00397 #ifdef DSR_CACHE_STATS
00398 if(stat.link_notice_count > link_notice_count)
00399 stat.route_notice_count++;
00400 if(stat.link_notice_bad_count > link_notice_bad_count)
00401 stat.route_notice_bad_count++;
00402 #endif
00403 }
00404
00405 void
00406 LinkCache::addRoute(const Path& route, Time t, const ID& who_from)
00407 {
00408 Path rt;
00409 int c;
00410
00411 if(pre_addRoute(route, rt, t, who_from) == 0)
00412 return;
00413
00414 #ifdef DSR_CACHE_STATS
00415 int link_add_count = stat.link_add_count;
00416 int link_add_bad_count = stat.link_add_bad_count;
00417 #endif
00418
00419 for(c = 0; c < rt.length() - 1; c++) {
00420 if(addLink(rt[c], rt[c+1], LINK_FLAG_UP,
00421 find_timeout(rt[c], rt[c+1], true))) {
00422 #ifdef DSR_CACHE_STATS
00423 checkLink(rt[c], rt[c+1], ACTION_ADD_ROUTE);
00424 #endif
00425 }
00426 }
00427
00428 #ifdef DSR_CACHE_STATS
00429 if(stat.link_add_count > link_add_count)
00430 stat.route_add_count++;
00431 if(stat.link_add_bad_count > link_add_bad_count)
00432 stat.route_add_bad_count++;
00433 #endif
00434 }
00435
00436 bool
00437 LinkCache::findRoute(ID dest, Path& route, int for_me = 0)
00438 {
00439 u_int32_t v;
00440 int rpath[MAX_SR_LEN];
00441 u_int32_t roff = 0;
00442
00443 if(verbose_debug) dumpLink();
00444
00445
00446
00447
00448 if(dirty <= CURRENT_TIME) {
00449 dijkstra();
00450
00451
00452 if(lc_evict_unreachable_links == true) {
00453 purgeLink();
00454 }
00455 }
00456 if(verbose_debug) dump_dijkstra(dest.addr);
00457
00458
00459
00460
00461 for(v = dest.addr; d[v] < INFINITY; v = pi[v]) {
00462
00463 if (roff >= MAX_SR_LEN) {
00464
00465 break;
00466 }
00467
00468 rpath[roff] = v;
00469 roff++;
00470
00471 if(v == net_id.addr)
00472 break;
00473 }
00474
00475 if(roff < 2 || d[v] == INFINITY || roff >= MAX_SR_LEN) {
00476 #ifdef DSR_CACHE_STATS
00477 stat.route_find_count += 1;
00478 if (for_me) stat.route_find_for_me += 1;
00479 stat.route_find_miss_count += 1;
00480 #endif
00481 return false;
00482 }
00483
00484
00485 #ifdef GOD_STABILITY
00486
00487
00488
00489
00490
00491
00492 if (lc_exppolicy == EXPPOLICY_GOD_OMNI) {
00493 int last = net_id.addr;
00494 for (v=1;v<roff;v++) {
00495 Link *l = findLink(last, rpath[roff-v-1]);
00496 #ifdef REALTIME_EXPIRE
00497 if (God::instance()->hops(last, rpath[roff-v-1])!=1) {
00498 LIST_REMOVE(l, ln_link);
00499 delete l;
00500 dirty = CURRENT_TIME;
00501 return findRoute(dest, route, for_me);
00502 }
00503 #else
00504 if (God::instance()->hops(last, rpath[roff-v-1])!=1) {
00505 l->ln_timeout = CURRENT_TIME;
00506 } else {
00507 l->ln_timeout = MAX_SIMTIME;
00508 }
00509 #endif
00510 last = rpath[roff-v-1];
00511 }
00512 }
00513 #endif //GOD_STABILITY
00514
00515
00516 #ifndef REALTIME_EXPIRE
00517 int last = net_id.addr;
00518 for (v=1;v<roff;v++) {
00519 Link *l = findLink(last, rpath[roff-v-1]);
00520 bool godsays = God::instance()->hops(last, rpath[roff-v-1])==1;
00521 last = rpath[roff-v-1];
00522 assert(l);
00523 if (l->expired()) {
00524 expirestats[CALLED_BAD + (godsays?IS_GOOD:IS_BAD)]++;
00525 LIST_REMOVE(l, ln_link);
00526 delete l;
00527 dirty = CURRENT_TIME;
00528 return findRoute(dest, route, for_me);
00529 } else {
00530 expirestats[CALLED_GOOD + (godsays?IS_GOOD:IS_BAD)]++;
00531 }
00532 }
00533 #endif
00534
00535
00536
00537
00538 ID id;
00539
00540 route.reset();
00541
00542 id.addr = net_id.addr;
00543 id.type = ::IP;
00544 id.link_type = LT_NONE;
00545 id.log_stat = LS_NONE;
00546 route.appendToPath(id);
00547
00548 for(v = 1; v < roff ; v++) {
00549 assert((int) (roff - v - 1) >= 0 && (roff - v - 1) < MAX_SR_LEN);
00550
00551 Link *l = findLink(route[v-1].addr, rpath[roff - v - 1]);
00552
00553 assert(l && !l->expired());
00554
00555 if (for_me)
00556 l->ln_timeout += lc_gen_use_bonus;
00557
00558 if (lc_exppolicy == EXPPOLICY_EXP) {
00559 exptable[route[v-1].addr] += lc_exp_add_amt;
00560 exptable[rpath[roff - v - 1]] += lc_exp_add_amt;
00561 }
00562
00563 id.addr = rpath[roff - v - 1];
00564 id.type = ::IP;
00565 id.link_type = LT_NONE;
00566 id.log_stat = LS_NONE;
00567 route.appendToPath(id);
00568
00569 route[v-1].t = l->ln_t;
00570 route[v-1].link_type = l->ln_linktype;
00571 route[v-1].log_stat = l->ln_logstat;
00572 }
00573
00574 #ifdef DSR_CACHE_STATS
00575 int bad = checkRoute_logall(&route, ACTION_FIND_ROUTE, 0);
00576 stat.route_find_count += 1;
00577 if (for_me) stat.route_find_for_me += 1;
00578 stat.route_find_bad_count += bad ? 1 : 0;
00579 stat.link_find_count += route.length() - 1;
00580 stat.link_find_bad_count += bad;
00581 #endif
00582 return true;
00583 }
00584
00585
00586 void
00587 LinkCache::Link_to_ID(Link *l, ID& id)
00588 {
00589 id.addr = l->ln_dst;
00590 id.type = ::IP;
00591 id.t = l->ln_t;
00592 id.link_type = l->ln_linktype;
00593 id.log_stat = l->ln_logstat;
00594 }
00595
00597
00598
00599
00600
00601
00602 void
00603 LinkCache::init_single_source(int s)
00604 {
00605 int v;
00606
00607 for(v = 1; v <= LC_MAX_NODES; v++) {
00608 d[v] = INFINITY;
00609 #ifdef LONGEST_LIVED_ROUTE
00610 dl[v] = 0;
00611 #endif
00612 pi[v] = 0;
00613
00614 S[v] = false;
00615 }
00616 d[s] = 0;
00617 #ifdef LONGEST_LIVED_ROUTE
00618 dl[s] = MAX_SIMTIME;
00619 #endif
00620 }
00621
00622 void
00623 #ifdef LONGEST_LIVED_ROUTE
00624 LinkCache::relax(u_int32_t u, u_int32_t v, u_int32_t w, double timeout)
00625 #else
00626 LinkCache::relax(u_int32_t u, u_int32_t v, u_int32_t w)
00627 #endif
00628 {
00629 assert(d[u] < INFINITY);
00630 assert(w == 1);
00631
00632 if(d[v] > d[u] + w
00633 #ifdef LONGEST_LIVED_ROUTE
00634 || (d[v] == d[u] + w && dl[v] < dl[u] && dl[v] < timeout)
00635 #endif
00636 ) {
00637 d[v] = d[u] + w;
00638 #ifdef LONGEST_LIVED_ROUTE
00639 dl[v] = (dl[u] > timeout) ? timeout : dl[u];
00640 #endif
00641 pi[v] = u;
00642 }
00643 }
00644
00645
00646 int
00647 LinkCache::extract_min_q()
00648 {
00649 int u;
00650 int min_u = 0;
00651
00652 for(u = 1; u <= LC_MAX_NODES; u++) {
00653 if(S[u] == false && d[u] < INFINITY &&
00654 (min_u == 0 || d[u] < d[min_u]
00655 #ifdef LONGEST_LIVED_ROUTE
00656 || (d[u] == d[min_u] && dl[u] > dl[min_u])
00657 #endif
00658 )) {
00659 min_u = u;
00660 }
00661 }
00662 return min_u;
00663 }
00664
00665 void
00666 LinkCache::dijkstra()
00667 {
00668 int u;
00669 Link *v;
00670
00671 dirty = MAX_SIMTIME;
00672
00673 #ifdef REALTIME_EXPIRE
00674 for (u=1; u <= LC_MAX_NODES; u++) {
00675 v = lcache[u].lh_first;
00676 while (v) {
00677 if(v->ln_timeout <= CURRENT_TIME) {
00678 Link *tmp;
00679 tmp = v->ln_link.le_next;
00680 LIST_REMOVE(v, ln_link);
00681 delete v;
00682 v = tmp;
00683 } else {
00684 if (v->ln_timeout < dirty)
00685 dirty = v->ln_timeout;
00686 v = v->ln_link.le_next;
00687 }
00688 }
00689 }
00690 #endif
00691
00692 init_single_source(net_id.addr);
00693
00694 while((u = extract_min_q()) != 0) {
00695 S[u] = true;
00696 v = lcache[u].lh_first;
00697 for( ; v; v = v->ln_link.le_next) {
00698 if(v->ln_flags & LINK_FLAG_UP) {
00699 #ifdef LONGEST_LIVED_ROUTE
00700 relax(u, v->ln_dst, v->ln_cost, v->ln_timeout);
00701 #else
00702 relax(u, v->ln_dst, v->ln_cost);
00703 #endif
00704 }
00705 }
00706 }
00707 }
00708
00709 void
00710 LinkCache::dump_dijkstra(int dst)
00711 {
00712 static char tbuf[512];
00713 u_int32_t u, toff = 0;
00714
00715 bzero(tbuf, sizeof(tbuf));
00716 sprintf(tbuf, "SRC %.9f _%s_ dijkstra *%d* ",
00717 CURRENT_TIME, net_id.dump(), dst);
00718 toff = strlen(tbuf);
00719
00720 for(u = 1; u <= LC_MAX_NODES; u++) {
00721 if(d[u] < INFINITY) {
00722 sprintf(tbuf+toff, "%d,%d,%d ", u, d[u], pi[u]);
00723 toff = strlen(tbuf);
00724 assert(toff < sizeof(tbuf));
00725 }
00726 }
00727
00728 trace("%s", tbuf);
00729 }
00730
00731
00733
00734 int
00735 LinkCache::addLink(const ID& from, const ID& to,
00736 int flags, double timeout, int cost)
00737 {
00738 Link *l;
00739 int rc = 0;
00740
00741 if((l = findLink(from.addr, to.addr)) == 0) {
00742 l = new Link(to.addr);
00743 assert(l);
00744 LIST_INSERT_HEAD(&lcache[from.addr], l, ln_link);
00745 dirty = CURRENT_TIME;
00746 l->ln_insert = CURRENT_TIME;
00747 rc = 1;
00748 } else if ((l->ln_flags & flags) != flags) {
00749
00750 dirty = CURRENT_TIME;
00751 l->ln_insert = CURRENT_TIME;
00752 }
00753
00754 l->ln_t = CURRENT_TIME;
00755 l->ln_linktype = from.link_type;
00756 l->ln_flags |= flags;
00757 l->ln_cost = cost;
00758 l->ln_timeout = timeout;
00759
00760 if(lc_bidirectional_links == false)
00761 return rc;
00762
00763
00764
00765
00766 if((l = findLink(to.addr, from.addr)) == 0) {
00767 l = new Link(from.addr);
00768 assert(l);
00769 l->ln_insert = CURRENT_TIME;
00770 LIST_INSERT_HEAD(&lcache[to.addr], l, ln_link);
00771 dirty = CURRENT_TIME;
00772 } else if ((l->ln_flags & flags) != flags) {
00773
00774 dirty = CURRENT_TIME;
00775 l->ln_insert = CURRENT_TIME;
00776 }
00777 l->ln_t = CURRENT_TIME;
00778 l->ln_linktype = from.link_type;
00779 l->ln_flags |= flags;
00780 l->ln_cost = cost;
00781 l->ln_timeout = timeout;
00782
00783 return rc;
00784 }
00785
00786 int
00787 LinkCache::delLink(const ID& from, const ID& to)
00788 {
00789 Link *l;
00790 int rc = 0;
00791
00792 if((l = findLink(from.addr, to.addr))) {
00793 LIST_REMOVE(l, ln_link);
00794 delete l;
00795 dirty = CURRENT_TIME;
00796 rc = 1;
00797 }
00798
00799 if(lc_bidirectional_links == false)
00800 return rc;
00801
00802
00803
00804
00805 if((l = findLink(to.addr, from.addr))) {
00806 LIST_REMOVE(l, ln_link);
00807 delete l;
00808 dirty = CURRENT_TIME;
00809 }
00810
00811 return rc;
00812 }
00813
00814 Link*
00815 LinkCache::findLink(int from, int to)
00816 {
00817 Link *l;
00818
00819 for(l = lcache[from].lh_first; l; l = l->ln_link.le_next) {
00820 if(l->ln_dst == to) {
00821 return l;
00822 }
00823 }
00824 return 0;
00825 }
00826
00827 void
00828 LinkCache::purgeLink()
00829 {
00830 int u;
00831 Link *l;
00832
00833 for(u = 1; u <= LC_MAX_NODES; u++) {
00834 if(d[u] == INFINITY) {
00835 ID from, to;
00836
00837 from.addr = u;
00838 from.type = ::IP;
00839 from.link_type = LT_NONE;
00840 from.log_stat = LS_NONE;
00841
00842 l = lcache[u].lh_first;
00843 for( ; l; l = l->ln_link.le_next) {
00844 Link_to_ID(l, to);
00845 #ifdef DSR_CACHE_STATS
00846 checkLink_logall(from, to, ACTION_EVICT);
00847 #endif
00848 (void) delLink(from, to);
00849 }
00850 }
00851 }
00852 }
00853
00854
00855 void
00856 LinkCache::dumpLink()
00857 {
00858 Link *l;
00859 int i;
00860 static char tbuf[512];
00861 u_int32_t toff = 0;
00862
00863 bzero(tbuf, sizeof(tbuf));
00864 sprintf(tbuf, "SRC %.9f _%s_ dump-link ", CURRENT_TIME, net_id.dump());
00865 toff = strlen(tbuf);
00866
00867 for(i = 1; i <= LC_MAX_NODES; i++) {
00868 for(l = lcache[i].lh_first; l; l = l->ln_link.le_next) {
00869 sprintf(tbuf+toff, "%d->%d, ", i, l->ln_dst);
00870 toff = strlen(tbuf);
00871 assert(toff < sizeof(tbuf));
00872 }
00873 }
00874
00875 trace("%s", tbuf);
00876 }
00877
00878 #ifdef DSR_CACHE_STATS
00879
00880
00881
00882
00883 void
00884 LinkCache::checkLink_logall(const ID& from, const ID& to, int action)
00885 {
00886 Link *l = findLink(from.addr, to.addr);
00887
00888 assert(action == ACTION_EVICT);
00889 assert(l);
00890
00891 if(God::instance()->hops(from.addr, to.addr) != 1) {
00892 trace("SRC %.9f _%s_ %s [%d %d] %s->%s dead %d %.9f",
00893 CURRENT_TIME, net_id.dump(),
00894 action_name[action], 0, 0,
00895 from.dump(), to.dump(),
00896 l->ln_linktype, l->ln_t);
00897 }
00898 }
00899
00900 void
00901 LinkCache::checkLink(const ID& from, const ID& to, int action)
00902 {
00903 Link *l = findLink(from.addr, to.addr);
00904 int alive = 0;
00905
00906 assert(l);
00907
00908 if(God::instance()->hops(from.addr, to.addr) != 1) {
00909 if(l->ln_logstat == LS_UNLOGGED) {
00910 trace("SRC %.9f _%s_ %s [%d %d] %s->%s dead %d %.9f",
00911 CURRENT_TIME, net_id.dump(),
00912 action_name[action], 0, 0,
00913 from.dump(), to.dump(),
00914 l->ln_linktype, l->ln_t);
00915 l->ln_logstat = LS_LOGGED;
00916 }
00917 } else {
00918 alive = 1;
00919 if(l->ln_logstat == LS_LOGGED) {
00920 trace("SRC %.9f _%s_ resurrected-link [%d %d] %s->%s dead %d %.9f",
00921 CURRENT_TIME, net_id.dump(), 0, 0,
00922 from.dump(), to.dump(),
00923 l->ln_linktype, l->ln_t);
00924 l->ln_logstat = LS_UNLOGGED;
00925 }
00926 }
00927
00928 switch(action) {
00929 case ACTION_ADD_ROUTE:
00930 stat.link_add_count += 1;
00931 if(alive == 0){
00932 stat.link_add_bad_count += 1;
00933 }
00934 if(l->ln_linktype == LT_TESTED)
00935 stat.link_add_tested += 1;
00936 break;
00937
00938 case ACTION_NOTICE_ROUTE:
00939 stat.link_notice_count += 1;
00940 if(alive == 0){
00941 stat.link_notice_bad_count += 1;
00942 }
00943 if(l->ln_linktype == LT_TESTED)
00944 stat.link_notice_tested += 1;
00945 break;
00946 }
00947 }
00948
00949 void
00950 LinkCache::periodic_checkCache()
00951 {
00952 int c;
00953 int link_count = 0;
00954 int link_bad_count = 0;
00955 double link_bad_time = 0.0;
00956 int link_bad_tested = 0;
00957 int link_good_tested = 0;
00958
00959 #ifndef REALTIME_EXPIRE
00960 if (ID(1,::IP) == net_id)
00961 trace("SRC %.9f _%s_ cache-expire-bits %d %d %d %d",
00962 CURRENT_TIME, net_id.dump(), expirestats[0], expirestats[1],
00963 expirestats[2], expirestats[3]);
00964 #endif
00965
00966 for(c = 1; c <= LC_MAX_NODES; c++) {
00967 Link *v = lcache[c].lh_first;
00968 for( ; v; v = v->ln_link.le_next) {
00969 link_count += 1;
00970 if(God::instance()->hops(c, v->ln_dst) != 1) {
00971 link_bad_count += 1;
00972 link_bad_time += CURRENT_TIME - v->ln_t;
00973 if(v->ln_linktype == LT_TESTED)
00974 link_bad_tested += 1;
00975 } else {
00976 if(v->ln_linktype == LT_TESTED)
00977 link_good_tested += 1;
00978 }
00979 }
00980 }
00981
00982 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",
00983 CURRENT_TIME, net_id.dump(),
00984 0,
00985 0,
00986 link_count,
00987 0,
00988
00989 link_bad_count,
00990 link_bad_count ? link_bad_time/link_bad_count : 0.0,
00991 link_bad_tested,
00992 link_good_tested,
00993
00994 stat.route_add_count,
00995 stat.route_add_bad_count,
00996 stat.link_add_count,
00997 stat.link_add_bad_count,
00998 stat.link_add_tested,
00999
01000 stat.route_notice_count,
01001 stat.route_notice_bad_count,
01002 stat.link_notice_count,
01003 stat.link_notice_bad_count,
01004 stat.link_notice_tested,
01005
01006 stat.route_find_count,
01007 stat.route_find_for_me,
01008 stat.route_find_bad_count,
01009 stat.route_find_miss_count,
01010 stat.subroute_find_count,
01011 stat.subroute_find_bad_count);
01012 stat.reset();
01013 }
01014
01015 #endif
01016 #endif //DSR_LINKCACHE