diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-03-07 19:35:26 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-03-07 19:35:26 +0000 |
commit | 5410702d6c31d4486766e111c6518d4c8814ddf3 (patch) | |
tree | 61f6e955454ce0f2ab5cf0ef33654b3ab44927c3 /src/fragmentation | |
parent | cd0ad4c559f9338eec2a152ded51d16e021eca06 (diff) | |
download | gnunet-5410702d6c31d4486766e111c6518d4c8814ddf3.tar.gz gnunet-5410702d6c31d4486766e111c6518d4c8814ddf3.zip |
trying to fix #3694: reduce duplicate ACKing
Diffstat (limited to 'src/fragmentation')
-rw-r--r-- | src/fragmentation/defragmentation.c | 49 | ||||
-rw-r--r-- | src/fragmentation/fragmentation.c | 56 |
2 files changed, 75 insertions, 30 deletions
diff --git a/src/fragmentation/defragmentation.c b/src/fragmentation/defragmentation.c index 3ef36dfdf..8470fe683 100644 --- a/src/fragmentation/defragmentation.c +++ b/src/fragmentation/defragmentation.c | |||
@@ -149,7 +149,7 @@ struct GNUNET_DEFRAGMENT_Context | |||
149 | struct MessageContext *tail; | 149 | struct MessageContext *tail; |
150 | 150 | ||
151 | /** | 151 | /** |
152 | * Closure for 'proc' and 'ackp'. | 152 | * Closure for @e proc and @e ackp. |
153 | */ | 153 | */ |
154 | void *cls; | 154 | void *cls; |
155 | 155 | ||
@@ -195,7 +195,7 @@ struct GNUNET_DEFRAGMENT_Context | |||
195 | * @param mtu the maximum message size for each fragment | 195 | * @param mtu the maximum message size for each fragment |
196 | * @param num_msgs how many fragmented messages | 196 | * @param num_msgs how many fragmented messages |
197 | * to we defragment at most at the same time? | 197 | * to we defragment at most at the same time? |
198 | * @param cls closure for proc and ackp | 198 | * @param cls closure for @a proc and @a ackp |
199 | * @param proc function to call with defragmented messages | 199 | * @param proc function to call with defragmented messages |
200 | * @param ackp function to call with acknowledgements (to send | 200 | * @param ackp function to call with acknowledgements (to send |
201 | * back to the other side) | 201 | * back to the other side) |
@@ -255,7 +255,8 @@ GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc) | |||
255 | * @param tc the scheduler context | 255 | * @param tc the scheduler context |
256 | */ | 256 | */ |
257 | static void | 257 | static void |
258 | send_ack (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 258 | send_ack (void *cls, |
259 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
259 | { | 260 | { |
260 | struct MessageContext *mc = cls; | 261 | struct MessageContext *mc = cls; |
261 | struct GNUNET_DEFRAGMENT_Context *dc = mc->dc; | 262 | struct GNUNET_DEFRAGMENT_Context *dc = mc->dc; |
@@ -267,9 +268,12 @@ send_ack (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
267 | fa.fragment_id = htonl (mc->fragment_id); | 268 | fa.fragment_id = htonl (mc->fragment_id); |
268 | fa.bits = GNUNET_htonll (mc->bits); | 269 | fa.bits = GNUNET_htonll (mc->bits); |
269 | GNUNET_STATISTICS_update (mc->dc->stats, | 270 | GNUNET_STATISTICS_update (mc->dc->stats, |
270 | _("# acknowledgements sent for fragment"), 1, | 271 | _("# acknowledgements sent for fragment"), |
272 | 1, | ||
271 | GNUNET_NO); | 273 | GNUNET_NO); |
272 | dc->ackp (dc->cls, mc->fragment_id, &fa.header); | 274 | dc->ackp (dc->cls, |
275 | mc->fragment_id, | ||
276 | &fa.header); | ||
273 | } | 277 | } |
274 | 278 | ||
275 | 279 | ||
@@ -402,7 +406,9 @@ discard_oldest_mc (struct GNUNET_DEFRAGMENT_Context *dc) | |||
402 | * | 406 | * |
403 | * @param dc the context | 407 | * @param dc the context |
404 | * @param msg the message that was received | 408 | * @param msg the message that was received |
405 | * @return GNUNET_OK on success, GNUNET_NO if this was a duplicate, GNUNET_SYSERR on error | 409 | * @return #GNUNET_OK on success, |
410 | * #GNUNET_NO if this was a duplicate, | ||
411 | * #GNUNET_SYSERR on error | ||
406 | */ | 412 | */ |
407 | int | 413 | int |
408 | GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | 414 | GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, |
@@ -453,7 +459,10 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
453 | GNUNET_break_op (0); | 459 | GNUNET_break_op (0); |
454 | return GNUNET_SYSERR; | 460 | return GNUNET_SYSERR; |
455 | } | 461 | } |
456 | GNUNET_STATISTICS_update (dc->stats, _("# fragments received"), 1, GNUNET_NO); | 462 | GNUNET_STATISTICS_update (dc->stats, |
463 | _("# fragments received"), | ||
464 | 1, | ||
465 | GNUNET_NO); | ||
457 | num_fragments = (ntohs (msg->size) + dc->mtu - sizeof (struct FragmentHeader)-1) / (dc->mtu - sizeof (struct FragmentHeader)); | 466 | num_fragments = (ntohs (msg->size) + dc->mtu - sizeof (struct FragmentHeader)-1) / (dc->mtu - sizeof (struct FragmentHeader)); |
458 | last = 0; | 467 | last = 0; |
459 | for (mc = dc->head; NULL != mc; mc = mc->next) | 468 | for (mc = dc->head; NULL != mc; mc = mc->next) |
@@ -495,7 +504,9 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
495 | mc->bits = (1LL << n) - 1; /* set lowest 'bits' bit */ | 504 | mc->bits = (1LL << n) - 1; /* set lowest 'bits' bit */ |
496 | if (dc->list_size >= dc->num_msgs) | 505 | if (dc->list_size >= dc->num_msgs) |
497 | discard_oldest_mc (dc); | 506 | discard_oldest_mc (dc); |
498 | GNUNET_CONTAINER_DLL_insert (dc->head, dc->tail, mc); | 507 | GNUNET_CONTAINER_DLL_insert (dc->head, |
508 | dc->tail, | ||
509 | mc); | ||
499 | dc->list_size++; | 510 | dc->list_size++; |
500 | } | 511 | } |
501 | 512 | ||
@@ -518,7 +529,9 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
518 | else | 529 | else |
519 | { | 530 | { |
520 | duplicate = GNUNET_YES; | 531 | duplicate = GNUNET_YES; |
521 | GNUNET_STATISTICS_update (dc->stats, _("# duplicate fragments received"), 1, | 532 | GNUNET_STATISTICS_update (dc->stats, |
533 | _("# duplicate fragments received"), | ||
534 | 1, | ||
522 | GNUNET_NO); | 535 | GNUNET_NO); |
523 | } | 536 | } |
524 | 537 | ||
@@ -529,9 +542,12 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
529 | bc++; | 542 | bc++; |
530 | 543 | ||
531 | /* notify about complete message */ | 544 | /* notify about complete message */ |
532 | if ((duplicate == GNUNET_NO) && (0 == mc->bits)) | 545 | if ( (duplicate == GNUNET_NO) && |
546 | (0 == mc->bits) ) | ||
533 | { | 547 | { |
534 | GNUNET_STATISTICS_update (dc->stats, _("# messages defragmented"), 1, | 548 | GNUNET_STATISTICS_update (dc->stats, |
549 | _("# messages defragmented"), | ||
550 | 1, | ||
535 | GNUNET_NO); | 551 | GNUNET_NO); |
536 | /* message complete, notify! */ | 552 | /* message complete, notify! */ |
537 | dc->proc (dc->cls, mc->msg); | 553 | dc->proc (dc->cls, mc->msg); |
@@ -541,10 +557,11 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
541 | { | 557 | { |
542 | dc->latency = estimate_latency (mc); | 558 | dc->latency = estimate_latency (mc); |
543 | } | 559 | } |
544 | delay = GNUNET_TIME_relative_multiply (dc->latency, bc + 1); | 560 | delay = GNUNET_TIME_relative_multiply (dc->latency, |
561 | bc + 1); | ||
545 | if ( (last + fid == num_fragments) || | 562 | if ( (last + fid == num_fragments) || |
546 | (0 == mc->bits) || | 563 | ( (0 == mc->bits) && |
547 | (GNUNET_YES == duplicate)) | 564 | (GNUNET_YES != duplicate)) ) |
548 | { | 565 | { |
549 | /* message complete or duplicate or last missing fragment in | 566 | /* message complete or duplicate or last missing fragment in |
550 | linear sequence; ACK now! */ | 567 | linear sequence; ACK now! */ |
@@ -552,7 +569,9 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
552 | } | 569 | } |
553 | if (NULL != mc->ack_task) | 570 | if (NULL != mc->ack_task) |
554 | GNUNET_SCHEDULER_cancel (mc->ack_task); | 571 | GNUNET_SCHEDULER_cancel (mc->ack_task); |
555 | mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay, &send_ack, mc); | 572 | mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay, |
573 | &send_ack, | ||
574 | mc); | ||
556 | if (duplicate == GNUNET_YES) | 575 | if (duplicate == GNUNET_YES) |
557 | return GNUNET_NO; | 576 | return GNUNET_NO; |
558 | return GNUNET_YES; | 577 | return GNUNET_YES; |
diff --git a/src/fragmentation/fragmentation.c b/src/fragmentation/fragmentation.c index 930fffcc6..ca5ca2ac9 100644 --- a/src/fragmentation/fragmentation.c +++ b/src/fragmentation/fragmentation.c | |||
@@ -80,7 +80,7 @@ struct GNUNET_FRAGMENT_Context | |||
80 | GNUNET_FRAGMENT_MessageProcessor proc; | 80 | GNUNET_FRAGMENT_MessageProcessor proc; |
81 | 81 | ||
82 | /** | 82 | /** |
83 | * Closure for 'proc'. | 83 | * Closure for @e proc. |
84 | */ | 84 | */ |
85 | void *proc_cls; | 85 | void *proc_cls; |
86 | 86 | ||
@@ -98,7 +98,7 @@ struct GNUNET_FRAGMENT_Context | |||
98 | /** | 98 | /** |
99 | * Task performing work for the fragmenter. | 99 | * Task performing work for the fragmenter. |
100 | */ | 100 | */ |
101 | struct GNUNET_SCHEDULER_Task * task; | 101 | struct GNUNET_SCHEDULER_Task *task; |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * Our fragmentation ID. (chosen at random) | 104 | * Our fragmentation ID. (chosen at random) |
@@ -121,12 +121,12 @@ struct GNUNET_FRAGMENT_Context | |||
121 | unsigned int num_transmissions; | 121 | unsigned int num_transmissions; |
122 | 122 | ||
123 | /** | 123 | /** |
124 | * GNUNET_YES if we called 'proc' and are now waiting for 'GNUNET_FRAGMENT_transmission_done' | 124 | * #GNUNET_YES if we called @e proc and are now waiting for #GNUNET_FRAGMENT_transmission_done() |
125 | */ | 125 | */ |
126 | int8_t proc_busy; | 126 | int8_t proc_busy; |
127 | 127 | ||
128 | /** | 128 | /** |
129 | * GNUNET_YES if we are waiting for an ACK. | 129 | * #GNUNET_YES if we are waiting for an ACK. |
130 | */ | 130 | */ |
131 | int8_t wack; | 131 | int8_t wack; |
132 | 132 | ||
@@ -139,13 +139,39 @@ struct GNUNET_FRAGMENT_Context | |||
139 | 139 | ||
140 | 140 | ||
141 | /** | 141 | /** |
142 | * Convert an ACK message to a printable format suitable for logging. | ||
143 | * | ||
144 | * @param ack message to print | ||
145 | * @return ack in human-readable format | ||
146 | */ | ||
147 | const char * | ||
148 | GNUNET_FRAGMENT_print_ack (const struct GNUNET_MessageHeader *ack) | ||
149 | { | ||
150 | static char buf[128]; | ||
151 | const struct FragmentAcknowledgement *fa; | ||
152 | |||
153 | if (sizeof (struct FragmentAcknowledgement) != | ||
154 | htons (ack->size)) | ||
155 | return "<malformed ack>"; | ||
156 | fa = (const struct FragmentAcknowledgement *) ack; | ||
157 | GNUNET_snprintf (buf, | ||
158 | sizeof (buf), | ||
159 | "%u-%llX", | ||
160 | ntohl (fa->fragment_id), | ||
161 | GNUNET_ntohll (fa->bits)); | ||
162 | return buf; | ||
163 | } | ||
164 | |||
165 | |||
166 | /** | ||
142 | * Transmit the next fragment to the other peer. | 167 | * Transmit the next fragment to the other peer. |
143 | * | 168 | * |
144 | * @param cls the 'struct GNUNET_FRAGMENT_Context' | 169 | * @param cls the `struct GNUNET_FRAGMENT_Context` |
145 | * @param tc scheduler context | 170 | * @param tc scheduler context |
146 | */ | 171 | */ |
147 | static void | 172 | static void |
148 | transmit_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 173 | transmit_next (void *cls, |
174 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
149 | { | 175 | { |
150 | struct GNUNET_FRAGMENT_Context *fc = cls; | 176 | struct GNUNET_FRAGMENT_Context *fc = cls; |
151 | char msg[fc->mtu]; | 177 | char msg[fc->mtu]; |
@@ -246,11 +272,11 @@ transmit_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
246 | 272 | ||
247 | /** | 273 | /** |
248 | * Create a fragmentation context for the given message. | 274 | * Create a fragmentation context for the given message. |
249 | * Fragments the message into fragments of size "mtu" or | 275 | * Fragments the message into fragments of size @a mtu or |
250 | * less. Calls 'proc' on each un-acknowledged fragment, | 276 | * less. Calls @a proc on each un-acknowledged fragment, |
251 | * using both the expected 'delay' between messages and | 277 | * using both the expected @a msg_delay between messages and |
252 | * acknowledgements and the given 'tracker' to guide the | 278 | * acknowledgements and the given @a tracker to guide the |
253 | * frequency of calls to 'proc'. | 279 | * frequency of calls to @a proc. |
254 | * | 280 | * |
255 | * @param stats statistics context | 281 | * @param stats statistics context |
256 | * @param mtu the maximum message size for each fragment | 282 | * @param mtu the maximum message size for each fragment |
@@ -261,7 +287,7 @@ transmit_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
261 | * and ACK based on previous messages | 287 | * and ACK based on previous messages |
262 | * @param msg the message to fragment | 288 | * @param msg the message to fragment |
263 | * @param proc function to call for each fragment to transmit | 289 | * @param proc function to call for each fragment to transmit |
264 | * @param proc_cls closure for proc | 290 | * @param proc_cls closure for @a proc |
265 | * @return the fragmentation context | 291 | * @return the fragmentation context |
266 | */ | 292 | */ |
267 | struct GNUNET_FRAGMENT_Context * | 293 | struct GNUNET_FRAGMENT_Context * |
@@ -336,10 +362,10 @@ GNUNET_FRAGMENT_context_transmission_done (struct GNUNET_FRAGMENT_Context *fc) | |||
336 | * | 362 | * |
337 | * @param fc fragmentation context | 363 | * @param fc fragmentation context |
338 | * @param msg acknowledgement message we received | 364 | * @param msg acknowledgement message we received |
339 | * @return GNUNET_OK if this ack completes the work of the 'fc' | 365 | * @return #GNUNET_OK if this ack completes the work of the 'fc' |
340 | * (all fragments have been received); | 366 | * (all fragments have been received); |
341 | * GNUNET_NO if more messages are pending | 367 | * #GNUNET_NO if more messages are pending |
342 | * GNUNET_SYSERR if this ack is not valid for this fc | 368 | * #GNUNET_SYSERR if this ack is not valid for this fc |
343 | */ | 369 | */ |
344 | int | 370 | int |
345 | GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, | 371 | GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, |