X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fgraph.c;h=5bec2c165762d121b0f47dc4ee68cb9341744b16;hb=7eeb29220a73ab9c5367f652873042f8a81c6cef;hp=a774eacc2ab86e62d9090826b4795daacad98ec3;hpb=f6e87ab476a0faf8b124ecaaa27f967d825e6457;p=tinc diff --git a/src/graph.c b/src/graph.c index a774eacc..5bec2c16 100644 --- a/src/graph.c +++ b/src/graph.c @@ -45,20 +45,17 @@ #include "system.h" #include "connection.h" -#include "device.h" #include "edge.h" #include "graph.h" #include "list.h" #include "logger.h" -#include "names.h" #include "netutl.h" #include "node.h" #include "protocol.h" #include "script.h" #include "subnet.h" -#include "utils.h" #include "xalloc.h" -#include "graph.h" +#include "address_cache.h" /* Implementation of Kruskal's algorithm. Running time: O(EN) @@ -68,7 +65,7 @@ static void mst_kruskal(void) { /* Clear MST status on connections */ - for list_each(connection_t, c, connection_list) { + for list_each(connection_t, c, &connection_list) { c->status.mst = false; } @@ -76,13 +73,13 @@ static void mst_kruskal(void) { /* Clear visited status on nodes */ - for splay_each(node_t, n, node_tree) { + for splay_each(node_t, n, &node_tree) { n->status.visited = false; } /* Starting point */ - for splay_each(edge_t, e, edge_weight_tree) { + for splay_each(edge_t, e, &edge_weight_tree) { if(e->from->status.reachable) { e->from->status.visited = true; break; @@ -93,7 +90,7 @@ static void mst_kruskal(void) { bool skipped = false; - for splay_each(edge_t, e, edge_weight_tree) { + for splay_each(edge_t, e, &edge_weight_tree) { if(!e->reverse || (e->from->status.visited == e->to->status.visited)) { skipped = true; continue; @@ -114,21 +111,23 @@ static void mst_kruskal(void) { if(skipped) { skipped = false; - next = edge_weight_tree->head; + next = edge_weight_tree.head; } } } +// Not putting it into header, the outside world doesn't need to know about it. +extern void sssp_bfs(void); + /* Implementation of a simple breadth-first search algorithm. Running time: O(E) */ - -static void sssp_bfs(void) { +void sssp_bfs(void) { list_t *todo_list = list_alloc(NULL); /* Clear visited status on nodes */ - for splay_each(node_t, n, node_tree) { + for splay_each(node_t, n, &node_tree) { n->status.visited = false; n->status.indirect = true; n->distance = -1; @@ -142,6 +141,7 @@ static void sssp_bfs(void) { myself->prevedge = NULL; myself->via = myself; myself->distance = 0; + myself->weighted_distance = 0; list_insert_head(todo_list, myself); /* Loop while todo_list is filled */ @@ -153,7 +153,7 @@ static void sssp_bfs(void) { abort(); } - for splay_each(edge_t, e, n->edge_tree) { /* "e" is the edge connected to "from" */ + for splay_each(edge_t, e, &n->edge_tree) { /* "e" is the edge connected to "from" */ if(!e->reverse || e->to == myself) { continue; } @@ -179,14 +179,15 @@ static void sssp_bfs(void) { if(e->to->status.visited && (!e->to->status.indirect || indirect) - && (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight)) { + && (e->to->distance != n->distance + 1 || e->to->weighted_distance <= n->weighted_distance + e->weight)) { continue; } // Only update nexthop if it doesn't increase the path length - if(!e->to->status.visited || (e->to->distance == n->distance + 1 && e->weight >= e->to->prevedge->weight)) { + if(!e->to->status.visited || (e->to->distance == n->distance + 1 && e->to->weighted_distance > n->weighted_distance + e->weight)) { e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop; + e->to->weighted_distance = n->weighted_distance + e->weight; } e->to->status.visited = true; @@ -217,7 +218,7 @@ static void check_reachability(void) { int became_reachable_count = 0; int became_unreachable_count = 0; - for splay_each(node_t, n, node_tree) { + for splay_each(node_t, n, &node_tree) { if(n->status.visited != n->status.reachable) { n->status.reachable = !n->status.reachable; n->last_state_change = now.tv_sec; @@ -228,6 +229,14 @@ static void check_reachability(void) { if(n != myself) { became_reachable_count++; + + if(n->connection && n->connection->outgoing) { + if(!n->address_cache) { + n->address_cache = open_address_cache(n); + } + + add_recent_address(n->address_cache, &n->connection->address); + } } } else { logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became unreachable", @@ -311,7 +320,7 @@ static void check_reachability(void) { } void graph(void) { - subnet_cache_flush(); + subnet_cache_flush_tables(); sssp_bfs(); check_reachability(); mst_kruskal();