aboutsummaryrefslogtreecommitdiff
path: root/src/fragmentation
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-07-11 22:34:11 +0000
committerChristian Grothoff <christian@grothoff.org>2011-07-11 22:34:11 +0000
commit6ce274c7e9fb01c76dc904d907fce9c893d0fc44 (patch)
treec4eec1e43ac6bfe81b29a367244df12637a3a788 /src/fragmentation
parentc4c451a78270f0e1ef90dd64b14b179d09b24801 (diff)
downloadgnunet-6ce274c7e9fb01c76dc904d907fce9c893d0fc44.tar.gz
gnunet-6ce274c7e9fb01c76dc904d907fce9c893d0fc44.zip
frag
Diffstat (limited to 'src/fragmentation')
-rw-r--r--src/fragmentation/defragmentation_new.c69
-rw-r--r--src/fragmentation/fragmentation_new.c24
-rw-r--r--src/fragmentation/test_fragmentation.c120
3 files changed, 167 insertions, 46 deletions
diff --git a/src/fragmentation/defragmentation_new.c b/src/fragmentation/defragmentation_new.c
index 2e1136f9f..379ec57d4 100644
--- a/src/fragmentation/defragmentation_new.c
+++ b/src/fragmentation/defragmentation_new.c
@@ -391,6 +391,7 @@ discard_oldest_mc (struct GNUNET_DEFRAGMENT_Context *dc)
391 if (GNUNET_SCHEDULER_NO_TASK != old->ack_task) 391 if (GNUNET_SCHEDULER_NO_TASK != old->ack_task)
392 GNUNET_SCHEDULER_cancel (old->ack_task); 392 GNUNET_SCHEDULER_cancel (old->ack_task);
393 GNUNET_free (old); 393 GNUNET_free (old);
394 fprintf (stderr, "D");
394} 395}
395 396
396 397
@@ -399,8 +400,9 @@ discard_oldest_mc (struct GNUNET_DEFRAGMENT_Context *dc)
399 * 400 *
400 * @param dc the context 401 * @param dc the context
401 * @param msg the message that was received 402 * @param msg the message that was received
403 * @return GNUNET_OK on success, GNUNET_NO if this was a duplicate, GNUNET_SYSERR on error
402 */ 404 */
403void 405int
404GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, 406GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc,
405 const struct GNUNET_MessageHeader *msg) 407 const struct GNUNET_MessageHeader *msg)
406{ 408{
@@ -415,25 +417,32 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc,
415 struct GNUNET_TIME_Relative delay; 417 struct GNUNET_TIME_Relative delay;
416 unsigned int bc; 418 unsigned int bc;
417 unsigned int b; 419 unsigned int b;
420 unsigned int n;
421 int duplicate;
418 422
419 if (ntohs(msg->size) < sizeof (struct FragmentHeader)) 423 if (ntohs(msg->size) < sizeof (struct FragmentHeader))
420 { 424 {
421 GNUNET_break_op (0); 425 GNUNET_break_op (0);
422 return; 426 return GNUNET_SYSERR;
423 } 427 }
424 if (ntohs (msg->size) > dc->mtu) 428 if (ntohs (msg->size) > dc->mtu)
425 { 429 {
426 GNUNET_break_op (0); 430 GNUNET_break_op (0);
427 return; 431 return GNUNET_SYSERR;
428 } 432 }
429 fh = (const struct FragmentHeader*) msg; 433 fh = (const struct FragmentHeader*) msg;
430 msize = ntohs (fh->total_size); 434 msize = ntohs (fh->total_size);
431 fid = ntohl (fh->fragment_id); 435 fid = ntohl (fh->fragment_id);
432 foff = ntohl (fh->offset); 436 foff = ntohs (fh->offset);
433 if (foff >= msize) 437 if (foff >= msize)
434 { 438 {
435 GNUNET_break_op (0); 439 GNUNET_break_op (0);
436 return; 440 return GNUNET_SYSERR;
441 }
442 if (0 != (foff % (dc->mtu - sizeof (struct FragmentHeader))))
443 {
444 GNUNET_break_op (0);
445 return GNUNET_SYSERR;
437 } 446 }
438 GNUNET_STATISTICS_update (dc->stats, 447 GNUNET_STATISTICS_update (dc->stats,
439 _("Fragments received"), 448 _("Fragments received"),
@@ -443,19 +452,19 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc,
443 while ( (NULL != mc) && 452 while ( (NULL != mc) &&
444 (fid != mc->fragment_id) ) 453 (fid != mc->fragment_id) )
445 mc = mc->next; 454 mc = mc->next;
446 bit = foff / dc->mtu; 455 bit = foff / (dc->mtu - sizeof (struct FragmentHeader));
447 if (bit * dc->mtu + ntohs (msg->size) 456 if (bit * (dc->mtu - sizeof (struct FragmentHeader)) + ntohs (msg->size)
448 - sizeof (struct FragmentHeader) > msize) 457 - sizeof (struct FragmentHeader) > msize)
449 { 458 {
450 /* payload extends past total message size */ 459 /* payload extends past total message size */
451 GNUNET_break_op (0); 460 GNUNET_break_op (0);
452 return; 461 return GNUNET_SYSERR;
453 } 462 }
454 if ( (NULL != mc) && (msize != mc->total_size) ) 463 if ( (NULL != mc) && (msize != mc->total_size) )
455 { 464 {
456 /* inconsistent message size */ 465 /* inconsistent message size */
457 GNUNET_break_op (0); 466 GNUNET_break_op (0);
458 return; 467 return GNUNET_SYSERR;
459 } 468 }
460 now = GNUNET_TIME_absolute_get (); 469 now = GNUNET_TIME_absolute_get ();
461 if (NULL == mc) 470 if (NULL == mc)
@@ -466,7 +475,11 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc,
466 mc->total_size = msize; 475 mc->total_size = msize;
467 mc->fragment_id = fid; 476 mc->fragment_id = fid;
468 mc->last_update = now; 477 mc->last_update = now;
469 mc->bits = (msize + dc->mtu - 1) / (dc->mtu - sizeof (struct FragmentHeader)); 478 n = (msize + dc->mtu - sizeof (struct FragmentHeader) - 1) / (dc->mtu - sizeof (struct FragmentHeader));
479 if (n == 64)
480 mc->bits = UINT64_MAX; /* set all 64 bit */
481 else
482 mc->bits = (1LL << n) - 1; /* set lowest 'bits' bit */
470 GNUNET_CONTAINER_DLL_insert (dc->head, 483 GNUNET_CONTAINER_DLL_insert (dc->head,
471 dc->tail, 484 dc->tail,
472 mc); 485 mc);
@@ -476,11 +489,11 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc,
476 } 489 }
477 490
478 /* copy data to 'mc' */ 491 /* copy data to 'mc' */
479 if (0 != (mc->bits & (1 << bit))) 492 if (0 != (mc->bits & (1LL << bit)))
480 { 493 {
481 mc->bits -= 1 << bit; 494 mc->bits -= 1LL << bit;
482 mbuf = (char* )&mc[1]; 495 mbuf = (char* )&mc[1];
483 memcpy (&mbuf[bit * dc->mtu], 496 memcpy (&mbuf[bit * (dc->mtu - sizeof (struct FragmentHeader))],
484 &fh[1], 497 &fh[1],
485 ntohs (msg->size) - sizeof (struct FragmentHeader)); 498 ntohs (msg->size) - sizeof (struct FragmentHeader));
486 mc->last_update = now; 499 mc->last_update = now;
@@ -490,19 +503,11 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc,
490 mc->frag_times[mc->frag_times_write_offset].time = now; 503 mc->frag_times[mc->frag_times_write_offset].time = now;
491 mc->frag_times[mc->frag_times_write_offset].bit = bit; 504 mc->frag_times[mc->frag_times_write_offset].bit = bit;
492 mc->frag_times_write_offset++; 505 mc->frag_times_write_offset++;
493 if (0 == mc->bits) 506 duplicate = GNUNET_NO;
494 {
495 /* message complete, notify! */
496 dc->proc (dc->cls,
497 mc->msg);
498 GNUNET_STATISTICS_update (dc->stats,
499 _("Messages defragmented"),
500 1,
501 GNUNET_NO);
502 }
503 } 507 }
504 else 508 else
505 { 509 {
510 duplicate = GNUNET_YES;
506 GNUNET_STATISTICS_update (dc->stats, 511 GNUNET_STATISTICS_update (dc->stats,
507 _("Duplicate fragments received"), 512 _("Duplicate fragments received"),
508 1, 513 1,
@@ -512,18 +517,32 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc,
512 /* count number of missing fragments */ 517 /* count number of missing fragments */
513 bc = 0; 518 bc = 0;
514 for (b=0;b<64;b++) 519 for (b=0;b<64;b++)
515 if (0 != (mc->bits & (1 << b))) bc++; 520 if (0 != (mc->bits & (1LL << b))) bc++;
516 if (mc->frag_times_write_offset - mc->frag_times_start_offset > 1) 521 if (mc->frag_times_write_offset - mc->frag_times_start_offset > 1)
517 dc->latency = estimate_latency (mc); 522 dc->latency = estimate_latency (mc);
518 delay = GNUNET_TIME_relative_multiply (dc->latency, 523 delay = GNUNET_TIME_relative_multiply (dc->latency,
519 bc + 1); 524 bc + 1);
520 if (0 == mc->bits) /* message complete, ACK now! */ 525 if ( (0 == mc->bits) || (GNUNET_YES == duplicate) ) /* message complete or duplicate, ACK now! */
521 delay = GNUNET_TIME_UNIT_ZERO; 526 delay = GNUNET_TIME_UNIT_ZERO;
522 if (GNUNET_SCHEDULER_NO_TASK != mc->ack_task) 527 if (GNUNET_SCHEDULER_NO_TASK != mc->ack_task)
523 GNUNET_SCHEDULER_cancel (mc->ack_task); 528 GNUNET_SCHEDULER_cancel (mc->ack_task);
524 mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay, 529 mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay,
525 &send_ack, 530 &send_ack,
526 mc); 531 mc);
532 if ( (duplicate == GNUNET_NO) &&
533 (0 == mc->bits) )
534 {
535 GNUNET_STATISTICS_update (dc->stats,
536 _("Messages defragmented"),
537 1,
538 GNUNET_NO);
539 /* message complete, notify! */
540 dc->proc (dc->cls,
541 mc->msg);
542 }
543 if (duplicate == GNUNET_YES)
544 return GNUNET_NO;
545 return GNUNET_YES;
527} 546}
528 547
529/* end of defragmentation_new.c */ 548/* end of defragmentation_new.c */
diff --git a/src/fragmentation/fragmentation_new.c b/src/fragmentation/fragmentation_new.c
index 17b4bb0ab..dbbaa859b 100644
--- a/src/fragmentation/fragmentation_new.c
+++ b/src/fragmentation/fragmentation_new.c
@@ -127,7 +127,7 @@ transmit_next (void *cls,
127 127
128 /* calculate delay */ 128 /* calculate delay */
129 wrap = 0; 129 wrap = 0;
130 while (0 == (fc->acks & (1 << fc->next_transmission))) 130 while (0 == (fc->acks & (1LL << fc->next_transmission)))
131 { 131 {
132 fc->next_transmission = (fc->next_transmission + 1) % 64; 132 fc->next_transmission = (fc->next_transmission + 1) % 64;
133 wrap |= (fc->next_transmission == 0); 133 wrap |= (fc->next_transmission == 0);
@@ -160,13 +160,12 @@ transmit_next (void *cls,
160 fh->header.type = htons (GNUNET_MESSAGE_TYPE_FRAGMENT); 160 fh->header.type = htons (GNUNET_MESSAGE_TYPE_FRAGMENT);
161 fh->fragment_id = htonl (fc->fragment_id); 161 fh->fragment_id = htonl (fc->fragment_id);
162 fh->total_size = fc->msg->size; /* already in big-endian */ 162 fh->total_size = fc->msg->size; /* already in big-endian */
163 fh->offset = htons (fc->mtu * bit); 163 fh->offset = htons ((fc->mtu - sizeof (struct FragmentHeader)) * bit);
164 memcpy (&fc[1], 164 memcpy (&fh[1],
165 &mbuf[bit * (fc->mtu - sizeof (struct FragmentHeader))], 165 &mbuf[bit * (fc->mtu - sizeof (struct FragmentHeader))],
166 fsize - sizeof (struct FragmentHeader)); 166 fsize - sizeof (struct FragmentHeader));
167 fc->proc (fc->proc_cls, &fh->header);
168 if (NULL != fc->tracker) 167 if (NULL != fc->tracker)
169 GNUNET_BANDWIDTH_tracker_consume (fc->tracker, fsize); 168 GNUNET_BANDWIDTH_tracker_consume (fc->tracker, fsize);
170 GNUNET_STATISTICS_update (fc->stats, 169 GNUNET_STATISTICS_update (fc->stats,
171 _("Fragments transmitted"), 170 _("Fragments transmitted"),
172 1, GNUNET_NO); 171 1, GNUNET_NO);
@@ -198,6 +197,7 @@ transmit_next (void *cls,
198 fc->task = GNUNET_SCHEDULER_add_delayed (delay, 197 fc->task = GNUNET_SCHEDULER_add_delayed (delay,
199 &transmit_next, 198 &transmit_next,
200 fc); 199 fc);
200 fc->proc (fc->proc_cls, &fh->header);
201} 201}
202 202
203 203
@@ -252,12 +252,12 @@ GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats,
252 fc->fragment_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 252 fc->fragment_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
253 UINT32_MAX); 253 UINT32_MAX);
254 memcpy (&fc[1], msg, size); 254 memcpy (&fc[1], msg, size);
255 bits = (size + mtu - 1) / (mtu - sizeof (struct FragmentHeader)); 255 bits = (size + mtu - sizeof (struct FragmentHeader) - 1) / (mtu - sizeof (struct FragmentHeader));
256 GNUNET_assert (bits <= 64); 256 GNUNET_assert (bits <= 64);
257 if (bits == 64) 257 if (bits == 64)
258 fc->acks = UINT64_MAX; /* set all 64 bit */ 258 fc->acks = UINT64_MAX; /* set all 64 bit */
259 else 259 else
260 fc->acks = (1 << bits) - 1; /* set lowest 'bits' bit */ 260 fc->acks = (1LL << bits) - 1; /* set lowest 'bits' bit */
261 fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, 261 fc->task = GNUNET_SCHEDULER_add_now (&transmit_next,
262 fc); 262 fc);
263 return fc; 263 return fc;
@@ -300,8 +300,14 @@ GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc,
300 ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round); 300 ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round);
301 fc->delay.rel_value = (ndelay.rel_value + 3 * fc->delay.rel_value) / 4; 301 fc->delay.rel_value = (ndelay.rel_value + 3 * fc->delay.rel_value) / 4;
302 } 302 }
303 303 if (abits != (fc->acks & abits))
304 fc->acks &= abits; 304 {
305 /* ID collission or message reordering, count! This should be rare! */
306 GNUNET_STATISTICS_update (fc->stats,
307 _("Bits removed from ACK"),
308 1, GNUNET_NO);
309 }
310 fc->acks = abits;
305 if (0 != fc->acks) 311 if (0 != fc->acks)
306 { 312 {
307 /* more to transmit, do so right now (if tracker permits...) */ 313 /* more to transmit, do so right now (if tracker permits...) */
diff --git a/src/fragmentation/test_fragmentation.c b/src/fragmentation/test_fragmentation.c
index 639c0ef17..8a9af04e7 100644
--- a/src/fragmentation/test_fragmentation.c
+++ b/src/fragmentation/test_fragmentation.c
@@ -25,14 +25,41 @@
25#include "platform.h" 25#include "platform.h"
26#include "gnunet_fragmentation_lib.h" 26#include "gnunet_fragmentation_lib.h"
27 27
28#define NUM_MSGS 1 28#define VERBOSE GNUNET_NO
29 29
30#define DETAILS GNUNET_NO
31
32/**
33 * Number of messages to transmit (note: each uses ~32k memory!)
34 */
35#define NUM_MSGS 500
36
37/**
38 * MTU to force on fragmentation (must be > 1k + 12)
39 */
30#define MTU 1111 40#define MTU 1111
31 41
42/**
43 * Simulate dropping of 1 out of how many messages? (must be > 1)
44 */
45#define DROPRATE 2
46
32static int ret = 1; 47static int ret = 1;
33 48
49static unsigned int dups;
50
51static unsigned int fragc;
52
53static unsigned int frag_drops;
54
55static unsigned int acks;
56
57static unsigned int ack_drops;
58
34static struct GNUNET_DEFRAGMENT_Context *defrag; 59static struct GNUNET_DEFRAGMENT_Context *defrag;
35 60
61static struct GNUNET_BANDWIDTH_Tracker trackers[NUM_MSGS];
62
36static struct GNUNET_FRAGMENT_Context *frags[NUM_MSGS]; 63static struct GNUNET_FRAGMENT_Context *frags[NUM_MSGS];
37 64
38static void 65static void
@@ -40,17 +67,36 @@ proc_msgs (void *cls,
40 const struct GNUNET_MessageHeader *hdr) 67 const struct GNUNET_MessageHeader *hdr)
41{ 68{
42 static unsigned int total; 69 static unsigned int total;
70 unsigned int i;
71 const char *buf;
43 72
44 fprintf (stderr, "!"); 73#if DETAILS
74 fprintf (stderr, "!"); /* message complete, good! */
75#endif
76 buf = (const char*) hdr;
77 for (i=sizeof (struct GNUNET_MessageHeader);i<ntohs(hdr->size);i++)
78 GNUNET_assert (buf[i] == (char) i);
45 total++; 79 total++;
80#if ! DETAILS
81 if (0 == (total % (NUM_MSGS / 100)))
82 fprintf (stderr, ".");
83#endif
46 if (total == NUM_MSGS) 84 if (total == NUM_MSGS)
47 { 85 {
48 ret = 0; 86 ret = 0;
49 GNUNET_DEFRAGMENT_context_destroy (defrag); 87 GNUNET_DEFRAGMENT_context_destroy (defrag);
50 defrag = NULL; 88 defrag = NULL;
89 for (i=0;i<NUM_MSGS;i++)
90 {
91 if (frags[i] == NULL)
92 continue;
93 GNUNET_FRAGMENT_context_destroy (frags[i]);
94 frags[i] = NULL;
95 }
51 } 96 }
52} 97}
53 98
99
54/** 100/**
55 * Process ACK (by passing to fragmenter) 101 * Process ACK (by passing to fragmenter)
56 */ 102 */
@@ -61,23 +107,39 @@ proc_acks (void *cls,
61 unsigned int i; 107 unsigned int i;
62 int ret; 108 int ret;
63 109
64 fprintf (stderr, "@"); 110 if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE))
111 {
112 ack_drops++;
113 return; /* random drop */
114 }
65 for (i=0;i<NUM_MSGS;i++) 115 for (i=0;i<NUM_MSGS;i++)
66 { 116 {
67 if (frags[i] == NULL) 117 if (frags[i] == NULL)
68 return; 118 continue;
69 ret = GNUNET_FRAGMENT_process_ack (frags[i], 119 ret = GNUNET_FRAGMENT_process_ack (frags[i],
70 hdr); 120 hdr);
71 if (ret == GNUNET_OK) 121 if (ret == GNUNET_OK)
72 { 122 {
123#if DETAILS
124 fprintf (stderr, "@"); /* good ACK */
125#endif
73 GNUNET_FRAGMENT_context_destroy (frags[i]); 126 GNUNET_FRAGMENT_context_destroy (frags[i]);
74 frags[i] = NULL; 127 frags[i] = NULL;
128 acks++;
75 return; 129 return;
76 } 130 }
77 if (ret == GNUNET_NO) 131 if (ret == GNUNET_NO)
78 return; 132 {
133#if DETAILS
134 fprintf (stderr, "@"); /* good ACK */
135#endif
136 acks++;
137 return;
138 }
79 } 139 }
80 fprintf (stderr, "Got ACK that nobody feels responsible for...\n"); 140#if DETAILS
141 fprintf (stderr, "_"); /* BAD: ack that nobody feels responsible for... */
142#endif
81} 143}
82 144
83 145
@@ -88,10 +150,33 @@ static void
88proc_frac (void *cls, 150proc_frac (void *cls,
89 const struct GNUNET_MessageHeader *hdr) 151 const struct GNUNET_MessageHeader *hdr)
90{ 152{
91 fprintf (stderr, "."); 153 int ret;
154
155 if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE))
156 {
157 frag_drops++;
158 return; /* random drop */
159 }
92 if (NULL == defrag) 160 if (NULL == defrag)
93 return; 161 {
94 GNUNET_DEFRAGMENT_process_fragment (defrag, hdr); 162 fprintf (stderr, "E"); /* Error: frag after shutdown!? */
163 return;
164 }
165 ret = GNUNET_DEFRAGMENT_process_fragment (defrag, hdr);
166 if (ret == GNUNET_NO)
167 {
168#if DETAILS
169 fprintf (stderr, "?"); /* duplicate fragment */
170#endif
171 dups++;
172 }
173 else if (ret == GNUNET_OK)
174 {
175#if DETAILS
176 fprintf (stderr, "."); /* good fragment */
177#endif
178 fragc++;
179 }
95} 180}
96 181
97 182
@@ -119,11 +204,11 @@ run (void *cls,
119 for (i=0;i<NUM_MSGS;i++) 204 for (i=0;i<NUM_MSGS;i++)
120 { 205 {
121 msg->type = htons ((uint16_t) i); 206 msg->type = htons ((uint16_t) i);
122 msg->size = htons (MTU + 1 + i % (32 * 1024)); 207 msg->size = htons (MTU + 1 + (17 * i) % (32 * 1024));
123 frags[i] = GNUNET_FRAGMENT_context_create (NULL /* no stats */, 208 frags[i] = GNUNET_FRAGMENT_context_create (NULL /* no stats */,
124 MTU, 209 MTU,
125 NULL /* no tracker -- infinite BW */, 210 &trackers[i],
126 GNUNET_TIME_UNIT_MILLISECONDS, 211 GNUNET_TIME_UNIT_SECONDS,
127 msg, 212 msg,
128 &proc_frac, 213 &proc_frac,
129 NULL); 214 NULL);
@@ -149,6 +234,7 @@ main (int argc, char *argv[])
149#endif 234#endif
150 NULL 235 NULL
151 }; 236 };
237 unsigned int i;
152 238
153 GNUNET_log_setup ("test-fragmentation", 239 GNUNET_log_setup ("test-fragmentation",
154#if VERBOSE 240#if VERBOSE
@@ -157,6 +243,16 @@ main (int argc, char *argv[])
157 "WARNING", 243 "WARNING",
158#endif 244#endif
159 NULL); 245 NULL);
246 for (i=0;i<NUM_MSGS;i++)
247 GNUNET_BANDWIDTH_tracker_init (&trackers[i],
248 GNUNET_BANDWIDTH_value_init ((i+1) * 1024),
249 100);
160 GNUNET_PROGRAM_run (5, argv_prog, "test-fragmentation", "nohelp", options, &run, NULL); 250 GNUNET_PROGRAM_run (5, argv_prog, "test-fragmentation", "nohelp", options, &run, NULL);
251 fprintf (stderr,
252 "\nHad %u good fragments, %u duplicate fragments, %u acks and %u simulated drops of acks\n",
253 fragc,
254 dups,
255 acks,
256 ack_drops);
161 return ret; 257 return ret;
162} 258}