aboutsummaryrefslogtreecommitdiff
path: root/src/fragmentation
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-10-22 12:36:41 +0000
committerChristian Grothoff <christian@grothoff.org>2012-10-22 12:36:41 +0000
commitddd69826be47a1956c6972c2cfcadfa7902b8639 (patch)
treedd632db2ba084a1a83b0ef57189333f2bbd354a6 /src/fragmentation
parent582f893b55d9536864b59ad3ccb1dfeb43ff31b7 (diff)
downloadgnunet-ddd69826be47a1956c6972c2cfcadfa7902b8639.tar.gz
gnunet-ddd69826be47a1956c6972c2cfcadfa7902b8639.zip
-trying to fix fragmentation / udp performance, not working yet
Diffstat (limited to 'src/fragmentation')
-rw-r--r--src/fragmentation/fragmentation.c91
-rw-r--r--src/fragmentation/test_fragmentation.c8
2 files changed, 75 insertions, 24 deletions
diff --git a/src/fragmentation/fragmentation.c b/src/fragmentation/fragmentation.c
index 4749f5378..19f7ff175 100644
--- a/src/fragmentation/fragmentation.c
+++ b/src/fragmentation/fragmentation.c
@@ -52,7 +52,12 @@ struct GNUNET_FRAGMENT_Context
52 /** 52 /**
53 * Current expected delay for ACKs. 53 * Current expected delay for ACKs.
54 */ 54 */
55 struct GNUNET_TIME_Relative delay; 55 struct GNUNET_TIME_Relative ack_delay;
56
57 /**
58 * Current expected delay between messages.
59 */
60 struct GNUNET_TIME_Relative msg_delay;
56 61
57 /** 62 /**
58 * Next allowed transmission time. 63 * Next allowed transmission time.
@@ -181,11 +186,11 @@ transmit_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
181 return; 186 return;
182 } 187 }
183 fc->next_transmission = (fc->next_transmission + 1) % 64; 188 fc->next_transmission = (fc->next_transmission + 1) % 64;
184 wrap |= (fc->next_transmission == 0); 189 wrap |= (0 == fc->next_transmission);
185 while (0 == (fc->acks & (1LL << fc->next_transmission))) 190 while (0 == (fc->acks & (1LL << fc->next_transmission)))
186 { 191 {
187 fc->next_transmission = (fc->next_transmission + 1) % 64; 192 fc->next_transmission = (fc->next_transmission + 1) % 64;
188 wrap |= (fc->next_transmission == 0); 193 wrap |= (0 == fc->next_transmission);
189 } 194 }
190 195
191 /* assemble fragmentation message */ 196 /* assemble fragmentation message */
@@ -217,16 +222,17 @@ transmit_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
217 delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, fsize); 222 delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, fsize);
218 else 223 else
219 delay = GNUNET_TIME_UNIT_ZERO; 224 delay = GNUNET_TIME_UNIT_ZERO;
225 delay = GNUNET_TIME_relative_max (delay,
226 fc->msg_delay);
220 if (wrap) 227 if (wrap)
221 { 228 {
222 /* full round transmitted wait 2x delay for ACK before going again */ 229 /* full round transmitted wait 2x delay for ACK before going again */
223 fc->num_rounds++; 230 fc->num_rounds++;
224 delay = 231 delay = GNUNET_TIME_relative_multiply (delay, 2);
225 GNUNET_TIME_relative_max (GNUNET_TIME_relative_multiply (delay, 2), 232 fc->msg_delay = GNUNET_TIME_relative_multiply (fc->msg_delay,
226 GNUNET_TIME_relative_multiply (fc->delay, 233 2 + (size / (fc->mtu - sizeof (struct FragmentHeader))));
227 fc->num_rounds));
228 /* never use zero, need some time for ACK always */ 234 /* never use zero, need some time for ACK always */
229 delay = GNUNET_TIME_relative_max (MIN_ACK_DELAY, delay); 235 delay = GNUNET_TIME_relative_max (MIN_ACK_DELAY, delay);
230 fc->wack = GNUNET_YES; 236 fc->wack = GNUNET_YES;
231 fc->last_round = GNUNET_TIME_absolute_get (); 237 fc->last_round = GNUNET_TIME_absolute_get ();
232 GNUNET_STATISTICS_update (fc->stats, _("# fragments wrap arounds"), 1, 238 GNUNET_STATISTICS_update (fc->stats, _("# fragments wrap arounds"), 1,
@@ -250,7 +256,9 @@ transmit_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
250 * @param stats statistics context 256 * @param stats statistics context
251 * @param mtu the maximum message size for each fragment 257 * @param mtu the maximum message size for each fragment
252 * @param tracker bandwidth tracker to use for flow control (can be NULL) 258 * @param tracker bandwidth tracker to use for flow control (can be NULL)
253 * @param delay expected delay between fragment transmission 259 * @param msg_delay initial delay to insert between fragment transmissions
260 * based on previous messages
261 * @param ack_delay expected delay between fragment transmission
254 * and ACK based on previous messages 262 * and ACK based on previous messages
255 * @param msg the message to fragment 263 * @param msg the message to fragment
256 * @param proc function to call for each fragment to transmit 264 * @param proc function to call for each fragment to transmit
@@ -261,7 +269,8 @@ struct GNUNET_FRAGMENT_Context *
261GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, 269GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats,
262 uint16_t mtu, 270 uint16_t mtu,
263 struct GNUNET_BANDWIDTH_Tracker *tracker, 271 struct GNUNET_BANDWIDTH_Tracker *tracker,
264 struct GNUNET_TIME_Relative delay, 272 struct GNUNET_TIME_Relative msg_delay,
273 struct GNUNET_TIME_Relative ack_delay,
265 const struct GNUNET_MessageHeader *msg, 274 const struct GNUNET_MessageHeader *msg,
266 GNUNET_FRAGMENT_MessageProcessor proc, 275 GNUNET_FRAGMENT_MessageProcessor proc,
267 void *proc_cls) 276 void *proc_cls)
@@ -280,7 +289,8 @@ GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats,
280 fc->stats = stats; 289 fc->stats = stats;
281 fc->mtu = mtu; 290 fc->mtu = mtu;
282 fc->tracker = tracker; 291 fc->tracker = tracker;
283 fc->delay = delay; 292 fc->ack_delay = ack_delay;
293 fc->msg_delay = msg_delay;
284 fc->msg = (const struct GNUNET_MessageHeader *) &fc[1]; 294 fc->msg = (const struct GNUNET_MessageHeader *) &fc[1];
285 fc->proc = proc; 295 fc->proc = proc;
286 fc->proc_cls = proc_cls; 296 fc->proc_cls = proc_cls;
@@ -339,7 +349,11 @@ GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc,
339 const struct FragmentAcknowledgement *fa; 349 const struct FragmentAcknowledgement *fa;
340 uint64_t abits; 350 uint64_t abits;
341 struct GNUNET_TIME_Relative ndelay; 351 struct GNUNET_TIME_Relative ndelay;
352 unsigned int ack_cnt;
353 unsigned int snd_cnt;
354 unsigned int i;
342 355
356 fprintf (stderr, "Got ACK!\n");
343 if (sizeof (struct FragmentAcknowledgement) != ntohs (msg->size)) 357 if (sizeof (struct FragmentAcknowledgement) != ntohs (msg->size))
344 { 358 {
345 GNUNET_break_op (0); 359 GNUNET_break_op (0);
@@ -355,9 +369,40 @@ GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc,
355 /* normal ACK, can update running average of delay... */ 369 /* normal ACK, can update running average of delay... */
356 fc->wack = GNUNET_NO; 370 fc->wack = GNUNET_NO;
357 ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round); 371 ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round);
358 fc->delay.rel_value = 372 fc->ack_delay.rel_value =
359 (ndelay.rel_value / fc->num_transmissions + 3 * fc->delay.rel_value) / 4; 373 (ndelay.rel_value / fc->num_transmissions + 3 * fc->ack_delay.rel_value) / 4;
360 fc->num_transmissions = 0; 374 fc->num_transmissions = 0;
375 /* calculate ratio msg sent vs. msg acked */
376 ack_cnt = 0;
377 snd_cnt = 0;
378 for (i=0;i<64;i++)
379 {
380 if (1 == (fc->acks_mask & (1 << i)))
381 {
382 snd_cnt++;
383 if (0 == (abits & (1 << i)))
384 ack_cnt++;
385 }
386 }
387 if (0 == ack_cnt)
388 {
389 /* complete loss */
390 fc->msg_delay = GNUNET_TIME_relative_multiply (fc->msg_delay,
391 snd_cnt);
392 }
393 else if (snd_cnt > ack_cnt)
394 {
395 /* some loss, slow down proportionally */
396 fc->msg_delay.rel_value = ((fc->msg_delay.rel_value * ack_cnt) / snd_cnt);
397 }
398 else if (0 < fc->msg_delay.rel_value)
399 {
400 fc->msg_delay.rel_value--; /* try a bit faster */
401 }
402 fc->msg_delay = GNUNET_TIME_relative_max (fc->msg_delay,
403 GNUNET_TIME_UNIT_SECONDS);
404 fprintf (stderr, "New msg delay: %llu\n",
405 (unsigned long long )fc->msg_delay.rel_value);
361 } 406 }
362 GNUNET_STATISTICS_update (fc->stats, 407 GNUNET_STATISTICS_update (fc->stats,
363 _("# fragment acknowledgements received"), 1, 408 _("# fragment acknowledgements received"), 1,
@@ -406,19 +451,23 @@ GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc,
406 * resources). 451 * resources).
407 * 452 *
408 * @param fc fragmentation context 453 * @param fc fragmentation context
409 * @return average delay between transmission and ACK for the 454 * @param msg_delay where to store average delay between individual message transmissions the
410 * last message, FOREVER if the message was not fully transmitted 455 * last message (OUT only)
456 * @param ack_delay where to store average delay between transmission and ACK for the
457 * last message, set to FOREVER if the message was not fully transmitted (OUT only)
411 */ 458 */
412struct GNUNET_TIME_Relative 459void
413GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc) 460GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc,
461 struct GNUNET_TIME_Relative *msg_delay,
462 struct GNUNET_TIME_Relative *ack_delay)
414{ 463{
415 struct GNUNET_TIME_Relative ret;
416
417 if (fc->task != GNUNET_SCHEDULER_NO_TASK) 464 if (fc->task != GNUNET_SCHEDULER_NO_TASK)
418 GNUNET_SCHEDULER_cancel (fc->task); 465 GNUNET_SCHEDULER_cancel (fc->task);
419 ret = fc->delay; 466 if (NULL != ack_delay)
467 *ack_delay = fc->ack_delay;
468 if (NULL != msg_delay)
469 *msg_delay = fc->msg_delay;
420 GNUNET_free (fc); 470 GNUNET_free (fc);
421 return ret;
422} 471}
423 472
424 473
diff --git a/src/fragmentation/test_fragmentation.c b/src/fragmentation/test_fragmentation.c
index 0381a8dd0..ecbcdddab 100644
--- a/src/fragmentation/test_fragmentation.c
+++ b/src/fragmentation/test_fragmentation.c
@@ -77,7 +77,7 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
77 { 77 {
78 if (frags[i] == NULL) 78 if (frags[i] == NULL)
79 continue; 79 continue;
80 GNUNET_FRAGMENT_context_destroy (frags[i]); 80 GNUNET_FRAGMENT_context_destroy (frags[i], NULL, NULL);
81 frags[i] = NULL; 81 frags[i] = NULL;
82 } 82 }
83} 83}
@@ -134,7 +134,7 @@ proc_acks (void *cls, uint32_t msg_id, const struct GNUNET_MessageHeader *hdr)
134#if DETAILS 134#if DETAILS
135 FPRINTF (stderr, "%s", "@"); /* good ACK */ 135 FPRINTF (stderr, "%s", "@"); /* good ACK */
136#endif 136#endif
137 GNUNET_FRAGMENT_context_destroy (frags[i]); 137 GNUNET_FRAGMENT_context_destroy (frags[i], NULL, NULL);
138 frags[i] = NULL; 138 frags[i] = NULL;
139 acks++; 139 acks++;
140 return; 140 return;
@@ -215,7 +215,9 @@ run (void *cls, char *const *args, const char *cfgfile,
215 htons (sizeof (struct GNUNET_MessageHeader) + (17 * i) % (32 * 1024)); 215 htons (sizeof (struct GNUNET_MessageHeader) + (17 * i) % (32 * 1024));
216 frags[i] = GNUNET_FRAGMENT_context_create (NULL /* no stats */ , 216 frags[i] = GNUNET_FRAGMENT_context_create (NULL /* no stats */ ,
217 MTU, &trackers[i], 217 MTU, &trackers[i],
218 GNUNET_TIME_UNIT_SECONDS, msg, 218 GNUNET_TIME_UNIT_MILLISECONDS,
219 GNUNET_TIME_UNIT_SECONDS,
220 msg,
219 &proc_frac, &frags[i]); 221 &proc_frac, &frags[i]);
220 } 222 }
221} 223}