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