diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-01-29 16:24:14 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-01-29 16:24:14 +0100 |
commit | f73216a9c9515d444213b6aa7701c5155f071c81 (patch) | |
tree | 82008c4d91d0ddf0f0a4424e6b41056550e03a8f /src/cadet | |
parent | 271dd457b4b7f42b9353fc94da231a9196ee714a (diff) | |
download | gnunet-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.in | 32 | ||||
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_core.c | 157 | ||||
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_peer.c | 1 |
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 | |||
11 | UNIX_MATCH_UID = YES | 11 | UNIX_MATCH_UID = YES |
12 | UNIX_MATCH_GID = YES | 12 | UNIX_MATCH_GID = YES |
13 | 13 | ||
14 | |||
15 | # How often do we send KEEPALIVE messages on connections to keep them | ||
16 | # from timing out? | ||
14 | REFRESH_CONNECTION_TIME = 5 min | 17 | REFRESH_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? | ||
15 | ID_ANNOUNCE_TIME = 1 h | 23 | ID_ANNOUNCE_TIME = 1 h |
24 | |||
25 | # FIXME: document | ||
16 | CONNECT_TIMEOUT = 30 s | 26 | CONNECT_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. | ||
17 | DHT_REPLICATION_LEVEL = 3 | 30 | DHT_REPLICATION_LEVEL = 3 |
18 | MAX_TUNNELS = 1000 | 31 | |
32 | # FIXME: not implemented | ||
33 | # MAX_TUNNELS = 1000 | ||
34 | |||
35 | # FIXME: not implemented, replaced by MAX_ROUTES in NEW CADET! | ||
19 | MAX_CONNECTIONS = 1000 | 36 | MAX_CONNECTIONS = 1000 |
37 | |||
38 | # How many routes do we participate in at most? Should be smaller | ||
39 | # than MAX_MSGS_QUEUE | ||
40 | MAX_ROUTES = 5000 | ||
41 | |||
42 | # FIXME: not implemented | ||
20 | MAX_MSGS_QUEUE = 10000 | 43 | MAX_MSGS_QUEUE = 10000 |
44 | |||
45 | # FIXME: not implemented | ||
21 | MAX_PEERS = 1000 | 46 | MAX_PEERS = 1000 |
47 | |||
48 | # How often do we advance the ratchet even if there is not | ||
49 | # any traffic? | ||
22 | RATCHET_TIME = 1 h | 50 | RATCHET_TIME = 1 h |
51 | |||
52 | # How often do we advance the ratched if there is traffic? | ||
23 | RATCHET_MESSAGES = 64 | 53 | RATCHET_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 | */ |
137 | static struct GNUNET_CONTAINER_MultiShortmap *routes; | 142 | static struct GNUNET_CONTAINER_MultiShortmap *routes; |
138 | 143 | ||
144 | /** | ||
145 | * Heap of routes, MIN-sorted by last activity. | ||
146 | */ | ||
147 | static struct GNUNET_CONTAINER_Heap *route_heap; | ||
148 | |||
149 | /** | ||
150 | * Maximum number of concurrent routes this peer will support. | ||
151 | */ | ||
152 | static unsigned long long max_routes; | ||
153 | |||
154 | /** | ||
155 | * Task to timeout routes. | ||
156 | */ | ||
157 | static 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 | */ | ||
375 | static void | ||
376 | timeout_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 | */ | ||
488 | static void | ||
489 | send_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 |