fix for evaluation
[oweals/gnunet.git] / src / ats-tests / perf_ats.c
1 /*
2  This file is part of GNUnet.
3  (C) 2010-2013 Christian Grothoff (and other contributing authors)
4
5  GNUnet is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published
7  by the Free Software Foundation; either version 3, or (at your
8  option) any later version.
9
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  General Public License for more details.
14
15  You should have received a copy of the GNU General Public License
16  along with GNUnet; see the file COPYING.  If not, write to the
17  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  Boston, MA 02111-1307, USA.
19  */
20 /**
21  * @file ats/perf_ats.c
22  * @brief ats benchmark: start peers and modify preferences, monitor change over time
23  * @author Christian Grothoff
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_testbed_service.h"
29 #include "gnunet_ats_service.h"
30 #include "gnunet_core_service.h"
31 #include "ats-testing.h"
32
33
34 #define TEST_ATS_PREFRENCE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
35 #define TEST_ATS_PREFRENCE_START 1.0
36 #define TEST_ATS_PREFRENCE_DELTA 1.0
37
38 #define TEST_MESSAGE_TYPE_PING 12345
39 #define TEST_MESSAGE_TYPE_PONG 12346
40 #define TEST_MESSAGE_SIZE 1000
41 #define TEST_MESSAGE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
42
43 #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
44 #define BENCHMARK_DURATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
45 #define LOGGING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500)
46 #define TESTNAME_PREFIX "perf_ats_"
47 #define DEFAULT_SLAVES_NUM 2
48 #define DEFAULT_MASTERS_NUM 1
49 /**
50  * Shutdown task
51  */
52 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
53
54 /**
55  * Progress task
56  */
57 static GNUNET_SCHEDULER_TaskIdentifier progress_task;
58
59 /**
60  * Test result
61  */
62 static int result;
63
64 /**
65  * Test result logging
66  */
67 static int logging;
68
69 /**Test core (GNUNET_YES) or transport (GNUNET_NO)
70  */
71 static int test_core;
72
73 /**
74  * Solver string
75  */
76 static char *solver;
77
78 /**
79  * Preference string
80  */
81 static char *testname;
82
83 /**
84  * Preference string
85  */
86 static char *pref_str;
87
88 /**
89  * ATS preference value
90  */
91 static int pref_val;
92
93 /**
94  * Benchmark duration
95  */
96 static struct GNUNET_TIME_Relative perf_duration;
97
98 /**
99  * Logging frequency
100  */
101 static struct GNUNET_TIME_Relative log_frequency;
102
103 /**
104  * Number master peers
105  */
106 static unsigned int num_masters;
107
108 /**
109  * Array of master peers
110  */
111 static struct BenchmarkPeer *mps;
112
113 /**
114  * Number slave peers
115  */
116 static unsigned int num_slaves;
117
118 /**
119  * Array of master peers
120  */
121 static struct BenchmarkPeer *sps;
122
123 static void
124 evaluate ()
125 {
126   int c_m;
127   int c_s;
128   unsigned int duration;
129   struct BenchmarkPeer *mp;
130   struct BenchmarkPartner *p;
131
132   unsigned int kb_sent_sec;
133   double kb_sent_percent;
134   unsigned int kb_recv_sec;
135   double kb_recv_percent;
136   unsigned int rtt;
137
138   duration = (perf_duration.rel_value_us / (1000 * 1000));
139   for (c_m = 0; c_m < num_masters; c_m++)
140   {
141     mp = &mps[c_m];
142     fprintf (stderr,
143         _("Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. = %u KiB/s\n"),
144         mp->no, mp->total_bytes_sent / 1024, duration,
145         (mp->total_bytes_sent / 1024) / duration,
146         mp->total_bytes_received / 1024, duration,
147         (mp->total_bytes_received / 1024) / duration);
148
149     for (c_s = 0; c_s < num_slaves; c_s++)
150     {
151       p = &mp->partners[c_s];
152
153       fprintf (stderr , "%u  %u %u\n", p->bytes_sent, (p->bytes_sent / 1024) / duration, duration);
154       fprintf (stderr , "%u %u %u \n", p->bytes_received, (p->bytes_sent / 1024) / duration, duration);
155
156       kb_sent_sec = 0;
157       kb_recv_sec = 0;
158       kb_sent_percent = 0.0;
159       kb_recv_percent = 0.0;
160       rtt = 0;
161
162       if (duration > 0)
163       {
164           kb_sent_sec = (p->bytes_sent / 1024) / duration;
165           kb_recv_sec = (p->bytes_received / 1024) / duration;
166       }
167
168       if (mp->total_bytes_sent > 0)
169           kb_sent_percent = ((double) p->bytes_sent * 100) / mp->total_bytes_sent;
170       if (mp->total_bytes_received > 0)
171           kb_recv_percent = ((double) p->bytes_received * 100) / mp->total_bytes_received;
172       if (1000 * p->messages_sent > 0)
173           rtt = p->total_app_rtt / (1000 * p->messages_sent);
174
175
176
177       fprintf (stderr,
178           "%c Master [%u] -> Slave [%u]: sent %u KiB/s (%.2f %%), received %u KiB/s (%.2f %%)\n",
179           (mp->pref_partner == p->dest) ? '*' : ' ',
180           mp->no, p->dest->no,
181           kb_sent_sec, kb_sent_percent,
182                   kb_recv_sec, kb_recv_percent);
183
184       fprintf (stderr,
185           "%c Master [%u] -> Slave [%u]: Average application layer RTT: %u ms\n",
186           (mp->pref_partner == p->dest) ? '*' : ' ',
187           mp->no, p->dest->no, rtt);
188     }
189   }
190 }
191
192 /**
193  * Shutdown nicely
194  *
195  * @param cls NULL
196  * @param tc the task context
197  */
198 static void
199 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
200 {
201
202   if (GNUNET_YES == logging)
203     GNUNET_ATS_TEST_logging_stop();
204
205   shutdown_task = GNUNET_SCHEDULER_NO_TASK;
206   if (GNUNET_SCHEDULER_NO_TASK != progress_task)
207   {
208     fprintf (stderr, "0\n");
209     GNUNET_SCHEDULER_cancel (progress_task);
210   }
211   progress_task = GNUNET_SCHEDULER_NO_TASK;
212
213   evaluate ();
214   GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n"));
215
216   GNUNET_ATS_TEST_shutdown_topology();
217 }
218
219 static size_t
220 comm_send_ready (void *cls, size_t size, void *buf)
221 {
222   static char msgbuf[TEST_MESSAGE_SIZE];
223   struct BenchmarkPartner *p = cls;
224   struct GNUNET_MessageHeader *msg;
225
226   if (GNUNET_YES == test_core)
227     p->cth = NULL;
228   else
229     p->tth = NULL;
230
231   if (NULL == buf)
232   {
233     GNUNET_break (0);
234     return 0;
235   }
236   if (size < TEST_MESSAGE_SIZE)
237   {
238     GNUNET_break (0);
239     return 0;
240   }
241
242   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Master [%u]: Sending PING to [%u]\n",
243       p->me->no, p->dest->no);
244
245   p->messages_sent++;
246   p->bytes_sent += TEST_MESSAGE_SIZE;
247   p->me->total_messages_sent++;
248   p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
249
250   msg = (struct GNUNET_MessageHeader *) &msgbuf;
251   memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
252   msg->type = htons (TEST_MESSAGE_TYPE_PING);
253   msg->size = htons (TEST_MESSAGE_SIZE);
254   memcpy (buf, msg, TEST_MESSAGE_SIZE);
255   return TEST_MESSAGE_SIZE;
256 }
257
258 static void
259 comm_schedule_send (struct BenchmarkPartner *p)
260 {
261   p->last_message_sent = GNUNET_TIME_absolute_get();
262   if (GNUNET_YES == test_core)
263   {
264     p->cth = GNUNET_CORE_notify_transmit_ready (
265       p->me->ch, GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES, &p->dest->id,
266       TEST_MESSAGE_SIZE, &comm_send_ready, p);
267   }
268   else
269   {
270     p->tth = GNUNET_TRANSPORT_notify_transmit_ready (
271       p->me->th, &p->dest->id, TEST_MESSAGE_SIZE, 0,GNUNET_TIME_UNIT_MINUTES,
272       &comm_send_ready, p);
273   }
274
275 }
276
277 static void
278 print_progress ()
279 {
280   static int calls;
281   progress_task = GNUNET_SCHEDULER_NO_TASK;
282
283   fprintf (stderr, "%llu..",
284       (long long unsigned) perf_duration.rel_value_us / (1000 * 1000) - calls);
285   calls++;
286
287   progress_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
288       &print_progress, NULL );
289 }
290
291 static void
292 ats_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
293 {
294   struct BenchmarkPeer *me = cls;
295
296   me->ats_task = GNUNET_SCHEDULER_NO_TASK;
297
298   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, " Master [%u] set preference for slave [%u] to %f\n",
299       me->no, me->pref_partner->no, me->pref_value);
300   GNUNET_ATS_performance_change_preference (me->ats_perf_handle,
301       &me->pref_partner->id,
302       pref_val, me->pref_value, GNUNET_ATS_PREFERENCE_END);
303   me->pref_value += TEST_ATS_PREFRENCE_DELTA;
304   me->ats_task = GNUNET_SCHEDULER_add_delayed (TEST_ATS_PREFRENCE_FREQUENCY,
305       &ats_pref_task, cls);
306 }
307
308 static void
309 do_benchmark (void *cls, struct BenchmarkPeer *masters, struct BenchmarkPeer *slaves)
310 {
311   int c_m;
312   int c_s;
313
314   mps = masters;
315   sps = slaves;
316
317   GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking start\n"));
318
319   if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
320     GNUNET_SCHEDULER_cancel (shutdown_task);
321   shutdown_task = GNUNET_SCHEDULER_add_delayed (perf_duration,
322       &do_shutdown, NULL );
323
324   progress_task = GNUNET_SCHEDULER_add_now (&print_progress, NULL );
325
326   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Topology connected, start benchmarking...\n");
327
328   /* Start sending test messages */
329   for (c_m = 0; c_m < num_masters; c_m++)
330   {
331     for (c_s = 0; c_s < num_slaves; c_s++)
332       comm_schedule_send (&masters[c_m].partners[c_s]);
333     if (pref_val != GNUNET_ATS_PREFERENCE_END)
334       masters[c_m].ats_task = GNUNET_SCHEDULER_add_now (&ats_pref_task, &masters[c_m]);
335   }
336
337   if (GNUNET_YES == logging)
338     GNUNET_ATS_TEST_logging_start (log_frequency, testname, mps, num_masters);
339 }
340
341
342 static size_t
343 comm_send_pong_ready (void *cls, size_t size, void *buf)
344 {
345   static char msgbuf[TEST_MESSAGE_SIZE];
346   struct BenchmarkPartner *p = cls;
347   struct GNUNET_MessageHeader *msg;
348
349   if (GNUNET_YES == test_core)
350     p->cth = NULL;
351   else
352     p->tth = NULL;
353
354   p->messages_sent++;
355   p->bytes_sent += TEST_MESSAGE_SIZE;
356   p->me->total_messages_sent++;
357   p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
358
359   msg = (struct GNUNET_MessageHeader *) &msgbuf;
360   memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
361   msg->type = htons (TEST_MESSAGE_TYPE_PONG);
362   msg->size = htons (TEST_MESSAGE_SIZE);
363   memcpy (buf, msg, TEST_MESSAGE_SIZE);
364
365   return TEST_MESSAGE_SIZE;
366 }
367
368 static struct BenchmarkPartner *
369 find_partner (struct BenchmarkPeer *me, const struct GNUNET_PeerIdentity * peer)
370 {
371   int c_m;
372   GNUNET_assert (NULL != me);
373   GNUNET_assert (NULL != peer);
374
375   for (c_m = 0; c_m < me->num_partners; c_m++)
376   {
377     /* Find a partner with other as destination */
378     if (0 == memcmp (peer, &me->partners[c_m].dest->id,
379             sizeof(struct GNUNET_PeerIdentity)))
380     {
381       return &me->partners[c_m];
382     }
383   }
384   return NULL;
385 }
386
387 static int
388 comm_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other,
389     const struct GNUNET_MessageHeader *message)
390 {
391
392   struct BenchmarkPeer *me = cls;
393   struct BenchmarkPartner *p = NULL;
394
395   if (NULL == (p = find_partner(me, other)))
396   {
397     GNUNET_break(0);
398     return GNUNET_SYSERR;
399   }
400
401   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
402       "Slave [%u]: Received PING from [%u], sending PONG\n", me->no,
403       p->dest->no);
404
405   p->messages_received++;
406   p->bytes_received += TEST_MESSAGE_SIZE;
407   p->me->total_messages_received++;
408   p->me->total_bytes_received += TEST_MESSAGE_SIZE;
409
410   if (GNUNET_YES == test_core)
411   {
412     GNUNET_assert (NULL == p->cth);
413     p->cth = GNUNET_CORE_notify_transmit_ready (me->ch, GNUNET_NO, 0,
414         GNUNET_TIME_UNIT_MINUTES, &p->dest->id, TEST_MESSAGE_SIZE,
415         &comm_send_pong_ready, p);
416   }
417   else
418   {
419     GNUNET_assert (NULL == p->tth);
420     p->tth = GNUNET_TRANSPORT_notify_transmit_ready (me->th, &p->dest->id,
421         TEST_MESSAGE_SIZE, 0, GNUNET_TIME_UNIT_MINUTES, &comm_send_pong_ready,
422         p);
423   }
424   return GNUNET_OK;
425 }
426
427 static int
428 comm_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other,
429     const struct GNUNET_MessageHeader *message)
430 {
431   struct BenchmarkPeer *me = cls;
432   struct BenchmarkPartner *p = NULL;
433
434   if (NULL == (p = find_partner (me, other)))
435   {
436     GNUNET_break(0);
437     return GNUNET_SYSERR;
438   }
439
440   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
441       "Master [%u]: Received PONG from [%u], next message\n", me->no,
442       p->dest->no);
443
444   p->messages_received++;
445   p->bytes_received += TEST_MESSAGE_SIZE;
446   p->me->total_messages_received++;
447   p->me->total_bytes_received += TEST_MESSAGE_SIZE;
448   p->total_app_rtt += GNUNET_TIME_absolute_get_difference(p->last_message_sent,
449       GNUNET_TIME_absolute_get()).rel_value_us;
450
451   comm_schedule_send (p);
452   return GNUNET_OK;
453 }
454
455
456 static void
457 test_recv_cb (void *cls,
458                       const struct GNUNET_PeerIdentity * peer,
459                       const struct GNUNET_MessageHeader * message)
460 {
461   if (TEST_MESSAGE_SIZE != ntohs (message->size) ||
462       (TEST_MESSAGE_TYPE_PING != ntohs (message->type) &&
463       TEST_MESSAGE_TYPE_PONG != ntohs (message->type)))
464   {
465     return;
466   }
467   if (TEST_MESSAGE_TYPE_PING == ntohs (message->type))
468     comm_handle_ping (cls, peer, message);
469
470   if (TEST_MESSAGE_TYPE_PONG == ntohs (message->type))
471     comm_handle_pong (cls, peer, message);
472 }
473
474
475 static void
476 ats_performance_info_cb (void *cls, const struct GNUNET_HELLO_Address *address,
477     int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
478     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
479     const struct GNUNET_ATS_Information *ats, uint32_t ats_count)
480 {
481   struct BenchmarkPeer *me = cls;
482   struct BenchmarkPartner *p;
483   int c_a;
484   int log;
485   char *peer_id;
486
487   p = find_partner (me, &address->peer);
488   if (NULL == p)
489   {
490     /* This is not one of my partners
491      * Will happen since the peers will connect to each other due to gossiping
492      */
493     return;
494   }
495   peer_id = GNUNET_strdup (GNUNET_i2s (&me->id));
496
497   log = GNUNET_NO;
498   if ((p->bandwidth_in != ntohl (bandwidth_in.value__)) ||
499       (p->bandwidth_out != ntohl (bandwidth_out.value__)))
500       log = GNUNET_YES;
501   p->bandwidth_in = ntohl (bandwidth_in.value__);
502   p->bandwidth_out = ntohl (bandwidth_out.value__);
503
504   for (c_a = 0; c_a < ats_count; c_a++)
505   {
506     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s [%u] received ATS information: %s %s %u\n",
507         (GNUNET_YES == p->me->master) ? "Master" : "Slave",
508         p->me->no,
509         GNUNET_i2s (&p->dest->id),
510         GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)),
511         ntohl(ats[c_a].value));
512     switch (ntohl (ats[c_a].type ))
513     {
514       case GNUNET_ATS_ARRAY_TERMINATOR:
515         break;
516       case GNUNET_ATS_UTILIZATION_OUT:
517         if (p->ats_utilization_up != ntohl (ats[c_a].value))
518             log = GNUNET_YES;
519         p->ats_utilization_up = ntohl (ats[c_a].value);
520
521         break;
522       case GNUNET_ATS_UTILIZATION_IN:
523         if (p->ats_utilization_down != ntohl (ats[c_a].value))
524             log = GNUNET_YES;
525         p->ats_utilization_down = ntohl (ats[c_a].value);
526         break;
527       case GNUNET_ATS_NETWORK_TYPE:
528         if (p->ats_network_type != ntohl (ats[c_a].value))
529             log = GNUNET_YES;
530         p->ats_network_type = ntohl (ats[c_a].value);
531         break;
532       case GNUNET_ATS_QUALITY_NET_DELAY:
533         if (p->ats_delay != ntohl (ats[c_a].value))
534             log = GNUNET_YES;
535         p->ats_delay = ntohl (ats[c_a].value);
536         break;
537       case GNUNET_ATS_QUALITY_NET_DISTANCE:
538         if (p->ats_distance != ntohl (ats[c_a].value))
539             log = GNUNET_YES;
540         p->ats_distance = ntohl (ats[c_a].value);
541         GNUNET_break (0);
542         break;
543       case GNUNET_ATS_COST_WAN:
544         if (p->ats_cost_wan != ntohl (ats[c_a].value))
545             log = GNUNET_YES;
546         p->ats_cost_wan = ntohl (ats[c_a].value);
547         break;
548       case GNUNET_ATS_COST_LAN:
549         if (p->ats_cost_lan != ntohl (ats[c_a].value))
550             log = GNUNET_YES;
551         p->ats_cost_lan = ntohl (ats[c_a].value);
552         break;
553       case GNUNET_ATS_COST_WLAN:
554         if (p->ats_cost_wlan != ntohl (ats[c_a].value))
555             log = GNUNET_YES;
556         p->ats_cost_wlan = ntohl (ats[c_a].value);
557         break;
558       default:
559         break;
560     }
561   }
562
563   if ((GNUNET_YES == logging) && (GNUNET_YES == log))
564     GNUNET_ATS_TEST_logging_now();
565
566   GNUNET_free(peer_id);
567 }
568
569
570 /*
571  * Start the performance test case
572  */
573 int
574 main (int argc, char *argv[])
575 {
576   char *tmp;
577   char *tmp_sep;
578   char *test_name;
579   char *conf_name;
580   char *comm_name;
581   char *dotexe;
582   char *prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
583   int c;
584
585   result = 0;
586
587   /* figure out testname */
588   tmp = strstr (argv[0], TESTNAME_PREFIX);
589   if (NULL == tmp)
590   {
591     fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
592     return GNUNET_SYSERR;
593   }
594   tmp += strlen (TESTNAME_PREFIX);
595   solver = GNUNET_strdup (tmp);
596   if (NULL != (dotexe = strstr (solver, ".exe")) && dotexe[4] == '\0')
597     dotexe[0] = '\0';
598   tmp_sep = strchr (solver, '_');
599   if (NULL == tmp_sep)
600   {
601     fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
602     GNUNET_free(solver);
603     return GNUNET_SYSERR;
604   }
605   tmp_sep[0] = '\0';
606   comm_name = GNUNET_strdup (&tmp_sep[1]);
607   tmp_sep = strchr (comm_name, '_');
608   if (NULL == tmp_sep)
609   {
610     fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
611     GNUNET_free(solver);
612     return GNUNET_SYSERR;
613   }
614   tmp_sep[0] = '\0';
615   for (c = 0; c <= strlen (comm_name); c++)
616     comm_name[c] = toupper (comm_name[c]);
617   if (0 == strcmp (comm_name, "CORE"))
618     test_core = GNUNET_YES;
619   else if (0 == strcmp (comm_name, "TRANSPORT"))
620     test_core = GNUNET_NO;
621   else
622   {
623     GNUNET_free (comm_name);
624     GNUNET_free (solver);
625     return GNUNET_SYSERR;
626   }
627
628   pref_str = GNUNET_strdup(tmp_sep + 1);
629
630   GNUNET_asprintf (&conf_name, "%s%s_%s.conf", TESTNAME_PREFIX, solver,
631       pref_str);
632   GNUNET_asprintf (&test_name, "%s%s_%s", TESTNAME_PREFIX, solver, pref_str);
633
634   for (c = 0; c <= strlen (pref_str); c++)
635     pref_str[c] = toupper (pref_str[c]);
636   pref_val = -1;
637
638   if (0 != strcmp (pref_str, "NONE"))
639   {
640     for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
641     {
642       if (0 == strcmp (pref_str, prefs[c]))
643       {
644         pref_val = c;
645         break;
646       }
647     }
648   }
649   else
650   {
651     /* abuse terminator to indicate no pref */
652     pref_val = GNUNET_ATS_PREFERENCE_END;
653   }
654   if (-1 == pref_val)
655   {
656     fprintf (stderr, "Unknown preference: `%s'\n", pref_str);
657     GNUNET_free(solver);
658     GNUNET_free(pref_str);
659     GNUNET_free (comm_name);
660     return -1;
661   }
662
663   for (c = 0; c < (argc - 1); c++)
664   {
665     if (0 == strcmp (argv[c], "-d"))
666       break;
667   }
668   if (c < argc - 1)
669   {
670     if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[c + 1], &perf_duration))
671         fprintf (stderr, "Failed to parse duration `%s'\n", argv[c + 1]);
672   }
673   else
674   {
675     perf_duration = BENCHMARK_DURATION;
676   }
677   fprintf (stderr, "Running benchmark for %llu secs\n", (unsigned long long) (perf_duration.rel_value_us) / (1000 * 1000));
678
679   for (c = 0; c < (argc - 1); c++)
680   {
681     if (0 == strcmp (argv[c], "-s"))
682       break;
683   }
684   if (c < argc - 1)
685   {
686     if ((0L != (num_slaves = strtol (argv[c + 1], NULL, 10)))
687         && (num_slaves >= 1))
688       fprintf (stderr, "Starting %u slave peers\n", num_slaves);
689     else
690       num_slaves = DEFAULT_SLAVES_NUM;
691   }
692   else
693     num_slaves = DEFAULT_SLAVES_NUM;
694
695   for (c = 0; c < (argc - 1); c++)
696   {
697     if (0 == strcmp (argv[c], "-m"))
698       break;
699   }
700   if (c < argc - 1)
701   {
702     if ((0L != (num_masters = strtol (argv[c + 1], NULL, 10)))
703         && (num_masters >= 2))
704       fprintf (stderr, "Starting %u master peers\n", num_masters);
705     else
706       num_masters = DEFAULT_MASTERS_NUM;
707   }
708   else
709     num_masters = DEFAULT_MASTERS_NUM;
710
711   logging = GNUNET_NO;
712   for (c = 0; c < argc; c++)
713   {
714     if (0 == strcmp (argv[c], "-l"))
715       logging = GNUNET_YES;
716   }
717
718   if (GNUNET_YES == logging)
719   {
720     for (c = 0; c < (argc - 1); c++)
721     {
722       if (0 == strcmp (argv[c], "-f"))
723         break;
724     }
725     if (c < argc - 1)
726     {
727       if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[c + 1], &log_frequency))
728           fprintf (stderr, "Failed to parse duration `%s'\n", argv[c + 1]);
729     }
730     else
731     {
732       log_frequency = LOGGING_FREQUENCY;
733     }
734     fprintf (stderr, "Using log frequency %llu ms\n",
735         (unsigned long long) (log_frequency.rel_value_us) / (1000));
736   }
737
738   GNUNET_asprintf (&testname, "%s_%s_%s",solver, comm_name, pref_str);
739
740   if (num_slaves < num_masters)
741   {
742     fprintf (stderr, "Number of master peers is lower than slaves! exit...\n");
743     GNUNET_free(test_name);
744     GNUNET_free(solver);
745     GNUNET_free(pref_str);
746     GNUNET_free (comm_name);
747     return GNUNET_SYSERR;
748   }
749
750   /**
751    * Core message handler to use for PING/PONG messages
752    */
753   static struct GNUNET_CORE_MessageHandler handlers[] = {
754       {&comm_handle_ping, TEST_MESSAGE_TYPE_PING, 0 },
755       {&comm_handle_pong, TEST_MESSAGE_TYPE_PONG, 0 },
756       { NULL, 0, 0 } };
757
758   /**
759    * Setup the topology
760    */
761   GNUNET_ATS_TEST_create_topology ("perf-ats", conf_name,
762       num_slaves, num_masters,
763       test_core,
764       &do_benchmark,
765       NULL, handlers,
766       &test_recv_cb,
767       &ats_performance_info_cb);
768
769   return result;
770 }
771
772 /* end of file perf_ats.c */