2 This file is part of GNUnet.
3 (C) 2010,2011 Christian Grothoff (and other contributing authors)
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.
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.
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.
21 * @file ats/perf_ats_solver.c
22 * @brief generic performance test for ATS solvers
23 * @author Christian Grothoff
24 * @author Matthias Wachs
27 #include "gnunet_util_lib.h"
28 #include "gnunet_statistics_service.h"
29 #include "gnunet-service-ats_addresses.h"
30 #include "gnunet-service-ats_normalization.h"
31 #include "gnunet_ats_service.h"
32 #include "gnunet_ats_plugin.h"
33 #include "test_ats_api_common.h"
35 #define DEFAULT_PEERS_START 100
36 #define DEFAULT_PEERS_END 100
37 #define DEFAULT_ADDRESSES 10
38 #define DEFAULT_ATS_COUNT 2
41 * Handle for ATS address component
45 struct PerfPeer *peers;
48 * #peers to start benchmarking with
53 * #peers to end benchmarking with
58 * #addresses to benchmarking with
64 int opt_update_percent;
65 int opt_update_quantity;
72 struct GNUNET_STATISTICS_Handle *stat;
75 * A multihashmap to store all addresses
77 struct GNUNET_CONTAINER_MultiPeerMap *addresses;
81 * Configured ATS solver
91 * Address suggestion requests DLL head
93 struct GAS_Addresses_Suggestion_Requests *r_head;
96 * Address suggestion requests DLL tail
98 struct GAS_Addresses_Suggestion_Requests *r_tail;
100 /* Solver functions */
101 struct GNUNET_ATS_PluginEnvironment env;
108 struct GNUNET_PeerIdentity id;
110 struct ATS_Address *head;
111 struct ATS_Address *tail;
114 static struct PerfHandle ph;
129 //static struct GNUNET_ATS_Information ats[2];
137 GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
141 if (NULL != addresses)
143 GNUNET_CONTAINER_multihashmap_iterate (addresses, &addr_it, NULL);
144 GNUNET_CONTAINER_multihashmap_destroy (addresses);
147 if (NULL != ph.peers)
149 GNUNET_free(ph.peers);
152 GAS_normalization_stop ();
158 perf_create_peer (int cp)
161 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
162 &ph.peers[cp].id.);*/
163 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Creating peer #%u: %s \n", cp,
164 GNUNET_i2s (&ph.peers[cp].id));
170 update_single_addresses (struct ATS_Address *cur)
175 r_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
179 r_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
180 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
181 "Updating peer `%s' address %p type %s val %u\n",
182 GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DELAY", r_val);
183 ph.env.sf.s_address_update_property (ph.solver, cur,
184 GNUNET_ATS_QUALITY_NET_DELAY,
185 r_val, (double) (100 + r_val / 100));
188 r_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10);
190 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
191 "Updating peer `%s' address %p type %s val %u\n",
192 GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DISTANCE", r_val);
193 ph.env.sf.s_address_update_property (ph.solver, cur,
194 GNUNET_ATS_QUALITY_NET_DISTANCE,
195 r_val, (double) (100 + r_val) / 100);
200 ph.env.sf.s_address_update_inuse (ph.solver, cur, GNUNET_YES);
206 bandwidth_changed_cb (void *cls, struct ATS_Address *address)
212 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
214 return GAS_normalization_get_preferences (id);
219 get_property_cb (void *cls, const struct ATS_Address *address)
221 return GAS_normalization_get_properties ((struct ATS_Address *) address);
225 normalized_property_changed_cb (void *cls, struct ATS_Address *peer,
226 uint32_t type, double prop_rel)
232 address_initial_update (void *solver,
233 struct GNUNET_CONTAINER_MultiPeerMap * addresses,
234 struct ATS_Address *address)
236 ph.env.sf.s_address_update_property (solver, address, GNUNET_ATS_QUALITY_NET_DELAY,
238 (double) (100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100))
241 ph.env.sf.s_address_update_property (solver, address,
242 GNUNET_ATS_QUALITY_NET_DISTANCE, 10,
243 (double) (100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100))
248 update_addresses (unsigned int cp, unsigned int ca, unsigned int up_q)
250 struct ATS_Address *cur;
256 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
257 "Updating addresses %u addresses per peer \n", up_q);
260 for (c_peer = 0; c_peer < cp; c_peer++)
262 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating peer `%s'\n",
263 GNUNET_i2s (&ph.peers[c_peer].id));
264 for (c_select = 0; c_select < ca; c_select++)
267 while (c_select < ph.opt_update_quantity)
269 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, ca);
278 for (cur = ph.peers[c_peer].head; NULL != cur; cur = cur->next)
281 update_single_addresses (cur);
288 static struct ATS_Address *
289 perf_create_address (int cp, int ca)
291 struct ATS_Address *a;
292 a = create_address (&ph.peers[cp].id, "Test 1", "test 1", strlen ("test 1") + 1,
294 GNUNET_CONTAINER_DLL_insert(ph.peers[cp].head, ph.peers[cp].tail, a);
295 GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a,
296 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
303 struct ATS_Address *cur;
304 struct ATS_Address *next;
307 int count_p = ph.N_peers_end;
308 int count_a = ph.N_address;
309 struct ATS_Address * cur_addr;
310 ph.peers = GNUNET_malloc ((count_p) * sizeof (struct PerfPeer));
312 for (cp = 0; cp < count_p; cp++)
313 perf_create_peer (cp);
315 for (cp = 0; cp < count_p; cp++)
317 for (ca = 0; ca < count_a; ca++)
319 cur_addr = perf_create_address (cp, ca);
321 ph.env.sf.s_add (ph.solver, cur_addr, GNUNET_ATS_NET_LAN);
322 address_initial_update (ph.solver, ph.addresses, cur_addr);
323 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
324 "Adding address for peer %u address %u\n", cp, ca);
326 //ph.env.sf.s_get (ph.solver, &ph.peers[cp].id);
327 if (cp + 1 >= ph.N_peers_start)
330 if ((0 < ph.opt_update_quantity) || (0 < ph.opt_update_percent))
333 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
334 "Updating problem with %u peers and %u addresses\n", cp + 1, ca);
335 //ph.env.sf.s_bulk_start (ph.solver);
336 //update_addresses (cp + 1, ca, ph.opt_update_quantity);
337 //ph.env.sf.s_bulk_stop (ph.solver);
341 for (cp = 0; cp < count_p; cp++)
343 for (cur = ph.peers[cp].head; cur != NULL ; cur = next)
345 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
346 "Deleting addresses for peer %u\n", cp);
347 ph.env.sf.s_del (ph.solver, cur, GNUNET_NO);
349 GNUNET_CONTAINER_DLL_remove(ph.peers[cp].head, ph.peers[cp].tail, cur);
354 GNUNET_free(ph.peers);
359 run (void *cls, char * const *args, const char *cfgfile,
360 const struct GNUNET_CONFIGURATION_Handle *cfg)
362 GNUNET_log_setup ("perf-ats", "WARNING", NULL);
364 char *src_filename = GNUNET_strdup (__FILE__);
365 char *test_filename = cls;
368 unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
369 unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
372 /* Extract test name */
373 if (NULL == (sep = (strstr (src_filename,".c"))))
381 if (NULL != (sep = strstr (test_filename, ".exe")))
384 if (NULL == (solver = strstr (test_filename, src_filename)))
390 solver += strlen (src_filename) +1;
392 if (0 == strcmp(solver, "proportional"))
394 ph.ats_mode = MODE_PROPORTIONAL;
395 ph.ats_string = "proportional";
397 else if (0 == strcmp(solver, "mlp"))
399 ph.ats_mode = MODE_MLP;
400 ph.ats_string = "mlp";
402 else if ((0 == strcmp(solver, "ril")))
404 ph.ats_mode = MODE_RIL;
405 ph.ats_string = "ril";
409 GNUNET_free (src_filename);
414 GNUNET_free (src_filename);
416 /* Calculcate peers */
417 if ((0 == ph.N_peers_start) && (0 == ph.N_peers_end))
419 ph.N_peers_start = DEFAULT_PEERS_START;
420 ph.N_peers_end = DEFAULT_PEERS_END;
422 if (0 == ph.N_address)
423 ph.N_address = DEFAULT_ADDRESSES;
425 if (ph.opt_update_quantity > ph.N_address)
428 _("Trying to update more addresses than we have per peer! (%u vs %u)"),
429 ph.opt_update_quantity, ph.N_address);
433 if (ph.N_peers_start != ph.N_peers_end)
434 fprintf (stderr, "Benchmarking solver `%s' with %u to %u peers and %u addresses\n",
435 ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address);
437 fprintf (stderr, "Benchmarking solver `%s' with %u peers and %u addresses\n",
438 ph.ats_string, ph.N_peers_end, ph.N_address);
441 if (GNUNET_ATS_NetworkTypeCount != load_quotas (cfg,
442 quotas_in, quotas_in, GNUNET_ATS_NetworkTypeCount))
451 ph.stat = GNUNET_STATISTICS_create ("ats", cfg);
452 ph.env.stats = ph.stat;
453 ph.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
454 ph.env.addresses = ph.addresses;
455 ph.env.bandwidth_changed_cb = bandwidth_changed_cb;
456 ph.env.get_preferences = &get_preferences_cb;
457 ph.env.get_property = &get_property_cb;
458 ph.env.network_count = GNUNET_ATS_NetworkTypeCount;
459 int networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType;
460 for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
462 ph.env.networks[c] = networks[c];
463 ph.env.out_quota[c] = quotas_out[c];
464 ph.env.in_quota[c] = quotas_in[c];
466 GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL );
469 GNUNET_asprintf (&plugin, "libgnunet_plugin_ats_%s", ph.ats_string);
470 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initializing solver `%s '`%s'\n"), ph.ats_string, plugin);
471 if (NULL == (ph.solver = GNUNET_PLUGIN_load (plugin, &ph.env)))
473 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize solver `%s'!\n"), plugin);
482 GNUNET_PLUGIN_unload (plugin, ph.solver);
483 GNUNET_free (plugin);
488 main (int argc, char *argv[])
490 /* extract command line arguments */
491 ph.opt_dump = GNUNET_NO;
492 ph.opt_update_quantity = 0;
493 ph.opt_update_percent = 0;
494 ph.N_peers_start = 0;
497 ph.ats_string = NULL;
499 static struct GNUNET_GETOPT_CommandLineOption options[] = {
500 { 'a', "addresses", NULL,
501 gettext_noop ("addresses to use"),
502 1, &GNUNET_GETOPT_set_uint, &ph.N_address },
503 { 's', "start", NULL,
504 gettext_noop ("start with peer"),
505 1, &GNUNET_GETOPT_set_uint, &ph.N_peers_start },
507 gettext_noop ("end with peer"),
508 1, &GNUNET_GETOPT_set_uint, &ph.N_peers_end },
509 { 'p', "percentage", NULL,
510 gettext_noop ("update a fix percentage of addresses"),
511 1, &GNUNET_GETOPT_set_uint, &ph.opt_update_percent },
512 { 'q', "quantity", NULL,
513 gettext_noop ("update a fix quantity of addresses"),
514 1, &GNUNET_GETOPT_set_uint, &ph.opt_update_quantity },
515 GNUNET_GETOPT_OPTION_END
518 GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
523 /* end of file perf_ats_solver.c */