improved network definition
[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_save;
57
58 /**
59  * cmd option -v: verbose logs
60  */
61 static int opt_verbose;
62
63 /**
64  * cmd option -p: print logs
65  */
66 static int opt_print;
67
68 static int res;
69
70 static void
71 end_now ();
72
73 static char *
74 print_generator_type (enum GeneratorType g)
75 {
76   switch (g) {
77     case GNUNET_ATS_TEST_TG_CONSTANT:
78       return "CONSTANT";
79     case GNUNET_ATS_TEST_TG_LINEAR:
80       return "LINEAR";
81     case GNUNET_ATS_TEST_TG_RANDOM:
82       return "RANDOM";
83     case GNUNET_ATS_TEST_TG_SINUS:
84       return "SINUS";
85     default:
86       return "INVALID";
87       break;
88   }
89 }
90
91 struct AddressLookupCtx
92 {
93   struct ATS_Address *res;
94   char *plugin;
95   char *addr;
96 };
97
98
99 int find_address_it (void *cls,
100                      const struct GNUNET_PeerIdentity *key,
101                      void *value)
102 {
103   struct AddressLookupCtx *ctx = cls;
104   struct ATS_Address *addr = value;
105
106   if ( (0 == strcmp (ctx->plugin, addr->plugin)) &&
107        (0 == strcmp (ctx->addr, addr->addr)) )
108   {
109        ctx->res = addr;
110        return GNUNET_NO;
111   }
112   return GNUNET_YES;
113 }
114
115 static struct TestPeer *
116 find_peer_by_id (int id)
117 {
118   struct TestPeer *cur;
119   for (cur = peer_head; NULL != cur; cur = cur->next)
120     if (cur->id == id)
121       return cur;
122   return NULL;
123 }
124
125 static struct TestPeer *
126 find_peer_by_pid (const struct GNUNET_PeerIdentity *pid)
127 {
128   struct TestPeer *cur;
129   for (cur = peer_head; NULL != cur; cur = cur->next)
130     if (0 == memcmp (&cur->peer_id, pid, sizeof (struct GNUNET_PeerIdentity)))
131       return cur;
132   return NULL;
133 }
134
135 static struct TestAddress *
136 find_address_by_id (struct TestPeer *peer, int aid)
137 {
138   struct TestAddress *cur;
139   for (cur = peer->addr_head; NULL != cur; cur = cur->next)
140     if (cur->aid == aid)
141       return cur;
142   return NULL;
143 }
144
145
146 static struct TestAddress *
147 find_address_by_ats_address (struct TestPeer *p, struct ATS_Address *addr)
148 {
149   struct TestAddress *cur;
150   for (cur = p->addr_head; NULL != cur; cur = cur->next)
151     if ((0 == strcmp(cur->ats_addr->plugin, addr->plugin)) &&
152          (cur->ats_addr->addr_len == addr->addr_len) &&
153         (0 == memcmp (cur->ats_addr->addr, addr->addr, addr->addr_len)))
154       return cur;
155   return NULL;
156 }
157
158
159 /**
160  * Logging
161  */
162
163 void
164 GNUNET_ATS_solver_logging_now (struct LoggingHandle *l)
165 {
166   struct LoggingTimeStep *lts;
167   struct TestPeer *cur;
168   struct TestAddress *cur_addr;
169   struct LoggingPeer *log_p;
170   struct LoggingAddress *log_a;
171   int c;
172
173   lts = GNUNET_new (struct LoggingTimeStep);
174   GNUNET_CONTAINER_DLL_insert_tail(l->head, l->tail, lts);
175   lts->timestamp = GNUNET_TIME_absolute_get();
176   if (NULL == lts->prev)
177     lts->delta = GNUNET_TIME_UNIT_ZERO;
178   else
179     lts->delta = GNUNET_TIME_absolute_get_duration(lts->prev->timestamp);
180
181   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging %llu, delta %llu\n",
182       lts->timestamp.abs_value_us, lts->delta.rel_value_us);
183
184
185   /* Store logging data here */
186   for (cur = peer_head; NULL != cur; cur = cur->next)
187   {
188     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging peer id %u\n", cur->peer_id);
189
190     log_p = GNUNET_new (struct LoggingPeer);
191     log_p->id = cur->id;
192     log_p->peer_id = cur->peer_id;
193     for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
194     {
195       log_p->pref_abs[c] = cur->pref_abs[c];
196       log_p->pref_norm[c] = cur->pref_norm[c];
197       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t %s = %.2f %.2f [abs/rel]\n",
198           GNUNET_ATS_print_preference_type(c),
199           log_p->pref_abs[c], log_p->pref_norm[c]);
200     }
201     GNUNET_CONTAINER_DLL_insert_tail(lts->head, lts->tail, log_p);
202
203     for (cur_addr = cur->addr_head; NULL != cur_addr; cur_addr = cur_addr->next)
204     {
205       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging peer id %u address %u\n", cur->peer_id, cur_addr->aid);
206       log_a = GNUNET_new (struct LoggingAddress);
207       log_a->aid = cur_addr->aid;
208       log_a->active = cur_addr->ats_addr->active;
209       log_a->network = cur_addr->network;
210       log_a->used = cur_addr->ats_addr->used;
211       log_a->assigned_bw_in = cur_addr->ats_addr->assigned_bw_in;
212       log_a->assigned_bw_out = cur_addr->ats_addr->assigned_bw_out;
213       for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
214       {
215         log_a->prop_abs[c] = cur_addr->prop_abs[c];
216         log_a->prop_norm[c] = cur_addr->prop_norm[c];
217         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t %s = %.2f %.2f [abs/rel]\n",
218             GNUNET_ATS_print_property_type(c),
219             log_a->prop_abs[c], log_a->prop_norm[c]);
220       }
221       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t Active = %i\n", log_a->active);
222       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t BW in = %llu\n", ntohl(log_a->assigned_bw_in.value__));
223       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t BW out = %llu\n", ntohl(log_a->assigned_bw_out.value__));
224
225       GNUNET_CONTAINER_DLL_insert_tail(log_p->addr_head, log_p->addr_tail, log_a);
226     }
227   }
228 }
229
230 static void
231 logging_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
232 {
233   struct LoggingHandle *l = cls;
234   l->logging_task = GNUNET_SCHEDULER_NO_TASK;
235
236   GNUNET_ATS_solver_logging_now (l);
237
238   l->logging_task = GNUNET_SCHEDULER_add_delayed (l->log_freq, &logging_task, l);
239
240 }
241
242 struct LoggingHandle *
243 GNUNET_ATS_solver_logging_start (struct GNUNET_TIME_Relative freq)
244 {
245   struct LoggingHandle *l;
246   l = GNUNET_new (struct LoggingHandle);
247
248   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start logging every  %s\n",
249       GNUNET_STRINGS_relative_time_to_string(freq, GNUNET_NO));
250   l->log_freq = freq;
251   l->logging_task = GNUNET_SCHEDULER_add_now (&logging_task, l);
252   return l;
253 }
254
255 void
256 GNUNET_ATS_solver_logging_stop (struct LoggingHandle *l)
257 {
258   if (GNUNET_SCHEDULER_NO_TASK != l->logging_task)
259     GNUNET_SCHEDULER_cancel (l->logging_task);
260
261   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop logging\n");
262
263   l->logging_task = GNUNET_SCHEDULER_NO_TASK;
264 }
265
266 static struct LoggingFileHandle *
267 find_logging_file_handle (struct LoggingFileHandle *lf_head,
268     struct LoggingFileHandle *lf_tail,
269     int peer_id, int address_id)
270 {
271   struct LoggingFileHandle *res;
272
273   for (res = lf_head; NULL != res; res = res->next)
274     if ((res->pid == peer_id) && (res->pid == address_id))
275       return res;
276   return NULL;
277
278 }
279
280 void
281 GNUNET_ATS_solver_logging_write_to_disk (struct LoggingHandle *l)
282 {
283   struct LoggingTimeStep *lts;
284   struct LoggingPeer *log_p;
285   struct LoggingAddress *log_a;
286   struct LoggingFileHandle *lf_head;
287   struct LoggingFileHandle *lf_tail;
288   struct LoggingFileHandle *cur;
289   struct LoggingFileHandle *next;
290   char * filename;
291   char * datastring;
292   char * propstring;
293   char * propstring_tmp;
294   char * prefstring;
295   char * prefstring_tmp;
296   int c;
297
298
299   lf_head = NULL;
300   lf_tail = NULL;
301
302   for (lts = l->head; NULL != lts; lts = lts->next)
303   {
304
305     fprintf (stderr, "Log step %llu %llu: \n",
306         (long long unsigned int) lts->timestamp.abs_value_us,
307         (long long unsigned int) lts->delta.rel_value_us);
308
309     for (log_p = lts->head; NULL != log_p; log_p = log_p->next)
310     {
311       for (log_a = log_p->addr_head; NULL != log_a; log_a = log_a->next)
312       {
313
314         cur = find_logging_file_handle (lf_head, lf_tail, log_p->id,
315             log_a->aid);
316         if (NULL == cur)
317         {
318           cur = GNUNET_new (struct LoggingFileHandle);
319           cur->aid = log_a->aid;
320           cur->pid = log_p->id;
321
322           fprintf (stderr, "Add logging for %i %i: \n",
323               cur->pid, cur->aid);
324
325           GNUNET_asprintf (&filename, "%s_%s_%u_%u_%llu.log", e->log_prefix, opt_solver,
326               cur->aid, cur->pid, l->head->timestamp.abs_value_us);
327           cur->f_hd = GNUNET_DISK_file_open (filename,
328               GNUNET_DISK_OPEN_READWRITE |
329               GNUNET_DISK_OPEN_CREATE |
330               GNUNET_DISK_OPEN_TRUNCATE,
331               GNUNET_DISK_PERM_USER_READ |
332               GNUNET_DISK_PERM_USER_WRITE |
333               GNUNET_DISK_PERM_GROUP_READ |
334               GNUNET_DISK_PERM_OTHER_READ);
335           if (NULL == cur->f_hd)
336           {
337             fprintf (stderr, "Cannot open `%s' to write log data!\n", filename);
338             GNUNET_free (filename);
339             goto cleanup;
340           }
341           GNUNET_free (filename);
342           GNUNET_CONTAINER_DLL_insert (lf_head, lf_tail, cur);
343
344           GNUNET_asprintf(&datastring,"#timestamp_abs; addr net; addr_active; bw in; bw out; " \
345               "UTILIZATION_UP [abs/rel]; UTILIZATION_UP; UTILIZATION_DOWN; UTILIZATION_DOWN; " \
346               "UTILIZATION_PAYLOAD_UP; UTILIZATION_PAYLOAD_UP; UTILIZATION_PAYLOAD_DOWN; UTILIZATION_PAYLOAD_DOWN;"\
347               "DELAY; DELAY; " \
348               "DISTANCE ;DISTANCE ; COST_WAN; COST_WAN; COST_LAN; COST_LAN; " \
349               "COST_WLAN; COST_WLAN; PREF BW abs; PREF BW rel; PREF LATENCY abs; PREF LATENCY rel;\n",
350               lts->timestamp.abs_value_us,
351               log_a->active,
352               ntohl (log_a->assigned_bw_in.value__),
353               ntohl (log_a->assigned_bw_out.value__));
354           GNUNET_DISK_file_write (cur->f_hd, datastring, strlen(datastring));
355           GNUNET_free (datastring);
356
357         }
358
359         prefstring = GNUNET_strdup("");
360         for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
361         {
362           fprintf(stderr,"\t %s = %.2f %.2f [abs/rel]\n",
363               GNUNET_ATS_print_preference_type(c),
364               log_p->pref_abs[c], log_p->pref_norm[c]);
365
366           GNUNET_asprintf(&prefstring_tmp,"%s;%.3f;%.3f",
367               prefstring, log_p->pref_abs[c], log_p->pref_norm[c]);
368           GNUNET_free (prefstring);
369           prefstring = GNUNET_strdup(prefstring_tmp);
370           GNUNET_free (prefstring_tmp);
371         }
372
373         propstring = GNUNET_strdup("");
374         for (c = 1; c < GNUNET_ATS_PropertyCount; c++)
375         {
376           if (GNUNET_ATS_NETWORK_TYPE == c)
377             continue;
378           fprintf(stderr, "\t %s = %.2f %.2f [abs/rel]\n",
379               GNUNET_ATS_print_property_type(c),
380               log_a->prop_abs[c], log_a->prop_norm[c]);
381           GNUNET_asprintf(&propstring_tmp,"%s;%.3f;%.3f",
382               propstring, log_a->prop_abs[c], log_a->prop_norm[c]);
383           GNUNET_free (propstring);
384           propstring = GNUNET_strdup(propstring_tmp);
385           GNUNET_free (propstring_tmp);
386         }
387
388
389         GNUNET_asprintf(&datastring,"%llu;%u;%i;%u;%u;%s\n",
390             lts->timestamp.abs_value_us,
391             log_a->network,
392             log_a->active,
393             ntohl (log_a->assigned_bw_in.value__),
394             ntohl (log_a->assigned_bw_out.value__),
395             propstring, prefstring);
396         GNUNET_DISK_file_write (cur->f_hd, datastring, strlen(datastring));
397         GNUNET_free (datastring);
398         GNUNET_free (prefstring);
399         GNUNET_free (propstring);
400       }
401     }
402   }
403
404 cleanup:
405   next = lf_head;
406   for (cur = next; NULL != cur; cur = next)
407   {
408     next = cur->next;
409     GNUNET_CONTAINER_DLL_remove (lf_head, lf_tail, cur);
410     if (NULL != cur->f_hd)
411       GNUNET_DISK_file_close (cur->f_hd);
412     GNUNET_free (cur);
413   }
414
415 }
416
417 void
418 GNUNET_ATS_solver_logging_eval (struct LoggingHandle *l)
419 {
420   struct LoggingTimeStep *lts;
421   struct LoggingPeer *log_p;
422   struct LoggingAddress *log_a;
423   int c;
424
425   for (lts = l->head; NULL != lts; lts = lts->next)
426   {
427     fprintf (stderr, "Log step %llu %llu: \n",
428         (long long unsigned int) lts->timestamp.abs_value_us,
429         (long long unsigned int) lts->delta.rel_value_us);
430
431     for (log_p = lts->head; NULL != log_p; log_p = log_p->next)
432     {
433       fprintf (stderr,"\tLogging peer pid %u\n", log_p->id);
434       for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
435       {
436         fprintf(stderr,"\t %s = %.2f %.2f [abs/rel]\n",
437             GNUNET_ATS_print_preference_type(c),
438             log_p->pref_abs[c], log_p->pref_norm[c]);
439       }
440
441       for (log_a = log_p->addr_head; NULL != log_a; log_a = log_a->next)
442       {
443         fprintf (stderr, "\tPeer pid %u address %u: %u %u %u\n",
444             log_p->id, log_a->aid, log_a->active,
445             ntohl(log_a->assigned_bw_in.value__),
446             ntohl(log_a->assigned_bw_out.value__));
447
448         for (c = 1; c < GNUNET_ATS_PropertyCount; c++)
449         {
450           if (GNUNET_ATS_NETWORK_TYPE == c)
451             continue;
452           fprintf(stderr, "\t %s = %.2f %.2f [abs/rel]\n",
453               GNUNET_ATS_print_property_type(c),
454               log_a->prop_abs[c], log_a->prop_norm[c]);
455         }
456       }
457     }
458   }
459 }
460
461 void
462 GNUNET_ATS_solver_logging_free (struct LoggingHandle *l)
463 {
464   struct LoggingTimeStep *lts_cur;
465   struct LoggingTimeStep *lts_next;
466   struct LoggingPeer *log_p_cur;
467   struct LoggingPeer *log_p_next;
468   struct LoggingAddress *log_a_cur;
469   struct LoggingAddress *log_a_next;
470
471   if (GNUNET_SCHEDULER_NO_TASK != l->logging_task)
472     GNUNET_SCHEDULER_cancel (l->logging_task);
473   l->logging_task = GNUNET_SCHEDULER_NO_TASK;
474
475   lts_next = l->head;
476   while (NULL != (lts_cur = lts_next))
477   {
478     lts_next = lts_cur->next;
479
480     log_p_next = lts_cur->head;
481     while (NULL != (log_p_cur = log_p_next))
482     {
483       log_p_next = log_p_cur->next;
484
485       log_a_next = log_p_cur->addr_head;
486       while (NULL != (log_a_cur = log_a_next))
487       {
488         log_a_next = log_a_cur->next;
489
490         GNUNET_CONTAINER_DLL_remove (log_p_cur->addr_head, log_p_cur->addr_tail, log_a_cur);
491         GNUNET_free (log_a_cur);
492       }
493
494       GNUNET_CONTAINER_DLL_remove (lts_cur->head, lts_cur->tail, log_p_cur);
495       GNUNET_free (log_p_cur);
496     }
497
498     GNUNET_CONTAINER_DLL_remove (l->head, l->tail, lts_cur);
499     GNUNET_free (lts_cur);
500   }
501
502   GNUNET_free (l);
503 }
504
505 /**
506  * Property Generators
507  */
508
509 static struct PropertyGenerator *prop_gen_head;
510 static struct PropertyGenerator *prop_gen_tail;
511
512 static double
513 get_property (struct PropertyGenerator *pg)
514 {
515   struct GNUNET_TIME_Relative time_delta;
516   double delta_value;
517   double pref_value;
518
519   /* Calculate the current preference value */
520   switch (pg->type) {
521     case GNUNET_ATS_TEST_TG_CONSTANT:
522       pref_value = pg->base_value;
523       break;
524     case GNUNET_ATS_TEST_TG_LINEAR:
525       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
526       /* Calculate point of time in the current period */
527       time_delta.rel_value_us = time_delta.rel_value_us %
528           pg->duration_period.rel_value_us;
529       delta_value = ((double) time_delta.rel_value_us  /
530           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
531       if ((pg->max_value < pg->base_value) &&
532           ((pg->max_value - pg->base_value) > pg->base_value))
533       {
534         /* This will cause an underflow */
535         GNUNET_break (0);
536       }
537       pref_value = pg->base_value + delta_value;
538       break;
539     case GNUNET_ATS_TEST_TG_RANDOM:
540       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
541           10000 * (pg->max_value - pg->base_value)) / 10000;
542       pref_value = pg->base_value + delta_value;
543       break;
544     case GNUNET_ATS_TEST_TG_SINUS:
545       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
546       /* Calculate point of time in the current period */
547       time_delta.rel_value_us = time_delta.rel_value_us %
548           pg->duration_period.rel_value_us;
549       if ((pg->max_value - pg->base_value) > pg->base_value)
550       {
551         /* This will cause an underflow for second half of sinus period,
552          * will be detected in general when experiments are loaded */
553         GNUNET_break (0);
554       }
555       delta_value = (pg->max_value - pg->base_value) *
556           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
557               time_delta.rel_value_us);
558       pref_value = pg->base_value + delta_value;
559       break;
560     default:
561       pref_value = 0.0;
562       break;
563   }
564   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current property value is %f\n",
565       pref_value);
566   return pref_value;
567 }
568
569
570 static void
571 set_prop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
572 {
573   struct PropertyGenerator *pg = cls;
574   struct TestPeer *p;
575   struct TestAddress *a;
576   double pref_value;
577   struct GNUNET_ATS_Information atsi;
578
579   pg->set_task = GNUNET_SCHEDULER_NO_TASK;
580
581   if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains_value (sh->addresses,
582       &pg->test_peer->peer_id, pg->test_address->ats_addr))
583   {
584     GNUNET_break (0);
585     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
586         "Setting property generation for unknown address [%u:%u]\n",
587         pg->peer, pg->address_id);
588     return;
589   }
590   if (NULL == (p = find_peer_by_id (pg->peer)))
591   {
592     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
593         "Setting property generation for unknown peer %u\n",
594         pg->peer);
595   }
596   if (NULL == (a = find_address_by_id (p, pg->address_id)))
597   {
598     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
599         "Setting property generation for unknown peer %u\n",
600         pg->peer);
601   }
602
603   pref_value = get_property (pg);
604   a->prop_abs[pg->ats_property] = pref_value;
605
606   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
607       "Setting property for peer [%u] address [%u] for %s to %f\n",
608       pg->peer, pg->address_id,
609       GNUNET_ATS_print_property_type (pg->ats_property), pref_value);
610
611   atsi.type = htonl (pg->ats_property);
612   atsi.value = htonl ((uint32_t) pref_value);
613
614   /* set performance here! */
615   sh->env.sf.s_bulk_start (sh->solver);
616   GAS_normalization_normalize_property (sh->addresses,
617       pg->test_address->ats_addr, &atsi, 1);
618   sh->env.sf.s_bulk_stop (sh->solver);
619
620   pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
621       &set_prop_task, pg);
622
623 }
624
625 /**
626  * Set ats_property to 0 to find all pgs
627  */
628
629 static struct PropertyGenerator *
630 find_prop_gen (unsigned int peer, unsigned int address,
631     uint32_t ats_property)
632 {
633   struct PropertyGenerator *cur;
634   for (cur = prop_gen_head; NULL != cur; cur = cur->next)
635     if ((cur->peer == peer) && (cur->address_id == address))
636     {
637       if ((cur->ats_property == ats_property) || (0 == ats_property))
638         return cur;
639     }
640   return NULL;
641 }
642
643 void
644 GNUNET_ATS_solver_generate_property_stop (struct PropertyGenerator *pg)
645 {
646   GNUNET_CONTAINER_DLL_remove (prop_gen_head, prop_gen_tail, pg);
647
648   if (GNUNET_SCHEDULER_NO_TASK != pg->set_task)
649   {
650     GNUNET_SCHEDULER_cancel (pg->set_task);
651     pg->set_task = GNUNET_SCHEDULER_NO_TASK;
652   }
653   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
654       "Removing old up preference generator peer [%u] address [%u] `%s'\n",
655       pg->peer, pg->address_id,
656       GNUNET_ATS_print_property_type(pg->ats_property));
657
658   GNUNET_free (pg);
659 }
660
661
662 /**
663  * Generate between the source master and the partner and set property with a
664  * value depending on the generator.
665  *
666  * @param peer source
667  * @param address_id partner
668  * @param test_peer the peer
669  * @param test_address the address
670  * @param type type of generator
671  * @param base_value base value
672  * @param value_rate maximum value
673  * @param period duration of a period of generation (~ 1/frequency)
674  * @param frequency how long to generate property
675  * @param ats_property ATS property to generate
676  * @return the property generator
677  */
678 struct PropertyGenerator *
679 GNUNET_ATS_solver_generate_property_start (unsigned int peer,
680     unsigned int address_id,
681     struct TestPeer *test_peer,
682     struct TestAddress *test_address,
683     enum GeneratorType type,
684     long int base_value,
685     long int value_rate,
686     struct GNUNET_TIME_Relative period,
687     struct GNUNET_TIME_Relative frequency,
688     uint32_t ats_property)
689 {
690   struct PropertyGenerator *pg;
691
692   pg = GNUNET_new (struct PropertyGenerator);
693   GNUNET_CONTAINER_DLL_insert (prop_gen_head, prop_gen_tail, pg);
694   pg->type = type;
695   pg->peer = peer;
696   pg->test_address = test_address;
697   pg->test_peer = test_peer;
698   pg->address_id = address_id;
699   pg->ats_property = ats_property;
700   pg->base_value = base_value;
701   pg->max_value = value_rate;
702   pg->duration_period = period;
703   pg->frequency = frequency;
704   pg->time_start = GNUNET_TIME_absolute_get();
705
706   switch (type) {
707     case GNUNET_ATS_TEST_TG_CONSTANT:
708       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
709           "Setting up %s property generator peer [%u] address [%u] `%s'"\
710           "max %u Bips\n",
711           print_generator_type(type), pg->peer, pg->address_id,
712           GNUNET_ATS_print_property_type (ats_property),
713           base_value);
714       break;
715     case GNUNET_ATS_TEST_TG_LINEAR:
716       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
717           "Setting up %s property generator peer [%u] address [%u] `%s' " \
718           "min %u Bips max %u Bips\n",
719           print_generator_type(type), pg->peer, pg->address_id,
720           GNUNET_ATS_print_property_type(ats_property),
721           base_value, value_rate);
722       break;
723     case GNUNET_ATS_TEST_TG_SINUS:
724       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
725           "Setting up %s property generator peer [%u] address [%u] `%s' "\
726           "baserate %u Bips, amplitude %u Bps\n",
727           print_generator_type(type), pg->peer, pg->address_id,
728           GNUNET_ATS_print_property_type(ats_property),
729           base_value, value_rate);
730       break;
731     case GNUNET_ATS_TEST_TG_RANDOM:
732       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
733           "Setting up %s property generator peer [%u] address [%u] `%s' "\
734           "min %u Bips max %u Bps\n",
735           print_generator_type(type), pg->peer, pg->address_id,
736           GNUNET_ATS_print_property_type(ats_property),
737           base_value, value_rate);
738       break;
739     default:
740       break;
741   }
742
743   pg->set_task = GNUNET_SCHEDULER_add_now (&set_prop_task, pg);
744   return pg;
745 }
746
747
748
749 /**
750  * Stop all preferences generators
751  */
752 void
753 GNUNET_ATS_solver_generate_property_stop_all ()
754 {
755   struct PropertyGenerator *cur;
756   struct PropertyGenerator *next;
757   next = prop_gen_head;
758   for (cur = next; NULL != cur; cur = next)
759   {
760       next = cur->next;
761       GNUNET_ATS_solver_generate_property_stop (cur);
762   }
763 }
764
765
766 /**
767  * Preference Generators
768  */
769
770 static struct PreferenceGenerator *pref_gen_head;
771 static struct PreferenceGenerator *pref_gen_tail;
772
773 static double
774 get_preference (struct PreferenceGenerator *pg)
775 {
776   struct GNUNET_TIME_Relative time_delta;
777   double delta_value;
778   double pref_value;
779
780   /* Calculate the current preference value */
781   switch (pg->type) {
782     case GNUNET_ATS_TEST_TG_CONSTANT:
783       pref_value = pg->base_value;
784       break;
785     case GNUNET_ATS_TEST_TG_LINEAR:
786       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
787       /* Calculate point of time in the current period */
788       time_delta.rel_value_us = time_delta.rel_value_us %
789           pg->duration_period.rel_value_us;
790       delta_value = ((double) time_delta.rel_value_us  /
791           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
792       if ((pg->max_value < pg->base_value) &&
793           ((pg->max_value - pg->base_value) > pg->base_value))
794       {
795         /* This will cause an underflow */
796         GNUNET_break (0);
797       }
798       pref_value = pg->base_value + delta_value;
799       break;
800     case GNUNET_ATS_TEST_TG_RANDOM:
801       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
802           10000 * (pg->max_value - pg->base_value)) / 10000;
803       pref_value = pg->base_value + delta_value;
804       break;
805     case GNUNET_ATS_TEST_TG_SINUS:
806       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
807       /* Calculate point of time in the current period */
808       time_delta.rel_value_us = time_delta.rel_value_us %
809           pg->duration_period.rel_value_us;
810       if ((pg->max_value - pg->base_value) > pg->base_value)
811       {
812         /* This will cause an underflow for second half of sinus period,
813          * will be detected in general when experiments are loaded */
814         GNUNET_break (0);
815       }
816       delta_value = (pg->max_value - pg->base_value) *
817           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
818               time_delta.rel_value_us);
819       pref_value = pg->base_value + delta_value;
820       break;
821     default:
822       pref_value = 0.0;
823       break;
824   }
825   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current preference value is %f\n",
826       pref_value);
827   return pref_value;
828 }
829
830
831 static void
832 set_pref_task (void *cls,
833                     const struct GNUNET_SCHEDULER_TaskContext *tc)
834 {
835   struct PreferenceGenerator *pg = cls;
836   struct TestPeer *p;
837   double pref_value;
838   pg->set_task = GNUNET_SCHEDULER_NO_TASK;
839
840   if (NULL == (p = find_peer_by_id (pg->peer)))
841   {
842     GNUNET_break (0);
843     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
844         "Setting preference for unknown peer %u\n", pg->peer);
845     return;
846   }
847
848   pref_value = get_preference (pg);
849   p->pref_abs[pg->kind] = pref_value;
850
851   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
852       "Setting preference for peer [%u] for client %p pref %s to %f\n",
853       pg->peer, NULL + (pg->client_id),
854       GNUNET_ATS_print_preference_type (pg->kind), pref_value);
855
856   sh->env.sf.s_bulk_start (sh->solver);
857   GAS_normalization_normalize_preference (NULL + (pg->client_id), &p->peer_id,
858       pg->kind, pref_value);
859   sh->env.sf.s_bulk_stop (sh->solver);
860
861   switch (pg->kind) {
862     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
863       //p->pref_bandwidth = pref_value;
864       break;
865     case GNUNET_ATS_PREFERENCE_LATENCY:
866       //p->pref_delay = pref_value;
867       break;
868     default:
869       break;
870   }
871
872   pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
873       set_pref_task, pg);
874
875 }
876
877 static struct PreferenceGenerator *
878 find_pref_gen (unsigned int peer, enum GNUNET_ATS_PreferenceKind kind)
879 {
880   struct PreferenceGenerator *cur;
881   for (cur = pref_gen_head; NULL != cur; cur = cur->next)
882     if (cur->peer == peer)
883     {
884       if ((cur->kind == kind) || (GNUNET_ATS_PREFERENCE_END == kind))
885         return cur;
886     }
887   return NULL;
888 }
889
890 void
891 GNUNET_ATS_solver_generate_preferences_stop (struct PreferenceGenerator *pg)
892 {
893   GNUNET_CONTAINER_DLL_remove (pref_gen_head, pref_gen_tail, pg);
894
895   if (GNUNET_SCHEDULER_NO_TASK != pg->set_task)
896   {
897     GNUNET_SCHEDULER_cancel (pg->set_task);
898     pg->set_task = GNUNET_SCHEDULER_NO_TASK;
899   }
900   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
901       "Removing old up preference generator peer [%u] `%s'\n",
902       pg->peer, GNUNET_ATS_print_preference_type(pg->kind));
903
904   GNUNET_free (pg);
905 }
906
907
908 /**
909  * Generate between the source master and the partner and set property with a
910  * value depending on the generator.
911  *
912  * @param peer source
913  * @param address_id partner
914  * @param client_id the client
915  * @param type type of generator
916  * @param base_value base value
917  * @param value_rate maximum value
918  * @param period duration of a period of generation (~ 1/frequency)
919  * @param frequency how long to generate property
920  * @param kind ATS preference to generate
921  * @return the preference generator
922  */
923 struct PreferenceGenerator *
924 GNUNET_ATS_solver_generate_preferences_start (unsigned int peer,
925     unsigned int address_id,
926     unsigned int client_id,
927     enum GeneratorType type,
928     long int base_value,
929     long int value_rate,
930     struct GNUNET_TIME_Relative period,
931     struct GNUNET_TIME_Relative frequency,
932     enum GNUNET_ATS_PreferenceKind kind)
933 {
934   struct PreferenceGenerator *pg;
935
936   pg = GNUNET_new (struct PreferenceGenerator);
937   GNUNET_CONTAINER_DLL_insert (pref_gen_head, pref_gen_tail, pg);
938   pg->type = type;
939   pg->peer = peer;
940   pg->client_id = client_id;
941   pg->kind = kind;
942   pg->base_value = base_value;
943   pg->max_value = value_rate;
944   pg->duration_period = period;
945   pg->frequency = frequency;
946   pg->time_start = GNUNET_TIME_absolute_get();
947
948   switch (type) {
949     case GNUNET_ATS_TEST_TG_CONSTANT:
950       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
951           "Setting up %s preference generator peer [%u] `%s' max %u Bips\n",
952           print_generator_type (type), pg->peer,
953           GNUNET_ATS_print_preference_type(kind),
954           base_value);
955       break;
956     case GNUNET_ATS_TEST_TG_LINEAR:
957       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
958           "Setting up %s preference generator peer [%u] `%s' min %u Bips max %u Bips\n",
959           print_generator_type (type), pg->peer, GNUNET_ATS_print_preference_type(kind),
960           base_value, value_rate);
961       break;
962     case GNUNET_ATS_TEST_TG_SINUS:
963       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
964           "Setting up %s preference generator peer [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
965           print_generator_type (type), pg->peer, GNUNET_ATS_print_preference_type(kind),
966           base_value, value_rate);
967       break;
968     case GNUNET_ATS_TEST_TG_RANDOM:
969       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
970           "Setting up %s preference generator peer [%u] `%s' min %u Bips max %u Bps\n",
971           print_generator_type (type), pg->peer, GNUNET_ATS_print_preference_type(kind),
972           base_value, value_rate);
973       break;
974     default:
975       break;
976   }
977
978   pg->set_task = GNUNET_SCHEDULER_add_now (&set_pref_task, pg);
979   return pg;
980 }
981
982
983
984 /**
985  * Stop all preferences generators
986  */
987 void
988 GNUNET_ATS_solver_generate_preferences_stop_all ()
989 {
990   struct PreferenceGenerator *cur;
991   struct PreferenceGenerator *next;
992   next = pref_gen_head;
993   for (cur = next; NULL != cur; cur = next)
994   {
995       next = cur->next;
996       GNUNET_ATS_solver_generate_preferences_stop(cur);
997   }
998 }
999
1000
1001
1002 /**
1003  * Experiments
1004  */
1005
1006 const char *
1007 print_op (enum OperationType op)
1008 {
1009   switch (op) {
1010     case SOLVER_OP_ADD_ADDRESS:
1011       return "ADD_ADDRESS";
1012     case SOLVER_OP_DEL_ADDRESS:
1013       return "DEL_ADDRESS";
1014     case SOLVER_OP_START_SET_PREFERENCE:
1015       return "START_SET_PREFERENCE";
1016     case SOLVER_OP_STOP_SET_PREFERENCE:
1017       return "STOP_STOP_PREFERENCE";
1018     case SOLVER_OP_START_SET_PROPERTY:
1019       return "START_SET_PROPERTY";
1020     case SOLVER_OP_STOP_SET_PROPERTY:
1021       return "STOP_SET_PROPERTY";
1022     case SOLVER_OP_START_REQUEST:
1023       return "START_REQUEST";
1024     case SOLVER_OP_STOP_REQUEST:
1025       return "STOP_REQUEST";
1026     default:
1027       break;
1028   }
1029   return "";
1030 }
1031
1032 static struct Experiment *
1033 create_experiment ()
1034 {
1035   struct Experiment *e;
1036   e = GNUNET_new (struct Experiment);
1037   e->name = NULL;
1038   e->start = NULL;
1039   e->total_duration = GNUNET_TIME_UNIT_ZERO;
1040   return e;
1041 }
1042
1043 static void
1044 free_experiment (struct Experiment *e)
1045 {
1046   struct Episode *cur;
1047   struct Episode *next;
1048   struct GNUNET_ATS_TEST_Operation *cur_o;
1049   struct GNUNET_ATS_TEST_Operation *next_o;
1050
1051   next = e->start;
1052   for (cur = next; NULL != cur; cur = next)
1053   {
1054     next = cur->next;
1055
1056     next_o = cur->head;
1057     for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
1058     {
1059       next_o = cur_o->next;
1060       GNUNET_free_non_null (cur_o->address);
1061       GNUNET_free_non_null (cur_o->plugin);
1062       GNUNET_free (cur_o);
1063     }
1064     GNUNET_free (cur);
1065   }
1066
1067   GNUNET_free_non_null (e->name);
1068   GNUNET_free_non_null (e->log_prefix);
1069   GNUNET_free_non_null (e->cfg_file);
1070   GNUNET_free (e);
1071 }
1072
1073
1074 static int
1075 load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
1076     struct Episode *e,
1077     int op_counter,
1078     char *sec_name,
1079     const struct GNUNET_CONFIGURATION_Handle *cfg)
1080 {
1081   char *op_name;
1082   char *op_network;
1083
1084   /* peer pid */
1085   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1086   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1087       sec_name, op_name, &o->peer_id))
1088   {
1089     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
1090         op_counter, "ADD_ADDRESS", op_name);
1091     GNUNET_free (op_name);
1092     return GNUNET_SYSERR;
1093   }
1094   GNUNET_free (op_name);
1095
1096   /* address pid */
1097   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1098   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1099       sec_name, op_name, &o->address_id))
1100   {
1101     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1102         op_counter, "ADD_ADDRESS", op_name);
1103     GNUNET_free (op_name);
1104     return GNUNET_SYSERR;
1105   }
1106   GNUNET_free (op_name);
1107
1108   /* plugin */
1109   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
1110   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1111       sec_name, op_name, &o->plugin))
1112   {
1113     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
1114         op_counter, "ADD_ADDRESS", op_name);
1115     GNUNET_free (op_name);
1116     return GNUNET_SYSERR;
1117   }
1118   GNUNET_free (op_name);
1119
1120   /* address  */
1121   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
1122   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1123       sec_name, op_name, &o->address))
1124   {
1125     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
1126         op_counter, "ADD_ADDRESS", op_name);
1127     GNUNET_free (op_name);
1128     return GNUNET_SYSERR;
1129   }
1130   GNUNET_free (op_name);
1131
1132   /* session */
1133   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
1134   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1135       sec_name, op_name, &o->address_session))
1136   {
1137     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
1138         op_counter, "ADD_ADDRESS", op_name);
1139     GNUNET_free (op_name);
1140     return GNUNET_SYSERR;
1141   }
1142   GNUNET_free (op_name);
1143
1144   /* network */
1145   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
1146   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1147       sec_name, op_name, &op_network))
1148   {
1149     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
1150         op_counter, "ADD_ADDRESS", op_name);
1151     GNUNET_free (op_name);
1152     return GNUNET_SYSERR;
1153   }
1154   else
1155   {
1156     GNUNET_STRINGS_utf8_toupper (op_network,op_network);
1157     if (0 == strcmp(op_network, "UNSPECIFIED"))
1158     {
1159       o->address_network = GNUNET_ATS_NET_UNSPECIFIED;
1160     }
1161     else if (0 == strcmp(op_network, "LOOPBACK"))
1162     {
1163       o->address_network = GNUNET_ATS_NET_LOOPBACK;
1164     }
1165     else if (0 == strcmp(op_network, "LAN"))
1166     {
1167       o->address_network = GNUNET_ATS_NET_LAN;
1168     }
1169     else if (0 == strcmp(op_network, "WAN"))
1170     {
1171       o->address_network = GNUNET_ATS_NET_WAN;
1172     }
1173     else if (0 == strcmp(op_network, "WLAN"))
1174     {
1175       o->address_network = GNUNET_ATS_NET_WLAN;
1176     }
1177     else if (0 == strcmp(op_network, "BT"))
1178     {
1179       o->address_network = GNUNET_ATS_NET_BT;
1180     }
1181     else
1182     {
1183       fprintf (stderr, "Invalid address-network in operation %u `%s' in episode `%s': `%s'\n",
1184           op_counter, "ADD_ADDRESS", op_name, op_network);
1185       GNUNET_free (op_network);
1186       GNUNET_free (op_name);
1187       return GNUNET_SYSERR;
1188     }
1189   }
1190   GNUNET_free (op_network);
1191   GNUNET_free (op_name);
1192
1193   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1194       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
1195       "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
1196
1197   return GNUNET_OK;
1198 }
1199
1200 static int
1201 load_op_del_address (struct GNUNET_ATS_TEST_Operation *o,
1202     struct Episode *e,
1203     int op_counter,
1204     char *sec_name,
1205     const struct GNUNET_CONFIGURATION_Handle *cfg)
1206 {
1207   char *op_name;
1208   char *op_network;
1209
1210   /* peer pid */
1211   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1212   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1213       sec_name, op_name, &o->peer_id))
1214   {
1215     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
1216         op_counter, "DEL_ADDRESS", op_name);
1217     GNUNET_free (op_name);
1218     return GNUNET_SYSERR;
1219   }
1220   GNUNET_free (op_name);
1221
1222   /* address pid */
1223   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1224   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1225       sec_name, op_name, &o->address_id))
1226   {
1227     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1228         op_counter, "DEL_ADDRESS", op_name);
1229     GNUNET_free (op_name);
1230     return GNUNET_SYSERR;
1231   }
1232   GNUNET_free (op_name);
1233
1234   /* plugin */
1235   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
1236   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1237       sec_name, op_name, &o->plugin))
1238   {
1239     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
1240         op_counter, "DEL_ADDRESS", op_name);
1241     GNUNET_free (op_name);
1242     return GNUNET_SYSERR;
1243   }
1244   GNUNET_free (op_name);
1245
1246   /* address  */
1247   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
1248   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1249       sec_name, op_name, &o->address))
1250   {
1251     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
1252         op_counter, "DEL_ADDRESS", op_name);
1253     GNUNET_free (op_name);
1254     return GNUNET_SYSERR;
1255   }
1256   GNUNET_free (op_name);
1257
1258   /* session */
1259   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
1260   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1261       sec_name, op_name, &o->address_session))
1262   {
1263     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
1264         op_counter, "DEL_ADDRESS", op_name);
1265     GNUNET_free (op_name);
1266     return GNUNET_SYSERR;
1267   }
1268   GNUNET_free (op_name);
1269
1270   /* network */
1271   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
1272   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1273       sec_name, op_name, &op_network))
1274   {
1275     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
1276         op_counter, "ADD_ADDRESS", op_name);
1277     GNUNET_free (op_name);
1278     return GNUNET_SYSERR;
1279   }
1280   else
1281   {
1282     GNUNET_STRINGS_utf8_toupper (op_network,op_network);
1283     if (0 == strcmp(op_network, "UNSPECIFIED"))
1284     {
1285       o->address_network = GNUNET_ATS_NET_UNSPECIFIED;
1286     }
1287     else if (0 == strcmp(op_network, "LOOPBACK"))
1288     {
1289       o->address_network = GNUNET_ATS_NET_LOOPBACK;
1290     }
1291     else if (0 == strcmp(op_network, "LAN"))
1292     {
1293       o->address_network = GNUNET_ATS_NET_LAN;
1294     }
1295     else if (0 == strcmp(op_network, "WAN"))
1296     {
1297       o->address_network = GNUNET_ATS_NET_WAN;
1298     }
1299     else if (0 == strcmp(op_network, "WLAN"))
1300     {
1301       o->address_network = GNUNET_ATS_NET_WLAN;
1302     }
1303     else if (0 == strcmp(op_network, "BT"))
1304     {
1305       o->address_network = GNUNET_ATS_NET_BT;
1306     }
1307     else
1308     {
1309       fprintf (stderr, "Invalid address-network in operation %u `%s' in episode `%s': `%s'\n",
1310           op_counter, "ADD_ADDRESS", op_name, op_network);
1311       GNUNET_free (op_network);
1312       GNUNET_free (op_name);
1313       return GNUNET_SYSERR;
1314     }
1315   }
1316   GNUNET_free (op_network);
1317   GNUNET_free (op_name);
1318
1319   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1320       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
1321       "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
1322
1323   return GNUNET_OK;
1324 }
1325
1326 static enum GNUNET_ATS_Property
1327 parse_preference_string (const char * str)
1328 {
1329   int c = 0;
1330   char *props[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
1331
1332   for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
1333     if (0 == strcmp(str, props[c]))
1334       return c;
1335   return 0;
1336 };
1337
1338 static int
1339 load_op_start_set_preference (struct GNUNET_ATS_TEST_Operation *o,
1340     struct Episode *e,
1341     int op_counter,
1342     char *sec_name,
1343     const struct GNUNET_CONFIGURATION_Handle *cfg)
1344 {
1345   char *op_name;
1346   char *type;
1347   char *pref;
1348
1349   /* peer pid */
1350   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1351   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1352       sec_name, op_name, &o->peer_id))
1353   {
1354     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1355         op_counter, "START_SET_PREFERENCE", op_name);
1356     GNUNET_free (op_name);
1357     return GNUNET_SYSERR;
1358   }
1359   GNUNET_free (op_name);
1360
1361   /* address pid */
1362   GNUNET_asprintf(&op_name, "op-%u-client-id", op_counter);
1363   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1364       sec_name, op_name, &o->client_id))
1365   {
1366     fprintf (stderr, "Missing client-id in operation %u `%s' in episode `%s'\n",
1367         op_counter, "START_SET_PREFERENCE", op_name);
1368     GNUNET_free (op_name);
1369     return GNUNET_SYSERR;
1370   }
1371   GNUNET_free (op_name);
1372
1373   /* generator */
1374   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
1375   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1376           sec_name, op_name, &type)) )
1377   {
1378     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
1379         op_counter, "START_SET_PREFERENCE", op_name);
1380     GNUNET_free (op_name);
1381     return GNUNET_SYSERR;
1382   }
1383
1384   /* Load arguments for set_rate, start_send, set_preference */
1385   if (0 == strcmp (type, "constant"))
1386   {
1387     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1388   }
1389   else if (0 == strcmp (type, "linear"))
1390   {
1391     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1392   }
1393   else if (0 == strcmp (type, "sinus"))
1394   {
1395     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1396   }
1397   else if (0 == strcmp (type, "random"))
1398   {
1399     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1400   }
1401   else
1402   {
1403     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
1404         op_counter, op_name, e->id);
1405     GNUNET_free (type);
1406     GNUNET_free (op_name);
1407     return GNUNET_SYSERR;
1408   }
1409   GNUNET_free (type);
1410   GNUNET_free (op_name);
1411
1412
1413   /* Get base rate */
1414   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1415   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1416       sec_name, op_name, &o->base_rate))
1417   {
1418     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1419         op_counter, op_name, e->id);
1420     GNUNET_free (op_name);
1421     return GNUNET_SYSERR;
1422   }
1423   GNUNET_free (op_name);
1424
1425
1426   /* Get max rate */
1427   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1428   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1429       sec_name, op_name, &o->max_rate))
1430   {
1431     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1432         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1433         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1434     {
1435       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1436           op_counter, op_name, e->id);
1437       GNUNET_free (op_name);
1438       return GNUNET_SYSERR;
1439     }
1440   }
1441   GNUNET_free (op_name);
1442
1443   /* Get period */
1444   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1445   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1446       sec_name, op_name, &o->period))
1447   {
1448     o->period = e->duration;
1449   }
1450   GNUNET_free (op_name);
1451
1452   /* Get frequency */
1453   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1454   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1455       sec_name, op_name, &o->frequency))
1456   {
1457       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1458           op_counter, op_name, e->id);
1459       GNUNET_free (op_name);
1460       return GNUNET_SYSERR;
1461   }
1462   GNUNET_free (op_name);
1463
1464   /* Get preference */
1465   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1466   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1467       sec_name, op_name, &pref))
1468   {
1469       fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
1470           op_counter, op_name, e->id);
1471       GNUNET_free (op_name);
1472       return GNUNET_SYSERR;
1473   }
1474
1475   if (0 == (o->pref_type = parse_preference_string(pref)))
1476   {
1477       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1478           op_counter, op_name, e->id);
1479       GNUNET_free (op_name);
1480       GNUNET_free (pref);
1481       return GNUNET_SYSERR;
1482   }
1483   GNUNET_free (pref);
1484   GNUNET_free (op_name);
1485
1486   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1487       "Found operation %s: [%llu:%llu]: %s = %llu\n",
1488       "START_SET_PREFERENCE", o->peer_id, o->address_id,
1489       GNUNET_ATS_print_preference_type(o->pref_type), o->base_rate);
1490
1491   return GNUNET_OK;
1492 }
1493
1494 static int
1495 load_op_stop_set_preference (struct GNUNET_ATS_TEST_Operation *o,
1496     struct Episode *e,
1497     int op_counter,
1498     char *sec_name,
1499     const struct GNUNET_CONFIGURATION_Handle *cfg)
1500 {
1501   char *op_name;
1502   char *pref;
1503
1504   /* peer pid */
1505   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1506   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1507       sec_name, op_name, &o->peer_id))
1508   {
1509     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1510         op_counter, "STOP_SET_PREFERENCE", op_name);
1511     GNUNET_free (op_name);
1512     return GNUNET_SYSERR;
1513   }
1514   GNUNET_free (op_name);
1515
1516   /* address pid */
1517   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1518   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1519       sec_name, op_name, &o->address_id))
1520   {
1521     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1522         op_counter, "STOP_SET_PREFERENCE", op_name);
1523     GNUNET_free (op_name);
1524     return GNUNET_SYSERR;
1525   }
1526   GNUNET_free (op_name);
1527
1528   /* Get preference */
1529   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1530   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1531       sec_name, op_name, &pref))
1532   {
1533     fprintf (stderr, "Missing preference in operation %u `%s' in episode `%s'\n",
1534         op_counter, "STOP_SET_PREFERENCE", op_name);
1535       GNUNET_free (op_name);
1536       return GNUNET_SYSERR;
1537   }
1538
1539   if (0 == (o->pref_type = parse_preference_string(pref)))
1540   {
1541       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1542           op_counter, op_name, e->id);
1543       GNUNET_free (op_name);
1544       GNUNET_free (pref);
1545       return GNUNET_SYSERR;
1546   }
1547   GNUNET_free (pref);
1548   GNUNET_free (op_name);
1549
1550   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1551       "Found operation %s: [%llu:%llu]: %s\n",
1552       "STOP_SET_PREFERENCE", o->peer_id, o->address_id,
1553       GNUNET_ATS_print_preference_type(o->pref_type));
1554   return GNUNET_OK;
1555 }
1556
1557 static enum GNUNET_ATS_Property
1558 parse_property_string (const char * str)
1559 {
1560   int c = 0;
1561   char *props[GNUNET_ATS_PropertyCount] = GNUNET_ATS_PropertyStrings;
1562
1563   for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
1564     if (0 == strcmp(str, props[c]))
1565       return c;
1566   return 0;
1567 };
1568
1569 static int
1570 load_op_start_set_property(struct GNUNET_ATS_TEST_Operation *o,
1571     struct Episode *e,
1572     int op_counter,
1573     char *sec_name,
1574     const struct GNUNET_CONFIGURATION_Handle *cfg)
1575 {
1576   char *op_name;
1577   char *type;
1578   char *prop;
1579
1580   /* peer pid */
1581   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1582   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1583       sec_name, op_name, &o->peer_id))
1584   {
1585     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1586         op_counter, "START_SET_PROPERTY", op_name);
1587     GNUNET_free (op_name);
1588     return GNUNET_SYSERR;
1589   }
1590   GNUNET_free (op_name);
1591
1592   /* address pid */
1593   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1594   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1595       sec_name, op_name, &o->address_id))
1596   {
1597     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1598         op_counter, "START_SET_PROPERTY", op_name);
1599     GNUNET_free (op_name);
1600     return GNUNET_SYSERR;
1601   }
1602   GNUNET_free (op_name);
1603
1604   /* generator */
1605   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
1606   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1607           sec_name, op_name, &type)) )
1608   {
1609     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
1610         op_counter, "START_SET_PROPERTY", op_name);
1611     GNUNET_free (op_name);
1612     return GNUNET_SYSERR;
1613   }
1614
1615   /* Load arguments for set_rate, start_send, set_preference */
1616   if (0 == strcmp (type, "constant"))
1617   {
1618     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1619   }
1620   else if (0 == strcmp (type, "linear"))
1621   {
1622     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1623   }
1624   else if (0 == strcmp (type, "sinus"))
1625   {
1626     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1627   }
1628   else if (0 == strcmp (type, "random"))
1629   {
1630     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1631   }
1632   else
1633   {
1634     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
1635         op_counter, op_name, e->id);
1636     GNUNET_free (type);
1637     GNUNET_free (op_name);
1638     return GNUNET_SYSERR;
1639   }
1640   GNUNET_free (type);
1641   GNUNET_free (op_name);
1642
1643
1644   /* Get base rate */
1645   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1646   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1647       sec_name, op_name, &o->base_rate))
1648   {
1649     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1650         op_counter, op_name, e->id);
1651     GNUNET_free (op_name);
1652     return GNUNET_SYSERR;
1653   }
1654   GNUNET_free (op_name);
1655
1656
1657   /* Get max rate */
1658   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1659   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1660       sec_name, op_name, &o->max_rate))
1661   {
1662     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1663         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1664         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1665     {
1666       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1667           op_counter, op_name, e->id);
1668       GNUNET_free (op_name);
1669       return GNUNET_SYSERR;
1670     }
1671   }
1672   GNUNET_free (op_name);
1673
1674   /* Get period */
1675   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1676   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1677       sec_name, op_name, &o->period))
1678   {
1679     o->period = e->duration;
1680   }
1681   GNUNET_free (op_name);
1682
1683   /* Get frequency */
1684   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1685   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1686       sec_name, op_name, &o->frequency))
1687   {
1688       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1689           op_counter, op_name, e->id);
1690       GNUNET_free (op_name);
1691       return GNUNET_SYSERR;
1692   }
1693   GNUNET_free (op_name);
1694
1695   /* Get preference */
1696   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
1697   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1698       sec_name, op_name, &prop))
1699   {
1700       fprintf (stderr, "Missing property in operation %u `%s' in episode %u\n",
1701           op_counter, op_name, e->id);
1702       GNUNET_free (op_name);
1703       GNUNET_free_non_null (prop);
1704       return GNUNET_SYSERR;
1705   }
1706
1707   if (0 == (o->prop_type = parse_property_string(prop)))
1708   {
1709       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1710           op_counter, op_name, e->id);
1711       GNUNET_free (op_name);
1712       GNUNET_free (prop);
1713       return GNUNET_SYSERR;
1714   }
1715
1716   GNUNET_free (prop);
1717   GNUNET_free (op_name);
1718
1719   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1720       "Found operation %s: [%llu:%llu] %s = %llu\n",
1721       "START_SET_PROPERTY", o->peer_id, o->address_id,
1722       GNUNET_ATS_print_property_type (o->prop_type), o->base_rate);
1723
1724   return GNUNET_OK;
1725 }
1726
1727 static int
1728 load_op_stop_set_property (struct GNUNET_ATS_TEST_Operation *o,
1729     struct Episode *e,
1730     int op_counter,
1731     char *sec_name,
1732     const struct GNUNET_CONFIGURATION_Handle *cfg)
1733 {
1734   char *op_name;
1735   char *pref;
1736
1737   /* peer pid */
1738   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1739   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1740       sec_name, op_name, &o->peer_id))
1741   {
1742     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1743         op_counter, "STOP_SET_PROPERTY", op_name);
1744     GNUNET_free (op_name);
1745     return GNUNET_SYSERR;
1746   }
1747   GNUNET_free (op_name);
1748
1749   /* address pid */
1750   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1751   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1752       sec_name, op_name, &o->address_id))
1753   {
1754     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1755         op_counter, "STOP_SET_PROPERTY", op_name);
1756     GNUNET_free (op_name);
1757     return GNUNET_SYSERR;
1758   }
1759   GNUNET_free (op_name);
1760
1761   /* Get property */
1762   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
1763   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1764       sec_name, op_name, &pref))
1765   {
1766     fprintf (stderr, "Missing property in operation %u `%s' in episode `%s'\n",
1767         op_counter, "STOP_SET_PROPERTY", op_name);
1768       GNUNET_free (op_name);
1769       GNUNET_free_non_null (pref);
1770       return GNUNET_SYSERR;
1771   }
1772
1773   if (0 == (o->prop_type = parse_property_string(pref)))
1774   {
1775       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1776           op_counter, op_name, e->id);
1777       GNUNET_free (op_name);
1778       GNUNET_free_non_null (pref);
1779       return GNUNET_SYSERR;
1780   }
1781
1782   GNUNET_free (pref);
1783   GNUNET_free (op_name);
1784
1785   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1786       "Found operation %s: [%llu:%llu] %s\n",
1787       "STOP_SET_PROPERTY", o->peer_id, o->address_id,
1788       GNUNET_ATS_print_property_type (o->prop_type));
1789
1790   return GNUNET_OK;
1791 }
1792
1793
1794 static int
1795 load_op_start_request (struct GNUNET_ATS_TEST_Operation *o,
1796     struct Episode *e,
1797     int op_counter,
1798     char *sec_name,
1799     const struct GNUNET_CONFIGURATION_Handle *cfg)
1800 {
1801   char *op_name;
1802
1803   /* peer pid */
1804   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1805   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1806       sec_name, op_name, &o->peer_id))
1807   {
1808     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1809         op_counter, "START_REQUEST", op_name);
1810     GNUNET_free (op_name);
1811     return GNUNET_SYSERR;
1812   }
1813   GNUNET_free (op_name);
1814   return GNUNET_OK;
1815 }
1816
1817 static int
1818 load_op_stop_request (struct GNUNET_ATS_TEST_Operation *o,
1819     struct Episode *e,
1820     int op_counter,
1821     char *sec_name,
1822     const struct GNUNET_CONFIGURATION_Handle *cfg)
1823 {
1824   char *op_name;
1825
1826   /* peer pid */
1827   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1828   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1829       sec_name, op_name, &o->peer_id))
1830   {
1831     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1832         op_counter, "STOP_REQUEST", op_name);
1833     GNUNET_free (op_name);
1834     return GNUNET_SYSERR;
1835   }
1836   GNUNET_free (op_name);
1837   return GNUNET_OK;
1838 }
1839
1840
1841 static int
1842 load_episode (struct Experiment *e, struct Episode *cur,
1843     struct GNUNET_CONFIGURATION_Handle *cfg)
1844 {
1845   struct GNUNET_ATS_TEST_Operation *o;
1846   char *sec_name;
1847   char *op_name;
1848   char *op;
1849   int op_counter = 0;
1850   int res;
1851   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Parsing episode %u\n",cur->id);
1852   GNUNET_asprintf(&sec_name, "episode-%u", cur->id);
1853
1854   while (1)
1855   {
1856     /* Load operation */
1857     GNUNET_asprintf(&op_name, "op-%u-operation", op_counter);
1858     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1859         sec_name, op_name, &op))
1860     {
1861       GNUNET_free (op_name);
1862       break;
1863     }
1864     o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
1865     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "==== Parsing operation %u: `%s'\n",
1866         cur->id, op_name);
1867
1868     /* operations = set_rate, start_send, stop_send, set_preference */
1869     if (0 == strcmp (op, "address_add"))
1870     {
1871       o->type = SOLVER_OP_ADD_ADDRESS;
1872       res = load_op_add_address (o, cur,
1873           op_counter, sec_name, cfg);
1874     }
1875     else if (0 == strcmp (op, "address_del"))
1876     {
1877       o->type = SOLVER_OP_DEL_ADDRESS;
1878       res = load_op_del_address (o, cur,
1879           op_counter, sec_name, cfg);
1880     }
1881     else if (0 == strcmp (op, "start_set_property"))
1882     {
1883       o->type = SOLVER_OP_START_SET_PROPERTY;
1884       res = load_op_start_set_property (o, cur,
1885           op_counter, sec_name, cfg);
1886     }
1887     else if (0 == strcmp (op, "stop_set_property"))
1888     {
1889       o->type = SOLVER_OP_STOP_SET_PROPERTY;
1890       res = load_op_stop_set_property (o, cur,
1891           op_counter, sec_name, cfg);
1892     }
1893     else if (0 == strcmp (op, "start_set_preference"))
1894     {
1895       o->type = SOLVER_OP_START_SET_PREFERENCE;
1896       res =  load_op_start_set_preference (o, cur,
1897           op_counter, sec_name, cfg);
1898     }
1899     else if (0 == strcmp (op, "stop_set_preference"))
1900     {
1901       o->type = SOLVER_OP_STOP_SET_PREFERENCE;
1902       res =  load_op_stop_set_preference (o, cur,
1903           op_counter, sec_name, cfg);
1904     }
1905     else if (0 == strcmp (op, "start_request"))
1906     {
1907       o->type = SOLVER_OP_START_REQUEST;
1908       res = load_op_start_request (o, cur,
1909           op_counter, sec_name, cfg);
1910     }
1911     else if (0 == strcmp (op, "stop_request"))
1912     {
1913       o->type = SOLVER_OP_STOP_REQUEST;
1914       res = load_op_stop_request(o, cur,
1915           op_counter, sec_name, cfg);
1916     }
1917     else
1918     {
1919       fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
1920           op_counter, op, cur->id);
1921       res = GNUNET_SYSERR;
1922     }
1923
1924     GNUNET_free (op);
1925     GNUNET_free (op_name);
1926
1927     if (GNUNET_SYSERR == res)
1928     {
1929       GNUNET_free (o);
1930       GNUNET_free (sec_name);
1931       return GNUNET_SYSERR;
1932     }
1933
1934     GNUNET_CONTAINER_DLL_insert_tail (cur->head,cur->tail, o);
1935     op_counter++;
1936   }
1937   GNUNET_free (sec_name);
1938   return GNUNET_OK;
1939 }
1940
1941 static int
1942 load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
1943 {
1944   int e_counter = 0;
1945   char *sec_name;
1946   struct GNUNET_TIME_Relative e_duration;
1947   struct Episode *cur;
1948   struct Episode *last;
1949
1950   e_counter = 0;
1951   last = NULL;
1952   while (1)
1953   {
1954     GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
1955     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
1956         sec_name, "duration", &e_duration))
1957     {
1958       GNUNET_free (sec_name);
1959       break;
1960     }
1961
1962     cur = GNUNET_new (struct Episode);
1963     cur->duration = e_duration;
1964     cur->id = e_counter;
1965
1966     if (GNUNET_OK != load_episode (e, cur, cfg))
1967     {
1968       GNUNET_free (sec_name);
1969       GNUNET_free (cur);
1970       return GNUNET_SYSERR;
1971     }
1972
1973     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Found episode %u with duration %s \n",
1974         e_counter,
1975         GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
1976
1977     /* Update experiment */
1978     e->num_episodes ++;
1979     e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
1980     /* Put in linked list */
1981     if (NULL == last)
1982       e->start = cur;
1983     else
1984       last->next = cur;
1985
1986     GNUNET_free (sec_name);
1987     e_counter ++;
1988     last = cur;
1989   }
1990   return e_counter;
1991 }
1992
1993 static void
1994 timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1995 {
1996   struct Experiment *e = cls;
1997   e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1998   fprintf (stderr, "Experiment timeout!\n");
1999
2000   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
2001   {
2002     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
2003     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
2004   }
2005
2006   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
2007       GNUNET_SYSERR);
2008 }
2009
2010 struct ATS_Address *
2011 create_ats_address (const struct GNUNET_PeerIdentity *peer,
2012                 const char *plugin_name,
2013                 const void *plugin_addr, size_t plugin_addr_len,
2014                 uint32_t session_id)
2015 {
2016   struct ATS_Address *aa = NULL;
2017
2018   aa = GNUNET_malloc (sizeof (struct ATS_Address) + plugin_addr_len + strlen (plugin_name) + 1);
2019   aa->peer = *peer;
2020   aa->addr_len = plugin_addr_len;
2021   aa->addr = &aa[1];
2022   aa->plugin = (char *) &aa[1] + plugin_addr_len;
2023   memcpy (&aa[1], plugin_addr, plugin_addr_len);
2024   memcpy (aa->plugin, plugin_name, strlen (plugin_name) + 1);
2025   aa->session_id = session_id;
2026   aa->active = GNUNET_NO;
2027   aa->used = GNUNET_NO;
2028   aa->solver_information = NULL;
2029   aa->assigned_bw_in = GNUNET_BANDWIDTH_value_init(0);
2030   aa->assigned_bw_out = GNUNET_BANDWIDTH_value_init(0);
2031   return aa;
2032 }
2033
2034
2035
2036 static void
2037 enforce_add_address (struct GNUNET_ATS_TEST_Operation *op)
2038 {
2039   struct TestPeer *p;
2040   struct TestAddress *a;
2041
2042   if (NULL == (p = find_peer_by_id (op->peer_id)))
2043   {
2044     p = GNUNET_new (struct TestPeer);
2045     p->id = op->peer_id;
2046     memset (&p->peer_id, op->peer_id, sizeof (p->peer_id));
2047     GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, p);
2048   }
2049
2050   if (NULL != (find_address_by_id (p, op->address_id)))
2051   {
2052     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Duplicate address %u for peer %u\n",
2053         op->address_id, op->peer_id);
2054     return;
2055   }
2056
2057   a = GNUNET_new (struct TestAddress);
2058   a->aid = op->address_id;
2059   a->network = op->address_network;
2060   a->ats_addr = create_ats_address (&p->peer_id, op->plugin, op->address,
2061       strlen (op->address) + 1, op->address_session);
2062   memset (&p->peer_id, op->peer_id, sizeof (p->peer_id));
2063   GNUNET_CONTAINER_DLL_insert (p->addr_head, p->addr_tail, a);
2064
2065   GNUNET_CONTAINER_multipeermap_put (sh->addresses, &p->peer_id, a->ats_addr,
2066     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2067
2068   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding address %u for peer %u in network `%s'\n",
2069     op->address_id, op->peer_id, GNUNET_ATS_print_network_type(op->address_network));
2070
2071   sh->env.sf.s_add (sh->solver, a->ats_addr, op->address_network);
2072
2073 }
2074
2075
2076 static void
2077 enforce_del_address (struct GNUNET_ATS_TEST_Operation *op)
2078 {
2079   struct TestPeer *p;
2080   struct TestAddress *a;
2081   struct AddressLookupCtx ctx;
2082   struct PropertyGenerator *pg;
2083
2084   if (NULL == (p = find_peer_by_id (op->peer_id)))
2085   {
2086     GNUNET_break (0);
2087     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2088         "Deleting address for unknown peer %u\n", op->peer_id);
2089     return;
2090   }
2091
2092   ctx.plugin = op->plugin;
2093   ctx.addr = op->address;
2094   ctx.res = NULL;
2095   GNUNET_CONTAINER_multipeermap_get_multiple (sh->addresses, &p->peer_id,
2096       find_address_it, &ctx);
2097   if (NULL == ctx.res)
2098   {
2099     GNUNET_break (0);
2100     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2101         "Deleting unknown address for peer %u\n", op->peer_id);
2102     return;
2103   }
2104
2105   if (NULL == (a =find_address_by_id (p, op->address_id)))
2106   {
2107     GNUNET_break (0);
2108     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2109         "Deleting address for unknown peer %u\n", op->peer_id);
2110     return;
2111   }
2112
2113   while (NULL != (pg = find_prop_gen (p->id, a->aid, 0)))
2114   {
2115     GNUNET_ATS_solver_generate_property_stop (pg);
2116   }
2117
2118   GNUNET_CONTAINER_DLL_remove(p->addr_head, p->addr_tail, a);
2119   GNUNET_free (a);
2120
2121   GNUNET_CONTAINER_multipeermap_remove (sh->addresses, &p->peer_id, ctx.res);
2122
2123   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Removing address %u for peer %u\n",
2124       op->address_id, op->peer_id);
2125
2126   sh->env.sf.s_del (sh->solver, ctx.res, GNUNET_NO);
2127   GNUNET_free (ctx.res);
2128
2129 }
2130
2131 static void
2132 enforce_start_property (struct GNUNET_ATS_TEST_Operation *op)
2133 {
2134   struct PropertyGenerator *pg;
2135   struct TestPeer *p;
2136   struct TestAddress *a;
2137
2138   if (NULL != (pg = find_prop_gen (op->peer_id, op->address_id, op->prop_type)))
2139   {
2140     GNUNET_ATS_solver_generate_property_stop (pg);
2141     GNUNET_free (pg);
2142   }
2143
2144   if (NULL == (p = find_peer_by_id (op->peer_id)))
2145   {
2146     GNUNET_break (0);
2147     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2148         "Starting property generation for unknown peer %u\n", op->peer_id);
2149     return;
2150   }
2151
2152   if (NULL == (a = find_address_by_id (p, op->address_id)))
2153   {
2154     GNUNET_break (0);
2155     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2156         "Setting property for unknown address %u\n", op->peer_id);
2157     return;
2158   }
2159
2160   GNUNET_ATS_solver_generate_property_start (op->peer_id,
2161     op->address_id,
2162     p, a,
2163     op->gen_type,
2164     op->base_rate,
2165     op->max_rate,
2166     op->period,
2167     op->frequency,
2168     op->prop_type);
2169 }
2170
2171 static void
2172 enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op)
2173 {
2174   struct PropertyGenerator *pg = find_prop_gen(op->peer_id, op->address_id,
2175       op->prop_type);
2176   if (NULL != pg)
2177       GNUNET_ATS_solver_generate_property_stop (pg);
2178 }
2179
2180 static void
2181 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
2182 {
2183   struct PreferenceGenerator *pg;
2184   if (NULL != (pg = find_pref_gen (op->peer_id, op->pref_type)))
2185   {
2186     GNUNET_ATS_solver_generate_preferences_stop (pg);
2187     GNUNET_free (pg);
2188   }
2189
2190   if (NULL == (find_peer_by_id (op->peer_id)))
2191   {
2192     GNUNET_break (0);
2193     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2194         "Starting preference generation for unknown peer %u\n", op->peer_id);
2195     return;
2196   }
2197
2198   GNUNET_ATS_solver_generate_preferences_start (op->peer_id,
2199     op->address_id,
2200     op->client_id,
2201     op->gen_type,
2202     op->base_rate,
2203     op->max_rate,
2204     op->period,
2205     op->frequency,
2206     op->pref_type);
2207 }
2208
2209 static void
2210 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
2211 {
2212   struct PreferenceGenerator *pg = find_pref_gen(op->peer_id,
2213       op->pref_type);
2214   if (NULL != pg)
2215       GNUNET_ATS_solver_generate_preferences_stop (pg);
2216 }
2217
2218
2219 static void
2220 enforce_start_request (struct GNUNET_ATS_TEST_Operation *op)
2221 {
2222   struct TestPeer *p;
2223   const struct ATS_Address *res;
2224
2225   if (NULL == (p = find_peer_by_id (op->peer_id)))
2226   {
2227     GNUNET_break (0);
2228     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2229         "Requesting address for unknown peer %u\n", op->peer_id);
2230     return;
2231   }
2232
2233   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Requesting address for peer %u\n",
2234       op->peer_id);
2235
2236   res = sh->env.sf.s_get (sh->solver, &p->peer_id);
2237   if (NULL != res)
2238   {
2239
2240   }
2241 }
2242
2243 static void
2244 enforce_stop_request (struct GNUNET_ATS_TEST_Operation *op)
2245 {
2246   struct TestPeer *p;
2247
2248   if (NULL == (p = find_peer_by_id (op->peer_id)))
2249   {
2250     GNUNET_break (0);
2251     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2252         "Requesting address for unknown peer %u\n", op->peer_id);
2253     return;
2254   }
2255
2256   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop requesting address for peer %u\n",
2257       op->peer_id);
2258
2259   sh->env.sf.s_get_stop (sh->solver, &p->peer_id);
2260 }
2261
2262 static void enforce_episode (struct Episode *ep)
2263 {
2264   struct GNUNET_ATS_TEST_Operation *cur;
2265   for (cur = ep->head; NULL != cur; cur = cur->next)
2266   {
2267     switch (cur->type) {
2268       case SOLVER_OP_ADD_ADDRESS:
2269         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
2270             print_op (cur->type), cur->peer_id, cur->address_id);
2271         enforce_add_address (cur);
2272         break;
2273       case SOLVER_OP_DEL_ADDRESS:
2274         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
2275             print_op (cur->type), cur->peer_id, cur->address_id);
2276         enforce_del_address (cur);
2277         break;
2278       case SOLVER_OP_START_SET_PROPERTY:
2279         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2280             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
2281         enforce_start_property (cur);
2282         break;
2283       case SOLVER_OP_STOP_SET_PROPERTY:
2284         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2285             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
2286         enforce_stop_property (cur);
2287         break;
2288       case SOLVER_OP_START_SET_PREFERENCE:
2289         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2290             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
2291         enforce_start_preference (cur);
2292         break;
2293       case SOLVER_OP_STOP_SET_PREFERENCE:
2294         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2295             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
2296         enforce_stop_preference (cur);
2297         break;
2298       case SOLVER_OP_START_REQUEST:
2299         fprintf (stderr, "Enforcing operation: %s [%llu]\n",
2300             print_op (cur->type), cur->peer_id);
2301         enforce_start_request (cur);
2302         break;
2303       case SOLVER_OP_STOP_REQUEST:
2304         fprintf (stderr, "Enforcing operation: %s [%llu]\n",
2305             print_op (cur->type), cur->peer_id);
2306         enforce_stop_request (cur);
2307         break;
2308       default:
2309         break;
2310     }
2311   }
2312 }
2313
2314 static void
2315 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
2316 {
2317   struct Experiment *e = cls;
2318   e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
2319   if (NULL != e->ep_done_cb)
2320     e->ep_done_cb (e->cur);
2321
2322   /* Scheduling next */
2323   e->cur = e->cur->next;
2324   if (NULL == e->cur)
2325   {
2326     /* done */
2327     fprintf (stderr, "Last episode done!\n");
2328     if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
2329     {
2330       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
2331       e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
2332     }
2333     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
2334     return;
2335   }
2336
2337   fprintf (stderr, "Running episode %u with timeout %s\n",
2338       e->cur->id,
2339       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
2340   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
2341       &timeout_episode, e);
2342   enforce_episode(e->cur);
2343
2344
2345 }
2346
2347
2348 void
2349 GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
2350     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
2351     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
2352 {
2353   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
2354       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
2355   e->e_done_cb = e_done_cb;
2356   e->ep_done_cb = ep_done_cb;
2357   e->start_time = GNUNET_TIME_absolute_get();
2358
2359   /* Start total time out */
2360   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
2361       &timeout_experiment, e);
2362
2363   /* Start */
2364   if (NULL == e->start)
2365   {
2366     GNUNET_break (0);
2367     return;
2368   }
2369
2370   e->cur = e->start;
2371   fprintf (stderr, "Running episode %u with timeout %s\n",
2372       e->cur->id,
2373       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
2374   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
2375       &timeout_episode, e);
2376   enforce_episode(e->cur);
2377
2378 }
2379
2380 void
2381 GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
2382 {
2383   if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
2384   {
2385     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
2386     e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
2387   }
2388   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
2389   {
2390     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
2391     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
2392   }
2393   if (NULL != e->cfg)
2394   {
2395     GNUNET_CONFIGURATION_destroy(e->cfg);
2396     e->cfg = NULL;
2397   }
2398   free_experiment (e);
2399 }
2400
2401
2402 struct Experiment *
2403 GNUNET_ATS_solvers_experimentation_load (char *filename)
2404 {
2405   struct Experiment *e;
2406   struct GNUNET_CONFIGURATION_Handle *cfg;
2407   e = NULL;
2408
2409   cfg = GNUNET_CONFIGURATION_create();
2410   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
2411   {
2412     fprintf (stderr, "Failed to load `%s'\n", filename);
2413     GNUNET_CONFIGURATION_destroy (cfg);
2414     return NULL;
2415   }
2416
2417   e = create_experiment ();
2418
2419   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
2420       "name", &e->name))
2421   {
2422     fprintf (stderr, "Invalid %s", "name");
2423     free_experiment (e);
2424     return NULL;
2425   }
2426   else
2427     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment name: `%s'\n", e->name);
2428
2429   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
2430       "log_prefix", &e->log_prefix))
2431   {
2432     fprintf (stderr, "Invalid %s", "name");
2433     free_experiment (e);
2434     return NULL;
2435   }
2436   else
2437     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging prefix: `%s'\n",
2438         e->log_prefix);
2439
2440   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
2441       "cfg_file", &e->cfg_file))
2442   {
2443     fprintf (stderr, "Invalid %s", "cfg_file");
2444     free_experiment (e);
2445     return NULL;
2446   }
2447   else
2448   {
2449     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment configuration: `%s'\n", e->cfg_file);
2450     e->cfg = GNUNET_CONFIGURATION_create();
2451     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
2452     {
2453       fprintf (stderr, "Invalid configuration %s", "cfg_file");
2454       free_experiment (e);
2455       return NULL;
2456     }
2457
2458   }
2459
2460   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2461       "log_freq", &e->log_freq))
2462   {
2463     fprintf (stderr, "Invalid %s", "log_freq");
2464     free_experiment (e);
2465     return NULL;
2466   }
2467   else
2468     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging frequency: `%s'\n",
2469         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
2470
2471   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2472       "max_duration", &e->max_duration))
2473   {
2474     fprintf (stderr, "Invalid %s", "max_duration");
2475     free_experiment (e);
2476     return NULL;
2477   }
2478   else
2479     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment duration: `%s'\n",
2480         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
2481
2482   if (GNUNET_SYSERR == load_episodes (e, cfg))
2483   {
2484     GNUNET_ATS_solvers_experimentation_stop (e);
2485     GNUNET_CONFIGURATION_destroy (cfg);
2486     e = NULL;
2487     fprintf (stderr, "Failed to load experiment\n");
2488     return NULL;
2489   }
2490   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loaded %u episodes with total duration %s\n",
2491       e->num_episodes,
2492       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
2493
2494   GNUNET_CONFIGURATION_destroy (cfg);
2495   return e;
2496 }
2497
2498
2499
2500 /**
2501  * Solver
2502  */
2503
2504 static int
2505 free_all_it (void *cls,
2506     const struct GNUNET_PeerIdentity *key,
2507     void *value)
2508 {
2509   struct ATS_Address *address = value;
2510   GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (sh->env.addresses,
2511       key, value));
2512   GNUNET_free (address);
2513
2514   return GNUNET_OK;
2515 }
2516
2517 void
2518 GNUNET_ATS_solvers_solver_stop (struct SolverHandle *sh)
2519 {
2520  GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats,
2521      GNUNET_NO);
2522  GNUNET_PLUGIN_unload (sh->plugin, sh->solver);
2523  GNUNET_CONTAINER_multipeermap_iterate (sh->addresses, &free_all_it, NULL);
2524  GNUNET_CONTAINER_multipeermap_destroy(sh->addresses);
2525  GNUNET_free (sh->plugin);
2526  GNUNET_free (sh);
2527 }
2528
2529 /**
2530  * Load quotas for networks from configuration
2531  *
2532  * @param cfg configuration handle
2533  * @param out_dest where to write outbound quotas
2534  * @param in_dest where to write inbound quotas
2535  * @param dest_length length of inbound and outbound arrays
2536  * @return number of networks loaded
2537  */
2538 unsigned int
2539 GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
2540                                                  unsigned long long *out_dest,
2541                                                  unsigned long long *in_dest,
2542                                                  int dest_length)
2543 {
2544   char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
2545   char * entry_in = NULL;
2546   char * entry_out = NULL;
2547   char * quota_out_str;
2548   char * quota_in_str;
2549   int c;
2550   int res;
2551
2552   for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++)
2553   {
2554     in_dest[c] = 0;
2555     out_dest[c] = 0;
2556     GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]);
2557     GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]);
2558
2559     /* quota out */
2560     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, &quota_out_str))
2561     {
2562       res = GNUNET_NO;
2563       if (0 == strcmp(quota_out_str, BIG_M_STRING))
2564       {
2565         out_dest[c] = GNUNET_ATS_MaxBandwidth;
2566         res = GNUNET_YES;
2567       }
2568       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c])))
2569         res = GNUNET_YES;
2570       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out,  &out_dest[c])))
2571          res = GNUNET_YES;
2572
2573       if (GNUNET_NO == res)
2574       {
2575           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2576               network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth);
2577           out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2578       }
2579       else
2580       {
2581           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Outbound quota configure for network `%s' is %llu\n"),
2582               network_str[c], out_dest[c]);
2583       }
2584       GNUNET_free (quota_out_str);
2585     }
2586     else
2587     {
2588       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
2589           network_str[c], GNUNET_ATS_DefaultBandwidth);
2590       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2591     }
2592
2593     /* quota in */
2594     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, &quota_in_str))
2595     {
2596       res = GNUNET_NO;
2597       if (0 == strcmp(quota_in_str, BIG_M_STRING))
2598       {
2599         in_dest[c] = GNUNET_ATS_MaxBandwidth;
2600         res = GNUNET_YES;
2601       }
2602       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c])))
2603         res = GNUNET_YES;
2604       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in,  &in_dest[c])))
2605          res = GNUNET_YES;
2606
2607       if (GNUNET_NO == res)
2608       {
2609           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2610               network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth);
2611           in_dest[c] = GNUNET_ATS_DefaultBandwidth;
2612       }
2613       else
2614       {
2615           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Inbound quota configured for network `%s' is %llu\n"),
2616               network_str[c], in_dest[c]);
2617       }
2618       GNUNET_free (quota_in_str);
2619     }
2620     else
2621     {
2622       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
2623           network_str[c], GNUNET_ATS_DefaultBandwidth);
2624       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2625     }
2626     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]);
2627     GNUNET_free (entry_out);
2628     GNUNET_free (entry_in);
2629   }
2630   return GNUNET_ATS_NetworkTypeCount;
2631 }
2632
2633 /**
2634  * Information callback for the solver
2635  *
2636  * @param cls the closure
2637  * @param op the solver operation
2638  * @param stat status of the solver operation
2639  * @param add additional solver information
2640  */
2641 static void
2642 solver_info_cb (void *cls,
2643     enum GAS_Solver_Operation op,
2644     enum GAS_Solver_Status stat,
2645     enum GAS_Solver_Additional_Information add)
2646 {
2647   char *add_info;
2648   switch (add) {
2649     case GAS_INFO_NONE:
2650       add_info = "GAS_INFO_NONE";
2651       break;
2652     case GAS_INFO_FULL:
2653       add_info = "GAS_INFO_MLP_FULL";
2654       break;
2655     case GAS_INFO_UPDATED:
2656       add_info = "GAS_INFO_MLP_UPDATED";
2657       break;
2658     case GAS_INFO_PROP_ALL:
2659       add_info = "GAS_INFO_PROP_ALL";
2660       break;
2661     case GAS_INFO_PROP_SINGLE:
2662       add_info = "GAS_INFO_PROP_SINGLE";
2663       break;
2664     default:
2665       add_info = "INVALID";
2666       break;
2667   }
2668
2669   switch (op)
2670   {
2671     case GAS_OP_SOLVE_START:
2672       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2673           "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
2674           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2675       return;
2676     case GAS_OP_SOLVE_STOP:
2677       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2678           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
2679           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2680       return;
2681
2682     case GAS_OP_SOLVE_SETUP_START:
2683       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2684           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
2685           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2686       return;
2687
2688     case GAS_OP_SOLVE_SETUP_STOP:
2689       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2690           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
2691           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2692       return;
2693
2694     case GAS_OP_SOLVE_MLP_LP_START:
2695       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2696           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
2697           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2698       return;
2699     case GAS_OP_SOLVE_MLP_LP_STOP:
2700       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2701           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
2702           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2703       return;
2704
2705     case GAS_OP_SOLVE_MLP_MLP_START:
2706       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2707           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
2708           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2709       return;
2710     case GAS_OP_SOLVE_MLP_MLP_STOP:
2711       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2712           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
2713           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2714       return;
2715     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
2716       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2717           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
2718           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2719       return;
2720     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
2721       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2722           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
2723           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2724       return;
2725     default:
2726       break;
2727     }
2728 }
2729
2730 static void
2731 solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
2732 {
2733   if ( (0 == ntohl (address->assigned_bw_out.value__)) &&
2734        (0 == ntohl (address->assigned_bw_in.value__)) )
2735   {
2736     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2737                 "Solver notified to disconnect peer `%s'\n",
2738                 GNUNET_i2s (&address->peer));
2739     return;
2740   }
2741
2742   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2743               "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
2744               GNUNET_i2s (&address->peer),
2745               address,
2746               (unsigned int) ntohl (address->assigned_bw_out.value__),
2747               (unsigned int) ntohl (address->assigned_bw_in.value__));
2748   /*if (GNUNET_YES == ph.bulk_running)
2749     GNUNET_break (0);*/
2750   return;
2751 }
2752
2753 const double *
2754 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
2755 {
2756   return GAS_normalization_get_preferences_by_peer (id);
2757 }
2758
2759
2760 const double *
2761 get_property_cb (void *cls, const struct ATS_Address *address)
2762 {
2763   return GAS_normalization_get_properties ((struct ATS_Address *) address);
2764 }
2765
2766 static void
2767 set_updated_property ( struct ATS_Address *address, uint32_t type, double prop_rel)
2768 {
2769   struct TestPeer *p;
2770   struct TestAddress *a;
2771
2772   if (NULL == (p = find_peer_by_pid (&address->peer)))
2773   {
2774     GNUNET_break (0);
2775     return;
2776   }
2777
2778   if (NULL == (a = find_address_by_ats_address (p, address)))
2779   {
2780     GNUNET_break (0);
2781     return;
2782   }
2783   a->prop_norm[type] = prop_rel;
2784   sh->env.sf.s_address_update_property (sh->solver, address, type, 0, prop_rel);
2785 }
2786
2787
2788 static void
2789 normalized_property_changed_cb (void *cls, struct ATS_Address *address,
2790     uint32_t type, double prop_rel)
2791 {
2792   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2793       "Normalized property %s for peer `%s' changed to %.3f \n",
2794       GNUNET_ATS_print_property_type (type), GNUNET_i2s (&address->peer),
2795       prop_rel);
2796
2797   set_updated_property (address, type, prop_rel);
2798 }
2799
2800 static void
2801 set_updated_preference (const struct GNUNET_PeerIdentity *peer,
2802     enum GNUNET_ATS_PreferenceKind kind,
2803     double pref_rel)
2804 {
2805   struct TestPeer *p;
2806
2807   if (NULL == (p = find_peer_by_pid (peer)))
2808   {
2809     GNUNET_break (0);
2810     return;
2811   }
2812
2813   p->pref_norm[kind] = pref_rel;
2814   sh->env.sf.s_pref (sh->solver, peer, kind, pref_rel);
2815 }
2816
2817
2818 static void
2819 normalized_preference_changed_cb (void *cls,
2820     const struct GNUNET_PeerIdentity *peer,
2821     enum GNUNET_ATS_PreferenceKind kind,
2822     double pref_rel)
2823 {
2824   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2825       "Normalized preference %s for peer `%s' changed to %.3f \n",
2826       GNUNET_ATS_print_preference_type (kind), GNUNET_i2s (peer),
2827       pref_rel);
2828
2829   set_updated_preference(peer, kind, pref_rel);
2830 }
2831
2832
2833 struct SolverHandle *
2834 GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
2835 {
2836   struct SolverHandle *sh;
2837   char * solver_str;
2838
2839   switch (type) {
2840     case GNUNET_ATS_SOLVER_PROPORTIONAL:
2841       solver_str = "proportional";
2842       break;
2843     case GNUNET_ATS_SOLVER_MLP:
2844       solver_str = "mlp";
2845       break;
2846     case GNUNET_ATS_SOLVER_RIL:
2847       solver_str = "ril";
2848       break;
2849     default:
2850       GNUNET_break (0);
2851       return NULL;
2852       break;
2853   }
2854
2855   sh = GNUNET_new (struct SolverHandle);
2856   GNUNET_asprintf (&sh->plugin, "libgnunet_plugin_ats_%s", solver_str);
2857
2858   sh->addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
2859   /* setup environment */
2860   sh->env.cfg = e->cfg;
2861   sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
2862   sh->env.addresses = sh->addresses;
2863   sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
2864   sh->env.get_preferences = &get_preferences_cb;
2865   sh->env.get_property = &get_property_cb;
2866   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
2867   sh->env.info_cb = &solver_info_cb;
2868   sh->env.info_cb_cls = NULL;
2869
2870
2871   /* start normalization */
2872   GAS_normalization_start (&normalized_preference_changed_cb, NULL,
2873       &normalized_property_changed_cb, NULL );
2874
2875   /* load quotas */
2876   if (GNUNET_ATS_NetworkTypeCount != GNUNET_ATS_solvers_load_quotas (e->cfg,
2877       sh->env.out_quota, sh->env.in_quota, GNUNET_ATS_NetworkTypeCount))
2878   {
2879     GNUNET_break(0);
2880     GNUNET_free (sh->plugin);
2881     GNUNET_free (sh);
2882     end_now ();
2883     return NULL;
2884   }
2885
2886   sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
2887   if (NULL == sh->solver)
2888   {
2889     fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
2890     GNUNET_break(0);
2891     GNUNET_free (sh->plugin);
2892     GNUNET_free (sh);
2893     end_now ();
2894     return NULL;
2895   }
2896   return sh;
2897 }
2898
2899 static void
2900 done ()
2901 {
2902   struct TestPeer *cur;
2903   struct TestPeer *next;
2904
2905   struct TestAddress *cur_a;
2906   struct TestAddress *next_a;
2907
2908   /* Stop logging */
2909   GNUNET_ATS_solver_logging_stop (l);
2910
2911   /* Stop all preference generation */
2912   GNUNET_ATS_solver_generate_preferences_stop_all ();
2913
2914   /* Stop all property generation */
2915   GNUNET_ATS_solver_generate_property_stop_all ();
2916
2917   if (opt_print)
2918   {
2919     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "== Printing log information \n");
2920     GNUNET_ATS_solver_logging_eval (l);
2921   }
2922   if (opt_save)
2923   {
2924     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "== Saving log information \n");
2925     GNUNET_ATS_solver_logging_write_to_disk (l);
2926   }
2927
2928   if (NULL != l)
2929   {
2930     GNUNET_ATS_solver_logging_free (l);
2931     l = NULL;
2932   }
2933
2934   /* Clean up experiment */
2935   if (NULL != e)
2936   {
2937     GNUNET_ATS_solvers_experimentation_stop (e);
2938     e = NULL;
2939   }
2940
2941   next = peer_head;
2942   while  (NULL != (cur = next))
2943   {
2944     next = cur->next;
2945     GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, cur);
2946     next_a = cur->addr_head;
2947     while  (NULL != (cur_a = next_a))
2948     {
2949       next_a = cur_a->next;
2950       GNUNET_CONTAINER_DLL_remove (cur->addr_head, cur->addr_tail, cur_a);
2951       GNUNET_free (cur_a);
2952     }
2953     GNUNET_free (cur);
2954   }
2955   if (NULL != sh)
2956   {
2957     GNUNET_ATS_solvers_solver_stop (sh);
2958     sh = NULL;
2959   }
2960   /* Shutdown */
2961   end_now();
2962 }
2963
2964 static void
2965 experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success)
2966 {
2967   if (GNUNET_OK == success)
2968     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
2969         GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
2970   else
2971     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
2972
2973   GNUNET_SCHEDULER_add_now (&done, NULL);
2974 }
2975
2976 static void
2977 episode_done_cb (struct Episode *ep)
2978 {
2979   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
2980 }
2981
2982
2983
2984 /**
2985  * Do shutdown
2986  */
2987 static void
2988 end_now ()
2989 {
2990   if (NULL != e)
2991   {
2992     GNUNET_ATS_solvers_experimentation_stop (e);
2993     e = NULL;
2994   }
2995   if (NULL != sh)
2996   {
2997     GNUNET_ATS_solvers_solver_stop (sh);
2998     sh = NULL;
2999   }
3000 }
3001
3002 static void
3003 run (void *cls, char * const *args, const char *cfgfile,
3004     const struct GNUNET_CONFIGURATION_Handle *cfg)
3005 {
3006   enum GNUNET_ATS_Solvers solver;
3007
3008   if (NULL == opt_exp_file)
3009   {
3010     fprintf (stderr, "No experiment given ...\n");
3011     res = 1;
3012     end_now ();
3013     return;
3014   }
3015
3016   if (NULL == opt_solver)
3017   {
3018     fprintf (stderr, "No solver given ...\n");
3019     res = 1;
3020     end_now ();
3021     return;
3022   }
3023
3024   if (0 == strcmp(opt_solver, "mlp"))
3025   {
3026     solver = GNUNET_ATS_SOLVER_MLP;
3027   }
3028   else if (0 == strcmp(opt_solver, "proportional"))
3029   {
3030     solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
3031   }
3032   else if (0 == strcmp(opt_solver, "ril"))
3033   {
3034     solver = GNUNET_ATS_SOLVER_RIL;
3035   }
3036   else
3037   {
3038     fprintf (stderr, "No solver given ...");
3039     res = 1;
3040     end_now ();
3041     return;
3042   }
3043
3044   /* load experiment */
3045   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Loading experiment\n");
3046   e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
3047   if (NULL == e)
3048   {
3049     fprintf (stderr, "Failed to load experiment ...\n");
3050     res = 1;
3051     end_now ();
3052     return;
3053   }
3054
3055   /* load solver */
3056   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Loading solver\n");
3057   sh = GNUNET_ATS_solvers_solver_start (solver);
3058   if (NULL == sh)
3059   {
3060     fprintf (stderr, "Failed to start solver ...\n");
3061     end_now ();
3062     res = 1;
3063     return;
3064   }
3065
3066   /* start logging */
3067   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Start logging \n");
3068   l = GNUNET_ATS_solver_logging_start (e->log_freq);
3069
3070   /* run experiment */
3071   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Running experiment \n");
3072   GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
3073       experiment_done_cb);
3074
3075   /* WAIT */
3076 }
3077
3078
3079 /**
3080  * Main function of the benchmark
3081  *
3082  * @param argc argument count
3083  * @param argv argument values
3084  */
3085 int
3086 main (int argc, char *argv[])
3087 {
3088   opt_exp_file = NULL;
3089   opt_solver = NULL;
3090   opt_log = GNUNET_NO;
3091   opt_save = GNUNET_NO;
3092
3093   res = 0;
3094
3095   static struct GNUNET_GETOPT_CommandLineOption options[] =
3096   {
3097     { 's', "solver", NULL,
3098         gettext_noop ("solver to use"),
3099         1, &GNUNET_GETOPT_set_string, &opt_solver},
3100     {  'e', "experiment", NULL,
3101       gettext_noop ("experiment to use"),
3102       1, &GNUNET_GETOPT_set_string, &opt_exp_file},
3103     {  'V', "verbose", NULL,
3104       gettext_noop ("be verbose"),
3105       0, &GNUNET_GETOPT_set_one, &opt_verbose},
3106     {  'p', "print", NULL,
3107       gettext_noop ("print logging"),
3108       0, &GNUNET_GETOPT_set_one, &opt_print},
3109     {  'f', "file", NULL,
3110         gettext_noop ("save logging to disk"),
3111         0, &GNUNET_GETOPT_set_one, &opt_save},
3112     GNUNET_GETOPT_OPTION_END
3113   };
3114
3115   GNUNET_PROGRAM_run (argc, argv, "gnunet-ats-solver-eval",
3116       NULL, options, &run, argv[0]);
3117
3118   return res;
3119 }
3120 /* end of file ats-testing-experiment.c*/
3121