linkcache.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:24k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * linkcache.cc
  3.  * Copyright (C) 2000 by the University of Southern California
  4.  * $Id: linkcache.cc,v 1.2 2005/08/25 18:58:05 johnh Exp $
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License,
  8.  * version 2, as published by the Free Software Foundation.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  18.  *
  19.  *
  20.  * The copyright of this module includes the following
  21.  * linking-with-specific-other-licenses addition:
  22.  *
  23.  * In addition, as a special exception, the copyright holders of
  24.  * this module give you permission to combine (via static or
  25.  * dynamic linking) this module with free software programs or
  26.  * libraries that are released under the GNU LGPL and with code
  27.  * included in the standard release of ns-2 under the Apache 2.0
  28.  * license or under otherwise-compatible licenses with advertising
  29.  * requirements (or modified versions of such code, with unchanged
  30.  * license).  You may copy and distribute such a system following the
  31.  * terms of the GNU GPL for this module and the licenses of the
  32.  * other code concerned, provided that you include the source code of
  33.  * that other code when and as the GNU GPL requires distribution of
  34.  * source code.
  35.  *
  36.  * Note that people who make modified versions of this module
  37.  * are not obligated to grant this special exception for their
  38.  * modified versions; it is their choice whether to do so.  The GNU
  39.  * General Public License gives permission to release a modified
  40.  * version without this exception; this exception also makes it
  41.  * possible to release a modified version which carries forward this
  42.  * exception.
  43.  *
  44.  */
  45. //
  46. // Other copyrights might apply to parts of this software and are so
  47. // noted when applicable.
  48. //
  49. // Ported from CMU/Monarch's code, appropriate copyright applies.  
  50. #ifdef DSR_LINKCACHE
  51. #include <god.h>
  52. #include "path.h"
  53. #include "routecache.h"
  54. #include <list.h>
  55. #ifdef DSR_CACHE_STATS
  56. #include "cache_stats.h"
  57. #endif
  58. #define CURRENT_TIME Scheduler::instance().clock()
  59. #define MAX_SIMTIME  86400
  60. bool cache_ignore_hints = false;     // ignore all hints?
  61. bool cache_use_overheard_routes = true; 
  62. // Specifies whether or not to retain links after they go bad
  63. // I don't think this is implemented.
  64. static const bool lc_cache_negative_links = false;
  65. static const double lc_neg_cache_life = 1.0;
  66. // When inserting/deleting link A->B, also insert/delete B->A.
  67. static const bool lc_bidirectional_links = true;
  68. // Evict "unreachable" links from the cache.
  69. static const bool lc_evict_unreachable_links = false;
  70. // do we expire in realtime? or do we wait for use?
  71. //#define REALTIME_EXPIRE
  72. // The maximum number of nodes supported by the cache.
  73. #define LC_MAX_NODES 200
  74. // General generational stuff...
  75. static const double lc_gen_use_bonus = 300;
  76. // Static stuff
  77. static const double lc_static_discover_life = 5.0;
  78. static const double lc_static_overhear_life = 5.0;
  79. // Table stuff
  80. static const double lc_table_init_val = 50.0;
  81. static const double lc_table_mult_by  = 0.5;
  82. static const double lc_linear_alpha   = 1.0/8.0;
  83. static const double lc_exp_add_amt    = 2.0;
  84. static const double lc_exp_div_amt    = 2.0;
  85. static const double lc_minlifetime    = 2.0;
  86. // types of linkgens
  87. #define EXPPOLICY_INFINITE  0
  88. #define EXPPOLICY_STATIC    1
  89. #define EXPPOLICY_LINEAR    2
  90. #define EXPPOLICY_EXP       3
  91. #ifdef GOD_STABILITY
  92. #define EXPPOLICY_GOD_OMNI  4
  93. #define EXPPOLICY_GOD_TABLE 5
  94. #endif
  95. #define LONGEST_LIVED_ROUTE
  96. static const int lc_exppolicy = EXPPOLICY_EXP;
  97. #ifdef GOD_STABILITY
  98. extern double *godavglife;
  99. #endif
  100. #ifndef REALTIME_EXPIRE
  101. // statistics...
  102. #define IS_GOOD     0
  103. #define IS_BAD      1
  104. #define CALLED_GOOD 0
  105. #define CALLED_BAD  2
  106. static int expirestats[4];
  107. #endif
  108. static int verbose_debug = 0;
  109. // *****************************************************
  110. class Link {
  111. public:
  112. Link(nsaddr_t dst) {
  113. ln_dst = dst;
  114. ln_flags = ln_cost = 0;
  115. ln_timeout = 0.0;
  116. ln_insert = 0.0;
  117. ln_t = 0.0;
  118. ln_linktype = LT_NONE;
  119. ln_logstat = LS_UNLOGGED;
  120. }
  121. inline bool expired() {
  122. return (ln_timeout <= CURRENT_TIME);
  123. }
  124. LIST_ENTRY(Link) ln_link;
  125. nsaddr_t   ln_dst;
  126. int        ln_flags;       // link status information
  127. #define LINK_FLAG_UP 0x01
  128. /*
  129.  * Right now all links have the same cost (1). - josh
  130.  */
  131. int        ln_cost;        // cost of using the link
  132. /*
  133.  * the use of ln_timeout to expire links from the
  134.  * cache has not yet been implemented. - josh
  135.  * Implemented. - yihchun
  136.  */
  137. double     ln_timeout;     // when the link expires
  138. double     ln_insert;      // when the link expires
  139. #define LINK_TIMEOUT MAX_SIMTIME
  140. // mirror the values kept in class ID
  141. Time    ln_t;
  142. Link_Type  ln_linktype;
  143. Log_Status ln_logstat;
  144. };
  145. LIST_HEAD(dsrLinkHead, Link);
  146. class LinkCache : public RouteCache {
  147. friend class MobiHandler;
  148. public:
  149. LinkCache();
  150. void noticeDeadLink(const ID&from, const ID& to, Time t);
  151. // the link from->to isn't working anymore, purge routes containing
  152. // it from the cache
  153. void noticeRouteUsed(const Path& route, Time t,
  154.      const ID& who_from);
  155. // tell the cache about a route we saw being used
  156. void addRoute(const Path& route, Time t, const ID& who_from);
  157. // add this route to the cache (presumably we did a route request
  158. // to find this route and don't want to lose it)
  159. bool findRoute(ID dest, Path& route, int for_me = 0);
  160. // if there is a cached path from us to dest returns true and fills in
  161. // the route accordingly. returns false otherwise
  162. // if for_use, then we assume that the node really wants to keep 
  163. // the returned route so it will be promoted to primary storage
  164. // if not there already
  165. int command(int argc, const char*const* argv);
  166. protected:
  167. dsrLinkHead lcache[LC_MAX_NODES + 1];
  168. // note the zeroth index is not used
  169. int addLink(const ID& from, const ID& to,
  170.     int flags, double timeout = LINK_TIMEOUT, int cost = 1);
  171. int delLink(const ID& from, const ID& to);
  172. Link* findLink(int from, int to);
  173. void purgeLink(void);
  174. void dumpLink(void);
  175. void Link_to_ID(Link* l, ID& id);
  176. #ifdef DSR_CACHE_STATS
  177. void checkLink_logall(const ID& from, const ID& to, int action);
  178. void checkLink(const ID& from, const ID& to, int action);
  179. void periodic_checkCache();
  180. struct cache_stats stat;
  181. #endif
  182. private:
  183. ////////////////////////////////////////////////////////////
  184. // Dijkstra's Algorithm
  185. double dirty; // the next time it gets dirty
  186. #ifdef LONGEST_LIVED_ROUTE
  187. double dl[LC_MAX_NODES + 1];
  188. #endif
  189. u_int32_t d[LC_MAX_NODES + 1];
  190. u_int32_t pi[LC_MAX_NODES + 1];
  191. bool S[LC_MAX_NODES + 1];
  192. double exptable[LC_MAX_NODES + 1];
  193. #define INFINITY 0x7fffffff
  194. void init_single_source(int s);
  195. #ifdef LONGEST_LIVED_ROUTE
  196. void relax(u_int32_t u, u_int32_t v, u_int32_t w, double);
  197. #else
  198. void relax(u_int32_t u, u_int32_t v, u_int32_t w);
  199. #endif
  200. int  extract_min_q(void);
  201. void dijkstra(void);
  202. void dump_dijkstra(int dst);
  203. double find_timeout(ID a, ID b, bool discovered);
  204. };
  205. ///////////////////////////////////////////////////////////////////////////
  206. double LinkCache::find_timeout(ID a, ID b, bool discovered) {
  207. double lifetime = 0.0;
  208. switch (lc_exppolicy) {
  209. case EXPPOLICY_INFINITE:
  210. #ifdef GOD_STABILITY
  211.         case EXPPOLICY_GOD_OMNI:
  212. #endif
  213. return MAX_SIMTIME;
  214. case EXPPOLICY_LINEAR: case EXPPOLICY_EXP:
  215. lifetime = exptable[a.addr] > exptable[b.addr] ? 
  216.   exptable[b.addr] : exptable[a.addr];
  217. lifetime *= lc_table_mult_by;
  218. break;
  219. #ifdef GOD_STABILITY
  220. case EXPPOLICY_GOD_TABLE:
  221. lifetime = godavglife[a.addr] > godavglife[b.addr] ? 
  222.   godavglife[b.addr] : godavglife[a.addr];
  223. lifetime *= lc_table_mult_by;
  224. break;
  225. #endif
  226. case EXPPOLICY_STATIC:
  227. lifetime = discovered ? lc_static_discover_life :
  228.   lc_static_overhear_life;
  229. break;
  230. default:
  231. assert(0);
  232. }
  233. if (lifetime < lc_minlifetime)
  234. lifetime = lc_minlifetime;
  235. return CURRENT_TIME + lifetime;
  236. }
  237. RouteCache *
  238. makeRouteCache()
  239. {
  240.   return new LinkCache();
  241. }
  242. LinkCache::LinkCache() : RouteCache()
  243. {
  244. int i = 0;
  245. for(i = 0; i <= LC_MAX_NODES; i++) {
  246. LIST_INIT(&lcache[i]);
  247. exptable[i] = lc_table_init_val;
  248. }
  249. #ifdef DSR_CACHE_STATS
  250. stat.reset();
  251. #endif
  252. dirty = -1;
  253. }
  254. int
  255. LinkCache::command(int argc, const char*const* argv)
  256. {
  257.   if(argc == 2 && strcasecmp(argv[1], "startdsr") == 0)
  258.     { 
  259.       if (ID(1,::IP) == net_id) 
  260. trace("Sconfig %.5f using LINKCACHE %d", Scheduler::instance().clock(),
  261. lc_exppolicy);
  262.       // FALL-THROUGH
  263.     }
  264.   if(argc == 3)
  265.     {   
  266.       if (strcasecmp(argv[1], "ip-addr") == 0)
  267.         {
  268.           assert(atoi(argv[2]) <= LC_MAX_NODES);
  269. #ifndef REALTIME_EXPIRE
  270.   if (atoi(argv[2]) == 1)
  271.     bzero(expirestats, sizeof(expirestats));
  272. #endif
  273.           // don't return
  274.         } 
  275.     }
  276.   return RouteCache::command(argc, argv);
  277. }
  278. void
  279. LinkCache::noticeDeadLink(const ID& from, const ID& to, Time)
  280. {
  281. Link *l = findLink(from.addr, to.addr);
  282. if (l && (l->ln_flags & LINK_FLAG_UP) &&
  283.     (lc_exppolicy == EXPPOLICY_LINEAR || 
  284.      lc_exppolicy == EXPPOLICY_EXP)) {
  285. if (lc_exppolicy == EXPPOLICY_LINEAR) {
  286. exptable[from.addr]=lc_linear_alpha*exptable[from.addr]
  287.   +(CURRENT_TIME-l->ln_insert)*(1-lc_linear_alpha);
  288. exptable[to.addr]=lc_linear_alpha*exptable[to.addr]
  289.   +(CURRENT_TIME-l->ln_insert)*(1-lc_linear_alpha);
  290. } else {
  291. exptable[from.addr] /= lc_exp_div_amt;
  292. exptable[to.addr] /= lc_exp_div_amt;
  293. }
  294. }
  295. if(lc_cache_negative_links == true) {
  296. if(l) {
  297. l->ln_flags &= ~LINK_FLAG_UP;
  298. l->ln_insert = CURRENT_TIME;
  299. l->ln_timeout = CURRENT_TIME + lc_neg_cache_life;
  300. dirty = CURRENT_TIME;
  301. } else {
  302. addLink(from, to, 0, CURRENT_TIME + lc_neg_cache_life);
  303. }
  304. }
  305. else {
  306. if(l) {
  307. #ifdef DSR_CACHE_STATS
  308. checkLink(from, to, ACTION_DEAD_LINK);
  309. #endif
  310. (void) delLink(from, to);
  311. }
  312. }
  313. }
  314. void
  315. LinkCache::noticeRouteUsed(const Path& p, Time t, const ID& who_from)
  316. {
  317.   Path stub;
  318.   int c;
  319.   if(pre_noticeRouteUsed(p, stub, t, who_from) == 0)
  320.   return;
  321.   
  322. #ifdef DSR_CACHE_STATS
  323.   int link_notice_count = stat.link_notice_count; 
  324.   int link_notice_bad_count = stat.link_notice_bad_count;   
  325. #endif
  326.   /*
  327.    * Add each link in the "path" to the route cache.
  328.    */
  329.   for(c = 0; c < stub.length() - 1; c++) {
  330.   if(addLink(stub[c], stub[c+1], LINK_FLAG_UP, 
  331.      find_timeout(stub[c], stub[c+1], false))) {
  332. #ifdef DSR_CACHE_STATS
  333. checkLink(stub[c], stub[c+1], ACTION_NOTICE_ROUTE);
  334. #endif
  335.   }
  336.   }
  337. #ifdef DSR_CACHE_STATS
  338.   if(stat.link_notice_count > link_notice_count)
  339.   stat.route_notice_count++;
  340.   if(stat.link_notice_bad_count > link_notice_bad_count)
  341.   stat.route_notice_bad_count++;
  342. #endif
  343. }
  344. void
  345. LinkCache::addRoute(const Path& route, Time t, const ID& who_from)
  346. {
  347.   Path rt;
  348.   int c;
  349.   if(pre_addRoute(route, rt, t, who_from) == 0)
  350.   return;
  351.   
  352. #ifdef DSR_CACHE_STATS
  353.   int link_add_count = stat.link_add_count; 
  354.   int link_add_bad_count = stat.link_add_bad_count;   
  355. #endif
  356.   for(c = 0; c < rt.length() - 1; c++) {
  357.   if(addLink(rt[c], rt[c+1], LINK_FLAG_UP,
  358.      find_timeout(rt[c], rt[c+1], true))) {
  359. #ifdef DSR_CACHE_STATS
  360.   checkLink(rt[c], rt[c+1], ACTION_ADD_ROUTE);
  361. #endif
  362.   }
  363.   }
  364. #ifdef DSR_CACHE_STATS
  365.   if(stat.link_add_count > link_add_count)
  366.   stat.route_add_count++;
  367.   if(stat.link_add_bad_count > link_add_bad_count)
  368.   stat.route_add_bad_count++;
  369. #endif
  370. }
  371. bool
  372. LinkCache::findRoute(ID dest, Path& route, int for_me = 0)
  373. {
  374. u_int32_t v;
  375. int rpath[MAX_SR_LEN];
  376. u_int32_t roff = 0;
  377. if(verbose_debug) dumpLink();
  378. /*
  379.  * Compute all of the shortest paths...
  380.  */
  381. if(dirty <= CURRENT_TIME) {
  382. dijkstra();
  383. // remove all of the links for nodes that are unreachable
  384. if(lc_evict_unreachable_links == true) {
  385. purgeLink();
  386. }
  387. }
  388. if(verbose_debug) dump_dijkstra(dest.addr);
  389. /*
  390.  * Trace backwards to figure out the path to DEST
  391.  */
  392. for(v = dest.addr; d[v] < INFINITY; v = pi[v]) {
  393.   //assert(v >= 1 && v <= LC_MAX_NODES);
  394. if (roff >= MAX_SR_LEN) {
  395.           // path between us and dest is too long to be useful
  396.         break;
  397. }
  398. rpath[roff] = v;
  399. roff++;
  400. if(v == net_id.addr)
  401. break;
  402. }
  403. if(roff < 2 || d[v] == INFINITY || roff >= MAX_SR_LEN) {
  404. #ifdef DSR_CACHE_STATS
  405. stat.route_find_count += 1;
  406. if (for_me) stat.route_find_for_me += 1; 
  407. stat.route_find_miss_count += 1;
  408. #endif
  409. return false; // no path
  410. }
  411. #ifdef GOD_STABILITY
  412. /* The logic for God's omniscient expiration policy:
  413.  *   if we expire in realtime, kill dead links immediately, and
  414.  *     goto top. XXX this could create unnecessary overhead.
  415.  *   if we expire on the fly, we set the timeout to an appropriate
  416.  *     value, depending on whether or not the link is valid.
  417.  */
  418. if (lc_exppolicy == EXPPOLICY_GOD_OMNI) {
  419. int last = net_id.addr;
  420. for (v=1;v<roff;v++) {
  421. Link *l = findLink(last, rpath[roff-v-1]);
  422. #ifdef REALTIME_EXPIRE
  423. if (God::instance()->hops(last, rpath[roff-v-1])!=1) {
  424. LIST_REMOVE(l, ln_link);
  425. delete l;
  426. dirty = CURRENT_TIME;
  427. return findRoute(dest, route, for_me);
  428. }
  429. #else
  430. if (God::instance()->hops(last, rpath[roff-v-1])!=1) {
  431. l->ln_timeout = CURRENT_TIME;
  432. } else {
  433. l->ln_timeout = MAX_SIMTIME;
  434. }
  435. #endif
  436. last = rpath[roff-v-1];
  437. }
  438. }
  439. #endif //GOD_STABILITY 
  440. #ifndef REALTIME_EXPIRE
  441. int last = net_id.addr;
  442. for (v=1;v<roff;v++) {
  443. Link *l = findLink(last, rpath[roff-v-1]);
  444. bool godsays = God::instance()->hops(last, rpath[roff-v-1])==1;
  445. last = rpath[roff-v-1];
  446. assert(l);
  447. if (l->expired()) {
  448. expirestats[CALLED_BAD + (godsays?IS_GOOD:IS_BAD)]++;
  449. LIST_REMOVE(l, ln_link);
  450. delete l;
  451. dirty = CURRENT_TIME;
  452. return findRoute(dest, route, for_me);
  453. } else {
  454. expirestats[CALLED_GOOD + (godsays?IS_GOOD:IS_BAD)]++;
  455. }
  456. }
  457. #endif
  458. /*
  459.  * Build the path that we need...
  460.  */
  461. ID id;
  462. route.reset();
  463. id.addr = net_id.addr;  // source route is rooted at "us"
  464. id.type = ::IP;
  465. id.link_type = LT_NONE;
  466. id.log_stat = LS_NONE;
  467. route.appendToPath(id);
  468. for(v = 1; v < roff ; v++) {
  469. assert((int) (roff - v - 1) >= 0 && (roff - v - 1) < MAX_SR_LEN);
  470. Link *l = findLink(route[v-1].addr, rpath[roff - v - 1]);
  471. assert(l && !l->expired());
  472. if (for_me)
  473. l->ln_timeout += lc_gen_use_bonus;
  474. if (lc_exppolicy == EXPPOLICY_EXP) {
  475. exptable[route[v-1].addr] += lc_exp_add_amt;
  476. exptable[rpath[roff - v - 1]] += lc_exp_add_amt;
  477. }
  478. id.addr = rpath[roff - v - 1];
  479. id.type = ::IP;
  480. id.link_type = LT_NONE;
  481. id.log_stat = LS_NONE;
  482. route.appendToPath(id);
  483. route[v-1].t = l->ln_t;
  484. route[v-1].link_type = l->ln_linktype;
  485. route[v-1].log_stat = l->ln_logstat;
  486. }
  487. #ifdef DSR_CACHE_STATS
  488. int bad = checkRoute_logall(&route, ACTION_FIND_ROUTE, 0);
  489. stat.route_find_count += 1; 
  490. if (for_me) stat.route_find_for_me += 1;     
  491. stat.route_find_bad_count += bad ? 1 : 0;
  492. stat.link_find_count += route.length() - 1;
  493. stat.link_find_bad_count +=  bad;
  494. #endif
  495. return true;
  496. }
  497. void
  498. LinkCache::Link_to_ID(Link *l, ID& id)
  499. {
  500. id.addr = l->ln_dst;
  501. id.type = ::IP;
  502. id.t = l->ln_t;
  503. id.link_type = l->ln_linktype;
  504. id.log_stat = l->ln_logstat;
  505. }
  506. ///////////////////////////////////////////////////////////////////////////
  507. /*
  508.  * Dijkstra's algorithm taken from CLR.
  509.  */
  510. void
  511. LinkCache::init_single_source(int s)
  512. {
  513. int v;
  514. for(v = 1; v <= LC_MAX_NODES; v++) {
  515. d[v] = INFINITY;
  516. #ifdef LONGEST_LIVED_ROUTE
  517. dl[v] = 0; // dies immediately
  518. #endif
  519. pi[v] = 0; // invalid node ID
  520. S[v] = false;
  521. }
  522. d[s] = 0;
  523. #ifdef LONGEST_LIVED_ROUTE
  524. dl[s] = MAX_SIMTIME;
  525. #endif
  526. }
  527. void
  528. #ifdef LONGEST_LIVED_ROUTE
  529. LinkCache::relax(u_int32_t u, u_int32_t v, u_int32_t w, double timeout)
  530. #else
  531. LinkCache::relax(u_int32_t u, u_int32_t v, u_int32_t w)
  532. #endif
  533. {
  534. assert(d[u] < INFINITY);
  535. assert(w == 1); /* make sure everything's working how I expect */
  536. if(d[v] > d[u] + w
  537. #ifdef LONGEST_LIVED_ROUTE
  538.    || (d[v] == d[u] + w && dl[v] < dl[u] && dl[v] < timeout)
  539. #endif
  540.    ) {
  541. d[v] = d[u] + w;
  542. #ifdef LONGEST_LIVED_ROUTE
  543. dl[v] = (dl[u] > timeout) ? timeout : dl[u];
  544. #endif
  545. pi[v] = u;
  546. }
  547. }
  548. int
  549. LinkCache::extract_min_q()
  550. {
  551. int u;
  552. int min_u = 0;
  553. for(u = 1; u <= LC_MAX_NODES; u++) {
  554. if(S[u] == false && d[u] < INFINITY && 
  555.    (min_u == 0 || d[u] < d[min_u] 
  556. #ifdef LONGEST_LIVED_ROUTE
  557.     || (d[u] == d[min_u] && dl[u] > dl[min_u])
  558. #endif
  559.    )) {
  560. min_u = u;
  561. }
  562. }
  563. return min_u; // (min_u == 0) ==> no valid link
  564. }
  565. void
  566. LinkCache::dijkstra()
  567. {
  568. int u;
  569. Link *v;
  570. dirty = MAX_SIMTIME;  // all of the info is up-to-date
  571. #ifdef REALTIME_EXPIRE
  572. for (u=1; u <= LC_MAX_NODES; u++) {
  573. v = lcache[u].lh_first;
  574. while (v) {
  575. if(v->ln_timeout <= CURRENT_TIME) {
  576. Link *tmp;
  577. tmp = v->ln_link.le_next;
  578. LIST_REMOVE(v, ln_link);
  579. delete v;
  580. v = tmp;
  581. } else {
  582. if (v->ln_timeout < dirty)
  583. dirty = v->ln_timeout;
  584. v = v->ln_link.le_next;
  585. }
  586. }
  587. }
  588. #endif
  589. init_single_source(net_id.addr);
  590. while((u = extract_min_q()) != 0) {
  591. S[u] = true;
  592. v = lcache[u].lh_first;
  593. for( ; v; v = v->ln_link.le_next) {
  594. if(v->ln_flags & LINK_FLAG_UP) {
  595. #ifdef LONGEST_LIVED_ROUTE
  596. relax(u, v->ln_dst, v->ln_cost, v->ln_timeout);
  597. #else
  598. relax(u, v->ln_dst, v->ln_cost);
  599. #endif
  600. }
  601. }
  602. }
  603. }
  604. void
  605. LinkCache::dump_dijkstra(int dst)
  606. {
  607. static char tbuf[512];
  608. u_int32_t u, toff = 0;
  609. bzero(tbuf, sizeof(tbuf));
  610. sprintf(tbuf, "SRC %.9f _%s_ dijkstra *%d* ",
  611. CURRENT_TIME, net_id.dump(), dst);
  612. toff = strlen(tbuf);
  613. for(u = 1; u <= LC_MAX_NODES; u++) {
  614. if(d[u] < INFINITY) {
  615. sprintf(tbuf+toff, "%d,%d,%d ", u, d[u], pi[u]);
  616. toff = strlen(tbuf);
  617. assert(toff < sizeof(tbuf));
  618. }
  619. }
  620. trace("%s", tbuf);
  621. }
  622. ///////////////////////////////////////////////////////////////////////////
  623. int
  624. LinkCache::addLink(const ID& from, const ID& to,
  625.    int flags, double timeout, int cost)
  626. {
  627. Link *l;
  628. int rc = 0;
  629. if((l = findLink(from.addr, to.addr)) == 0) {
  630. l = new Link(to.addr);
  631. assert(l);
  632. LIST_INSERT_HEAD(&lcache[from.addr], l, ln_link);
  633. dirty = CURRENT_TIME;
  634. l->ln_insert = CURRENT_TIME;
  635. rc = 1;
  636. } else if ((l->ln_flags & flags) != flags) {
  637. // we want to set flags
  638. dirty = CURRENT_TIME;
  639. l->ln_insert = CURRENT_TIME;
  640. }
  641. l->ln_t = CURRENT_TIME;
  642. l->ln_linktype = from.link_type;
  643. l->ln_flags |= flags;
  644. l->ln_cost = cost;
  645. l->ln_timeout = timeout;
  646. if(lc_bidirectional_links == false)
  647. return rc;
  648. /*
  649.  * Add the "other" direction of the link...
  650.  */
  651. if((l = findLink(to.addr, from.addr)) == 0) {
  652. l = new Link(from.addr);
  653. assert(l);
  654. l->ln_insert = CURRENT_TIME;
  655. LIST_INSERT_HEAD(&lcache[to.addr], l, ln_link);
  656. dirty = CURRENT_TIME;
  657. } else if ((l->ln_flags & flags) != flags) {
  658. // we want to set flags
  659. dirty = CURRENT_TIME;
  660. l->ln_insert = CURRENT_TIME;
  661. }
  662. l->ln_t = CURRENT_TIME;
  663. l->ln_linktype = from.link_type;
  664. l->ln_flags |= flags;
  665. l->ln_cost = cost;
  666. l->ln_timeout = timeout;
  667. return rc;
  668. }
  669. int
  670. LinkCache::delLink(const ID& from, const ID& to)
  671. {
  672. Link *l;
  673. int rc = 0;
  674. if((l = findLink(from.addr, to.addr))) {
  675. LIST_REMOVE(l, ln_link);
  676. delete l;
  677. dirty = CURRENT_TIME;
  678. rc = 1;
  679. }
  680. if(lc_bidirectional_links == false)
  681. return rc;
  682. /*
  683.  * Remove the "other" direction of the link...
  684.  */
  685. if((l = findLink(to.addr, from.addr))) {
  686. LIST_REMOVE(l, ln_link);
  687. delete l;
  688. dirty = CURRENT_TIME;
  689. }
  690. return rc;
  691. }
  692. Link*
  693. LinkCache::findLink(int from, int to)
  694. {
  695. Link *l;
  696. for(l = lcache[from].lh_first; l; l = l->ln_link.le_next) {
  697. if(l->ln_dst == to) {
  698. return l;
  699. }
  700. }
  701. return 0;
  702. }
  703. void
  704. LinkCache::purgeLink()
  705. {
  706. int u;
  707. Link *l;
  708. for(u = 1; u <= LC_MAX_NODES; u++) {
  709. if(d[u] == INFINITY) {
  710. ID from, to;
  711. from.addr = u;
  712. from.type = ::IP;
  713. from.link_type = LT_NONE;
  714. from.log_stat = LS_NONE;
  715. l = lcache[u].lh_first;
  716. for( ; l; l = l->ln_link.le_next) {
  717. Link_to_ID(l, to);
  718. #ifdef DSR_CACHE_STATS
  719. checkLink_logall(from, to, ACTION_EVICT);
  720. #endif
  721. (void) delLink(from, to);
  722. }
  723. }
  724. }
  725. }
  726. void
  727. LinkCache::dumpLink()
  728. {
  729. Link *l;
  730. int i;
  731. static char tbuf[512];
  732. u_int32_t toff = 0;
  733. bzero(tbuf, sizeof(tbuf));
  734. sprintf(tbuf, "SRC %.9f _%s_ dump-link ", CURRENT_TIME, net_id.dump());
  735. toff = strlen(tbuf);
  736. for(i = 1; i <= LC_MAX_NODES; i++) {
  737. for(l = lcache[i].lh_first; l; l = l->ln_link.le_next) {
  738. sprintf(tbuf+toff, "%d->%d, ", i, l->ln_dst);
  739. toff = strlen(tbuf);
  740. assert(toff < sizeof(tbuf));
  741. }
  742. }
  743. trace("%s", tbuf);
  744. }
  745. #ifdef DSR_CACHE_STATS
  746. /*
  747.  * Called only from "purgeLink"
  748.  */
  749. void
  750. LinkCache::checkLink_logall(const ID& from, const ID& to, int action)
  751. {
  752. Link *l = findLink(from.addr, to.addr);
  753. assert(action == ACTION_EVICT);
  754. assert(l);
  755. if(God::instance()->hops(from.addr, to.addr) != 1) {
  756. trace("SRC %.9f _%s_ %s [%d %d] %s->%s dead %d %.9f",
  757.       CURRENT_TIME, net_id.dump(),
  758.       action_name[action], 0, 0,
  759.       from.dump(), to.dump(),
  760.       l->ln_linktype, l->ln_t);
  761. }
  762. }
  763. void
  764. LinkCache::checkLink(const ID& from, const ID& to, int action)
  765. {
  766. Link *l = findLink(from.addr, to.addr);
  767. int alive = 0;
  768. assert(l);
  769. if(God::instance()->hops(from.addr, to.addr) != 1) {
  770. if(l->ln_logstat == LS_UNLOGGED) {
  771. trace("SRC %.9f _%s_ %s [%d %d] %s->%s dead %d %.9f",
  772. CURRENT_TIME, net_id.dump(),
  773. action_name[action], 0, 0,
  774. from.dump(), to.dump(),
  775. l->ln_linktype, l->ln_t);
  776. l->ln_logstat = LS_LOGGED;
  777. }
  778. } else {
  779. alive = 1;
  780. if(l->ln_logstat == LS_LOGGED) {
  781. trace("SRC %.9f _%s_ resurrected-link [%d %d] %s->%s dead %d %.9f",
  782. CURRENT_TIME, net_id.dump(), 0, 0,
  783. from.dump(), to.dump(),
  784. l->ln_linktype, l->ln_t);
  785. l->ln_logstat = LS_UNLOGGED;
  786. }
  787.         }
  788. switch(action) {
  789. case ACTION_ADD_ROUTE:
  790. stat.link_add_count += 1;
  791. if(alive == 0){
  792.         stat.link_add_bad_count += 1;
  793. }
  794. if(l->ln_linktype == LT_TESTED)
  795. stat.link_add_tested += 1;
  796. break;
  797. case ACTION_NOTICE_ROUTE:
  798. stat.link_notice_count += 1;
  799. if(alive == 0){
  800. stat.link_notice_bad_count += 1;
  801. }
  802. if(l->ln_linktype == LT_TESTED)
  803. stat.link_notice_tested += 1;
  804. break;
  805. }
  806. }
  807. void
  808. LinkCache::periodic_checkCache()
  809. {
  810.   int c;
  811.   int link_count = 0;
  812.   int link_bad_count = 0;
  813.   double link_bad_time = 0.0;
  814.   int link_bad_tested = 0;
  815.   int link_good_tested = 0;
  816. #ifndef REALTIME_EXPIRE
  817.   if (ID(1,::IP) == net_id) 
  818.     trace("SRC %.9f _%s_ cache-expire-bits %d %d %d %d",
  819.   CURRENT_TIME, net_id.dump(), expirestats[0], expirestats[1], 
  820.   expirestats[2], expirestats[3]);
  821. #endif
  822.   for(c = 1; c <= LC_MAX_NODES; c++) {
  823. Link *v = lcache[c].lh_first;
  824. for( ; v; v = v->ln_link.le_next) {
  825. link_count += 1;
  826. if(God::instance()->hops(c, v->ln_dst) != 1) {
  827. link_bad_count += 1;
  828. link_bad_time += CURRENT_TIME - v->ln_t;
  829. if(v->ln_linktype == LT_TESTED)
  830. link_bad_tested += 1;
  831. } else {
  832. if(v->ln_linktype == LT_TESTED)
  833. link_good_tested += 1;
  834. }
  835. }
  836.   }
  837.   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",
  838. CURRENT_TIME, net_id.dump(),
  839.         0, //route_count,
  840.         0, // route_bad_count,
  841.         link_count, // subroute_count,
  842.         0, // subroute_bad_count,
  843.         link_bad_count,
  844.         link_bad_count ? link_bad_time/link_bad_count : 0.0,
  845.         link_bad_tested,
  846.         link_good_tested,
  847.         stat.route_add_count,     // always 0 -- not increment
  848.         stat.route_add_bad_count, // always 0 -- not increment
  849.         stat.link_add_count, // stat.subroute_add_count,
  850.         stat.link_add_bad_count, // stat.subroute_add_bad_count,
  851.         stat.link_add_tested,
  852.              
  853.         stat.route_notice_count,
  854.         stat.route_notice_bad_count,
  855.         stat.link_notice_count, // stat.subroute_notice_count,
  856.         stat.link_notice_bad_count, // stat.subroute_notice_bad_count,
  857.         stat.link_notice_tested,
  858.              
  859.         stat.route_find_count,
  860. stat.route_find_for_me,
  861.         stat.route_find_bad_count,
  862.         stat.route_find_miss_count,
  863.         stat.subroute_find_count,
  864.         stat.subroute_find_bad_count);
  865.   stat.reset();
  866. }
  867. #endif
  868. #endif //DSR_LINKCACHE