diff options
author | Bart Polot <bart@net.in.tum.de> | 2013-07-11 14:30:44 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2013-07-11 14:30:44 +0000 |
commit | 1645fa570bf1b3835616eaebf6c45e18626f4a5d (patch) | |
tree | 003588c8d78f384e4e12fcc53ebaae802eff5cd4 /src/mesh/gnunet-service-mesh.c | |
parent | ae54e92bc769931e94cf036b414e856376f4dda7 (diff) | |
download | gnunet-1645fa570bf1b3835616eaebf6c45e18626f4a5d.tar.gz gnunet-1645fa570bf1b3835616eaebf6c45e18626f4a5d.zip |
Finishing mesh reliable:
- per-tunnel retransmission, always retransmit oldest not-ACK'd message
- adaptive retransmission delay
-- start with 1s
-- use per-message timing to update expected delay on each ACK as d = avg (d, new)
-- update pending retransmissions with new values
Diffstat (limited to 'src/mesh/gnunet-service-mesh.c')
-rw-r--r-- | src/mesh/gnunet-service-mesh.c | 235 |
1 files changed, 150 insertions, 85 deletions
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index e61b978f0..dfb018b45 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c | |||
@@ -287,42 +287,72 @@ struct MESH_TunnelID | |||
287 | /** | 287 | /** |
288 | * Info needed to retry a message in case it gets lost. | 288 | * Info needed to retry a message in case it gets lost. |
289 | */ | 289 | */ |
290 | struct MeshSentMessage | 290 | struct MeshReliableMessage |
291 | { | 291 | { |
292 | /** | 292 | /** |
293 | * Double linked list, FIFO style | 293 | * Double linked list, FIFO style |
294 | */ | 294 | */ |
295 | struct MeshSentMessage *next; | 295 | struct MeshReliableMessage *next; |
296 | struct MeshSentMessage *prev; | 296 | struct MeshReliableMessage *prev; |
297 | 297 | ||
298 | /** | 298 | /** |
299 | * Tunnel this message is in. | 299 | * Tunnel Reliability queue this message is in. |
300 | */ | 300 | */ |
301 | struct MeshTunnel *t; | 301 | struct MeshTunnelReliability *rel; |
302 | 302 | ||
303 | /** | 303 | /** |
304 | * ID of the message (ACK needed to free) | 304 | * ID of the message (ACK needed to free) |
305 | */ | 305 | */ |
306 | uint32_t id; | 306 | uint32_t id; |
307 | 307 | ||
308 | /** | 308 | /** |
309 | * Task to resend/poll in case no ACK is received. | 309 | * When was this message issued (to calculate ACK delay) FIXME update with traffic |
310 | */ | 310 | */ |
311 | GNUNET_SCHEDULER_TaskIdentifier retry_task; // FIXME move to per tunnel timer? | 311 | struct GNUNET_TIME_Absolute timestamp; |
312 | 312 | ||
313 | /** | 313 | /* struct GNUNET_MESH_Data with payload */ |
314 | * Counter for exponential backoff. | 314 | }; |
315 | */ | ||
316 | struct GNUNET_TIME_Relative retry_timer; | ||
317 | 315 | ||
318 | /** | ||
319 | * Is this a forward or backward going message? | ||
320 | */ | ||
321 | int is_forward; | ||
322 | 316 | ||
323 | /* struct GNUNET_MESH_Data with payload */ | 317 | /** |
318 | * Data needed for reliable tunnel endpoint retransmission management. | ||
319 | */ | ||
320 | struct MeshTunnelReliability | ||
321 | { | ||
322 | /** | ||
323 | * Tunnel this is about. | ||
324 | */ | ||
325 | struct MeshTunnel *t; | ||
326 | |||
327 | /** | ||
328 | * DLL of messages sent and not yet ACK'd. | ||
329 | */ | ||
330 | struct MeshReliableMessage *head_sent; | ||
331 | struct MeshReliableMessage *tail_sent; | ||
332 | |||
333 | /** | ||
334 | * DLL of messages received out of order. | ||
335 | */ | ||
336 | struct MeshReliableMessage *head_recv; | ||
337 | struct MeshReliableMessage *tail_recv; | ||
338 | |||
339 | /** | ||
340 | * Task to resend/poll in case no ACK is received. | ||
341 | */ | ||
342 | GNUNET_SCHEDULER_TaskIdentifier retry_task; | ||
343 | |||
344 | /** | ||
345 | * Counter for exponential backoff. | ||
346 | */ | ||
347 | struct GNUNET_TIME_Relative retry_timer; | ||
348 | |||
349 | /** | ||
350 | * How long does it usually take to get an ACK. FIXME update with traffic | ||
351 | */ | ||
352 | struct GNUNET_TIME_Relative expected_delay; | ||
324 | }; | 353 | }; |
325 | 354 | ||
355 | |||
326 | /** | 356 | /** |
327 | * Struct containing all information regarding a tunnel | 357 | * Struct containing all information regarding a tunnel |
328 | * For an intermediate node the improtant info used will be: | 358 | * For an intermediate node the improtant info used will be: |
@@ -442,19 +472,17 @@ struct MeshTunnel | |||
442 | */ | 472 | */ |
443 | unsigned int pending_messages; | 473 | unsigned int pending_messages; |
444 | 474 | ||
445 | /** | 475 | /** |
446 | * Messages sent and not yet ACK'd. | 476 | * Reliability data. |
447 | * Only present (non-NULL) at the owner of a tunnel. | 477 | * Only present (non-NULL) at the owner of a tunnel. |
448 | */ | 478 | */ |
449 | struct MeshSentMessage *fwd_head; | 479 | struct MeshTunnelReliability *fwd_rel; |
450 | struct MeshSentMessage *fwd_tail; | ||
451 | 480 | ||
452 | /** | 481 | /** |
453 | * Messages sent and not yet ACK'd. | 482 | * Reliability data. |
454 | * Only present (non-NULL) at the destination of a tunnel. | 483 | * Only present (non-NULL) at the destination of a tunnel. |
455 | */ | 484 | */ |
456 | struct MeshSentMessage *bck_head; | 485 | struct MeshTunnelReliability *bck_rel; |
457 | struct MeshSentMessage *bck_tail; | ||
458 | }; | 486 | }; |
459 | 487 | ||
460 | 488 | ||
@@ -2284,29 +2312,34 @@ tunnel_send_client_to_orig (struct MeshTunnel *t, | |||
2284 | /** | 2312 | /** |
2285 | * We haven't received an ACK after a certain time: restransmit the message. | 2313 | * We haven't received an ACK after a certain time: restransmit the message. |
2286 | * | 2314 | * |
2287 | * @param cls Closure (MeshSentMessage with the message to restransmit) | 2315 | * @param cls Closure (MeshReliableMessage with the message to restransmit) |
2288 | * @param tc TaskContext. | 2316 | * @param tc TaskContext. |
2289 | */ | 2317 | */ |
2290 | static void | 2318 | static void |
2291 | tunnel_retransmit_message (void *cls, | 2319 | tunnel_retransmit_message (void *cls, |
2292 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 2320 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
2293 | { | 2321 | { |
2294 | struct MeshSentMessage *copy = cls; | 2322 | struct MeshTunnelReliability *rel = cls; |
2323 | struct MeshReliableMessage *copy; | ||
2324 | struct MeshTunnel *t; | ||
2295 | struct GNUNET_MESH_Data *payload; | 2325 | struct GNUNET_MESH_Data *payload; |
2296 | GNUNET_PEER_Id hop; | 2326 | GNUNET_PEER_Id hop; |
2297 | 2327 | ||
2298 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! Retransmit \n"); | 2328 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; |
2299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! id %u\n", copy->id); | ||
2300 | copy->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
2301 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 2329 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
2302 | return; | 2330 | return; |
2303 | 2331 | ||
2332 | t = rel->t; | ||
2333 | copy = rel->head_sent; | ||
2334 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! Retransmit \n"); | ||
2335 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! id %u\n", copy->id); | ||
2336 | |||
2304 | payload = (struct GNUNET_MESH_Data *) ©[1]; | 2337 | payload = (struct GNUNET_MESH_Data *) ©[1]; |
2305 | hop = copy->is_forward ? copy->t->next_hop : copy->t->prev_hop; | 2338 | hop = rel == t->fwd_rel ? t->next_hop : t->prev_hop; |
2306 | send_prebuilt_message (&payload->header, hop, copy->t); | 2339 | send_prebuilt_message (&payload->header, hop, t); |
2307 | GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO); | 2340 | GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO); |
2308 | copy->retry_timer = GNUNET_TIME_STD_BACKOFF (copy->retry_timer); | 2341 | rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer); // FIXME adapt |
2309 | copy->retry_task = GNUNET_SCHEDULER_add_delayed (copy->retry_timer, | 2342 | rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer, |
2310 | &tunnel_retransmit_message, | 2343 | &tunnel_retransmit_message, |
2311 | cls); | 2344 | cls); |
2312 | } | 2345 | } |
@@ -3428,7 +3461,12 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
3428 | next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; | 3461 | next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; |
3429 | 3462 | ||
3430 | if (GNUNET_YES == t->reliable) | 3463 | if (GNUNET_YES == t->reliable) |
3464 | { | ||
3431 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n"); | 3465 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n"); |
3466 | t->bck_rel = GNUNET_malloc (sizeof (struct MeshTunnelReliability)); | ||
3467 | t->bck_rel->t = t; | ||
3468 | t->bck_rel->expected_delay = MESH_RETRANSMIT_TIME; | ||
3469 | } | ||
3432 | 3470 | ||
3433 | tunnel_add_client (t, c); | 3471 | tunnel_add_client (t, c); |
3434 | send_client_tunnel_create (t); | 3472 | send_client_tunnel_create (t); |
@@ -3883,13 +3921,14 @@ handle_mesh_data_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
3883 | const struct GNUNET_MessageHeader *message) | 3921 | const struct GNUNET_MessageHeader *message) |
3884 | { | 3922 | { |
3885 | struct GNUNET_MESH_DataACK *msg; | 3923 | struct GNUNET_MESH_DataACK *msg; |
3886 | struct MeshSentMessage *copy; | 3924 | struct MeshTunnelReliability *rel; |
3887 | struct MeshSentMessage *next; | 3925 | struct MeshReliableMessage *copy; |
3888 | struct MeshSentMessage *head; | 3926 | struct MeshReliableMessage *next; |
3889 | struct MeshTunnel *t; | 3927 | struct MeshTunnel *t; |
3890 | GNUNET_PEER_Id id; | 3928 | GNUNET_PEER_Id id; |
3891 | uint32_t ack; | 3929 | uint32_t ack; |
3892 | uint16_t type; | 3930 | uint16_t type; |
3931 | int work; | ||
3893 | 3932 | ||
3894 | type = ntohs (message->type); | 3933 | type = ntohs (message->type); |
3895 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a %s message from %s!\n", | 3934 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a %s message from %s!\n", |
@@ -3916,7 +3955,7 @@ handle_mesh_data_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
3916 | send_prebuilt_message (message, t->prev_hop, t); | 3955 | send_prebuilt_message (message, t->prev_hop, t); |
3917 | return GNUNET_OK; | 3956 | return GNUNET_OK; |
3918 | } | 3957 | } |
3919 | head = t->fwd_head; | 3958 | rel = t->fwd_rel; |
3920 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST); | 3959 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST); |
3921 | } | 3960 | } |
3922 | else if (t->prev_hop == id && GNUNET_MESSAGE_TYPE_MESH_TO_ORIG_ACK == type) | 3961 | else if (t->prev_hop == id && GNUNET_MESSAGE_TYPE_MESH_TO_ORIG_ACK == type) |
@@ -3927,41 +3966,64 @@ handle_mesh_data_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
3927 | send_prebuilt_message (message, t->next_hop, t); | 3966 | send_prebuilt_message (message, t->next_hop, t); |
3928 | return GNUNET_OK; | 3967 | return GNUNET_OK; |
3929 | } | 3968 | } |
3930 | head = t->bck_head; | 3969 | rel = t->bck_rel; |
3931 | tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); | 3970 | tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); |
3932 | } | 3971 | } |
3933 | else | 3972 | else |
3934 | { | 3973 | { |
3935 | GNUNET_break_op (0); | 3974 | GNUNET_break_op (0); |
3936 | head = NULL; | 3975 | return GNUNET_OK; |
3937 | } | 3976 | } |
3938 | 3977 | ||
3939 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! ACK \n"); | 3978 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! ACK \n"); |
3940 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! ack %u\n", ack); | 3979 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! ack %u\n", ack); |
3941 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! head %p\n", head); | 3980 | for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next) |
3942 | for (copy = head; copy != NULL; copy = next) | ||
3943 | { | 3981 | { |
3982 | struct GNUNET_TIME_Relative time; | ||
3983 | |||
3944 | if (copy->id > ack) | 3984 | if (copy->id > ack) |
3945 | { | 3985 | { |
3946 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! head is %u, out!\n", copy->id); | 3986 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! head %u, out!\n", copy->id); |
3947 | return GNUNET_OK; | 3987 | return GNUNET_OK; |
3948 | } | 3988 | } |
3949 | 3989 | work = GNUNET_YES; | |
3950 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! id %u\n", copy->id); | 3990 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! id %u\n", copy->id); |
3991 | GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy); | ||
3951 | next = copy->next; | 3992 | next = copy->next; |
3952 | 3993 | GNUNET_free (copy); | |
3953 | /* This CANNOT use the variable 'head', as the macro must modify 't'*/ | 3994 | time = GNUNET_TIME_absolute_get_duration (copy->timestamp); |
3954 | if (GNUNET_MESSAGE_TYPE_MESH_UNICAST_ACK == type) | 3995 | rel->expected_delay.rel_value += time.rel_value; |
3955 | GNUNET_CONTAINER_DLL_remove (t->fwd_head, t->fwd_tail, copy); | 3996 | rel->expected_delay.rel_value /= 2; |
3956 | else | 3997 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! new expected delay %s!\n", |
3957 | GNUNET_CONTAINER_DLL_remove (t->bck_head, t->bck_tail, copy); | 3998 | GNUNET_STRINGS_relative_time_to_string (rel->expected_delay, |
3958 | 3999 | GNUNET_NO)); | |
3959 | if (GNUNET_SCHEDULER_NO_TASK != copy->retry_task) | 4000 | rel->retry_timer = rel->expected_delay; |
3960 | GNUNET_SCHEDULER_cancel (copy->retry_task); | 4001 | } |
4002 | if (GNUNET_YES == work) | ||
4003 | { | ||
4004 | if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task) | ||
4005 | { | ||
4006 | GNUNET_SCHEDULER_cancel (rel->retry_task); | ||
4007 | if (NULL == rel->head_sent) | ||
4008 | { | ||
4009 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
4010 | } | ||
4011 | else | ||
4012 | { | ||
4013 | struct GNUNET_TIME_Absolute new_target; | ||
4014 | struct GNUNET_TIME_Relative delay; | ||
4015 | |||
4016 | new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp, | ||
4017 | rel->retry_timer); | ||
4018 | delay = GNUNET_TIME_absolute_get_remaining (new_target); | ||
4019 | rel->retry_task = | ||
4020 | GNUNET_SCHEDULER_add_delayed (delay, | ||
4021 | &tunnel_retransmit_message, | ||
4022 | rel); | ||
4023 | } | ||
4024 | } | ||
3961 | else | 4025 | else |
3962 | GNUNET_break (0); | 4026 | GNUNET_break (0); |
3963 | |||
3964 | GNUNET_free (copy); | ||
3965 | } | 4027 | } |
3966 | return GNUNET_OK; | 4028 | return GNUNET_OK; |
3967 | } | 4029 | } |
@@ -4520,7 +4582,12 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, | |||
4520 | t->port = ntohl (t_msg->port); | 4582 | t->port = ntohl (t_msg->port); |
4521 | tunnel_set_options (t, ntohl (t_msg->options)); | 4583 | tunnel_set_options (t, ntohl (t_msg->options)); |
4522 | if (GNUNET_YES == t->reliable) | 4584 | if (GNUNET_YES == t->reliable) |
4585 | { | ||
4523 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n"); | 4586 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n"); |
4587 | t->fwd_rel = GNUNET_malloc (sizeof (struct MeshTunnelReliability)); | ||
4588 | t->fwd_rel->t = t; | ||
4589 | t->fwd_rel->expected_delay = MESH_RETRANSMIT_TIME; | ||
4590 | } | ||
4524 | 4591 | ||
4525 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s[%x]:%u (%x)\n", | 4592 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s[%x]:%u (%x)\n", |
4526 | GNUNET_i2s (&my_full_id), t->id.tid, t->port, t->local_tid); | 4593 | GNUNET_i2s (&my_full_id), t->id.tid, t->port, t->local_tid); |
@@ -4683,26 +4750,24 @@ handle_local_data (void *cls, struct GNUNET_SERVER_Client *client, | |||
4683 | fc = tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV ? &t->prev_fc : &t->next_fc; | 4750 | fc = tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV ? &t->prev_fc : &t->next_fc; |
4684 | if (GNUNET_YES == t->reliable) | 4751 | if (GNUNET_YES == t->reliable) |
4685 | { | 4752 | { |
4686 | struct MeshSentMessage *copy; | 4753 | struct MeshTunnelReliability *rel; |
4754 | struct MeshReliableMessage *copy; | ||
4687 | 4755 | ||
4688 | copy = GNUNET_malloc (sizeof (struct MeshSentMessage) | 4756 | copy = GNUNET_malloc (sizeof (struct MeshReliableMessage) |
4689 | + sizeof(struct GNUNET_MESH_Data) | 4757 | + sizeof(struct GNUNET_MESH_Data) |
4690 | + size); | 4758 | + size); |
4691 | copy->t = t; | ||
4692 | copy->id = fc->last_pid_recv + 1; | 4759 | copy->id = fc->last_pid_recv + 1; |
4693 | copy->is_forward = (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV); | 4760 | copy->timestamp = GNUNET_TIME_absolute_get (); |
4694 | copy->retry_timer = MESH_RETRANSMIT_TIME; | 4761 | rel = (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) ? t->fwd_rel : t->bck_rel; |
4695 | copy->retry_task = | 4762 | copy->rel = rel; |
4696 | GNUNET_SCHEDULER_add_delayed (copy->retry_timer, | 4763 | GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy); |
4697 | &tunnel_retransmit_message, | 4764 | if (GNUNET_SCHEDULER_NO_TASK == rel->retry_task) |
4698 | copy); | ||
4699 | if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) | ||
4700 | { | ||
4701 | GNUNET_CONTAINER_DLL_insert_tail (t->fwd_head, t->fwd_tail, copy); | ||
4702 | } | ||
4703 | else | ||
4704 | { | 4765 | { |
4705 | GNUNET_CONTAINER_DLL_insert_tail (t->bck_head, t->bck_tail, copy); | 4766 | rel->retry_timer = rel->expected_delay; |
4767 | rel->retry_task = | ||
4768 | GNUNET_SCHEDULER_add_delayed (rel->retry_timer, | ||
4769 | &tunnel_retransmit_message, | ||
4770 | rel); | ||
4706 | } | 4771 | } |
4707 | payload = (struct GNUNET_MESH_Data *) ©[1]; | 4772 | payload = (struct GNUNET_MESH_Data *) ©[1]; |
4708 | } | 4773 | } |