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