b5c57bb94810538a7a37191c797ef39fd0a05f5f
[oweals/gnunet.git] / src / ats / gnunet-ats-solver-eval.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-tests/ats-testing-experiment.c
22  * @brief ats benchmark: controlled experiment execution
23  * @author Christian Grothoff
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet-ats-solver-eval.h"
29
30
31 #define BIG_M_STRING "unlimited"
32
33 static struct Experiment *e;
34
35 static struct GNUNET_ATS_TESTING_SolverHandle *sh;
36
37 /**
38  * cmd option -e: experiment file
39  */
40 static char *opt_exp_file;
41
42 static char *opt_solver;
43
44 /**
45  * cmd option -l: enable logging
46  */
47 static int opt_log;
48
49 /**
50  * cmd option -p: enable plots
51  */
52 static int opt_plot;
53
54 /**
55  * cmd option -v: verbose logs
56  */
57 static int opt_verbose;
58
59 static int res;
60
61 static void
62 end_now ();
63
64 static char *
65 print_generator_type (enum GeneratorType g)
66 {
67   switch (g) {
68     case GNUNET_ATS_TEST_TG_CONSTANT:
69       return "CONSTANT";
70     case GNUNET_ATS_TEST_TG_LINEAR:
71       return "LINEAR";
72     case GNUNET_ATS_TEST_TG_RANDOM:
73       return "RANDOM";
74     case GNUNET_ATS_TEST_TG_SINUS:
75       return "SINUS";
76     default:
77       return "INVALID";
78       break;
79   }
80 }
81
82 /**
83  * Property Generators
84  */
85
86 static struct PropertyGenerator *prop_gen_head;
87 static struct PropertyGenerator *prop_gen_tail;
88
89 static double
90 get_property (struct PropertyGenerator *pg)
91 {
92   struct GNUNET_TIME_Relative time_delta;
93   double delta_value;
94   double pref_value;
95
96   /* Calculate the current preference value */
97   switch (pg->type) {
98     case GNUNET_ATS_TEST_TG_CONSTANT:
99       pref_value = pg->base_value;
100       break;
101     case GNUNET_ATS_TEST_TG_LINEAR:
102       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
103       /* Calculate point of time in the current period */
104       time_delta.rel_value_us = time_delta.rel_value_us %
105           pg->duration_period.rel_value_us;
106       delta_value = ((double) time_delta.rel_value_us  /
107           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
108       if ((pg->max_value < pg->base_value) &&
109           ((pg->max_value - pg->base_value) > pg->base_value))
110       {
111         /* This will cause an underflow */
112         GNUNET_break (0);
113       }
114       pref_value = pg->base_value + delta_value;
115       break;
116     case GNUNET_ATS_TEST_TG_RANDOM:
117       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
118           10000 * (pg->max_value - pg->base_value)) / 10000;
119       pref_value = pg->base_value + delta_value;
120       break;
121     case GNUNET_ATS_TEST_TG_SINUS:
122       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
123       /* Calculate point of time in the current period */
124       time_delta.rel_value_us = time_delta.rel_value_us %
125           pg->duration_period.rel_value_us;
126       if ((pg->max_value - pg->base_value) > pg->base_value)
127       {
128         /* This will cause an underflow for second half of sinus period,
129          * will be detected in general when experiments are loaded */
130         GNUNET_break (0);
131       }
132       delta_value = (pg->max_value - pg->base_value) *
133           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
134               time_delta.rel_value_us);
135       pref_value = pg->base_value + delta_value;
136       break;
137     default:
138       pref_value = 0.0;
139       break;
140   }
141   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current property value is %f\n",
142       pref_value);
143   return pref_value;
144 }
145
146
147 static void
148 set_prop_task (void *cls,
149                     const struct GNUNET_SCHEDULER_TaskContext *tc)
150 {
151   struct PropertyGenerator *pg = cls;
152   double pref_value;
153   pg->set_task = GNUNET_SCHEDULER_NO_TASK;
154
155   pref_value = get_property (pg);
156
157   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
158       "Setting property for peer [%u] address [%u] for %s to %f\n",
159       pg->peer, pg->address_id,
160       GNUNET_ATS_print_property_type (pg->ats_property), pref_value);
161
162   /* set performance here!
163   GNUNET_ATS_performance_change_preference(p->me->ats_perf_handle,
164       &p->dest->id, p->pg->kind, pref_value, GNUNET_ATS_PREFERENCE_END);
165 */
166
167   switch (pg->ats_property) {
168     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
169       //p->pref_bandwidth = pref_value;
170       break;
171     case GNUNET_ATS_PREFERENCE_LATENCY:
172       //p->pref_delay = pref_value;
173       break;
174     default:
175       break;
176   }
177
178   pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
179       &set_prop_task, pg);
180
181 }
182
183 static struct PropertyGenerator *
184 find_prop_gen (unsigned int peer, unsigned int address,
185     uint32_t ats_property)
186 {
187   struct PropertyGenerator *cur;
188   for (cur = prop_gen_head; NULL != cur; cur = cur->next)
189     if ((cur->peer == peer) && (cur->address_id == address) &&
190         (cur->ats_property == ats_property))
191       return cur;
192   return NULL;
193 }
194
195 void
196 GNUNET_ATS_solver_generate_property_stop (struct PropertyGenerator *pg)
197 {
198   GNUNET_CONTAINER_DLL_remove (prop_gen_head, prop_gen_tail, pg);
199
200   if (GNUNET_SCHEDULER_NO_TASK != pg->set_task)
201   {
202     GNUNET_SCHEDULER_cancel (pg->set_task);
203     pg->set_task = GNUNET_SCHEDULER_NO_TASK;
204   }
205   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
206       "Removing old up preference generator peer [%u] address [%u] `%s'\n",
207       pg->peer, pg->address_id,
208       GNUNET_ATS_print_property_type(pg->ats_property));
209
210   GNUNET_free (pg);
211 }
212
213
214 /**
215  * Generate between the source master and the partner and set preferences with a
216  * value depending on the generator.
217  *
218  * @param src source
219  * @param dest partner
220  * @param type type of preferences to generate
221  * @param base_rate traffic base rate to send data with
222  * @param max_rate  traffic maximum rate to send data with
223  * @param period duration of a period of traffic generation (~ 1/frequency)
224  * @param duration how long to generate traffic
225  * @return the traffic generator
226  */
227 struct PropertyGenerator *
228 GNUNET_ATS_solver_generate_property_start (unsigned int peer,
229     unsigned int address_id,
230     enum GeneratorType type,
231     long int base_value,
232     long int value_rate,
233     struct GNUNET_TIME_Relative period,
234     struct GNUNET_TIME_Relative frequency,
235     uint32_t ats_property)
236 {
237   struct PropertyGenerator *pg;
238
239   pg = GNUNET_new (struct PropertyGenerator);
240   GNUNET_CONTAINER_DLL_insert (prop_gen_head, prop_gen_tail, pg);
241   pg->type = type;
242   pg->peer = peer;
243   pg->address_id = address_id;
244   pg->ats_property = ats_property;
245   pg->base_value = base_value;
246   pg->max_value = value_rate;
247   pg->duration_period = period;
248   pg->frequency = frequency;
249   pg->time_start = GNUNET_TIME_absolute_get();
250
251   switch (type) {
252     case GNUNET_ATS_TEST_TG_CONSTANT:
253       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
254           "Setting up constant property generator peer [%u] address [%u] `%s' max %u Bips\n",
255           pg->peer, pg->address_id,  GNUNET_ATS_print_property_type (ats_property),
256           base_value);
257       break;
258     case GNUNET_ATS_TEST_TG_LINEAR:
259       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
260           "Setting up linear property generator peer [%u] address [%u] `%s' min %u Bips max %u Bips\n",
261           pg->peer, pg->address_id, GNUNET_ATS_print_property_type(ats_property),
262           base_value, value_rate);
263       break;
264     case GNUNET_ATS_TEST_TG_SINUS:
265       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
266           "Setting up sinus property generator peer [%u] address [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
267           pg->peer, pg->address_id, GNUNET_ATS_print_property_type(ats_property),
268           base_value, value_rate);
269
270       break;
271     case GNUNET_ATS_TEST_TG_RANDOM:
272       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
273           "Setting up random property generator peer [%u] address [%u] `%s' min %u Bips max %u Bps\n",
274           pg->peer, pg->address_id, GNUNET_ATS_print_property_type(ats_property),
275           base_value, value_rate);
276       break;
277     default:
278       break;
279   }
280
281   pg->set_task = GNUNET_SCHEDULER_add_now (&set_prop_task, pg);
282   return pg;
283 }
284
285
286
287 /**
288  * Stop all preferences generators
289  */
290 void
291 GNUNET_ATS_solver_generate_property_stop_all ()
292 {
293   struct PropertyGenerator *cur;
294   struct PropertyGenerator *next;
295   next = prop_gen_head;
296   for (cur = next; NULL != cur; cur = next)
297   {
298       next = cur->next;
299       GNUNET_ATS_solver_generate_property_stop (cur);
300   }
301 }
302
303
304 /**
305  * Preference Generators
306  */
307
308 static struct PreferenceGenerator *pref_gen_head;
309 static struct PreferenceGenerator *pref_gen_tail;
310
311 static double
312 get_preference (struct PreferenceGenerator *pg)
313 {
314   struct GNUNET_TIME_Relative time_delta;
315   double delta_value;
316   double pref_value;
317
318   /* Calculate the current preference value */
319   switch (pg->type) {
320     case GNUNET_ATS_TEST_TG_CONSTANT:
321       pref_value = pg->base_value;
322       break;
323     case GNUNET_ATS_TEST_TG_LINEAR:
324       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
325       /* Calculate point of time in the current period */
326       time_delta.rel_value_us = time_delta.rel_value_us %
327           pg->duration_period.rel_value_us;
328       delta_value = ((double) time_delta.rel_value_us  /
329           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
330       if ((pg->max_value < pg->base_value) &&
331           ((pg->max_value - pg->base_value) > pg->base_value))
332       {
333         /* This will cause an underflow */
334         GNUNET_break (0);
335       }
336       pref_value = pg->base_value + delta_value;
337       break;
338     case GNUNET_ATS_TEST_TG_RANDOM:
339       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
340           10000 * (pg->max_value - pg->base_value)) / 10000;
341       pref_value = pg->base_value + delta_value;
342       break;
343     case GNUNET_ATS_TEST_TG_SINUS:
344       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
345       /* Calculate point of time in the current period */
346       time_delta.rel_value_us = time_delta.rel_value_us %
347           pg->duration_period.rel_value_us;
348       if ((pg->max_value - pg->base_value) > pg->base_value)
349       {
350         /* This will cause an underflow for second half of sinus period,
351          * will be detected in general when experiments are loaded */
352         GNUNET_break (0);
353       }
354       delta_value = (pg->max_value - pg->base_value) *
355           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
356               time_delta.rel_value_us);
357       pref_value = pg->base_value + delta_value;
358       break;
359     default:
360       pref_value = 0.0;
361       break;
362   }
363   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current preference value is %f\n",
364       pref_value);
365   return pref_value;
366 }
367
368
369 static void
370 set_pref_task (void *cls,
371                     const struct GNUNET_SCHEDULER_TaskContext *tc)
372 {
373   struct PreferenceGenerator *pg = cls;
374   double pref_value;
375   pg->set_task = GNUNET_SCHEDULER_NO_TASK;
376
377   pref_value = get_preference (pg);
378
379   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
380       "Setting preference for peer [%u] address [%u] for %s to %f\n",
381       pg->peer, pg->address_id,
382       GNUNET_ATS_print_preference_type (pg->kind), pref_value);
383
384   /* set performance here!
385   GNUNET_ATS_performance_change_preference(p->me->ats_perf_handle,
386       &p->dest->id, p->pg->kind, pref_value, GNUNET_ATS_PREFERENCE_END);
387 */
388
389   switch (pg->kind) {
390     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
391       //p->pref_bandwidth = pref_value;
392       break;
393     case GNUNET_ATS_PREFERENCE_LATENCY:
394       //p->pref_delay = pref_value;
395       break;
396     default:
397       break;
398   }
399
400   pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
401       set_pref_task, pg);
402
403 }
404
405 static struct PreferenceGenerator *
406 find_pref_gen (unsigned int peer, unsigned int address,
407     enum GNUNET_ATS_PreferenceKind kind)
408 {
409   struct PreferenceGenerator *cur;
410   for (cur = pref_gen_head; NULL != cur; cur = cur->next)
411     if ((cur->peer == peer) && (cur->address_id == address) && (cur->kind == kind))
412       return cur;
413   return NULL;
414 }
415
416 void
417 GNUNET_ATS_solver_generate_preferences_stop (struct PreferenceGenerator *pg)
418 {
419   GNUNET_CONTAINER_DLL_remove (pref_gen_head, pref_gen_tail, pg);
420
421   if (GNUNET_SCHEDULER_NO_TASK != pg->set_task)
422   {
423     GNUNET_SCHEDULER_cancel (pg->set_task);
424     pg->set_task = GNUNET_SCHEDULER_NO_TASK;
425   }
426   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
427       "Removing old up preference generator peer [%u] address [%u] `%s'\n",
428       pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(pg->kind));
429
430   GNUNET_free (pg);
431 }
432
433
434 /**
435  * Generate between the source master and the partner and set preferences with a
436  * value depending on the generator.
437  *
438  * @param src source
439  * @param dest partner
440  * @param type type of preferences to generate
441  * @param base_rate traffic base rate to send data with
442  * @param max_rate  traffic maximum rate to send data with
443  * @param period duration of a period of traffic generation (~ 1/frequency)
444  * @param duration how long to generate traffic
445  * @return the traffic generator
446  */
447 struct PreferenceGenerator *
448 GNUNET_ATS_solver_generate_preferences_start (unsigned int peer,
449     unsigned int address_id,
450     enum GeneratorType type,
451     long int base_value,
452     long int value_rate,
453     struct GNUNET_TIME_Relative period,
454     struct GNUNET_TIME_Relative frequency,
455     enum GNUNET_ATS_PreferenceKind kind)
456 {
457   struct PreferenceGenerator *pg;
458
459   pg = GNUNET_new (struct PreferenceGenerator);
460   GNUNET_CONTAINER_DLL_insert (pref_gen_head, pref_gen_tail, pg);
461   pg->type = type;
462   pg->peer = peer;
463   pg->address_id = address_id;
464   pg->kind = kind;
465   pg->base_value = base_value;
466   pg->max_value = value_rate;
467   pg->duration_period = period;
468   pg->frequency = frequency;
469   pg->time_start = GNUNET_TIME_absolute_get();
470
471   switch (type) {
472     case GNUNET_ATS_TEST_TG_CONSTANT:
473       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
474           "Setting up %s preference generator peer [%u] address [%u] `%s' max %u Bips\n",
475           print_generator_type (type), pg->peer, pg->address_id,
476           GNUNET_ATS_print_preference_type(kind),
477           base_value);
478       break;
479     case GNUNET_ATS_TEST_TG_LINEAR:
480       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
481           "Setting up %s preference generator peer [%u] address [%u] `%s' min %u Bips max %u Bips\n",
482           print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind),
483           base_value, value_rate);
484       break;
485     case GNUNET_ATS_TEST_TG_SINUS:
486       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
487           "Setting up %s preference generator peer [%u] address [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
488           print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind),
489           base_value, value_rate);
490       break;
491     case GNUNET_ATS_TEST_TG_RANDOM:
492       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
493           "Setting up %s preference generator peer [%u] address [%u] `%s' min %u Bips max %u Bps\n",
494           print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind),
495           base_value, value_rate);
496       break;
497     default:
498       break;
499   }
500
501   pg->set_task = GNUNET_SCHEDULER_add_now (&set_pref_task, pg);
502   return pg;
503 }
504
505
506
507 /**
508  * Stop all preferences generators
509  */
510 void
511 GNUNET_ATS_solver_generate_preferences_stop_all ()
512 {
513   struct PreferenceGenerator *cur;
514   struct PreferenceGenerator *next;
515   next = pref_gen_head;
516   for (cur = next; NULL != cur; cur = next)
517   {
518       next = cur->next;
519       GNUNET_ATS_solver_generate_preferences_stop(cur);
520   }
521 }
522
523
524
525 /**
526  * Experiments
527  */
528
529 const char *
530 print_op (enum OperationType op)
531 {
532   switch (op) {
533     case SOLVER_OP_ADD_ADDRESS:
534       return "ADD_ADDRESS";
535     case SOLVER_OP_DEL_ADDRESS:
536       return "DEL_ADDRESS";
537     case SOLVER_OP_START_SET_PREFERENCE:
538       return "START_SET_PREFERENCE";
539     case SOLVER_OP_STOP_SET_PREFERENCE:
540       return "STOP_STOP_PREFERENCE";
541     case SOLVER_OP_START_SET_PROPERTY:
542           return "START_SET_PROPERTY";
543     case SOLVER_OP_STOP_SET_PROPERTY:
544       return "STOP_SET_PROPERTY";
545     default:
546       break;
547   }
548   return "";
549 }
550
551 static struct Experiment *
552 create_experiment ()
553 {
554   struct Experiment *e;
555   e = GNUNET_new (struct Experiment);
556   e->name = NULL;
557   e->num_masters = 0;
558   e->num_slaves = 0;
559   e->start = NULL;
560   e->total_duration = GNUNET_TIME_UNIT_ZERO;
561   return e;
562 }
563
564 static void
565 free_experiment (struct Experiment *e)
566 {
567   struct Episode *cur;
568   struct Episode *next;
569   struct GNUNET_ATS_TEST_Operation *cur_o;
570   struct GNUNET_ATS_TEST_Operation *next_o;
571
572   next = e->start;
573   for (cur = next; NULL != cur; cur = next)
574   {
575     next = cur->next;
576
577     next_o = cur->head;
578     for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
579     {
580       next_o = cur_o->next;
581       GNUNET_free_non_null (cur_o->address);
582       GNUNET_free_non_null (cur_o->plugin);
583       GNUNET_free (cur_o);
584     }
585     GNUNET_free (cur);
586   }
587
588   GNUNET_free_non_null (e->name);
589   GNUNET_free_non_null (e->cfg_file);
590   GNUNET_free (e);
591 }
592
593
594 static int
595 load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
596     struct Episode *e,
597     int op_counter,
598     char *sec_name,
599     const struct GNUNET_CONFIGURATION_Handle *cfg)
600 {
601   char *op_name;
602
603   /* peer id */
604   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
605   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
606       sec_name, op_name, &o->peer_id))
607   {
608     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
609         op_counter, "ADD_ADDRESS", op_name);
610     GNUNET_free (op_name);
611     return GNUNET_SYSERR;
612   }
613   GNUNET_free (op_name);
614
615   /* address id */
616   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
617   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
618       sec_name, op_name, &o->address_id))
619   {
620     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
621         op_counter, "ADD_ADDRESS", op_name);
622     GNUNET_free (op_name);
623     return GNUNET_SYSERR;
624   }
625   GNUNET_free (op_name);
626
627   /* plugin */
628   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
629   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
630       sec_name, op_name, &o->plugin))
631   {
632     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
633         op_counter, "ADD_ADDRESS", op_name);
634     GNUNET_free (op_name);
635     return GNUNET_SYSERR;
636   }
637   GNUNET_free (op_name);
638
639   /* address  */
640   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
641   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
642       sec_name, op_name, &o->address))
643   {
644     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
645         op_counter, "ADD_ADDRESS", op_name);
646     GNUNET_free (op_name);
647     return GNUNET_SYSERR;
648   }
649   GNUNET_free (op_name);
650
651   /* session */
652   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
653   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
654       sec_name, op_name, &o->address_session))
655   {
656     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
657         op_counter, "ADD_ADDRESS", op_name);
658     GNUNET_free (op_name);
659     return GNUNET_SYSERR;
660   }
661   GNUNET_free (op_name);
662
663   /* network */
664   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
665   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
666       sec_name, op_name, &o->address_network))
667   {
668     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
669         op_counter, "ADD_ADDRESS", op_name);
670     GNUNET_free (op_name);
671     return GNUNET_SYSERR;
672   }
673   GNUNET_free (op_name);
674
675   fprintf (stderr,
676       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
677       "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
678
679   return GNUNET_OK;
680 }
681
682 static int
683 load_op_del_address (struct GNUNET_ATS_TEST_Operation *o,
684     struct Episode *e,
685     int op_counter,
686     char *sec_name,
687     const struct GNUNET_CONFIGURATION_Handle *cfg)
688 {
689   char *op_name;
690
691   /* peer id */
692   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
693   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
694       sec_name, op_name, &o->peer_id))
695   {
696     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
697         op_counter, "DEL_ADDRESS", op_name);
698     GNUNET_free (op_name);
699     return GNUNET_SYSERR;
700   }
701   GNUNET_free (op_name);
702
703   /* address id */
704   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
705   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
706       sec_name, op_name, &o->address_id))
707   {
708     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
709         op_counter, "DEL_ADDRESS", op_name);
710     GNUNET_free (op_name);
711     return GNUNET_SYSERR;
712   }
713   GNUNET_free (op_name);
714
715   /* plugin */
716   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
717   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
718       sec_name, op_name, &o->plugin))
719   {
720     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
721         op_counter, "DEL_ADDRESS", op_name);
722     GNUNET_free (op_name);
723     return GNUNET_SYSERR;
724   }
725   GNUNET_free (op_name);
726
727   /* address  */
728   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
729   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
730       sec_name, op_name, &o->address))
731   {
732     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
733         op_counter, "DEL_ADDRESS", op_name);
734     GNUNET_free (op_name);
735     return GNUNET_SYSERR;
736   }
737   GNUNET_free (op_name);
738
739   /* session */
740   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
741   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
742       sec_name, op_name, &o->address_session))
743   {
744     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
745         op_counter, "DEL_ADDRESS", op_name);
746     GNUNET_free (op_name);
747     return GNUNET_SYSERR;
748   }
749   GNUNET_free (op_name);
750
751   /* network */
752   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
753   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
754       sec_name, op_name, &o->address_network))
755   {
756     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
757         op_counter, "DEL_ADDRESS", op_name);
758     GNUNET_free (op_name);
759     return GNUNET_SYSERR;
760   }
761   GNUNET_free (op_name);
762
763   fprintf (stderr,
764       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
765       "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
766
767   return GNUNET_OK;
768 }
769
770 static enum GNUNET_ATS_Property
771 parse_preference_string (const char * str)
772 {
773   int c = 0;
774   char *props[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
775
776   for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
777     if (0 == strcmp(str, props[c]))
778       return c;
779   return 0;
780 };
781
782 static int
783 load_op_start_set_preference (struct GNUNET_ATS_TEST_Operation *o,
784     struct Episode *e,
785     int op_counter,
786     char *sec_name,
787     const struct GNUNET_CONFIGURATION_Handle *cfg)
788 {
789   char *op_name;
790   char *type;
791   char *pref;
792
793   /* peer id */
794   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
795   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
796       sec_name, op_name, &o->peer_id))
797   {
798     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
799         op_counter, "START_SET_PREFERENCE", op_name);
800     GNUNET_free (op_name);
801     return GNUNET_SYSERR;
802   }
803   GNUNET_free (op_name);
804
805   /* address id */
806   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
807   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
808       sec_name, op_name, &o->address_id))
809   {
810     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
811         op_counter, "START_SET_PREFERENCE", op_name);
812     GNUNET_free (op_name);
813     return GNUNET_SYSERR;
814   }
815   GNUNET_free (op_name);
816
817   /* generator */
818   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
819   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
820           sec_name, op_name, &type)) )
821   {
822     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
823         op_counter, "START_SET_PREFERENCE", op_name);
824     GNUNET_free (op_name);
825     return GNUNET_SYSERR;
826   }
827
828   /* Load arguments for set_rate, start_send, set_preference */
829   if (0 == strcmp (type, "constant"))
830   {
831     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
832   }
833   else if (0 == strcmp (type, "linear"))
834   {
835     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
836   }
837   else if (0 == strcmp (type, "sinus"))
838   {
839     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
840   }
841   else if (0 == strcmp (type, "random"))
842   {
843     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
844   }
845   else
846   {
847     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
848         op_counter, op_name, e->id);
849     GNUNET_free (type);
850     GNUNET_free (op_name);
851     return GNUNET_SYSERR;
852   }
853   GNUNET_free (type);
854   GNUNET_free (op_name);
855
856
857   /* Get base rate */
858   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
859   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
860       sec_name, op_name, &o->base_rate))
861   {
862     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
863         op_counter, op_name, e->id);
864     GNUNET_free (op_name);
865     return GNUNET_SYSERR;
866   }
867   GNUNET_free (op_name);
868
869
870   /* Get max rate */
871   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
872   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
873       sec_name, op_name, &o->max_rate))
874   {
875     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
876         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
877         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
878     {
879       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
880           op_counter, op_name, e->id);
881       GNUNET_free (op_name);
882       return GNUNET_SYSERR;
883     }
884   }
885   GNUNET_free (op_name);
886
887   /* Get period */
888   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
889   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
890       sec_name, op_name, &o->period))
891   {
892     o->period = e->duration;
893   }
894   GNUNET_free (op_name);
895
896   /* Get frequency */
897   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
898   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
899       sec_name, op_name, &o->frequency))
900   {
901       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
902           op_counter, op_name, e->id);
903       GNUNET_free (op_name);
904       return GNUNET_SYSERR;
905   }
906   GNUNET_free (op_name);
907
908   /* Get preference */
909   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
910   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
911       sec_name, op_name, &pref))
912   {
913       fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
914           op_counter, op_name, e->id);
915       GNUNET_free (op_name);
916       return GNUNET_SYSERR;
917   }
918
919   if (0 == (o->pref_type = parse_preference_string(pref)))
920   {
921       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
922           op_counter, op_name, e->id);
923       GNUNET_free (op_name);
924       GNUNET_free (pref);
925       return GNUNET_SYSERR;
926   }
927   GNUNET_free (pref);
928   GNUNET_free (op_name);
929
930   fprintf (stderr,
931       "Found operation %s: [%llu:%llu]: %s = %llu\n",
932       "START_SET_PREFERENCE", o->peer_id, o->address_id,
933       GNUNET_ATS_print_preference_type(o->pref_type), o->base_rate);
934
935   return GNUNET_OK;
936 }
937
938 static int
939 load_op_stop_set_preference (struct GNUNET_ATS_TEST_Operation *o,
940     struct Episode *e,
941     int op_counter,
942     char *sec_name,
943     const struct GNUNET_CONFIGURATION_Handle *cfg)
944 {
945   char *op_name;
946   char *pref;
947
948   /* peer id */
949   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
950   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
951       sec_name, op_name, &o->peer_id))
952   {
953     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
954         op_counter, "STOP_SET_PREFERENCE", op_name);
955     GNUNET_free (op_name);
956     return GNUNET_SYSERR;
957   }
958   GNUNET_free (op_name);
959
960   /* address id */
961   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
962   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
963       sec_name, op_name, &o->address_id))
964   {
965     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
966         op_counter, "STOP_SET_PREFERENCE", op_name);
967     GNUNET_free (op_name);
968     return GNUNET_SYSERR;
969   }
970   GNUNET_free (op_name);
971
972   /* Get preference */
973   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
974   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
975       sec_name, op_name, &pref))
976   {
977     fprintf (stderr, "Missing preference in operation %u `%s' in episode `%s'\n",
978         op_counter, "STOP_SET_PREFERENCE", op_name);
979       GNUNET_free (op_name);
980       return GNUNET_SYSERR;
981   }
982
983   if (0 == (o->pref_type = parse_preference_string(pref)))
984   {
985       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
986           op_counter, op_name, e->id);
987       GNUNET_free (op_name);
988       GNUNET_free (pref);
989       return GNUNET_SYSERR;
990   }
991   GNUNET_free (pref);
992   GNUNET_free (op_name);
993
994   fprintf (stderr,
995       "Found operation %s: [%llu:%llu]: %s\n",
996       "STOP_SET_PREFERENCE", o->peer_id, o->address_id,
997       GNUNET_ATS_print_preference_type(o->pref_type));
998   return GNUNET_OK;
999 }
1000
1001 static enum GNUNET_ATS_Property
1002 parse_property_string (const char * str)
1003 {
1004   int c = 0;
1005   char *props[GNUNET_ATS_PropertyCount] = GNUNET_ATS_PropertyStrings;
1006
1007   for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
1008     if (0 == strcmp(str, props[c]))
1009       return c;
1010   return 0;
1011 };
1012
1013 static int
1014 load_op_start_set_property(struct GNUNET_ATS_TEST_Operation *o,
1015     struct Episode *e,
1016     int op_counter,
1017     char *sec_name,
1018     const struct GNUNET_CONFIGURATION_Handle *cfg)
1019 {
1020   char *op_name;
1021   char *type;
1022   char *prop;
1023
1024   /* peer id */
1025   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1026   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1027       sec_name, op_name, &o->peer_id))
1028   {
1029     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1030         op_counter, "START_SET_PROPERTY", op_name);
1031     GNUNET_free (op_name);
1032     return GNUNET_SYSERR;
1033   }
1034   GNUNET_free (op_name);
1035
1036   /* address id */
1037   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1038   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1039       sec_name, op_name, &o->address_id))
1040   {
1041     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1042         op_counter, "START_SET_PROPERTY", op_name);
1043     GNUNET_free (op_name);
1044     return GNUNET_SYSERR;
1045   }
1046   GNUNET_free (op_name);
1047
1048   /* generator */
1049   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
1050   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1051           sec_name, op_name, &type)) )
1052   {
1053     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
1054         op_counter, "START_SET_PROPERTY", op_name);
1055     GNUNET_free (op_name);
1056     return GNUNET_SYSERR;
1057   }
1058
1059   /* Load arguments for set_rate, start_send, set_preference */
1060   if (0 == strcmp (type, "constant"))
1061   {
1062     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1063     GNUNET_break (0);
1064   }
1065   else if (0 == strcmp (type, "linear"))
1066   {
1067     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1068     GNUNET_break (0);
1069   }
1070   else if (0 == strcmp (type, "sinus"))
1071   {
1072     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1073     GNUNET_break (0);
1074   }
1075   else if (0 == strcmp (type, "random"))
1076   {
1077     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1078     GNUNET_break (0);
1079   }
1080   else
1081   {
1082     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
1083         op_counter, op_name, e->id);
1084     GNUNET_free (type);
1085     GNUNET_free (op_name);
1086     return GNUNET_SYSERR;
1087   }
1088   GNUNET_free (type);
1089   GNUNET_free (op_name);
1090
1091
1092   /* Get base rate */
1093   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1094   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1095       sec_name, op_name, &o->base_rate))
1096   {
1097     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1098         op_counter, op_name, e->id);
1099     GNUNET_free (op_name);
1100     return GNUNET_SYSERR;
1101   }
1102   GNUNET_free (op_name);
1103
1104
1105   /* Get max rate */
1106   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1107   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1108       sec_name, op_name, &o->max_rate))
1109   {
1110     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1111         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1112         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1113     {
1114       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1115           op_counter, op_name, e->id);
1116       GNUNET_free (op_name);
1117       return GNUNET_SYSERR;
1118     }
1119   }
1120   GNUNET_free (op_name);
1121
1122   /* Get period */
1123   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1124   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1125       sec_name, op_name, &o->period))
1126   {
1127     o->period = e->duration;
1128   }
1129   GNUNET_free (op_name);
1130
1131   /* Get frequency */
1132   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1133   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1134       sec_name, op_name, &o->frequency))
1135   {
1136       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1137           op_counter, op_name, e->id);
1138       GNUNET_free (op_name);
1139       return GNUNET_SYSERR;
1140   }
1141   GNUNET_free (op_name);
1142
1143   /* Get preference */
1144   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
1145   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1146       sec_name, op_name, &prop))
1147   {
1148       fprintf (stderr, "Missing property in operation %u `%s' in episode %u\n",
1149           op_counter, op_name, e->id);
1150       GNUNET_free (op_name);
1151       GNUNET_free_non_null (prop);
1152       return GNUNET_SYSERR;
1153   }
1154
1155   if (0 == (o->prop_type = parse_property_string(prop)))
1156   {
1157       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1158           op_counter, op_name, e->id);
1159       GNUNET_free (op_name);
1160       GNUNET_free (prop);
1161       return GNUNET_SYSERR;
1162   }
1163
1164   GNUNET_free (prop);
1165   GNUNET_free (op_name);
1166
1167   fprintf (stderr,
1168       "Found operation %s: [%llu:%llu] %s = %llu\n",
1169       "START_SET_PROPERTY", o->peer_id, o->address_id,
1170       GNUNET_ATS_print_property_type (o->prop_type), o->base_rate);
1171
1172   return GNUNET_OK;
1173 }
1174
1175 static int
1176 load_op_stop_set_property (struct GNUNET_ATS_TEST_Operation *o,
1177     struct Episode *e,
1178     int op_counter,
1179     char *sec_name,
1180     const struct GNUNET_CONFIGURATION_Handle *cfg)
1181 {
1182   char *op_name;
1183   char *pref;
1184
1185   /* peer id */
1186   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1187   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1188       sec_name, op_name, &o->peer_id))
1189   {
1190     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1191         op_counter, "STOP_SET_PROPERTY", op_name);
1192     GNUNET_free (op_name);
1193     return GNUNET_SYSERR;
1194   }
1195   GNUNET_free (op_name);
1196
1197   /* address id */
1198   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1199   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1200       sec_name, op_name, &o->address_id))
1201   {
1202     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1203         op_counter, "STOP_SET_PROPERTY", op_name);
1204     GNUNET_free (op_name);
1205     return GNUNET_SYSERR;
1206   }
1207   GNUNET_free (op_name);
1208
1209   /* Get property */
1210   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
1211   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1212       sec_name, op_name, &pref))
1213   {
1214     fprintf (stderr, "Missing property in operation %u `%s' in episode `%s'\n",
1215         op_counter, "STOP_SET_PROPERTY", op_name);
1216       GNUNET_free (op_name);
1217       GNUNET_free_non_null (pref);
1218       return GNUNET_SYSERR;
1219   }
1220
1221   if (0 == (o->prop_type = parse_property_string(pref)))
1222   {
1223       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1224           op_counter, op_name, e->id);
1225       GNUNET_free (op_name);
1226       GNUNET_free (pref);
1227       GNUNET_free_non_null (pref);
1228       return GNUNET_SYSERR;
1229   }
1230
1231   GNUNET_free (pref);
1232   GNUNET_free (op_name);
1233
1234   fprintf (stderr,
1235       "Found operation %s: [%llu:%llu] %s\n",
1236       "STOP_SET_PROPERTY", o->peer_id, o->address_id,
1237       GNUNET_ATS_print_property_type (o->prop_type));
1238
1239   return GNUNET_OK;
1240 }
1241
1242 static int
1243 load_episode (struct Experiment *e, struct Episode *cur,
1244     struct GNUNET_CONFIGURATION_Handle *cfg)
1245 {
1246   struct GNUNET_ATS_TEST_Operation *o;
1247   char *sec_name;
1248   char *op_name;
1249   char *op;
1250   int op_counter = 0;
1251   fprintf (stderr, "Parsing episode %u\n",cur->id);
1252   GNUNET_asprintf(&sec_name, "episode-%u", cur->id);
1253
1254   while (1)
1255   {
1256     /* Load operation */
1257     GNUNET_asprintf(&op_name, "op-%u-operation", op_counter);
1258     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1259         sec_name, op_name, &op))
1260     {
1261       GNUNET_free (op_name);
1262       break;
1263     }
1264     o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
1265     /* operations = set_rate, start_send, stop_send, set_preference */
1266     if (0 == strcmp (op, "address_add"))
1267     {
1268       o->type = SOLVER_OP_ADD_ADDRESS;
1269       if (GNUNET_SYSERR == load_op_add_address (o, cur,
1270           op_counter, sec_name, cfg))
1271       {
1272         GNUNET_free (o);
1273         GNUNET_free (op);
1274         GNUNET_free (op_name);
1275         GNUNET_free (sec_name);
1276         return GNUNET_SYSERR;
1277       }
1278     }
1279     else if (0 == strcmp (op, "address_del"))
1280     {
1281       o->type = SOLVER_OP_DEL_ADDRESS;
1282       if (GNUNET_SYSERR == load_op_del_address (o, cur,
1283           op_counter, sec_name, cfg))
1284       {
1285         GNUNET_free (o);
1286         GNUNET_free (op);
1287         GNUNET_free (op_name);
1288         GNUNET_free (sec_name);
1289         return GNUNET_SYSERR;
1290       }
1291     }
1292     else if (0 == strcmp (op, "start_set_property"))
1293     {
1294       o->type = SOLVER_OP_START_SET_PROPERTY;
1295       if (GNUNET_SYSERR == load_op_start_set_property (o, cur,
1296           op_counter, sec_name, cfg))
1297       {
1298         GNUNET_free (o);
1299         GNUNET_free (op);
1300         GNUNET_free (op_name);
1301         GNUNET_free (sec_name);
1302         return GNUNET_SYSERR;
1303       }
1304     }
1305     else if (0 == strcmp (op, "stop_set_property"))
1306     {
1307       o->type = SOLVER_OP_STOP_SET_PROPERTY;
1308       if (GNUNET_SYSERR == load_op_stop_set_property (o, cur,
1309           op_counter, sec_name, cfg))
1310       {
1311         GNUNET_free (o);
1312         GNUNET_free (op);
1313         GNUNET_free (op_name);
1314         GNUNET_free (sec_name);
1315         return GNUNET_SYSERR;
1316       }
1317     }
1318     else if (0 == strcmp (op, "start_set_preference"))
1319     {
1320       o->type = SOLVER_OP_START_SET_PREFERENCE;
1321       if (GNUNET_SYSERR == load_op_start_set_preference (o, cur,
1322           op_counter, sec_name, cfg))
1323       {
1324         GNUNET_free (o);
1325         GNUNET_free (op);
1326         GNUNET_free (op_name);
1327         GNUNET_free (sec_name);
1328         return GNUNET_SYSERR;
1329       }
1330     }
1331     else if (0 == strcmp (op, "stop_set_preference"))
1332     {
1333       o->type = SOLVER_OP_STOP_SET_PREFERENCE;
1334       if (GNUNET_SYSERR == load_op_stop_set_preference (o, cur,
1335           op_counter, sec_name, cfg))
1336       {
1337         GNUNET_free (o);
1338         GNUNET_free (op);
1339         GNUNET_free (op_name);
1340         GNUNET_free (sec_name);
1341         return GNUNET_SYSERR;
1342       }
1343     }
1344     else
1345     {
1346       fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
1347           op_counter, op, cur->id);
1348       GNUNET_free (o);
1349       GNUNET_free (op);
1350       GNUNET_free (op_name);
1351       GNUNET_free (sec_name);
1352       return GNUNET_SYSERR;
1353     }
1354     GNUNET_free (op);
1355     GNUNET_free (op_name);
1356
1357     GNUNET_CONTAINER_DLL_insert (cur->head,cur->tail, o);
1358     op_counter++;
1359   }
1360   GNUNET_free (sec_name);
1361
1362
1363 #if 0
1364     /* Get source */
1365     GNUNET_asprintf(&op_name, "op-%u-src", op_counter);
1366     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1367         sec_name, op_name, &o->src_id))
1368     {
1369       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
1370           op_counter, op, cur->id);
1371       GNUNET_free (op);
1372       GNUNET_free (op_name);
1373       return GNUNET_SYSERR;
1374     }
1375     if (o->src_id > (e->num_masters - 1))
1376     {
1377       fprintf (stderr, "Invalid src %llu in operation %u `%s' in episode %u\n",
1378           o->src_id, op_counter, op, cur->id);
1379       GNUNET_free (op);
1380       GNUNET_free (op_name);
1381       return GNUNET_SYSERR;
1382     }
1383     GNUNET_free (op_name);
1384
1385     /* Get destination */
1386     GNUNET_asprintf(&op_name, "op-%u-dest", op_counter);
1387     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1388         sec_name, op_name, &o->dest_id))
1389     {
1390       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
1391           op_counter, op, cur->id);
1392       GNUNET_free (op);
1393       GNUNET_free (op_name);
1394       return GNUNET_SYSERR;
1395     }
1396     if (o->dest_id > (e->num_slaves - 1))
1397     {
1398       fprintf (stderr, "Invalid destination %llu in operation %u `%s' in episode %u\n",
1399           o->dest_id, op_counter, op, cur->id);
1400       GNUNET_free (op);
1401       GNUNET_free (op_name);
1402       return GNUNET_SYSERR;
1403     }
1404     GNUNET_free (op_name);
1405
1406     GNUNET_asprintf(&op_name, "op-%u-type", op_counter);
1407     if ( (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_string(cfg,
1408             sec_name, op_name, &type)) &&
1409         ((STOP_SEND != o->type) || (STOP_PREFERENCE != o->type)))
1410     {
1411       /* Load arguments for set_rate, start_send, set_preference */
1412       if (0 == strcmp (type, "constant"))
1413       {
1414         o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1415       }
1416       else if (0 == strcmp (type, "linear"))
1417       {
1418         o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1419       }
1420       else if (0 == strcmp (type, "sinus"))
1421       {
1422         o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1423       }
1424       else if (0 == strcmp (type, "random"))
1425       {
1426         o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1427       }
1428       else
1429       {
1430         fprintf (stderr, "Invalid type %u `%s' in episode %u\n",
1431             op_counter, op, cur->id);
1432         GNUNET_free (type);
1433         GNUNET_free (op);
1434         GNUNET_free (op_name);
1435         return GNUNET_SYSERR;
1436       }
1437       GNUNET_free (op_name);
1438
1439       /* Get base rate */
1440       GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1441       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1442           sec_name, op_name, &o->base_rate))
1443       {
1444         fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1445             op_counter, op, cur->id);
1446         GNUNET_free (type);
1447         GNUNET_free (op);
1448         GNUNET_free (op_name);
1449         return GNUNET_SYSERR;
1450       }
1451       GNUNET_free (op_name);
1452
1453       /* Get max rate */
1454       GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1455       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1456           sec_name, op_name, &o->max_rate))
1457       {
1458         if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1459             (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1460             (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1461         {
1462           fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1463               op_counter, op, cur->id);
1464           GNUNET_free (type);
1465           GNUNET_free (op_name);
1466           GNUNET_free (op);
1467           return GNUNET_SYSERR;
1468         }
1469       }
1470       GNUNET_free (op_name);
1471
1472       /* Get period */
1473       GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1474       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1475           sec_name, op_name, &o->period))
1476       {
1477         o->period = cur->duration;
1478       }
1479       GNUNET_free (op_name);
1480
1481       if (START_PREFERENCE == o->type)
1482       {
1483           /* Get frequency */
1484           GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1485           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1486               sec_name, op_name, &o->frequency))
1487           {
1488               fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1489                   op_counter, op, cur->id);
1490               GNUNET_free (type);
1491               GNUNET_free (op_name);
1492               GNUNET_free (op);
1493               return GNUNET_SYSERR;
1494           }
1495           GNUNET_free (op_name);
1496
1497           /* Get preference */
1498           GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1499           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1500               sec_name, op_name, &pref))
1501           {
1502               fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
1503                   op_counter, op, cur->id);
1504               GNUNET_free (type);
1505               GNUNET_free (op_name);
1506               GNUNET_free (op);
1507               GNUNET_free_non_null (pref);
1508               return GNUNET_SYSERR;
1509           }
1510
1511           if (0 == strcmp(pref, "bandwidth"))
1512             o->pref_type = GNUNET_ATS_PREFERENCE_BANDWIDTH;
1513           else if (0 == strcmp(pref, "latency"))
1514             o->pref_type = GNUNET_ATS_PREFERENCE_LATENCY;
1515           else
1516           {
1517               fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1518                   op_counter, op, cur->id);
1519               GNUNET_free (type);
1520               GNUNET_free (op_name);
1521               GNUNET_free (op);
1522               GNUNET_free (pref);
1523               GNUNET_free_non_null (pref);
1524               return GNUNET_SYSERR;
1525           }
1526           GNUNET_free (pref);
1527           GNUNET_free (op_name);
1528       }
1529     }
1530
1531     /* Safety checks */
1532     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1533         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1534     {
1535       if ((o->max_rate - o->base_rate) > o->base_rate)
1536       {
1537         /* This will cause an underflow */
1538         GNUNET_break (0);
1539       }
1540       fprintf (stderr, "Selected max rate and base rate cannot be used for desired traffic form!\n");
1541     }
1542
1543     if ((START_SEND == o->type) || (START_PREFERENCE == o->type))
1544       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu] == %s, %llu -> %llu in %s\n",
1545         op_counter, cur->id, print_op (o->type), o->src_id,
1546         o->dest_id, (NULL != type) ? type : "",
1547         o->base_rate, o->max_rate,
1548         GNUNET_STRINGS_relative_time_to_string (o->period, GNUNET_YES));
1549     else
1550       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu]\n",
1551         op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id);
1552
1553     GNUNET_free_non_null (type);
1554     GNUNET_free (op);
1555 #endif
1556
1557   return GNUNET_OK;
1558 }
1559
1560 static int
1561 load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
1562 {
1563   int e_counter = 0;
1564   char *sec_name;
1565   struct GNUNET_TIME_Relative e_duration;
1566   struct Episode *cur;
1567   struct Episode *last;
1568
1569   e_counter = 0;
1570   last = NULL;
1571   while (1)
1572   {
1573     GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
1574     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
1575         sec_name, "duration", &e_duration))
1576     {
1577       GNUNET_free (sec_name);
1578       break;
1579     }
1580
1581     cur = GNUNET_new (struct Episode);
1582     cur->duration = e_duration;
1583     cur->id = e_counter;
1584
1585     if (GNUNET_OK != load_episode (e, cur, cfg))
1586     {
1587       GNUNET_free (sec_name);
1588       GNUNET_free (cur);
1589       return GNUNET_SYSERR;
1590     }
1591
1592     fprintf (stderr, "Found episode %u with duration %s \n",
1593         e_counter,
1594         GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
1595
1596     /* Update experiment */
1597     e->num_episodes ++;
1598     e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
1599     /* Put in linked list */
1600     if (NULL == last)
1601       e->start = cur;
1602     else
1603     last->next = cur;
1604
1605     GNUNET_free (sec_name);
1606     e_counter ++;
1607     last = cur;
1608   }
1609   return e_counter;
1610 }
1611
1612 static void
1613 timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1614 {
1615   struct Experiment *e = cls;
1616   e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1617   fprintf (stderr, "Experiment timeout!\n");
1618
1619   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1620   {
1621     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1622     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1623   }
1624
1625   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
1626       GNUNET_SYSERR);
1627 }
1628
1629 static void
1630 enforce_add_address (struct GNUNET_ATS_TEST_Operation *op)
1631 {
1632   /*
1633   struct BenchmarkPeer *peer;
1634   struct BenchmarkPartner *partner;
1635
1636   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
1637   if (NULL == peer)
1638   {
1639     GNUNET_break (0);
1640     return;
1641   }
1642
1643   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
1644   if (NULL == partner)
1645   {
1646     GNUNET_break (0);
1647     return;
1648   }
1649
1650   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
1651
1652   if (NULL != partner->tg)
1653   {
1654     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id);
1655     GNUNET_ATS_TEST_generate_traffic_stop(partner->tg);
1656     partner->tg = NULL;
1657   }
1658
1659   partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner,
1660       op->tg_type, op->base_rate, op->max_rate, op->period,
1661       GNUNET_TIME_UNIT_FOREVER_REL);
1662    */
1663 }
1664
1665 static void
1666 enforce_del_address (struct GNUNET_ATS_TEST_Operation *op)
1667 {
1668   /*
1669   struct BenchmarkPartner *p;
1670   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
1671   if (NULL == p)
1672   {
1673     GNUNET_break (0);
1674     return;
1675   }
1676
1677   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
1678
1679   if (NULL != p->tg)
1680   {
1681     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
1682         op->src_id, op->dest_id);
1683     GNUNET_ATS_TEST_generate_traffic_stop(p->tg);
1684     p->tg = NULL;
1685   }
1686   */
1687 }
1688
1689 static void
1690 enforce_start_property (struct GNUNET_ATS_TEST_Operation *op)
1691 {
1692   struct PropertyGenerator *pg;
1693   if (NULL != (pg = find_prop_gen (op->peer_id, op->address_id, op->prop_type)))
1694   {
1695     GNUNET_ATS_solver_generate_property_stop (pg);
1696     GNUNET_free (pg);
1697   }
1698
1699   GNUNET_ATS_solver_generate_property_start (op->peer_id,
1700     op->address_id,
1701     op->type,
1702     op->base_rate,
1703     op->max_rate,
1704     op->period,
1705     op->frequency,
1706     op->prop_type);
1707 }
1708
1709 static void
1710 enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op)
1711 {
1712   struct PropertyGenerator *pg = find_prop_gen(op->peer_id, op->address_id,
1713       op->prop_type);
1714   if (NULL != pg)
1715       GNUNET_ATS_solver_generate_property_stop (pg);
1716 }
1717
1718 static void
1719 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
1720 {
1721   struct PreferenceGenerator *pg;
1722   if (NULL != (pg = find_pref_gen (op->peer_id, op->address_id, op->pref_type)))
1723   {
1724     GNUNET_ATS_solver_generate_preferences_stop (pg);
1725     GNUNET_free (pg);
1726   }
1727
1728   fprintf (stderr, "ENFORECE: %s, %u\n", print_generator_type (op->gen_type),
1729       op->base_rate);
1730
1731   GNUNET_ATS_solver_generate_preferences_start (op->peer_id,
1732     op->address_id,
1733     op->gen_type,
1734     op->base_rate,
1735     op->max_rate,
1736     op->period,
1737     op->frequency,
1738     op->pref_type);
1739 }
1740
1741 static void
1742 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
1743 {
1744   struct PreferenceGenerator *pg = find_pref_gen(op->peer_id, op->address_id,
1745       op->pref_type);
1746   if (NULL != pg)
1747       GNUNET_ATS_solver_generate_preferences_stop (pg);
1748 }
1749
1750 static void enforce_episode (struct Episode *ep)
1751 {
1752   struct GNUNET_ATS_TEST_Operation *cur;
1753   for (cur = ep->head; NULL != cur; cur = cur->next)
1754   {
1755     switch (cur->type) {
1756       case SOLVER_OP_ADD_ADDRESS:
1757         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
1758             print_op (cur->type), cur->peer_id, cur->address_id);
1759         enforce_add_address (cur);
1760         break;
1761       case SOLVER_OP_DEL_ADDRESS:
1762         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
1763             print_op (cur->type), cur->peer_id, cur->address_id);
1764         enforce_del_address (cur);
1765         break;
1766       case SOLVER_OP_START_SET_PROPERTY:
1767         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1768             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1769         enforce_start_property (cur);
1770         break;
1771       case SOLVER_OP_STOP_SET_PROPERTY:
1772         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1773             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1774         enforce_stop_property (cur);
1775         break;
1776       case SOLVER_OP_START_SET_PREFERENCE:
1777         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1778             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1779         enforce_start_preference (cur);
1780         break;
1781       case SOLVER_OP_STOP_SET_PREFERENCE:
1782         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1783             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1784         enforce_stop_preference (cur);
1785         break;
1786       default:
1787         break;
1788     }
1789   }
1790 }
1791
1792 static void
1793 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1794 {
1795   struct Experiment *e = cls;
1796   e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1797   if (NULL != e->ep_done_cb)
1798     e->ep_done_cb (e->cur);
1799
1800   /* Scheduling next */
1801   e->cur = e->cur->next;
1802   if (NULL == e->cur)
1803   {
1804     /* done */
1805     fprintf (stderr, "Last episode done!\n");
1806     if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
1807     {
1808       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1809       e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1810     }
1811     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
1812     return;
1813   }
1814
1815   fprintf (stderr, "Running episode %u with timeout %s\n",
1816       e->cur->id,
1817       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
1818   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
1819       &timeout_episode, e);
1820   enforce_episode(e->cur);
1821
1822
1823 }
1824
1825
1826 void
1827 GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
1828     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
1829     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
1830 {
1831   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
1832       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
1833   e->e_done_cb = e_done_cb;
1834   e->ep_done_cb = ep_done_cb;
1835   e->start_time = GNUNET_TIME_absolute_get();
1836
1837   /* Start total time out */
1838   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
1839       &timeout_experiment, e);
1840
1841
1842   /* Start */
1843   if (NULL == e->start)
1844   {
1845     GNUNET_break (0);
1846     return;
1847   }
1848   e->cur = e->start;
1849   fprintf (stderr, "Running episode %u with timeout %s\n",
1850       e->cur->id,
1851       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
1852   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
1853       &timeout_episode, e);
1854   enforce_episode(e->cur);
1855
1856 }
1857
1858 void
1859 GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
1860 {
1861   if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
1862   {
1863     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1864     e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1865   }
1866   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1867   {
1868     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1869     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1870   }
1871   if (NULL != e->cfg)
1872   {
1873     GNUNET_CONFIGURATION_destroy(e->cfg);
1874     e->cfg = NULL;
1875   }
1876   free_experiment (e);
1877 }
1878
1879
1880 struct Experiment *
1881 GNUNET_ATS_solvers_experimentation_load (char *filename)
1882 {
1883   struct Experiment *e;
1884   struct GNUNET_CONFIGURATION_Handle *cfg;
1885   e = NULL;
1886
1887   cfg = GNUNET_CONFIGURATION_create();
1888   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
1889   {
1890     fprintf (stderr, "Failed to load `%s'\n", filename);
1891     GNUNET_CONFIGURATION_destroy (cfg);
1892     return NULL;
1893   }
1894
1895   e = create_experiment ();
1896
1897   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
1898       "name", &e->name))
1899   {
1900     fprintf (stderr, "Invalid %s", "name");
1901     free_experiment (e);
1902     return NULL;
1903   }
1904   else
1905     fprintf (stderr, "Experiment name: `%s'\n", e->name);
1906
1907   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
1908       "cfg_file", &e->cfg_file))
1909   {
1910     fprintf (stderr, "Invalid %s", "cfg_file");
1911     free_experiment (e);
1912     return NULL;
1913   }
1914   else
1915   {
1916     fprintf (stderr, "Experiment name: `%s'\n", e->cfg_file);
1917     e->cfg = GNUNET_CONFIGURATION_create();
1918     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
1919     {
1920       fprintf (stderr, "Invalid configuration %s", "cfg_file");
1921       free_experiment (e);
1922       return NULL;
1923     }
1924
1925   }
1926
1927   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
1928       "masters", &e->num_masters))
1929   {
1930     fprintf (stderr, "Invalid %s", "masters");
1931     free_experiment (e);
1932     return NULL;
1933   }
1934   else
1935     fprintf (stderr, "Experiment masters: `%llu'\n",
1936         e->num_masters);
1937
1938   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
1939       "slaves", &e->num_slaves))
1940   {
1941     fprintf (stderr, "Invalid %s", "slaves");
1942     free_experiment (e);
1943     return NULL;
1944   }
1945   else
1946     fprintf (stderr, "Experiment slaves: `%llu'\n",
1947         e->num_slaves);
1948
1949   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
1950       "log_freq", &e->log_freq))
1951   {
1952     fprintf (stderr, "Invalid %s", "log_freq");
1953     free_experiment (e);
1954     return NULL;
1955   }
1956   else
1957     fprintf (stderr, "Experiment logging frequency: `%s'\n",
1958         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
1959
1960   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
1961       "max_duration", &e->max_duration))
1962   {
1963     fprintf (stderr, "Invalid %s", "max_duration");
1964     free_experiment (e);
1965     return NULL;
1966   }
1967   else
1968     fprintf (stderr, "Experiment duration: `%s'\n",
1969         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
1970
1971   if (GNUNET_SYSERR == load_episodes (e, cfg))
1972   {
1973     GNUNET_ATS_solvers_experimentation_stop (e);
1974     GNUNET_CONFIGURATION_destroy (cfg);
1975     e = NULL;
1976     fprintf (stderr, "Failed to load experiment\n");
1977     return NULL;
1978   }
1979   fprintf (stderr, "Loaded %u episodes with total duration %s\n",
1980       e->num_episodes,
1981       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
1982
1983   GNUNET_CONFIGURATION_destroy (cfg);
1984   return e;
1985 }
1986
1987 /**
1988  * Logging
1989  */
1990
1991
1992 /**
1993  * Solver
1994  */
1995
1996 struct GNUNET_ATS_TESTING_SolverHandle
1997 {
1998   char * plugin;
1999   struct GNUNET_ATS_PluginEnvironment env;
2000   void *solver;
2001   struct GNUNET_CONTAINER_MultiPeerMap *addresses;
2002 };
2003
2004 enum GNUNET_ATS_Solvers
2005 {
2006   GNUNET_ATS_SOLVER_PROPORTIONAL,
2007   GNUNET_ATS_SOLVER_MLP,
2008   GNUNET_ATS_SOLVER_RIL,
2009 };
2010
2011
2012 void
2013 GNUNET_ATS_solvers_solver_stop (struct GNUNET_ATS_TESTING_SolverHandle *sh)
2014 {
2015  GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats,
2016      GNUNET_NO);
2017  GNUNET_CONTAINER_multipeermap_destroy(sh->env.addresses);
2018  GNUNET_PLUGIN_unload (sh->plugin, sh->solver);
2019  GNUNET_CONTAINER_multipeermap_destroy(sh->addresses);
2020  GNUNET_free (sh->plugin);
2021  GNUNET_free (sh);
2022 }
2023
2024 /**
2025  * Load quotas for networks from configuration
2026  *
2027  * @param cfg configuration handle
2028  * @param out_dest where to write outbound quotas
2029  * @param in_dest where to write inbound quotas
2030  * @param dest_length length of inbound and outbound arrays
2031  * @return number of networks loaded
2032  */
2033 unsigned int
2034 GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
2035                                                  unsigned long long *out_dest,
2036                                                  unsigned long long *in_dest,
2037                                                  int dest_length)
2038 {
2039   char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
2040   char * entry_in = NULL;
2041   char * entry_out = NULL;
2042   char * quota_out_str;
2043   char * quota_in_str;
2044   int c;
2045   int res;
2046
2047   for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++)
2048   {
2049     in_dest[c] = 0;
2050     out_dest[c] = 0;
2051     GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]);
2052     GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]);
2053
2054     /* quota out */
2055     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, &quota_out_str))
2056     {
2057       res = GNUNET_NO;
2058       if (0 == strcmp(quota_out_str, BIG_M_STRING))
2059       {
2060         out_dest[c] = GNUNET_ATS_MaxBandwidth;
2061         res = GNUNET_YES;
2062       }
2063       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c])))
2064         res = GNUNET_YES;
2065       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out,  &out_dest[c])))
2066          res = GNUNET_YES;
2067
2068       if (GNUNET_NO == res)
2069       {
2070           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2071               network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth);
2072           out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2073       }
2074       else
2075       {
2076           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Outbound quota configure for network `%s' is %llu\n"),
2077               network_str[c], out_dest[c]);
2078       }
2079       GNUNET_free (quota_out_str);
2080     }
2081     else
2082     {
2083       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
2084           network_str[c], GNUNET_ATS_DefaultBandwidth);
2085       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2086     }
2087
2088     /* quota in */
2089     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, &quota_in_str))
2090     {
2091       res = GNUNET_NO;
2092       if (0 == strcmp(quota_in_str, BIG_M_STRING))
2093       {
2094         in_dest[c] = GNUNET_ATS_MaxBandwidth;
2095         res = GNUNET_YES;
2096       }
2097       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c])))
2098         res = GNUNET_YES;
2099       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in,  &in_dest[c])))
2100          res = GNUNET_YES;
2101
2102       if (GNUNET_NO == res)
2103       {
2104           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2105               network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth);
2106           in_dest[c] = GNUNET_ATS_DefaultBandwidth;
2107       }
2108       else
2109       {
2110           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Inbound quota configured for network `%s' is %llu\n"),
2111               network_str[c], in_dest[c]);
2112       }
2113       GNUNET_free (quota_in_str);
2114     }
2115     else
2116     {
2117       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
2118           network_str[c], GNUNET_ATS_DefaultBandwidth);
2119       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2120     }
2121     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded quota for network `%s' (in/out): %llu %llu\n", network_str[c], in_dest[c], out_dest[c]);
2122     GNUNET_free (entry_out);
2123     GNUNET_free (entry_in);
2124   }
2125   return GNUNET_ATS_NetworkTypeCount;
2126 }
2127
2128 /**
2129  * Information callback for the solver
2130  *
2131  * @param op the solver operation
2132  * @param stat status of the solver operation
2133  * @param add additional solver information
2134  */
2135 static void
2136 solver_info_cb (void *cls,
2137     enum GAS_Solver_Operation op,
2138     enum GAS_Solver_Status stat,
2139     enum GAS_Solver_Additional_Information add)
2140 {
2141   char *add_info;
2142   switch (add) {
2143     case GAS_INFO_NONE:
2144       add_info = "GAS_INFO_NONE";
2145       break;
2146     case GAS_INFO_FULL:
2147       add_info = "GAS_INFO_MLP_FULL";
2148       break;
2149     case GAS_INFO_UPDATED:
2150       add_info = "GAS_INFO_MLP_UPDATED";
2151       break;
2152     case GAS_INFO_PROP_ALL:
2153       add_info = "GAS_INFO_PROP_ALL";
2154       break;
2155     case GAS_INFO_PROP_SINGLE:
2156       add_info = "GAS_INFO_PROP_SINGLE";
2157       break;
2158     default:
2159       add_info = "INVALID";
2160       break;
2161   }
2162
2163   switch (op)
2164   {
2165     case GAS_OP_SOLVE_START:
2166       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2167           "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
2168           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2169       return;
2170     case GAS_OP_SOLVE_STOP:
2171       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2172           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
2173           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2174       return;
2175
2176     case GAS_OP_SOLVE_SETUP_START:
2177       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2178           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
2179           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2180       return;
2181
2182     case GAS_OP_SOLVE_SETUP_STOP:
2183       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2184           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
2185           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2186       return;
2187
2188     case GAS_OP_SOLVE_MLP_LP_START:
2189       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2190           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
2191           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2192       return;
2193     case GAS_OP_SOLVE_MLP_LP_STOP:
2194       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2195           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
2196           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2197       return;
2198
2199     case GAS_OP_SOLVE_MLP_MLP_START:
2200       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2201           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
2202           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2203       return;
2204     case GAS_OP_SOLVE_MLP_MLP_STOP:
2205       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2206           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
2207           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2208       return;
2209     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
2210       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2211           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
2212           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2213       return;
2214     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
2215       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2216           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
2217           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2218       return;
2219     default:
2220       break;
2221     }
2222 }
2223
2224 static void
2225 solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
2226 {
2227   if ( (0 == ntohl (address->assigned_bw_out.value__)) &&
2228        (0 == ntohl (address->assigned_bw_in.value__)) )
2229     return;
2230
2231   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2232               "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
2233               GNUNET_i2s (&address->peer),
2234               address,
2235               (unsigned int) ntohl (address->assigned_bw_out.value__),
2236               (unsigned int) ntohl (address->assigned_bw_in.value__));
2237   /*if (GNUNET_YES == ph.bulk_running)
2238     GNUNET_break (0);*/
2239   return;
2240 }
2241
2242 const double *
2243 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
2244 {
2245   return GAS_normalization_get_preferences_by_peer (id);
2246 }
2247
2248
2249 const double *
2250 get_property_cb (void *cls, const struct ATS_Address *address)
2251 {
2252   return GAS_normalization_get_properties ((struct ATS_Address *) address);
2253 }
2254
2255 static void
2256 normalized_property_changed_cb (void *cls, struct ATS_Address *peer,
2257     uint32_t type, double prop_rel)
2258 {
2259   /* TODO */
2260 }
2261
2262
2263 struct GNUNET_ATS_TESTING_SolverHandle *
2264 GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
2265 {
2266   struct GNUNET_ATS_TESTING_SolverHandle *sh;
2267   char * solver_str;
2268   unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
2269   unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
2270
2271   switch (type) {
2272     case GNUNET_ATS_SOLVER_PROPORTIONAL:
2273       solver_str = "proportional";
2274       break;
2275     case GNUNET_ATS_SOLVER_MLP:
2276       solver_str = "mlp";
2277       break;
2278     case GNUNET_ATS_SOLVER_RIL:
2279       solver_str = "ril";
2280       break;
2281     default:
2282       GNUNET_break (0);
2283       return NULL;
2284       break;
2285   }
2286
2287   sh = GNUNET_new (struct GNUNET_ATS_TESTING_SolverHandle);
2288   GNUNET_asprintf (&sh->plugin, "libgnunet_plugin_ats_%s", solver_str);
2289
2290   /* setup environment */
2291   sh->env.cfg = e->cfg;
2292   sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
2293   sh->env.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
2294   sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
2295   sh->env.get_preferences = &get_preferences_cb;
2296   sh->env.get_property = &get_property_cb;
2297   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
2298   sh->env.info_cb = &solver_info_cb;
2299   sh->env.info_cb_cls = NULL;
2300
2301   /* start normalization */
2302   GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL );
2303
2304   /* load quotas */
2305   if (GNUNET_ATS_NetworkTypeCount != GNUNET_ATS_solvers_load_quotas (e->cfg,
2306       quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount))
2307   {
2308     GNUNET_break(0);
2309     GNUNET_free (sh->plugin);
2310     GNUNET_free (sh);
2311     end_now ();
2312     return NULL;
2313   }
2314
2315   sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
2316   if (NULL == sh->solver)
2317   {
2318     fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
2319     GNUNET_break(0);
2320     GNUNET_free (sh->plugin);
2321     GNUNET_free (sh);
2322     end_now ();
2323     return NULL;
2324   }
2325
2326   sh->addresses = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
2327
2328   return sh;
2329 }
2330
2331 static void
2332 done ()
2333 {
2334   /* Clean up experiment */
2335   GNUNET_ATS_solver_generate_preferences_stop_all ();
2336   GNUNET_ATS_solvers_experimentation_stop (e);
2337   e = NULL;
2338
2339   /* Shutdown */
2340   end_now();
2341
2342 }
2343
2344 static void
2345 experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success)
2346 {
2347   if (GNUNET_OK == success)
2348     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
2349         GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
2350   else
2351     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
2352
2353   /* Stop logging */
2354   // GNUNET_ATS_TEST_logging_stop (l);
2355
2356   /* Stop traffic generation */
2357   // GNUNET_ATS_TEST_generate_traffic_stop_all();
2358
2359   /* Stop all preference generations */
2360   GNUNET_ATS_solver_generate_preferences_stop_all ();
2361
2362   /*
2363   evaluate (duration);
2364   if (opt_log)
2365     GNUNET_ATS_TEST_logging_write_to_file(l, opt_exp_file, opt_plot);
2366
2367   if (NULL != l)
2368   {
2369     GNUNET_ATS_TEST_logging_stop (l);
2370     GNUNET_ATS_TEST_logging_clean_up (l);
2371     l = NULL;
2372   }
2373   */
2374   GNUNET_SCHEDULER_add_now (&done, NULL);
2375 }
2376
2377 static void
2378 episode_done_cb (struct Episode *ep)
2379 {
2380   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
2381 }
2382
2383
2384
2385 /**
2386  * Do shutdown
2387  */
2388 static void
2389 end_now ()
2390 {
2391   if (NULL != e)
2392   {
2393     GNUNET_ATS_solvers_experimentation_stop (e);
2394     e = NULL;
2395   }
2396   if (NULL != sh)
2397   {
2398     GNUNET_ATS_solvers_solver_stop (sh);
2399     sh = NULL;
2400   }
2401 }
2402
2403 static void
2404 run (void *cls, char * const *args, const char *cfgfile,
2405     const struct GNUNET_CONFIGURATION_Handle *cfg)
2406 {
2407   enum GNUNET_ATS_Solvers solver;
2408
2409   if (NULL == opt_exp_file)
2410   {
2411     fprintf (stderr, "No experiment given ...\n");
2412     res = 1;
2413     end_now ();
2414     return;
2415   }
2416
2417   if (NULL == opt_solver)
2418   {
2419     fprintf (stderr, "No solver given ...\n");
2420     res = 1;
2421     end_now ();
2422     return;
2423   }
2424
2425   if (0 == strcmp(opt_solver, "mlp"))
2426   {
2427     solver = GNUNET_ATS_SOLVER_MLP;
2428   }
2429   else if (0 == strcmp(opt_solver, "proportional"))
2430   {
2431     solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
2432   }
2433   else if (0 == strcmp(opt_solver, "ril"))
2434   {
2435     solver = GNUNET_ATS_SOLVER_RIL;
2436   }
2437   else
2438   {
2439     fprintf (stderr, "No solver given ...");
2440     res = 1;
2441     end_now ();
2442     return;
2443   }
2444
2445   /* load experiment */
2446   e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
2447   if (NULL == e)
2448   {
2449     fprintf (stderr, "Failed to load experiment ...\n");
2450     res = 1;
2451     end_now ();
2452     return;
2453   }
2454
2455
2456   /* load solver */
2457   sh = GNUNET_ATS_solvers_solver_start (solver);
2458   if (NULL == sh)
2459   {
2460     fprintf (stderr, "Failed to start solver ...\n");
2461     end_now ();
2462     res = 1;
2463     return;
2464   }
2465
2466   /* start logging */
2467
2468
2469   /* run experiment */
2470   GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
2471       experiment_done_cb);
2472
2473   /* WAIT */
2474 }
2475
2476
2477 /**
2478  * Main function of the benchmark
2479  *
2480  * @param argc argument count
2481  * @param argv argument values
2482  */
2483 int
2484 main (int argc, char *argv[])
2485 {
2486   opt_exp_file = NULL;
2487   opt_solver = NULL;
2488   opt_log = GNUNET_NO;
2489   opt_plot = GNUNET_NO;
2490
2491   res = 0;
2492
2493   static struct GNUNET_GETOPT_CommandLineOption options[] =
2494   {
2495     { 's', "solver", NULL,
2496         gettext_noop ("solver to use"),
2497         1, &GNUNET_GETOPT_set_string, &opt_solver},
2498     {  'e', "experiment", NULL,
2499       gettext_noop ("experiment to use"),
2500       1, &GNUNET_GETOPT_set_string, &opt_exp_file},
2501     {  'e', "experiment", NULL,
2502       gettext_noop ("experiment to use"),
2503       1, &GNUNET_GETOPT_set_one, &opt_verbose},
2504     GNUNET_GETOPT_OPTION_END
2505   };
2506
2507   GNUNET_PROGRAM_run (argc, argv, "gnunet-ats-solver-eval",
2508       NULL, options, &run, argv[0]);
2509
2510   return res;
2511 }
2512 /* end of file ats-testing-experiment.c*/
2513