aboutsummaryrefslogtreecommitdiff
path: root/src/cadet
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-01-29 16:24:14 +0100
committerChristian Grothoff <christian@grothoff.org>2017-01-29 16:24:14 +0100
commitf73216a9c9515d444213b6aa7701c5155f071c81 (patch)
tree82008c4d91d0ddf0f0a4424e6b41056550e03a8f /src/cadet
parent271dd457b4b7f42b9353fc94da231a9196ee714a (diff)
downloadgnunet-f73216a9c9515d444213b6aa7701c5155f071c81.tar.gz
gnunet-f73216a9c9515d444213b6aa7701c5155f071c81.zip
implement route timeouts at 3x keepalive frequency
Diffstat (limited to 'src/cadet')
-rw-r--r--src/cadet/cadet.conf.in32
-rw-r--r--src/cadet/gnunet-service-cadet-new_core.c157
-rw-r--r--src/cadet/gnunet-service-cadet-new_peer.c1
3 files changed, 169 insertions, 21 deletions
diff --git a/src/cadet/cadet.conf.in b/src/cadet/cadet.conf.in
index a6d762786..86ba2e535 100644
--- a/src/cadet/cadet.conf.in
+++ b/src/cadet/cadet.conf.in
@@ -11,13 +11,43 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-cadet.sock
11UNIX_MATCH_UID = YES 11UNIX_MATCH_UID = YES
12UNIX_MATCH_GID = YES 12UNIX_MATCH_GID = YES
13 13
14
15# How often do we send KEEPALIVE messages on connections to keep them
16# from timing out?
14REFRESH_CONNECTION_TIME = 5 min 17REFRESH_CONNECTION_TIME = 5 min
18
19# Percentage of packets CADET is artificially dropping. Used for testing only!
20# DROP_PERCENT =
21
22# How frequently do we usually anounce our presence in the DHT?
15ID_ANNOUNCE_TIME = 1 h 23ID_ANNOUNCE_TIME = 1 h
24
25# FIXME: document
16CONNECT_TIMEOUT = 30 s 26CONNECT_TIMEOUT = 30 s
27
28# What is the replication level we give to the DHT when announcing our
29# existence? Usually there is no need to change this.
17DHT_REPLICATION_LEVEL = 3 30DHT_REPLICATION_LEVEL = 3
18MAX_TUNNELS = 1000 31
32# FIXME: not implemented
33# MAX_TUNNELS = 1000
34
35# FIXME: not implemented, replaced by MAX_ROUTES in NEW CADET!
19MAX_CONNECTIONS = 1000 36MAX_CONNECTIONS = 1000
37
38# How many routes do we participate in at most? Should be smaller
39# than MAX_MSGS_QUEUE
40MAX_ROUTES = 5000
41
42# FIXME: not implemented
20MAX_MSGS_QUEUE = 10000 43MAX_MSGS_QUEUE = 10000
44
45# FIXME: not implemented
21MAX_PEERS = 1000 46MAX_PEERS = 1000
47
48# How often do we advance the ratchet even if there is not
49# any traffic?
22RATCHET_TIME = 1 h 50RATCHET_TIME = 1 h
51
52# How often do we advance the ratched if there is traffic?
23RATCHET_MESSAGES = 64 53RATCHET_MESSAGES = 64
diff --git a/src/cadet/gnunet-service-cadet-new_core.c b/src/cadet/gnunet-service-cadet-new_core.c
index 956a1207d..25ffcb3ce 100644
--- a/src/cadet/gnunet-service-cadet-new_core.c
+++ b/src/cadet/gnunet-service-cadet-new_core.c
@@ -27,6 +27,7 @@
27 * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom)) 27 * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
28 * 28 *
29 * TODO: 29 * TODO:
30 * - properly implement GLOBAL message buffer, instead of per-route buffers
30 * - Optimization: given BROKEN messages, destroy paths (?) 31 * - Optimization: given BROKEN messages, destroy paths (?)
31 */ 32 */
32#include "platform.h" 33#include "platform.h"
@@ -123,6 +124,10 @@ struct CadetRoute
123 */ 124 */
124 struct GNUNET_TIME_Absolute last_use; 125 struct GNUNET_TIME_Absolute last_use;
125 126
127 /**
128 * Position of this route in the #route_heap.
129 */
130 struct GNUNET_CONTAINER_HeapNode *hn;
126}; 131};
127 132
128 133
@@ -136,6 +141,21 @@ static struct GNUNET_CORE_Handle *core;
136 */ 141 */
137static struct GNUNET_CONTAINER_MultiShortmap *routes; 142static struct GNUNET_CONTAINER_MultiShortmap *routes;
138 143
144/**
145 * Heap of routes, MIN-sorted by last activity.
146 */
147static struct GNUNET_CONTAINER_Heap *route_heap;
148
149/**
150 * Maximum number of concurrent routes this peer will support.
151 */
152static unsigned long long max_routes;
153
154/**
155 * Task to timeout routes.
156 */
157static struct GNUNET_SCHEDULER_Task *timeout_task;
158
139 159
140/** 160/**
141 * Get the route corresponding to a hash. 161 * Get the route corresponding to a hash.
@@ -187,6 +207,9 @@ route_message (struct CadetPeer *prev,
187 env); 207 env);
188 return; 208 return;
189 } 209 }
210 route->last_use = GNUNET_TIME_absolute_get ();
211 GNUNET_CONTAINER_heap_update_cost (route->hn,
212 route->last_use.abs_value_us);
190 dir = (prev == route->prev.hop) ? &route->next : &route->prev; 213 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
191 if (GNUNET_YES == dir->is_ready) 214 if (GNUNET_YES == dir->is_ready)
192 { 215 {
@@ -294,6 +317,8 @@ destroy_route (struct CadetRoute *route)
294 GNUNET_i2s (GCP_get_id (route->prev.hop)), 317 GNUNET_i2s (GCP_get_id (route->prev.hop)),
295 GNUNET_i2s2 (GCP_get_id (route->next.hop)), 318 GNUNET_i2s2 (GCP_get_id (route->next.hop)),
296 GNUNET_sh2s (&route->cid.connection_of_tunnel)); 319 GNUNET_sh2s (&route->cid.connection_of_tunnel));
320 GNUNET_assert (route ==
321 GNUNET_CONTAINER_heap_remove_node (route->hn));
297 destroy_direction (&route->prev); 322 destroy_direction (&route->prev);
298 destroy_direction (&route->next); 323 destroy_direction (&route->next);
299 GNUNET_free (route); 324 GNUNET_free (route);
@@ -341,6 +366,49 @@ send_broken (struct RouteDirection *target,
341 366
342 367
343/** 368/**
369 * Function called to check if any routes have timed out, and if
370 * so, to clean them up. Finally, schedules itself again at the
371 * earliest time where there might be more work.
372 *
373 * @param cls NULL
374 */
375static void
376timeout_cb (void *cls)
377{
378 struct CadetRoute *r;
379 struct GNUNET_TIME_Relative linger;
380 struct GNUNET_TIME_Absolute exp;
381
382 timeout_task = NULL;
383 linger = GNUNET_TIME_relative_multiply (keepalive_period,
384 3);
385 while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
386 {
387 exp = GNUNET_TIME_absolute_add (r->last_use,
388 linger);
389 if (0 != GNUNET_TIME_absolute_get_duration (exp).rel_value_us)
390 {
391 /* Route not yet timed out, wait until it does. */
392 timeout_task = GNUNET_SCHEDULER_add_at (exp,
393 &timeout_cb,
394 NULL);
395 return;
396 }
397 send_broken (&r->prev,
398 &r->cid,
399 NULL,
400 NULL);
401 send_broken (&r->next,
402 &r->cid,
403 NULL,
404 NULL);
405 destroy_route (r);
406 }
407 /* No more routes left, so no need for a #timeout_task */
408}
409
410
411/**
344 * Function called when the message queue to the previous hop 412 * Function called when the message queue to the previous hop
345 * becomes available/unavailable. We expect this function to 413 * becomes available/unavailable. We expect this function to
346 * be called immediately when we register, and then again 414 * be called immediately when we register, and then again
@@ -408,6 +476,35 @@ dir_init (struct RouteDirection *dir,
408 476
409 477
410/** 478/**
479 * We could not create the desired route. Send a
480 * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
481 * message to @a target.
482 *
483 * @param target who should receive the message
484 * @param cid identifier of the connection/route that failed
485 * @param failure_at neighbour with which we failed to route,
486 * or NULL.
487 */
488static void
489send_broken_without_mqm (struct CadetPeer *target,
490 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
491 const struct GNUNET_PeerIdentity *failure_at)
492{
493 struct GNUNET_MQ_Envelope *env;
494 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
495
496 env = GNUNET_MQ_msg (bm,
497 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
498 bm->cid = *cid;
499 bm->peer1 = my_full_id;
500 if (NULL != failure_at)
501 bm->peer2 = *failure_at;
502 GCP_send_ooo (target,
503 env);
504}
505
506
507/**
411 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE 508 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
412 * 509 *
413 * @param cls Closure (CadetPeer for neighbor that sent the message). 510 * @param cls Closure (CadetPeer for neighbor that sent the message).
@@ -492,20 +589,14 @@ handle_connection_create (void *cls,
492 { 589 {
493 /* Send back BROKEN: duplicate connection on the same path, 590 /* Send back BROKEN: duplicate connection on the same path,
494 we will use the other one. */ 591 we will use the other one. */
495 struct GNUNET_MQ_Envelope *env;
496 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
497
498 LOG (GNUNET_ERROR_TYPE_DEBUG, 592 LOG (GNUNET_ERROR_TYPE_DEBUG,
499 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n", 593 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
500 GCP_2s (sender), 594 GCP_2s (sender),
501 GNUNET_sh2s (&msg->cid.connection_of_tunnel), 595 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
502 GCPP_2s (path)); 596 GCPP_2s (path));
503 env = GNUNET_MQ_msg (bm, 597 send_broken_without_mqm (sender,
504 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); 598 &msg->cid,
505 bm->cid = msg->cid; 599 NULL);
506 bm->peer1 = my_full_id;
507 GCP_send_ooo (sender,
508 env);
509 return; 600 return;
510 } 601 }
511 return; 602 return;
@@ -517,22 +608,26 @@ handle_connection_create (void *cls,
517 (GNUNET_NO == GCP_has_core_connection (next)) ) 608 (GNUNET_NO == GCP_has_core_connection (next)) )
518 { 609 {
519 /* unworkable, send back BROKEN notification */ 610 /* unworkable, send back BROKEN notification */
520 struct GNUNET_MQ_Envelope *env;
521 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
522
523 LOG (GNUNET_ERROR_TYPE_DEBUG, 611 LOG (GNUNET_ERROR_TYPE_DEBUG,
524 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n", 612 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
525 GCP_2s (sender), 613 GCP_2s (sender),
526 GNUNET_sh2s (&msg->cid.connection_of_tunnel), 614 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
527 GNUNET_i2s (&pids[off + 1]), 615 GNUNET_i2s (&pids[off + 1]),
528 off + 1); 616 off + 1);
529 env = GNUNET_MQ_msg (bm, 617 send_broken_without_mqm (sender,
530 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); 618 &msg->cid,
531 bm->cid = msg->cid; 619 &pids[off + 1]);
532 bm->peer1 = pids[off + 1]; 620 return;
533 bm->peer2 = my_full_id; 621 }
534 GCP_send_ooo (sender, 622 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
535 env); 623 {
624 LOG (GNUNET_ERROR_TYPE_DEBUG,
625 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
626 GCP_2s (sender),
627 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
628 send_broken_without_mqm (sender,
629 &msg->cid,
630 &pids[off - 1]);
536 return; 631 return;
537 } 632 }
538 633
@@ -545,6 +640,7 @@ handle_connection_create (void *cls,
545 off + 1); 640 off + 1);
546 route = GNUNET_new (struct CadetRoute); 641 route = GNUNET_new (struct CadetRoute);
547 route->cid = msg->cid; 642 route->cid = msg->cid;
643 route->last_use = GNUNET_TIME_absolute_get ();
548 dir_init (&route->prev, 644 dir_init (&route->prev,
549 route, 645 route,
550 sender); 646 sender);
@@ -556,6 +652,14 @@ handle_connection_create (void *cls,
556 &route->cid.connection_of_tunnel, 652 &route->cid.connection_of_tunnel,
557 route, 653 route,
558 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 654 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
655 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
656 route,
657 route->last_use.abs_value_us);
658 if (NULL == timeout_task)
659 timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (keepalive_period,
660 3),
661 &timeout_cb,
662 NULL);
559} 663}
560 664
561 665
@@ -953,8 +1057,15 @@ GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
953 GNUNET_MQ_handler_end () 1057 GNUNET_MQ_handler_end ()
954 }; 1058 };
955 1059
1060 if (GNUNET_OK !=
1061 GNUNET_CONFIGURATION_get_value_number (c,
1062 "CADET",
1063 "MAX_ROUTES",
1064 &max_routes))
1065 max_routes = 10000;
956 routes = GNUNET_CONTAINER_multishortmap_create (1024, 1066 routes = GNUNET_CONTAINER_multishortmap_create (1024,
957 GNUNET_NO); 1067 GNUNET_NO);
1068 route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
958 core = GNUNET_CORE_connect (c, 1069 core = GNUNET_CORE_connect (c,
959 NULL, 1070 NULL,
960 &core_init_cb, 1071 &core_init_cb,
@@ -977,6 +1088,14 @@ GCO_shutdown ()
977 } 1088 }
978 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes)); 1089 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
979 GNUNET_CONTAINER_multishortmap_destroy (routes); 1090 GNUNET_CONTAINER_multishortmap_destroy (routes);
1091 routes = NULL;
1092 GNUNET_CONTAINER_heap_destroy (route_heap);
1093 route_heap = NULL;
1094 if (NULL != timeout_task)
1095 {
1096 GNUNET_SCHEDULER_cancel (timeout_task);
1097 timeout_task = NULL;
1098 }
980} 1099}
981 1100
982/* end of gnunet-cadet-service_core.c */ 1101/* end of gnunet-cadet-service_core.c */
diff --git a/src/cadet/gnunet-service-cadet-new_peer.c b/src/cadet/gnunet-service-cadet-new_peer.c
index 180fdab54..97bb1378e 100644
--- a/src/cadet/gnunet-service-cadet-new_peer.c
+++ b/src/cadet/gnunet-service-cadet-new_peer.c
@@ -25,7 +25,6 @@
25 * @author Christian Grothoff 25 * @author Christian Grothoff
26 * 26 *
27 * TODO: 27 * TODO:
28 * - timeout for routes
29 * - optimize stopping/restarting DHT search to situations 28 * - optimize stopping/restarting DHT search to situations
30 * where we actually need it (i.e. not if we have a direct connection, 29 * where we actually need it (i.e. not if we have a direct connection,
31 * or if we already have plenty of good short ones, or maybe even 30 * or if we already have plenty of good short ones, or maybe even