adding DEBUG logic for #3863
[oweals/gnunet.git] / src / ats-tests / gnunet-ats-sim.c
1 /*
2  This file is part of GNUnet.
3  Copyright (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., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19  */
20 /**
21  * @file ats-tests/gnunet-ats-sim.c
22  * @brief ats traffic simulator: this tool uses the ats-test library to setup a
23  * topology and generate traffic between these peers. The traffic description
24  * is loaded from a experiment description file
25  * @author Christian Grothoff
26  * @author Matthias Wachs
27  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_testbed_service.h"
31 #include "gnunet_ats_service.h"
32 #include "gnunet_core_service.h"
33 #include "ats-testing.h"
34
35 #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
36
37 static struct BenchmarkPeer *masters_p;
38 static struct BenchmarkPeer *slaves_p;
39
40 /**
41  * cmd option -e: experiment file
42  */
43 static char *opt_exp_file;
44
45 /**
46  * cmd option -l: enable logging
47  */
48 static int opt_log;
49
50 /**
51  * cmd option -p: enable plots
52  */
53 static int opt_plot;
54
55 /**
56  * cmd option -v: verbose logs
57  */
58 static int opt_verbose;
59
60 struct GNUNET_SCHEDULER_Task * timeout_task;
61
62 struct Experiment *e;
63 struct LoggingHandle *l;
64
65 static void
66 evaluate (struct GNUNET_TIME_Relative duration_total)
67 {
68   int c_m;
69   int c_s;
70   unsigned int duration;
71   struct BenchmarkPeer *mp;
72   struct BenchmarkPartner *p;
73
74   unsigned int b_sent_sec;
75   double kb_sent_percent;
76   unsigned int b_recv_sec;
77   double kb_recv_percent;
78   unsigned int rtt;
79
80
81   duration = (duration_total.rel_value_us / (1000 * 1000));
82   for (c_m = 0; c_m < e->num_masters; c_m++)
83   {
84     mp = &masters_p[c_m];
85     fprintf (stderr,
86         _("Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. = %u KiB/s\n"),
87         mp->no, mp->total_bytes_sent / 1024, duration,
88         (mp->total_bytes_sent / 1024) / duration,
89         mp->total_bytes_received / 1024, duration,
90         (mp->total_bytes_received / 1024) / duration);
91
92     for (c_s = 0; c_s < e->num_slaves; c_s++)
93     {
94       p = &mp->partners[c_s];
95
96       b_sent_sec = 0;
97       b_recv_sec = 0;
98       kb_sent_percent = 0.0;
99       kb_recv_percent = 0.0;
100       rtt = 0;
101
102       if (duration > 0)
103       {
104           b_sent_sec = p->bytes_sent / duration;
105           b_recv_sec = p->bytes_received / duration;
106       }
107
108       if (mp->total_bytes_sent > 0)
109           kb_sent_percent = ((double) p->bytes_sent * 100) / mp->total_bytes_sent;
110       if (mp->total_bytes_received > 0)
111           kb_recv_percent = ((double) p->bytes_received * 100) / mp->total_bytes_received;
112       if (1000 * p->messages_sent > 0)
113           rtt = p->total_app_rtt / (1000 * p->messages_sent);
114       fprintf (stderr,
115           "%c Master [%u] -> Slave [%u]: sent %u Bips (%.2f %%), received %u Bips (%.2f %%)\n",
116           (mp->pref_partner == p->dest) ? '*' : ' ',
117           mp->no, p->dest->no,
118           b_sent_sec, kb_sent_percent,
119                   b_recv_sec, kb_recv_percent);
120       fprintf (stderr,
121           "%c Master [%u] -> Slave [%u]: Average application layer RTT: %u ms\n",
122           (mp->pref_partner == p->dest) ? '*' : ' ',
123           mp->no, p->dest->no, rtt);
124     }
125   }
126 }
127
128 static void
129 do_shutdown ()
130 {
131   fprintf (stderr, "Shutdown\n");
132   /* timeout */
133   if (NULL != l)
134   {
135     GNUNET_ATS_TEST_logging_stop (l);
136     GNUNET_ATS_TEST_logging_clean_up (l);
137     l = NULL;
138   }
139
140   /* Stop traffic generation */
141   GNUNET_ATS_TEST_generate_traffic_stop_all();
142
143   /* Stop all preference generations */
144   GNUNET_ATS_TEST_generate_preferences_stop_all ();
145
146   if (NULL != e)
147   {
148     GNUNET_ATS_TEST_experimentation_stop (e);
149     e = NULL;
150   }
151   GNUNET_ATS_TEST_shutdown_topology ();
152 }
153
154
155 static void
156 transport_recv_cb (void *cls,
157                    const struct GNUNET_PeerIdentity * peer,
158                    const struct GNUNET_MessageHeader * message)
159 {
160
161 }
162
163 static void
164 log_request__cb (void *cls, const struct GNUNET_HELLO_Address *address,
165     int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
166     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
167     const struct GNUNET_ATS_Properties *ats)
168 {
169
170   if (NULL != l)
171   {
172     //GNUNET_break (0);
173     //GNUNET_ATS_TEST_logging_now (l);
174   }
175
176 }
177
178 static void
179 experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success)
180 {
181   if (GNUNET_OK == success)
182     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
183         GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
184   else
185     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
186   if (NULL != timeout_task)
187   {
188     GNUNET_SCHEDULER_cancel (timeout_task);
189     timeout_task = NULL;
190   }
191   /* Stop logging */
192   GNUNET_ATS_TEST_logging_stop (l);
193
194   /* Stop traffic generation */
195   GNUNET_ATS_TEST_generate_traffic_stop_all();
196
197   /* Stop all preference generations */
198   GNUNET_ATS_TEST_generate_preferences_stop_all ();
199
200   evaluate (duration);
201   if (opt_log)
202     GNUNET_ATS_TEST_logging_write_to_file(l, opt_exp_file, opt_plot);
203
204   if (NULL != l)
205   {
206     GNUNET_ATS_TEST_logging_stop (l);
207     GNUNET_ATS_TEST_logging_clean_up (l);
208     l = NULL;
209   }
210
211   /* Clean up experiment */
212   GNUNET_ATS_TEST_experimentation_stop (e);
213   e = NULL;
214
215   /* Shutdown topology */
216   GNUNET_ATS_TEST_shutdown_topology ();
217 }
218
219 static void
220 episode_done_cb (struct Episode *ep)
221 {
222   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
223 }
224
225 static void topology_setup_done (void *cls,
226     struct BenchmarkPeer *masters,
227     struct BenchmarkPeer *slaves)
228 {
229   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Topology setup complete!\n");
230
231   masters_p = masters;
232   slaves_p = slaves;
233
234   l = GNUNET_ATS_TEST_logging_start (e->log_freq,
235       e->name,
236       masters_p,
237       e->num_masters, e->num_slaves,
238       opt_verbose);
239   GNUNET_ATS_TEST_experimentation_run (e, &episode_done_cb, &experiment_done_cb);
240 /*
241   GNUNET_ATS_TEST_generate_preferences_start(&masters[0],&masters[0].partners[0],
242       GNUNET_ATS_TEST_TG_CONSTANT, 1, 1, GNUNET_TIME_UNIT_SECONDS,
243       GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250),
244       GNUNET_ATS_PREFERENCE_BANDWIDTH);
245 */
246 /*
247   GNUNET_ATS_TEST_generate_preferences_start(&masters[0],&masters[0].partners[0],
248       GNUNET_ATS_TEST_TG_LINEAR, 1, 50,
249       GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 2),
250       GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250),
251       GNUNET_ATS_PREFERENCE_BANDWIDTH);
252 */
253 /*
254   GNUNET_ATS_TEST_generate_preferences_start(&masters[0],&masters[0].partners[0],
255         GNUNET_ATS_TEST_TG_RANDOM, 1, 50,
256         GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 2),
257         GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250),
258         GNUNET_ATS_PREFERENCE_BANDWIDTH);
259 */
260   /*
261   GNUNET_ATS_TEST_generate_preferences_start(&masters[0],&masters[0].partners[0],
262         GNUNET_ATS_TEST_TG_SINUS, 10, 5,
263         GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5),
264         GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250),
265         GNUNET_ATS_PREFERENCE_BANDWIDTH);
266 */
267 #if 0
268   int c_m;
269   int c_s;
270   for (c_m = 0; c_m < e->num_masters; c_m++)
271   {
272       for (c_s = 0; c_s < e->num_slaves; c_s++)
273       {
274         /* Generate maximum traffic to all peers */
275         /* Example: Generate traffic with constant 10,000 Bytes/s */
276         GNUNET_ATS_TEST_generate_traffic_start (&masters[c_m],
277             &masters[c_m].partners[c_s],
278             GNUNET_ATS_TEST_TG_CONSTANT,
279             10000,
280             GNUNET_TIME_UNIT_FOREVER_REL);
281         /* Example: Generate traffic with an increasing rate from 1000 to 2000
282          * Bytes/s with in a minute */
283         GNUNET_ATS_TEST_generate_traffic_start (&masters[c_m],
284             &masters[c_m].partners[c_s],
285             GNUNET_ATS_TEST_TG_LINEAR,
286             1000,
287             2000,
288             GNUNET_TIME_UNIT_MINUTES,
289             GNUNET_TIME_UNIT_FOREVER_REL);
290         /* Example: Generate traffic with a random rate between 1000 to 2000
291          * Bytes/s */
292         GNUNET_ATS_TEST_generate_traffic_start (&masters[c_m],
293             &masters[c_m].partners[c_s],
294             GNUNET_ATS_TEST_TG_RANDOM,
295             1000,
296             2000,
297             GNUNET_TIME_UNIT_FOREVER_REL,
298             GNUNET_TIME_UNIT_FOREVER_REL);
299         /* Example: Generate traffic with a sinus form, a base rate of
300          * 1000 Bytes/s, an amplitude of (max-base), and a period of 1 minute */
301         GNUNET_ATS_TEST_generate_traffic_start (&masters[c_m],
302             &masters[c_m].partners[c_s],
303             GNUNET_ATS_TEST_TG_SINUS,
304             1000,
305             2000,
306             GNUNET_TIME_UNIT_MINUTES,
307             GNUNET_TIME_UNIT_FOREVER_REL);
308       }
309   }
310 #endif
311
312   timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_add (GNUNET_TIME_UNIT_MINUTES,
313       e->max_duration), &do_shutdown, NULL);
314 }
315
316 static void
317 parse_args (int argc, char *argv[])
318 {
319   int c;
320   opt_exp_file = NULL;
321   opt_log = GNUNET_NO;
322   opt_plot = GNUNET_NO;
323
324   for (c = 0; c < argc; c++)
325   {
326     if ((c < (argc - 1)) && (0 == strcmp (argv[c], "-e")))
327     {
328       opt_exp_file = GNUNET_strdup ( argv[c + 1]);
329     }
330     if (0 == strcmp (argv[c], "-l"))
331     {
332       opt_log = GNUNET_YES;
333     }
334     if (0 == strcmp (argv[c], "-p"))
335     {
336       opt_plot = GNUNET_YES;
337     }
338     if (0 == strcmp (argv[c], "-v"))
339     {
340       opt_verbose = GNUNET_YES;
341     }
342   }
343 }
344
345 int
346 main (int argc, char *argv[])
347 {
348   GNUNET_log_setup("gnunet-ats-sim", "INFO", NULL);
349
350   parse_args (argc, argv);
351   if (NULL == opt_exp_file )
352   {
353     fprintf (stderr, "No experiment given...\n");
354     return 1;
355   }
356
357   fprintf (stderr, "Loading experiment `%s' \n", opt_exp_file );
358   e = GNUNET_ATS_TEST_experimentation_load (opt_exp_file);
359   if (NULL == e)
360   {
361     fprintf (stderr, "Invalid experiment\n");
362     return 1;
363   }
364   if (0 == e->num_episodes)
365   {
366     fprintf (stderr, "No episodes included\n");
367     return 1;
368   }
369
370   /* Setup a topology with */
371   GNUNET_ATS_TEST_create_topology ("gnunet-ats-sim", e->cfg_file,
372       e->num_slaves,
373       e->num_masters,
374       GNUNET_NO,
375       &topology_setup_done,
376       NULL,
377       &transport_recv_cb,
378       &log_request__cb);
379   GNUNET_free (opt_exp_file);
380   return 0;
381 }
382 /* end of file gnunet-ats-sim.c */