6198d1464c9f3784261a83a5d803afa7967f4c73
[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 "perf_ats.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 /**
44  * Connect peers with testbed
45  */
46 struct TestbedConnectOperation
47 {
48   /**
49    * The benchmarking master initiating this connection
50    */
51   struct BenchmarkPeer *master;
52
53   /**
54    * The benchmarking slave to connect to
55    */
56   struct BenchmarkPeer *slave;
57
58   /**
59    * Testbed operation to connect peers
60    */
61   struct GNUNET_TESTBED_Operation *connect_op;
62 };
63
64 /**
65  * Overall state of the performance benchmark
66  */
67 struct BenchmarkState
68 {
69   /* Are we connected to ATS service of all peers: GNUNET_YES/NO */
70   int connected_ATS_service;
71
72   /* Are we connected to CORE service of all peers: GNUNET_YES/NO */
73   int connected_COMM_service;
74
75   /* Are we connected to all peers: GNUNET_YES/NO */
76   int connected_PEERS;
77
78   /* Are we connected to all slave peers on CORE level: GNUNET_YES/NO */
79   int connected_CORE;
80
81   /* Are we connected to CORE service of all peers: GNUNET_YES/NO */
82   int benchmarking;
83 };
84
85 /**
86  * Shutdown task
87  */
88 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
89
90 /**
91  * Progress task
92  */
93 static GNUNET_SCHEDULER_TaskIdentifier progress_task;
94
95 /**
96  * Test result
97  */
98 static int result;
99
100 /**
101  * Test result logging
102  */
103 static int logging;
104
105 /**Test core (GNUNET_YES) or transport (GNUNET_NO)
106  */
107 static int test_core;
108
109 /**
110  * Solver string
111  */
112 static char *solver;
113
114 /**
115  * Preference string
116  */
117 static char *testname;
118
119 /**
120  * Preference string
121  */
122 static char *pref_str;
123
124 /**
125  * ATS preference value
126  */
127 static int pref_val;
128
129 /**
130  * Number master peers
131  */
132 static int num_masters;
133
134 /**
135  * Array of master peers
136  */
137 static  struct BenchmarkPeer *mps;
138
139 /**
140  * Number slave peers
141  */
142 static int num_slaves;
143 /**
144  * Array of slave peers
145  */
146 static struct BenchmarkPeer *sps;
147
148 /**
149  * Benchmark duration
150  */
151 static struct GNUNET_TIME_Relative perf_duration;
152
153 /**
154  * Logging frequency
155  */
156 static struct GNUNET_TIME_Relative log_frequency;
157
158 /**
159  * Benchmark state
160  */
161 static struct BenchmarkState state;
162
163 static void
164 evaluate ()
165 {
166   int c_m;
167   int c_s;
168   unsigned int duration;
169   struct BenchmarkPeer *mp;
170
171   duration = (perf_duration.rel_value_us / (1000 * 1000));
172   for (c_m = 0; c_m < num_masters; c_m++)
173   {
174     mp = &mps[c_m];
175     fprintf (stderr,
176         _("Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. = %u KiB/s\n"),
177         mp->no, mp->total_bytes_sent / 1024, duration,
178         (mp->total_bytes_sent / 1024) / duration,
179         mp->total_bytes_received / 1024, duration,
180         (mp->total_bytes_received / 1024) / duration);
181
182     for (c_s = 0; c_s < num_slaves; c_s++)
183     {
184       fprintf (stderr,
185           "%c Master [%u] -> Slave [%u]: sent %u KiB/s (%.2f \%), received %u KiB/s (%.2f \%)\n",
186           (mp->pref_partner == mp->partners[c_s].dest) ? '*' : ' ',
187           mp->no, mp->partners[c_s].dest->no,
188           (mp->partners[c_s].bytes_sent / 1024) / duration,
189           ((double) mp->partners[c_s].bytes_sent * 100) / mp->total_bytes_sent,
190           (mp->partners[c_s].bytes_received / 1024) / duration,
191           ((double) mp->partners[c_s].bytes_received * 100) / mp->total_bytes_received );
192     }
193   }
194 }
195
196 /**
197  * Shutdown nicely
198  *
199  * @param cls NULL
200  * @param tc the task context
201  */
202 static void
203 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
204 {
205   int c_m;
206   int c_s;
207   int c_op;
208
209   if (GNUNET_YES == logging)
210     perf_logging_stop();
211
212   shutdown_task = GNUNET_SCHEDULER_NO_TASK;
213   if (GNUNET_SCHEDULER_NO_TASK != progress_task)
214   {
215     fprintf (stderr, "0\n");
216     GNUNET_SCHEDULER_cancel (progress_task);
217   }
218   progress_task = GNUNET_SCHEDULER_NO_TASK;
219
220   evaluate ();
221   state.benchmarking = GNUNET_NO;
222   GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n"));
223
224   for (c_m = 0; c_m < num_masters; c_m++)
225   {
226     if (NULL != mps[c_m].peer_id_op)
227     {
228       GNUNET_TESTBED_operation_done (mps[c_m].peer_id_op);
229       mps[c_m].peer_id_op = NULL;
230     }
231
232     if (GNUNET_SCHEDULER_NO_TASK != mps[c_m].ats_task)
233       GNUNET_SCHEDULER_cancel (mps[c_m].ats_task);
234     mps[c_m].ats_task = GNUNET_SCHEDULER_NO_TASK;
235
236     for (c_op = 0; c_op < num_slaves; c_op++)
237     {
238
239       if (NULL != mps[c_m].partners[c_op].cth)
240       {
241         GNUNET_CORE_notify_transmit_ready_cancel (mps[c_m].partners[c_op].cth);
242         mps[c_m].partners[c_op].cth = NULL;
243       }
244       if (NULL != mps[c_m].partners[c_op].tth)
245       {
246         GNUNET_TRANSPORT_notify_transmit_ready_cancel (mps[c_m].partners[c_op].tth);
247         mps[c_m].partners[c_op].tth = NULL;
248       }
249
250
251       if (NULL != mps[c_m].core_connect_ops[c_op].connect_op)
252       {
253         GNUNET_log(GNUNET_ERROR_TYPE_INFO,
254             _("Failed to connect peer 0 and %u\n"), c_op);
255         GNUNET_TESTBED_operation_done (
256             mps[c_m].core_connect_ops[c_op].connect_op);
257         mps[c_m].core_connect_ops[c_op].connect_op = NULL;
258         result = 1;
259       }
260     }
261
262     if (NULL != mps[c_m].ats_perf_op)
263     {
264       GNUNET_TESTBED_operation_done (mps[c_m].ats_perf_op);
265       mps[c_m].ats_perf_op = NULL;
266     }
267
268     if (NULL != mps[c_m].comm_op)
269     {
270       GNUNET_TESTBED_operation_done (mps[c_m].comm_op);
271       mps[c_m].comm_op = NULL;
272     }
273     GNUNET_free(mps[c_m].core_connect_ops);
274     GNUNET_free(mps[c_m].partners);
275     mps[c_m].partners = NULL;
276   }
277
278   for (c_s = 0; c_s < num_slaves; c_s++)
279   {
280     if (NULL != sps[c_s].peer_id_op)
281     {
282       GNUNET_TESTBED_operation_done (sps[c_s].peer_id_op);
283       sps[c_s].peer_id_op = NULL;
284     }
285
286     for (c_op = 0; c_op < num_slaves; c_op++)
287     {
288       if (NULL != sps[c_s].partners[c_op].cth)
289       {
290         GNUNET_CORE_notify_transmit_ready_cancel (sps[c_s].partners[c_op].cth);
291         sps[c_s].partners[c_op].cth = NULL;
292       }
293
294       if (NULL != sps[c_s].partners[c_op].tth)
295       {
296         GNUNET_TRANSPORT_notify_transmit_ready_cancel (sps[c_s].partners[c_op].tth);
297         sps[c_s].partners[c_op].tth = NULL;
298       }
299     }
300
301     if (NULL != sps[c_s].ats_perf_op)
302     {
303       GNUNET_TESTBED_operation_done (sps[c_s].ats_perf_op);
304       sps[c_s].ats_perf_op = NULL;
305     }
306     if (NULL != sps[c_s].comm_op)
307     {
308       GNUNET_TESTBED_operation_done (sps[c_s].comm_op);
309       sps[c_s].comm_op = NULL;
310     }
311
312     GNUNET_free(sps[c_s].partners);
313     sps[c_s].partners = NULL;
314   }
315
316   GNUNET_SCHEDULER_shutdown ();
317 }
318
319 static struct BenchmarkPeer *
320 find_peer (const struct GNUNET_PeerIdentity * peer)
321 {
322   int c_p;
323
324   for (c_p = 0; c_p < num_masters; c_p++)
325   {
326     if (0 == memcmp (&mps[c_p].id, peer, sizeof(struct GNUNET_PeerIdentity)))
327       return &mps[c_p];
328   }
329
330   for (c_p = 0; c_p < num_slaves; c_p++)
331   {
332     if (0 == memcmp (&sps[c_p].id, peer, sizeof(struct GNUNET_PeerIdentity)))
333       return &sps[c_p];
334   }
335   return NULL ;
336 }
337
338 /**
339  * Controller event callback
340  *
341  * @param cls NULL
342  * @param event the controller event
343  */
344 static void
345 controller_event_cb (void *cls,
346     const struct GNUNET_TESTBED_EventInformation *event)
347 {
348   //struct BenchmarkPeer *p = cls;
349   switch (event->type)
350   {
351   case GNUNET_TESTBED_ET_CONNECT:
352     break;
353   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
354     break;
355   default:
356     GNUNET_break(0);
357     result = 2;
358     GNUNET_SCHEDULER_cancel (shutdown_task);
359     shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL );
360   }
361 }
362
363 static size_t
364 comm_send_ready (void *cls, size_t size, void *buf)
365 {
366   static char msgbuf[TEST_MESSAGE_SIZE];
367   struct BenchmarkPartner *p = cls;
368   struct GNUNET_MessageHeader *msg;
369
370   if (GNUNET_YES == test_core)
371     p->cth = NULL;
372   else
373     p->tth = NULL;
374
375   if (NULL == buf)
376   {
377     GNUNET_break (0);
378     return 0;
379   }
380   if (size < TEST_MESSAGE_SIZE)
381   {
382     GNUNET_break (0);
383     return 0;
384   }
385
386   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Master [%u]: Sending PING to [%u]\n",
387       p->me->no, p->dest->no);
388
389   p->messages_sent++;
390   p->bytes_sent += TEST_MESSAGE_SIZE;
391   p->me->total_messages_sent++;
392   p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
393
394   msg = (struct GNUNET_MessageHeader *) &msgbuf;
395   memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
396   msg->type = htons (TEST_MESSAGE_TYPE_PING);
397   msg->size = htons (TEST_MESSAGE_SIZE);
398   memcpy (buf, msg, TEST_MESSAGE_SIZE);
399   return TEST_MESSAGE_SIZE;
400 }
401
402 static void
403 comm_schedule_send (struct BenchmarkPartner *p)
404 {
405   if (GNUNET_YES == test_core)
406   {
407     p->cth = GNUNET_CORE_notify_transmit_ready (
408       p->me->ch, GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES, &p->dest->id,
409       TEST_MESSAGE_SIZE, &comm_send_ready, p);
410   }
411   else
412   {
413     p->tth = GNUNET_TRANSPORT_notify_transmit_ready (
414       p->me->th, &p->dest->id, TEST_MESSAGE_SIZE, 0,GNUNET_TIME_UNIT_MINUTES,
415       &comm_send_ready, p);
416   }
417
418 }
419
420 static void
421 print_progress ()
422 {
423   static int calls;
424   progress_task = GNUNET_SCHEDULER_NO_TASK;
425
426   fprintf (stderr, "%llu..",
427       (long long unsigned) perf_duration.rel_value_us / (1000 * 1000) - calls);
428   calls++;
429
430   progress_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
431       &print_progress, NULL );
432 }
433
434 static void
435 ats_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
436 {
437   struct BenchmarkPeer *me = cls;
438
439   me->ats_task = GNUNET_SCHEDULER_NO_TASK;
440
441   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, " Master [%u] set preference for slave [%u] to %f\n",
442       me->no, me->pref_partner->no, me->pref_value);
443   GNUNET_ATS_performance_change_preference (me->ats_perf_handle,
444       &me->pref_partner->id,
445       pref_val, me->pref_value, GNUNET_ATS_PREFERENCE_END);
446   me->pref_value += TEST_ATS_PREFRENCE_DELTA;
447   me->ats_task = GNUNET_SCHEDULER_add_delayed (TEST_ATS_PREFRENCE_FREQUENCY,
448       &ats_pref_task, cls);
449 }
450
451 static void
452 do_benchmark ()
453 {
454   int c_m;
455   int c_s;
456
457   if ((state.connected_ATS_service == GNUNET_NO)
458       || (state.connected_COMM_service == GNUNET_NO)
459       || (state.connected_PEERS == GNUNET_NO)
460       || (state.connected_CORE == GNUNET_NO))
461     return;
462
463   state.benchmarking = GNUNET_YES;
464   GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking start\n"));
465
466   if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
467     GNUNET_SCHEDULER_cancel (shutdown_task);
468   shutdown_task = GNUNET_SCHEDULER_add_delayed (perf_duration,
469       &do_shutdown, NULL );
470
471   progress_task = GNUNET_SCHEDULER_add_now (&print_progress, NULL );
472
473   /* Start sending test messages */
474   for (c_m = 0; c_m < num_masters; c_m++)
475   {
476     for (c_s = 0; c_s < num_slaves; c_s++)
477       comm_schedule_send (&mps[c_m].partners[c_s]);
478     if (pref_val != GNUNET_ATS_PREFERENCE_END)
479       mps[c_m].ats_task = GNUNET_SCHEDULER_add_now (&ats_pref_task, &mps[c_m]);
480   }
481   if (GNUNET_YES == logging)
482     perf_logging_start (log_frequency, testname, mps, num_masters);
483
484 }
485
486 static void
487 connect_completion_callback (void *cls, struct GNUNET_TESTBED_Operation *op,
488     const char *emsg)
489 {
490   struct TestbedConnectOperation *cop = cls;
491   static int ops = 0;
492   int c;
493   if (NULL == emsg)
494   {
495     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
496         _("Connected master [%u] with slave [%u]\n"), cop->master->no,
497         cop->slave->no);
498   }
499   else
500   {
501     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
502         _("Failed to connect master peer [%u] with slave [%u]\n"),
503         cop->master->no, cop->slave->no);
504     GNUNET_break(0);
505     if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
506       GNUNET_SCHEDULER_cancel (shutdown_task);
507     shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
508   }
509   GNUNET_TESTBED_operation_done (op);
510   ops++;
511   for (c = 0; c < num_slaves; c++)
512   {
513     if (cop == &cop->master->core_connect_ops[c])
514       cop->master->core_connect_ops[c].connect_op = NULL;
515   }
516   if (ops == num_masters * num_slaves)
517   {
518     state.connected_PEERS = GNUNET_YES;
519     GNUNET_SCHEDULER_add_now (&do_benchmark, NULL );
520   }
521 }
522
523 static void
524 do_connect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
525 {
526   int c_m;
527   int c_s;
528   struct BenchmarkPeer *p;
529
530   if ((state.connected_ATS_service == GNUNET_NO)
531       || (state.connected_COMM_service == GNUNET_NO))
532     return;
533
534   GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Connecting peers on CORE level\n"));
535
536   for (c_m = 0; c_m < num_masters; c_m++)
537   {
538     p = &mps[c_m];
539     p->core_connect_ops = GNUNET_malloc (num_slaves *
540         sizeof (struct TestbedConnectOperation));
541
542     for (c_s = 0; c_s < num_slaves; c_s++)
543     {
544       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
545           _("Connecting master [%u] with slave [%u]\n"), p->no, sps[c_s].no);
546       p->core_connect_ops[c_s].master = p;
547       p->core_connect_ops[c_s].slave = &sps[c_s];
548       p->core_connect_ops[c_s].connect_op = GNUNET_TESTBED_overlay_connect (
549           NULL, &connect_completion_callback, &p->core_connect_ops[c_s],
550           sps[c_s].peer, p->peer);
551       if (NULL == p->core_connect_ops[c_s].connect_op)
552       {
553         GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
554             _("Could not connect master [%u] and slave [%u]\n"), p->no,
555             sps[c_s].no);
556         GNUNET_break(0);
557         if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
558           GNUNET_SCHEDULER_cancel (shutdown_task);
559         shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
560         return;
561       }
562     }
563   }
564 }
565
566 /**
567  * Method called whenever a given peer connects.
568  *
569  * @param cls closure
570  * @param peer peer identity this notification is about
571  */
572 static void
573 comm_connect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
574 {
575   struct BenchmarkPeer *me = cls;
576   struct BenchmarkPeer *remote;
577   char *id;
578   int c;
579   int completed;
580
581   remote = find_peer (peer);
582   if (NULL == remote)
583   {
584     GNUNET_break(0);
585     return;
586   }
587
588   id = GNUNET_strdup (GNUNET_i2s (&me->id));
589   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s [%u] `%s' connected to %s [%u] %s\n",
590       (me->master == GNUNET_YES) ? "Master": "Slave", me->no, id,
591       (remote->master == GNUNET_YES) ? "Master": "Slave", remote->no,
592       GNUNET_i2s (peer));
593
594   me->core_connections++;
595   if ((GNUNET_YES == me->master) && (GNUNET_NO == remote->master)
596       && (GNUNET_NO == state.connected_CORE))
597   {
598     me->core_slave_connections++;
599
600     if (me->core_slave_connections == num_slaves)
601     {
602       GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Master [%u] connected all slaves\n",
603           me->no);
604     }
605     completed = GNUNET_YES;
606     for (c = 0; c < num_masters; c++)
607     {
608       if (mps[c].core_slave_connections != num_slaves)
609         completed = GNUNET_NO;
610     }
611     if (GNUNET_YES == completed)
612     {
613       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
614           "All master peers connected all slave peers\n", id,
615           GNUNET_i2s (peer));
616       state.connected_CORE = GNUNET_YES;
617       GNUNET_SCHEDULER_add_now (&do_benchmark, NULL );
618     }
619   }
620   GNUNET_free(id);
621 }
622
623 static void
624 comm_disconnect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
625 {
626   struct BenchmarkPeer *me = cls;
627   struct BenchmarkPeer *remote;
628   char *id;
629
630   remote = find_peer (peer);
631   if (NULL == remote)
632   {
633     GNUNET_break(0);
634     return;
635   }
636
637   id = GNUNET_strdup (GNUNET_i2s (&me->id));
638   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s disconnected from %s \n", id,
639       GNUNET_i2s (peer));
640   GNUNET_assert(me->core_connections > 0);
641   me->core_connections--;
642
643   if ((GNUNET_YES == state.benchmarking)
644       && ((GNUNET_YES == me->master) || (GNUNET_YES == remote->master)))
645   {
646     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
647         "%s disconnected from %s while benchmarking \n", id, GNUNET_i2s (peer));
648   }
649   GNUNET_free(id);
650 }
651
652 static size_t
653 comm_send_pong_ready (void *cls, size_t size, void *buf)
654 {
655   static char msgbuf[TEST_MESSAGE_SIZE];
656   struct BenchmarkPartner *p = cls;
657   struct GNUNET_MessageHeader *msg;
658
659   if (GNUNET_YES == test_core)
660     p->cth = NULL;
661   else
662     p->tth = NULL;
663
664   p->messages_sent++;
665   p->bytes_sent += TEST_MESSAGE_SIZE;
666   p->me->total_messages_sent++;
667   p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
668
669   msg = (struct GNUNET_MessageHeader *) &msgbuf;
670   memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
671   msg->type = htons (TEST_MESSAGE_TYPE_PONG);
672   msg->size = htons (TEST_MESSAGE_SIZE);
673   memcpy (buf, msg, TEST_MESSAGE_SIZE);
674
675   return TEST_MESSAGE_SIZE;
676 }
677
678 static int
679 comm_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other,
680     const struct GNUNET_MessageHeader *message)
681 {
682   int c_m;
683   struct BenchmarkPeer *me = cls;
684   struct BenchmarkPartner *p = NULL;
685   for (c_m = 0; c_m < num_masters; c_m++)
686   {
687     /* Find a partner with other as destination */
688     if (0 == memcmp (other, &me->partners[c_m].dest->id,
689             sizeof(struct GNUNET_PeerIdentity)))
690     {
691       p = &me->partners[c_m];
692       break;
693     }
694   }
695   if (NULL == p)
696   {
697     GNUNET_break(0);
698     return GNUNET_SYSERR;
699   }
700
701   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
702       "Slave [%u]: Received PING from [%u], sending PONG\n", me->no,
703       p->dest->no);
704
705   p->messages_received++;
706   p->bytes_received += TEST_MESSAGE_SIZE;
707   p->me->total_messages_received++;
708   p->me->total_bytes_received += TEST_MESSAGE_SIZE;
709
710   if (GNUNET_YES == test_core)
711   {
712     GNUNET_assert (NULL == p->cth);
713     p->cth = GNUNET_CORE_notify_transmit_ready (me->ch, GNUNET_NO, 0,
714         GNUNET_TIME_UNIT_MINUTES, &p->dest->id, TEST_MESSAGE_SIZE,
715         &comm_send_pong_ready, p);
716   }
717   else
718   {
719     GNUNET_assert (NULL == p->tth);
720     p->tth = GNUNET_TRANSPORT_notify_transmit_ready (me->th, &p->dest->id,
721         TEST_MESSAGE_SIZE, 0, GNUNET_TIME_UNIT_MINUTES, &comm_send_pong_ready,
722         p);
723   }
724   return GNUNET_OK;
725 }
726
727 static int
728 comm_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other,
729     const struct GNUNET_MessageHeader *message)
730 {
731   int c_s;
732   struct BenchmarkPeer *me = cls;
733   struct BenchmarkPartner *p = NULL;
734
735   for (c_s = 0; c_s < num_slaves; c_s++)
736   {
737     if (0
738         == memcmp (other, &me->partners[c_s].dest->id,
739             sizeof(struct GNUNET_PeerIdentity)))
740     {
741       p = &me->partners[c_s];
742       break;
743     }
744   }
745   if (NULL == p)
746   {
747     GNUNET_break(0);
748     return GNUNET_SYSERR;
749   }
750
751   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
752       "Master [%u]: Received PONG from [%u], next message\n", me->no,
753       p->dest->no);
754
755   p->messages_received++;
756   p->bytes_received += TEST_MESSAGE_SIZE;
757   p->me->total_messages_received++;
758   p->me->total_bytes_received += TEST_MESSAGE_SIZE;
759
760   comm_schedule_send (p);
761   return GNUNET_OK;
762 }
763
764 static void *
765 core_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
766 {
767   struct BenchmarkPeer *me = cls;
768
769   static const struct GNUNET_CORE_MessageHandler handlers[] = { {
770       &comm_handle_ping, TEST_MESSAGE_TYPE_PING, 0 }, { &comm_handle_pong,
771       TEST_MESSAGE_TYPE_PONG, 0 }, { NULL, 0, 0 } };
772
773   me->ch = GNUNET_CORE_connect (cfg, me, NULL, comm_connect_cb,
774       comm_disconnect_cb, NULL, GNUNET_NO, NULL, GNUNET_NO, handlers);
775   if (NULL == me->ch)
776     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create core connection \n");
777   return me->ch;
778 }
779
780 static void
781 core_disconnect_adapter (void *cls, void *op_result)
782 {
783   struct BenchmarkPeer *me = cls;
784
785   GNUNET_CORE_disconnect (me->ch);
786   me->ch = NULL;
787 }
788
789 static void
790 comm_connect_completion_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
791     void *ca_result, const char *emsg)
792 {
793   static int comm_done = 0;
794   if ((NULL != emsg) || (NULL == ca_result))
795   {
796     GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initialization failed, shutdown\n"));
797     GNUNET_break(0);
798     if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
799       GNUNET_SCHEDULER_cancel (shutdown_task);
800     shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
801     return;
802   }
803   comm_done++;
804
805   if (comm_done == num_slaves + num_masters)
806   {
807     GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connected to all %s services\n",
808         (GNUNET_YES == test_core) ? "CORE" : "TRANSPORT");
809     state.connected_COMM_service = GNUNET_YES;
810     GNUNET_SCHEDULER_add_now (&do_connect_peers, NULL );
811   }
812 }
813
814 static void
815 transport_recv_cb (void *cls,
816                    const struct GNUNET_PeerIdentity * peer,
817                    const struct GNUNET_MessageHeader * message)
818 {
819   if (TEST_MESSAGE_SIZE != ntohs (message->size) ||
820       (TEST_MESSAGE_TYPE_PING != ntohs (message->type) &&
821       TEST_MESSAGE_TYPE_PONG != ntohs (message->type)))
822   {
823     return;
824   }
825   if (TEST_MESSAGE_TYPE_PING == ntohs (message->type))
826     comm_handle_ping (cls, peer, message);
827
828   if (TEST_MESSAGE_TYPE_PONG == ntohs (message->type))
829     comm_handle_pong (cls, peer, message);
830 }
831
832
833 static void *
834 transport_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
835 {
836   struct BenchmarkPeer *me = cls;
837
838   me->th = GNUNET_TRANSPORT_connect (cfg, &me->id, me,  &transport_recv_cb,
839       &comm_connect_cb, &comm_disconnect_cb);
840   if (NULL == me->th)
841     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create transport connection \n");
842   return me->th;
843 }
844
845 static void
846 transport_disconnect_adapter (void *cls, void *op_result)
847 {
848   struct BenchmarkPeer *me = cls;
849
850   GNUNET_TRANSPORT_disconnect (me->th);
851   me->th = NULL;
852 }
853
854 static void
855 do_comm_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
856 {
857   int c_s;
858   int c_m;
859   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connecting to all %s services\n",
860       (GNUNET_YES == test_core) ? "CORE" : "TRANSPORT");
861   for (c_m = 0; c_m < num_masters; c_m++)
862   {
863     if (GNUNET_YES == test_core)
864       mps[c_m].comm_op = GNUNET_TESTBED_service_connect (NULL, mps[c_m].peer,
865         "core", &comm_connect_completion_cb, NULL, &core_connect_adapter,
866         &core_disconnect_adapter, &mps[c_m]);
867     else
868     {
869       mps[c_m].comm_op = GNUNET_TESTBED_service_connect (NULL, mps[c_m].peer,
870         "transport", &comm_connect_completion_cb, NULL, &transport_connect_adapter,
871         &transport_disconnect_adapter, &mps[c_m]);
872     }
873   }
874
875   for (c_s = 0; c_s < num_slaves; c_s++)
876   {
877     if (GNUNET_YES == test_core)
878       sps[c_s].comm_op = GNUNET_TESTBED_service_connect (NULL, sps[c_s].peer,
879         "core", &comm_connect_completion_cb, NULL, &core_connect_adapter,
880         &core_disconnect_adapter, &sps[c_s]);
881     else
882     {
883       sps[c_s].comm_op = GNUNET_TESTBED_service_connect (NULL, sps[c_s].peer,
884         "transport", &comm_connect_completion_cb, NULL, &transport_connect_adapter,
885         &transport_disconnect_adapter, &sps[c_s]);
886     }
887   }
888 }
889
890 static void
891 ats_performance_info_cb (void *cls, const struct GNUNET_HELLO_Address *address,
892     int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
893     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
894     const struct GNUNET_ATS_Information *ats, uint32_t ats_count)
895 {
896   struct BenchmarkPeer *me = cls;
897   int c_a;
898   char *peer_id;
899
900   peer_id = GNUNET_strdup (GNUNET_i2s (&me->id));
901   for (c_a = 0; c_a < ats_count; c_a++)
902   {
903     /*GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("%c %03u: %s %s %u\n"),
904      (GNUNET_YES == p->master) ? 'M' : 'S',
905      p->no,
906      GNUNET_i2s (&address->peer),
907      GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)),
908      ntohl(ats[c_a].value));*/
909   }
910 #if 0
911   if ((GNUNET_YES == me->master)
912       && (0 == memcmp (&address->peer, &me->destination->id,
913               sizeof(struct GNUNET_PeerIdentity))))
914   {
915     GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Bandwidth for master %u: %lu %lu\n",
916         me->no, (long unsigned int ) ntohl (bandwidth_in.value__),
917         (long unsigned int ) ntohl (bandwidth_in.value__));
918   }
919
920   store_information (&bp->id, address, address_active, bandwidth_in,
921       bandwidth_out, ats, ats_count);
922 #endif
923   GNUNET_free(peer_id);
924 }
925
926 static void *
927 ats_perf_connect_adapter (void *cls,
928     const struct GNUNET_CONFIGURATION_Handle *cfg)
929 {
930   struct BenchmarkPeer *me = cls;
931
932   me->ats_perf_handle = GNUNET_ATS_performance_init (cfg,
933       &ats_performance_info_cb, me);
934   if (NULL == me->ats_perf_handle)
935     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
936         "Failed to create ATS performance handle \n");
937   return me->ats_perf_handle;
938 }
939
940 static void
941 ats_perf_disconnect_adapter (void *cls, void *op_result)
942 {
943   struct BenchmarkPeer *me = cls;
944
945   GNUNET_ATS_performance_done (me->ats_perf_handle);
946   me->ats_perf_handle = NULL;
947 }
948
949 static void
950 ats_connect_completion_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
951     void *ca_result, const char *emsg)
952 {
953   static int op_done = 0;
954
955   if ((NULL != emsg) || (NULL == ca_result))
956   {
957     GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initialization failed, shutdown\n"));
958     GNUNET_break(0);
959     if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
960       GNUNET_SCHEDULER_cancel (shutdown_task);
961     shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
962     return;
963   }
964   op_done++;
965   if (op_done == (num_masters + num_slaves))
966   {
967     GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connected to all ATS services\n");
968     state.connected_ATS_service = GNUNET_YES;
969     GNUNET_SCHEDULER_add_now (&do_comm_connect, NULL );
970   }
971 }
972
973 static void
974 do_connect_ats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
975 {
976   int c_m;
977   int c_s;
978
979   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connecting to all ATS services\n");
980   for (c_m = 0; c_m < num_masters; c_m++)
981   {
982     mps[c_m].ats_perf_op = GNUNET_TESTBED_service_connect (NULL, mps[c_m].peer,
983         "ats", ats_connect_completion_cb, NULL, &ats_perf_connect_adapter,
984         &ats_perf_disconnect_adapter, &mps[c_m]);
985
986   }
987
988   for (c_s = 0; c_s < num_slaves; c_s++)
989   {
990     sps[c_s].ats_perf_op = GNUNET_TESTBED_service_connect (NULL, sps[c_s].peer,
991         "ats", ats_connect_completion_cb, NULL, &ats_perf_connect_adapter,
992         &ats_perf_disconnect_adapter, &sps[c_s]);
993   }
994
995 }
996
997 static void
998 peerinformation_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op,
999     const struct GNUNET_TESTBED_PeerInformation*pinfo, const char *emsg)
1000 {
1001   struct BenchmarkPeer *p = cb_cls;
1002   static int done = 0;
1003
1004   GNUNET_assert(pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY);
1005
1006   p->id = *pinfo->result.id;
1007   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "%s [%u] has peer id `%s'\n",
1008       (p->master == GNUNET_YES) ? "Master" : "Slave", p->no,
1009       GNUNET_i2s (&p->id));
1010
1011   GNUNET_TESTBED_operation_done (op);
1012   p->peer_id_op = NULL;
1013   done++;
1014
1015   if (done == num_slaves + num_masters)
1016   {
1017     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1018         "Retrieved all peer ID, connect to ATS\n");
1019     GNUNET_SCHEDULER_add_now (&do_connect_ats, NULL );
1020   }
1021 }
1022
1023 /**
1024  * Signature of a main function for a testcase.
1025  *
1026  * @param cls closure
1027  * @param num_peers number of peers in 'peers'
1028  * @param peers_ handle to peers run in the testbed
1029  * @param links_succeeded the number of overlay link connection attempts that
1030  *          succeeded
1031  * @param links_failed the number of overlay link connection attempts that
1032  *          failed
1033  */
1034 static void
1035 main_run (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers,
1036     struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded,
1037     unsigned int links_failed)
1038 {
1039   int c_m;
1040   int c_s;
1041   GNUNET_assert(NULL == cls);
1042   GNUNET_assert(num_masters + num_slaves == num_peers);
1043   GNUNET_assert(NULL != peers_);
1044
1045   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1046       _("Benchmarking solver `%s' on preference `%s' with %u master and %u slave peers\n"),
1047       solver, pref_str, num_masters, num_slaves);
1048
1049   shutdown_task = GNUNET_SCHEDULER_add_delayed (
1050       GNUNET_TIME_relative_multiply (TEST_TIMEOUT, num_masters + num_slaves),
1051       &do_shutdown, NULL );
1052
1053   /* Setup master peers */
1054   for (c_m = 0; c_m < num_masters; c_m++)
1055   {
1056     GNUNET_assert(NULL != peers_[c_m]);
1057     mps[c_m].peer = peers_[c_m];
1058     mps[c_m].no = c_m;
1059     mps[c_m].master = GNUNET_YES;
1060     mps[c_m].pref_partner = &sps[c_m];
1061     mps[c_m].pref_value = TEST_ATS_PREFRENCE_START;
1062     mps[c_m].partners =
1063         GNUNET_malloc (num_slaves * sizeof (struct BenchmarkPeer));
1064     mps[c_m].num_partners = num_slaves;
1065     /* Initialize partners */
1066     for (c_s = 0; c_s < num_slaves; c_s++)
1067     {
1068       mps[c_m].partners[c_s].me = &mps[c_m];
1069       mps[c_m].partners[c_s].dest = &sps[c_s];
1070     }
1071     mps[c_m].peer_id_op = GNUNET_TESTBED_peer_get_information (mps[c_m].peer,
1072         GNUNET_TESTBED_PIT_IDENTITY, &peerinformation_cb, &mps[c_m]);
1073   }
1074
1075   /* Setup slave peers */
1076   for (c_s = 0; c_s < num_slaves; c_s++)
1077   {
1078     GNUNET_assert(NULL != peers_[c_s + num_masters]);
1079     sps[c_s].peer = peers_[c_s + num_masters];
1080     sps[c_s].no = c_s + num_masters;
1081     sps[c_s].master = GNUNET_NO;
1082     sps[c_s].partners =
1083         GNUNET_malloc (num_masters * sizeof (struct BenchmarkPeer));
1084     sps[c_s].num_partners = num_masters;
1085     /* Initialize partners */
1086     for (c_m = 0; c_m < num_masters; c_m++)
1087     {
1088       sps[c_s].partners[c_m].me = &sps[c_s];
1089       sps[c_s].partners[c_m].dest = &mps[c_m];
1090     }
1091     sps[c_s].peer_id_op = GNUNET_TESTBED_peer_get_information (sps[c_s].peer,
1092         GNUNET_TESTBED_PIT_IDENTITY, &peerinformation_cb, &sps[c_s]);
1093   }
1094 }
1095
1096 int
1097 main (int argc, char *argv[])
1098 {
1099   char *tmp;
1100   char *tmp_sep;
1101   char *test_name;
1102   char *conf_name;
1103   char *comm_name;
1104   char *dotexe;
1105   char *prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
1106   int c;
1107
1108   result = 0;
1109
1110   /* figure out testname */
1111   tmp = strstr (argv[0], TESTNAME_PREFIX);
1112   if (NULL == tmp)
1113   {
1114     fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1115     return GNUNET_SYSERR;
1116   }
1117   tmp += strlen (TESTNAME_PREFIX);
1118   solver = GNUNET_strdup (tmp);
1119   if (NULL != (dotexe = strstr (solver, ".exe")) && dotexe[4] == '\0')
1120     dotexe[0] = '\0';
1121   tmp_sep = strchr (solver, '_');
1122   if (NULL == tmp_sep)
1123   {
1124     fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1125     GNUNET_free(solver);
1126     return GNUNET_SYSERR;
1127   }
1128   tmp_sep[0] = '\0';
1129   comm_name = GNUNET_strdup (&tmp_sep[1]);
1130   tmp_sep = strchr (comm_name, '_');
1131   if (NULL == tmp_sep)
1132   {
1133     fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1134     GNUNET_free(solver);
1135     return GNUNET_SYSERR;
1136   }
1137   tmp_sep[0] = '\0';
1138   for (c = 0; c <= strlen (comm_name); c++)
1139     comm_name[c] = toupper (comm_name[c]);
1140   if (0 == strcmp (comm_name, "CORE"))
1141     test_core = GNUNET_YES;
1142   else if (0 == strcmp (comm_name, "TRANSPORT"))
1143     test_core = GNUNET_NO;
1144   else
1145   {
1146     GNUNET_free (comm_name);
1147     GNUNET_free (solver);
1148     return GNUNET_SYSERR;
1149   }
1150
1151   pref_str = GNUNET_strdup(tmp_sep + 1);
1152
1153   GNUNET_asprintf (&conf_name, "%s%s_%s.conf", TESTNAME_PREFIX, solver,
1154       pref_str);
1155   GNUNET_asprintf (&test_name, "%s%s_%s", TESTNAME_PREFIX, solver, pref_str);
1156
1157   for (c = 0; c <= strlen (pref_str); c++)
1158     pref_str[c] = toupper (pref_str[c]);
1159   pref_val = -1;
1160
1161   if (0 != strcmp (pref_str, "NONE"))
1162   {
1163     for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
1164     {
1165       if (0 == strcmp (pref_str, prefs[c]))
1166       {
1167         pref_val = c;
1168         break;
1169       }
1170     }
1171   }
1172   else
1173   {
1174     /* abuse terminator to indicate no pref */
1175     pref_val = GNUNET_ATS_PREFERENCE_END;
1176   }
1177   if (-1 == pref_val)
1178   {
1179     fprintf (stderr, "Unknown preference: `%s'\n", pref_str);
1180     GNUNET_free(solver);
1181     GNUNET_free(pref_str);
1182     GNUNET_free (comm_name);
1183     return -1;
1184   }
1185
1186   for (c = 0; c < (argc - 1); c++)
1187   {
1188     if (0 == strcmp (argv[c], "-d"))
1189       break;
1190   }
1191   if (c < argc - 1)
1192   {
1193     if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[c + 1], &perf_duration))
1194         fprintf (stderr, "Failed to parse duration `%s'\n", argv[c + 1]);
1195   }
1196   else
1197   {
1198     perf_duration = BENCHMARK_DURATION;
1199   }
1200   fprintf (stderr, "Running benchmark for %llu secs\n", (unsigned long long) (perf_duration.rel_value_us) / (1000 * 1000));
1201
1202   for (c = 0; c < (argc - 1); c++)
1203   {
1204     if (0 == strcmp (argv[c], "-s"))
1205       break;
1206   }
1207   if (c < argc - 1)
1208   {
1209     if ((0L != (num_slaves = strtol (argv[c + 1], NULL, 10)))
1210         && (num_slaves >= 1))
1211       fprintf (stderr, "Starting %u slave peers\n", num_slaves);
1212     else
1213       num_slaves = DEFAULT_SLAVES_NUM;
1214   }
1215   else
1216     num_slaves = DEFAULT_SLAVES_NUM;
1217
1218   for (c = 0; c < (argc - 1); c++)
1219   {
1220     if (0 == strcmp (argv[c], "-m"))
1221       break;
1222   }
1223   if (c < argc - 1)
1224   {
1225     if ((0L != (num_masters = strtol (argv[c + 1], NULL, 10)))
1226         && (num_masters >= 2))
1227       fprintf (stderr, "Starting %u master peers\n", num_masters);
1228     else
1229       num_masters = DEFAULT_MASTERS_NUM;
1230   }
1231   else
1232     num_masters = DEFAULT_MASTERS_NUM;
1233
1234   logging = GNUNET_NO;
1235   for (c = 0; c < argc; c++)
1236   {
1237     if (0 == strcmp (argv[c], "-l"))
1238       logging = GNUNET_YES;
1239   }
1240
1241   if (GNUNET_YES == logging)
1242   {
1243     for (c = 0; c < (argc - 1); c++)
1244     {
1245       if (0 == strcmp (argv[c], "-f"))
1246         break;
1247     }
1248     if (c < argc - 1)
1249     {
1250       if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[c + 1], &log_frequency))
1251           fprintf (stderr, "Failed to parse duration `%s'\n", argv[c + 1]);
1252     }
1253     else
1254     {
1255       log_frequency = LOGGING_FREQUENCY;
1256     }
1257     fprintf (stderr, "Using log frequency %llu ms\n",
1258         (unsigned long long) (log_frequency.rel_value_us) / (1000));
1259   }
1260
1261   GNUNET_asprintf (&testname, "%s_%s_%s",solver, comm_name, pref_str);
1262
1263   if (num_slaves < num_masters)
1264   {
1265     fprintf (stderr, "Number of master peers is lower than slaves! exit...\n");
1266     GNUNET_free(test_name);
1267     GNUNET_free(solver);
1268     GNUNET_free(pref_str);
1269     GNUNET_free (comm_name);
1270     return GNUNET_SYSERR;
1271   }
1272
1273   state.connected_ATS_service = GNUNET_NO;
1274   state.connected_COMM_service = GNUNET_NO;
1275   state.connected_PEERS = GNUNET_NO;
1276   state.benchmarking = GNUNET_NO;
1277   state.connected_PEERS = GNUNET_NO;
1278
1279   mps = GNUNET_malloc (num_masters * sizeof (struct BenchmarkPeer));
1280   sps = GNUNET_malloc (num_slaves * sizeof (struct BenchmarkPeer));
1281
1282   /* Start topology */
1283   uint64_t event_mask;
1284   event_mask = 0;
1285   event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
1286   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
1287   (void) GNUNET_TESTBED_test_run ("perf-ats", conf_name,
1288       num_slaves + num_masters, event_mask, &controller_event_cb, NULL,
1289       &main_run, NULL );
1290
1291   GNUNET_free(solver);
1292   GNUNET_free(pref_str);
1293   GNUNET_free(conf_name);
1294   GNUNET_free(test_name);
1295   GNUNET_free(testname);
1296   GNUNET_free (comm_name);
1297   GNUNET_free(mps);
1298   GNUNET_free(sps);
1299
1300   return result;
1301 }
1302
1303 /* end of file perf_ats.c */