aboutsummaryrefslogtreecommitdiff
path: root/src/mesh/gnunet-service-mesh.c
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2013-07-11 14:30:44 +0000
committerBart Polot <bart@net.in.tum.de>2013-07-11 14:30:44 +0000
commit1645fa570bf1b3835616eaebf6c45e18626f4a5d (patch)
tree003588c8d78f384e4e12fcc53ebaae802eff5cd4 /src/mesh/gnunet-service-mesh.c
parentae54e92bc769931e94cf036b414e856376f4dda7 (diff)
downloadgnunet-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.c235
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 */
290struct MeshSentMessage 290struct 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 */
320struct 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 */
2290static void 2318static void
2291tunnel_retransmit_message (void *cls, 2319tunnel_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 *) &copy[1]; 2337 payload = (struct GNUNET_MESH_Data *) &copy[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 *) &copy[1]; 4772 payload = (struct GNUNET_MESH_Data *) &copy[1];
4708 } 4773 }