-disable NSE POW during cadet tests
[oweals/gnunet.git] / src / ats-tests / ats-testing-experiment.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 "ats-testing.h"
29
30 const char *
31 print_op (enum OperationType op)
32 {
33   switch (op) {
34     case START_SEND:
35       return "START_SEND";
36     case STOP_SEND:
37       return "STOP_SEND";
38     case START_PREFERENCE:
39       return "START_PREFERENCE";
40     case STOP_PREFERENCE:
41       return "STOP_PREFERENCE";
42     default:
43       break;
44   }
45   return "";
46 }
47
48
49 static struct Experiment *
50 create_experiment ()
51 {
52   struct Experiment *e;
53   e = GNUNET_new (struct Experiment);
54   e->name = NULL;
55   e->num_masters = 0;
56   e->num_slaves = 0;
57   e->start = NULL;
58   e->total_duration = GNUNET_TIME_UNIT_ZERO;
59   return e;
60 }
61
62 static void
63 free_experiment (struct Experiment *e)
64 {
65   struct Episode *cur;
66   struct Episode *next;
67   struct GNUNET_ATS_TEST_Operation *cur_o;
68   struct GNUNET_ATS_TEST_Operation *next_o;
69
70   next = e->start;
71   for (cur = next; NULL != cur; cur = next)
72   {
73     next = cur->next;
74
75     next_o = cur->head;
76     for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
77     {
78       next_o = cur_o->next;
79       GNUNET_free (cur_o);
80     }
81     GNUNET_free (cur);
82   }
83
84   GNUNET_free_non_null (e->name);
85   GNUNET_free_non_null (e->cfg_file);
86   GNUNET_free (e);
87 }
88
89 static int
90 load_episode (struct Experiment *e, struct Episode *cur,
91     struct GNUNET_CONFIGURATION_Handle *cfg)
92 {
93   struct GNUNET_ATS_TEST_Operation *o;
94   char *sec_name;
95   char *op_name;
96   char *op;
97   char *type;
98   char *pref;
99   int op_counter = 0;
100
101   fprintf (stderr, "Parsing episode %u\n",cur->id);
102   GNUNET_asprintf(&sec_name, "episode-%u", cur->id);
103
104   while (1)
105   {
106     /* Load operation */
107     GNUNET_asprintf(&op_name, "op-%u-operation", op_counter);
108     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
109         sec_name, op_name, &op))
110     {
111       GNUNET_free (op_name);
112       break;
113     }
114     o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
115     /* operations = set_rate, start_send, stop_send, set_preference */
116     if (0 == strcmp (op, "start_send"))
117     {
118       o->type = START_SEND;
119     }
120     else if (0 == strcmp (op, "stop_send"))
121     {
122       o->type = STOP_SEND;
123     }
124     else if (0 == strcmp (op, "start_preference"))
125     {
126       o->type = START_PREFERENCE;
127     }
128     else if (0 == strcmp (op, "stop_preference"))
129     {
130       o->type = STOP_PREFERENCE;
131     }
132     else
133     {
134       fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
135           op_counter, op, cur->id);
136       GNUNET_free (op);
137       GNUNET_free (op_name);
138       GNUNET_free (o);
139       return GNUNET_SYSERR;
140     }
141     GNUNET_free (op_name);
142
143     /* Get source */
144     GNUNET_asprintf(&op_name, "op-%u-src", op_counter);
145     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
146         sec_name, op_name, &o->src_id))
147     {
148       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
149           op_counter, op, cur->id);
150       GNUNET_free (op);
151       GNUNET_free (op_name);
152       GNUNET_free (o);
153       return GNUNET_SYSERR;
154     }
155     if (o->src_id > (e->num_masters - 1))
156     {
157       fprintf (stderr, "Invalid src %llu in operation %u `%s' in episode %u\n",
158           o->src_id, op_counter, op, cur->id);
159       GNUNET_free (op);
160       GNUNET_free (op_name);
161       GNUNET_free (o);
162       return GNUNET_SYSERR;
163     }
164     GNUNET_free (op_name);
165
166     /* Get destination */
167     GNUNET_asprintf(&op_name, "op-%u-dest", op_counter);
168     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
169         sec_name, op_name, &o->dest_id))
170     {
171       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
172           op_counter, op, cur->id);
173       GNUNET_free (op);
174       GNUNET_free (op_name);
175       GNUNET_free (o);
176       return GNUNET_SYSERR;
177     }
178     if (o->dest_id > (e->num_slaves - 1))
179     {
180       fprintf (stderr, "Invalid destination %llu in operation %u `%s' in episode %u\n",
181           o->dest_id, op_counter, op, cur->id);
182       GNUNET_free (op);
183       GNUNET_free (op_name);
184       GNUNET_free (o);
185       return GNUNET_SYSERR;
186     }
187     GNUNET_free (op_name);
188
189     GNUNET_asprintf(&op_name, "op-%u-type", op_counter);
190     if ( (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_string(cfg,
191             sec_name, op_name, &type)) &&
192         ((STOP_SEND != o->type) || (STOP_PREFERENCE != o->type)))
193     {
194       /* Load arguments for set_rate, start_send, set_preference */
195       if (0 == strcmp (type, "constant"))
196       {
197         o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
198       }
199       else if (0 == strcmp (type, "linear"))
200       {
201         o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
202       }
203       else if (0 == strcmp (type, "sinus"))
204       {
205         o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
206       }
207       else if (0 == strcmp (type, "random"))
208       {
209         o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
210       }
211       else
212       {
213         fprintf (stderr, "Invalid type %u `%s' in episode %u\n",
214             op_counter, op, cur->id);
215         GNUNET_free (type);
216         GNUNET_free (op);
217         GNUNET_free (op_name);
218         GNUNET_free (sec_name);
219         GNUNET_free (o);
220         return GNUNET_SYSERR;
221       }
222       GNUNET_free (op_name);
223
224       /* Get base rate */
225       GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
226       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
227           sec_name, op_name, &o->base_rate))
228       {
229         fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
230             op_counter, op, cur->id);
231         GNUNET_free (type);
232         GNUNET_free (op);
233         GNUNET_free (op_name);
234         GNUNET_free (sec_name);
235         GNUNET_free (o);
236         return GNUNET_SYSERR;
237       }
238       GNUNET_free (op_name);
239
240       /* Get max rate */
241       GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
242       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
243           sec_name, op_name, &o->max_rate))
244       {
245         if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
246             (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
247             (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
248         {
249           fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
250               op_counter, op, cur->id);
251           GNUNET_free (type);
252           GNUNET_free (op_name);
253           GNUNET_free (op);
254           GNUNET_free (o);
255           return GNUNET_SYSERR;
256         }
257       }
258       GNUNET_free (op_name);
259
260       /* Get period */
261       GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
262       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
263           sec_name, op_name, &o->period))
264       {
265         o->period = cur->duration;
266       }
267       GNUNET_free (op_name);
268
269       if (START_PREFERENCE == o->type)
270       {
271           /* Get frequency */
272           GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
273           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
274               sec_name, op_name, &o->frequency))
275           {
276               fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
277                   op_counter, op, cur->id);
278               GNUNET_free (type);
279               GNUNET_free (op_name);
280               GNUNET_free (op);
281               GNUNET_free (o);
282               return GNUNET_SYSERR;
283           }
284           GNUNET_free (op_name);
285
286           /* Get preference */
287           GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
288           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
289               sec_name, op_name, &pref))
290           {
291               fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
292                   op_counter, op, cur->id);
293               GNUNET_free (type);
294               GNUNET_free (op_name);
295               GNUNET_free (op);
296               GNUNET_free_non_null (pref);
297               GNUNET_free (o);
298               return GNUNET_SYSERR;
299           }
300
301           if (0 == strcmp(pref, "bandwidth"))
302             o->pref_type = GNUNET_ATS_PREFERENCE_BANDWIDTH;
303           else if (0 == strcmp(pref, "latency"))
304             o->pref_type = GNUNET_ATS_PREFERENCE_LATENCY;
305           else
306           {
307               fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
308                   op_counter, op, cur->id);
309               GNUNET_free (type);
310               GNUNET_free (op_name);
311               GNUNET_free (op);
312               GNUNET_free (pref);
313               GNUNET_free_non_null (pref);
314               GNUNET_free (o);
315               return GNUNET_SYSERR;
316           }
317           GNUNET_free (pref);
318           GNUNET_free (op_name);
319       }
320     }
321
322     /* Safety checks */
323     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
324         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
325     {
326       if ((o->max_rate - o->base_rate) > o->base_rate)
327       {
328         /* This will cause an underflow */
329         GNUNET_break (0);
330       }
331       fprintf (stderr, "Selected max rate and base rate cannot be used for desired traffic form!\n");
332     }
333
334     if ((START_SEND == o->type) || (START_PREFERENCE == o->type))
335       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu] == %s, %llu -> %llu in %s\n",
336         op_counter, cur->id, print_op (o->type), o->src_id,
337         o->dest_id, (NULL != type) ? type : "",
338         o->base_rate, o->max_rate,
339         GNUNET_STRINGS_relative_time_to_string (o->period, GNUNET_YES));
340     else
341       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu]\n",
342         op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id);
343
344     GNUNET_free_non_null (type);
345     GNUNET_free (op);
346
347     GNUNET_CONTAINER_DLL_insert (cur->head,cur->tail, o);
348     op_counter++;
349   }
350   GNUNET_free (sec_name);
351
352   return GNUNET_OK;
353 }
354
355 static int
356 load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
357 {
358   int e_counter = 0;
359   char *sec_name;
360   struct GNUNET_TIME_Relative e_duration;
361   struct Episode *cur;
362   struct Episode *last;
363
364   e_counter = 0;
365   last = NULL;
366   while (1)
367   {
368     GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
369     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
370         sec_name, "duration", &e_duration))
371     {
372       GNUNET_free (sec_name);
373       break;
374     }
375
376     cur = GNUNET_new (struct Episode);
377     cur->duration = e_duration;
378     cur->id = e_counter;
379
380     if (GNUNET_OK != load_episode (e, cur, cfg))
381     {
382       GNUNET_free (sec_name);
383       GNUNET_free (cur);
384       return GNUNET_SYSERR;
385     }
386
387     fprintf (stderr, "Found episode %u with duration %s \n",
388         e_counter,
389         GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
390
391     /* Update experiment */
392     e->num_episodes ++;
393     e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
394     /* Put in linked list */
395     if (NULL == last)
396       e->start = cur;
397     else
398     last->next = cur;
399
400     GNUNET_free (sec_name);
401     e_counter ++;
402     last = cur;
403   }
404   return e_counter;
405 }
406
407 static void
408 timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
409 {
410   struct Experiment *e = cls;
411   e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
412   fprintf (stderr, "Experiment timeout!\n");
413
414   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
415   {
416     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
417     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
418   }
419
420   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
421       GNUNET_SYSERR);
422 }
423
424 static void
425 enforce_start_send (struct GNUNET_ATS_TEST_Operation *op)
426 {
427   struct BenchmarkPeer *peer;
428   struct BenchmarkPartner *partner;
429
430   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
431   if (NULL == peer)
432   {
433     GNUNET_break (0);
434     return;
435   }
436
437   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
438   if (NULL == partner)
439   {
440     GNUNET_break (0);
441     return;
442   }
443
444   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
445
446   if (NULL != partner->tg)
447   {
448     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id);
449     GNUNET_ATS_TEST_generate_traffic_stop(partner->tg);
450     partner->tg = NULL;
451   }
452
453   partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner,
454       op->gen_type, op->base_rate, op->max_rate, op->period,
455       GNUNET_TIME_UNIT_FOREVER_REL);
456 }
457
458 static void
459 enforce_stop_send (struct GNUNET_ATS_TEST_Operation *op)
460 {
461   struct BenchmarkPartner *p;
462   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
463   if (NULL == p)
464   {
465     GNUNET_break (0);
466     return;
467   }
468
469   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
470
471   if (NULL != p->tg)
472   {
473     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
474         op->src_id, op->dest_id);
475     GNUNET_ATS_TEST_generate_traffic_stop(p->tg);
476     p->tg = NULL;
477   }
478 }
479
480
481 static void
482 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
483 {
484   struct BenchmarkPeer *peer;
485   struct BenchmarkPartner *partner;
486
487   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
488   if (NULL == peer)
489   {
490     GNUNET_break (0);
491     return;
492   }
493
494   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
495   if (NULL == partner)
496   {
497     GNUNET_break (0);
498     return;
499   }
500
501   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
502
503   if (NULL != partner->pg)
504   {
505     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
506         op->src_id, op->dest_id);
507     GNUNET_ATS_TEST_generate_preferences_stop(partner->pg);
508     partner->pg = NULL;
509   }
510
511   partner->pg = GNUNET_ATS_TEST_generate_preferences_start(peer, partner,
512       op->gen_type, op->base_rate, op->max_rate, op->period, op->frequency,
513       op->pref_type);
514 }
515
516 static void
517 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
518 {
519   struct BenchmarkPartner *p;
520   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
521   if (NULL == p)
522   {
523     GNUNET_break (0);
524     return;
525   }
526
527   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
528
529   if (NULL != p->pg)
530   {
531     fprintf (stderr, "Stopping preference between master %llu slave %llu\n",
532         op->src_id, op->dest_id);
533     GNUNET_ATS_TEST_generate_preferences_stop (p->pg);
534     p->pg = NULL;
535   }
536 }
537
538 static void enforce_episode (struct Episode *ep)
539 {
540   struct GNUNET_ATS_TEST_Operation *cur;
541   for (cur = ep->head; NULL != cur; cur = cur->next)
542   {
543
544     fprintf (stderr, "Enforcing operation: %s [%llu]->[%llu] == %llu\n",
545         print_op (cur->type), cur->src_id, cur->dest_id, cur->base_rate);
546     switch (cur->type) {
547       case START_SEND:
548         enforce_start_send (cur);
549         break;
550       case STOP_SEND:
551         enforce_stop_send (cur);
552         break;
553       case START_PREFERENCE:
554         enforce_start_preference (cur);
555         break;
556       case STOP_PREFERENCE:
557         enforce_stop_preference (cur);
558         break;
559       default:
560         break;
561     }
562   }
563 }
564
565 static void
566 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
567 {
568   struct Experiment *e = cls;
569   e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
570   if (NULL != e->ep_done_cb)
571     e->ep_done_cb (e->cur);
572
573   /* Scheduling next */
574   e->cur = e->cur->next;
575   if (NULL == e->cur)
576   {
577     /* done */
578     fprintf (stderr, "Last episode done!\n");
579     if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
580     {
581       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
582       e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
583     }
584     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
585     return;
586   }
587
588   fprintf (stderr, "Running episode %u with timeout %s\n",
589       e->cur->id,
590       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
591   enforce_episode(e->cur);
592
593   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
594       &timeout_episode, e);
595 }
596
597
598 void
599 GNUNET_ATS_TEST_experimentation_run (struct Experiment *e,
600     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
601     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
602 {
603   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
604       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
605   e->e_done_cb = e_done_cb;
606   e->ep_done_cb = ep_done_cb;
607   e->start_time = GNUNET_TIME_absolute_get();
608
609   /* Start total time out */
610   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
611       &timeout_experiment, e);
612
613   /* Start */
614   e->cur = e->start;
615   fprintf (stderr, "Running episode %u with timeout %s\n",
616       e->cur->id,
617       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
618   enforce_episode(e->cur);
619   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
620       &timeout_episode, e);
621
622
623 }
624
625
626 struct Experiment *
627 GNUNET_ATS_TEST_experimentation_load (char *filename)
628 {
629   struct Experiment *e;
630   struct GNUNET_CONFIGURATION_Handle *cfg;
631   e = NULL;
632
633   cfg = GNUNET_CONFIGURATION_create();
634   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
635   {
636     fprintf (stderr, "Failed to load `%s'\n", filename);
637     GNUNET_CONFIGURATION_destroy (cfg);
638     return NULL;
639   }
640
641   e = create_experiment ();
642
643   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
644       "name", &e->name))
645   {
646     fprintf (stderr, "Invalid %s", "name");
647     free_experiment (e);
648     return NULL;
649   }
650   else
651     fprintf (stderr, "Experiment name: `%s'\n", e->name);
652
653   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
654       "cfg_file", &e->cfg_file))
655   {
656     fprintf (stderr, "Invalid %s", "cfg_file");
657     free_experiment (e);
658     return NULL;
659   }
660   else
661     fprintf (stderr, "Experiment name: `%s'\n", e->cfg_file);
662
663   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
664       "masters", &e->num_masters))
665   {
666     fprintf (stderr, "Invalid %s", "masters");
667     free_experiment (e);
668     return NULL;
669   }
670   else
671     fprintf (stderr, "Experiment masters: `%llu'\n",
672         e->num_masters);
673
674   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
675       "slaves", &e->num_slaves))
676   {
677     fprintf (stderr, "Invalid %s", "slaves");
678     free_experiment (e);
679     return NULL;
680   }
681   else
682     fprintf (stderr, "Experiment slaves: `%llu'\n",
683         e->num_slaves);
684
685   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
686       "log_freq", &e->log_freq))
687   {
688     fprintf (stderr, "Invalid %s", "log_freq");
689     free_experiment (e);
690     return NULL;
691   }
692   else
693     fprintf (stderr, "Experiment logging frequency: `%s'\n",
694         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
695
696   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
697       "max_duration", &e->max_duration))
698   {
699     fprintf (stderr, "Invalid %s", "max_duration");
700     free_experiment (e);
701     return NULL;
702   }
703   else
704     fprintf (stderr, "Experiment duration: `%s'\n",
705         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
706
707   load_episodes (e, cfg);
708   fprintf (stderr, "Loaded %u episodes with total duration %s\n",
709       e->num_episodes,
710       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
711
712   GNUNET_CONFIGURATION_destroy (cfg);
713   return e;
714 }
715
716 void
717 GNUNET_ATS_TEST_experimentation_stop (struct Experiment *e)
718 {
719   if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
720   {
721     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
722     e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
723   }
724   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
725   {
726     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
727     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
728   }
729   free_experiment (e);
730 }
731
732 /* end of file ats-testing-experiment.c*/
733