X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fdht%2Fgnunet_dht_profiler.c;h=60c78c2805a0d2c85f6b56e2c9533c6014477ec2;hb=1b49510e7736620d7e10a33326076e2d75c86943;hp=9fa9f33c471168c205041b6ba98d9c3a3c8bfd6e;hpb=5ac199dcc8af3a7052086087d36feda38bc4b4de;p=oweals%2Fgnunet.git diff --git a/src/dht/gnunet_dht_profiler.c b/src/dht/gnunet_dht_profiler.c index 9fa9f33c4..60c78c280 100644 --- a/src/dht/gnunet_dht_profiler.c +++ b/src/dht/gnunet_dht_profiler.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** @@ -38,14 +38,20 @@ /** * Number of peers which should perform a PUT out of 100 peers */ -#define PUT_PROBABILITY 100 +#define PUT_PROBABILITY 50 +#if ENABLE_MALICIOUS /** - * Percentage of peers that should act maliciously. - * These peers will never start PUT/GET request. - * n_active and n_malicious should not intersect. + * Number of peers which should act as malicious peers */ -#define MALICIOUS_PEERS 0 +#define MALICIOUS_PROBABILITY 20 + +/** + * Context for a peer which should act maliciously. + */ +struct MaliciousContext; +#endif + /** * Configuration @@ -67,7 +73,6 @@ struct ActiveContext; */ struct Context { - /** * The testbed peer this context belongs to */ @@ -82,6 +87,13 @@ struct Context * Active context; NULL if this peer is not an active peer */ struct ActiveContext *ac; + +#if ENABLE_MALICIOUS + /** + * Malicious context; NULL if this peer is NOT malicious. + */ + struct MaliciousContext *mc; +#endif }; @@ -100,6 +112,11 @@ struct MaliciousContext * Handler to the DHT service */ struct GNUNET_DHT_Handle *dht; + + /** + * Handler to malicious api + */ + struct GNUNET_DHT_ActMaliciousHandle *dht_malicious; }; /** @@ -107,6 +124,32 @@ struct MaliciousContext */ struct Context **malicious_peer_contexts = NULL; +/** + * Context for a peer which should act maliciously. + */ +struct Malicious_Context +{ + /** + * The linked peer context + */ + struct Context *ctx; + + /** + * Handler to the DHT service + */ + struct GNUNET_DHT_Handle *dht; +}; + +/** + * Array of malicious peers. + */ +static struct MaliciousContext *a_mc; + +/** + * Number or malicious peers. + */ +static unsigned int n_malicious; + #endif /** @@ -152,7 +195,7 @@ struct ActiveContext /** * Delay task */ - GNUNET_SCHEDULER_TaskIdentifier delay_task; + struct GNUNET_SCHEDULER_Task * delay_task; /** * The size of the @e put_data @@ -177,9 +220,19 @@ static struct Context *a_ctx; static struct ActiveContext *a_ac; /** - * The delay between starting to do PUTS and GETS + * The delay between rounds for collecting statistics */ -static struct GNUNET_TIME_Relative delay; +static struct GNUNET_TIME_Relative delay_stats; + +/** + * The delay to start puts. + */ +static struct GNUNET_TIME_Relative delay_put; + +/** + * The delay to start puts. + */ +static struct GNUNET_TIME_Relative delay_get; /** * The timeout for GET and PUT @@ -191,13 +244,6 @@ static struct GNUNET_TIME_Relative timeout; */ static unsigned int num_peers; -#if ENABLE_MALICIOUS -/** - * Number or malicious peers. - */ -static unsigned int n_malicious; -#endif - /** * Number of active peers */ @@ -264,7 +310,7 @@ static struct GNUNET_TESTBED_Operation *successor_stats_op; static struct GNUNET_TESTBED_Peer **testbed_handles; /** - * Total number of messages sent by peer. + * Total number of messages sent by peer. */ static uint64_t outgoing_bandwidth; @@ -279,27 +325,27 @@ static uint64_t incoming_bandwidth; static double average_put_path_length; /** - * Average number of hops taken to do get. + * Average number of hops taken to do get. */ static double average_get_path_length; /** - * Total put path length across all peers. + * Total put path length across all peers. */ static unsigned int total_put_path_length; /** - * Total get path length across all peers. + * Total get path length across all peers. */ static unsigned int total_get_path_length; /** - * Hashmap to store pair of peer and its corresponding successor. + * Hashmap to store pair of peer and its corresponding successor. */ static struct GNUNET_CONTAINER_MultiHashMap *successor_peer_hashmap; /** - * Key to start the lookup on successor_peer_hashmap. + * Key to start the lookup on successor_peer_hashmap. */ static struct GNUNET_HashCode *start_key; @@ -311,7 +357,7 @@ static int flag = 0; /** * Task to collect peer and its current successor statistics. */ -static GNUNET_SCHEDULER_TaskIdentifier successor_stats_task; +static struct GNUNET_SCHEDULER_Task * successor_stats_task; /** * Closure for successor_stats_task. @@ -319,10 +365,10 @@ static GNUNET_SCHEDULER_TaskIdentifier successor_stats_task; struct Collect_Stat_Context { /** - * Current Peer Context. + * Current Peer Context. */ struct Context *service_connect_ctx; - + /** * Testbed operation acting on this peer */ @@ -335,11 +381,10 @@ struct Collect_Stat_Context struct Context **peer_contexts = NULL; /** - * Counter to keep track of peers added to peer_context lists. + * Counter to keep track of peers added to peer_context lists. */ static int peers_started = 0; - /** * Should we do a PUT (mode = 0) or GET (mode = 1); */ @@ -350,14 +395,30 @@ static enum MODE_GET = 1 } mode; + /** - * Task that collects successor statistics from all the peers. + * Are we shutting down + */ +static int in_shutdown = 0; + +/** + * Total number of times to check if circle is formed or not. + */ +static unsigned int tries; + +/** + * Task that collects successor statistics from all the peers. * @param cls * @param tc */ static void collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); +/** + * Connect to DHT services of active peers + */ +static void +start_profiling(); /** * Shutdown task. Cleanup all resources and operations. @@ -371,29 +432,33 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct ActiveContext *ac; unsigned int cnt; + in_shutdown = GNUNET_YES; if (NULL != a_ctx) { for (cnt=0; cnt < num_peers; cnt++) { - if (NULL != a_ctx[cnt].op) - GNUNET_TESTBED_operation_done (a_ctx[cnt].op); //FIXME: assertion fails. - /* Cleanup active context if this peer is an active peer */ ac = a_ctx[cnt].ac; - if (NULL == ac) - continue; - if (GNUNET_SCHEDULER_NO_TASK != ac->delay_task) - GNUNET_SCHEDULER_cancel (ac->delay_task); - if (NULL != ac->put_data) - GNUNET_free (ac->put_data); - if (NULL != ac->dht_put) - GNUNET_DHT_put_cancel (ac->dht_put); - if (NULL != ac->dht_get) - GNUNET_DHT_get_stop (ac->dht_get); + if (NULL != ac) + { + if (NULL != ac->delay_task) + GNUNET_SCHEDULER_cancel (ac->delay_task); + if (NULL != ac->put_data) + GNUNET_free (ac->put_data); + if (NULL != ac->dht_put) + GNUNET_DHT_put_cancel (ac->dht_put); + if (NULL != ac->dht_get) + GNUNET_DHT_get_stop (ac->dht_get); + } + /* Cleanup testbed operation handle at the last as this operation may + contain service connection to DHT */ + if (NULL != a_ctx[cnt].op) + GNUNET_TESTBED_operation_done (a_ctx[cnt].op); } GNUNET_free (a_ctx); a_ctx = NULL; } + //FIXME: Should we collect stats only for put/get not for other messages. if(NULL != bandwidth_stats_op) GNUNET_TESTBED_operation_done (bandwidth_stats_op); bandwidth_stats_op = NULL; @@ -411,13 +476,13 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * operation has executed successfully. */ static void -bandwidth_stats_cont (void *cls, - struct GNUNET_TESTBED_Operation *op, +bandwidth_stats_cont (void *cls, + struct GNUNET_TESTBED_Operation *op, const char *emsg) { INFO ("# Outgoing bandwidth: %u\n", outgoing_bandwidth); INFO ("# Incoming bandwidth: %u\n", incoming_bandwidth); - GNUNET_SCHEDULER_shutdown (); + GNUNET_SCHEDULER_shutdown (); } @@ -433,11 +498,11 @@ bandwidth_stats_cont (void *cls, * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int -bandwidth_stats_iterator (void *cls, +bandwidth_stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, - const char *subsystem, + const char *subsystem, const char *name, - uint64_t value, + uint64_t value, int is_persistent) { static const char *s_sent = "# Bytes transmitted to other peers"; @@ -447,7 +512,7 @@ bandwidth_stats_iterator (void *cls, outgoing_bandwidth = outgoing_bandwidth + value; else if (0 == strncmp(s_recv, name, strlen (s_recv))) incoming_bandwidth = incoming_bandwidth + value; - + return GNUNET_OK; } @@ -463,7 +528,7 @@ summarize () INFO ("# GETS failed: %u\n", n_gets_fail); INFO ("# average_put_path_length: %f\n", average_put_path_length); INFO ("# average_get_path_length: %f\n", average_get_path_length); - + if (NULL == testbed_handles) { INFO ("No peers found\n"); @@ -472,7 +537,7 @@ summarize () /* Collect Stats*/ bandwidth_stats_op = GNUNET_TESTBED_get_statistics (n_active, testbed_handles, "dht", NULL, - bandwidth_stats_iterator, + bandwidth_stats_iterator, bandwidth_stats_cont, NULL); } @@ -489,7 +554,7 @@ cancel_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct ActiveContext *ac = cls; struct Context *ctx = ac->ctx; - ac->delay_task = GNUNET_SCHEDULER_NO_TASK; + ac->delay_task = NULL; GNUNET_assert (NULL != ac->dht_get); GNUNET_DHT_get_stop (ac->dht_get); ac->dht_get = NULL; @@ -500,8 +565,11 @@ cancel_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /* If profiling is complete, summarize */ if (n_active == n_gets_fail + n_gets_ok) + { + average_put_path_length = (double)total_put_path_length/(double)n_active; + average_get_path_length = (double)total_get_path_length/(double )n_gets_ok; summarize (); - + } } @@ -540,25 +608,26 @@ get_iter (void *cls, /* Check the keys of put and get match or not. */ GNUNET_assert (0 == memcmp (key, &get_ac->hash, sizeof (struct GNUNET_HashCode))); /* we found the data we are looking for */ - DEBUG ("We found a GET request; %u remaining\n", n_gets - (n_gets_fail + n_gets_ok)); + DEBUG ("We found a GET request; %u remaining\n", n_gets - (n_gets_fail + n_gets_ok)); //FIXME: It always prints 1. n_gets_ok++; get_ac->nrefs--; GNUNET_DHT_get_stop (ac->dht_get); ac->dht_get = NULL; - GNUNET_SCHEDULER_cancel (ac->delay_task); - ac->delay_task = GNUNET_SCHEDULER_NO_TASK; + if (ac->delay_task != NULL) + GNUNET_SCHEDULER_cancel (ac->delay_task); + ac->delay_task = NULL; GNUNET_assert (NULL != ctx->op); GNUNET_TESTBED_operation_done (ctx->op); ctx->op = NULL; - - total_put_path_length = total_put_path_length + put_path_length; - total_get_path_length = total_get_path_length + get_path_length; - + + total_put_path_length = total_put_path_length + (double)put_path_length; + total_get_path_length = total_get_path_length + (double)get_path_length; + DEBUG ("total_put_path_length = %f,put_path \n",total_put_path_length); /* Summarize if profiling is complete */ if (n_active == n_gets_fail + n_gets_ok) { average_put_path_length = (double)total_put_path_length/(double)n_active; - average_get_path_length = (double)total_get_path_length/(double )n_active; + average_get_path_length = (double)total_get_path_length/(double )n_gets_ok; summarize (); } } @@ -577,7 +646,7 @@ delayed_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct ActiveContext *get_ac; unsigned int r; - ac->delay_task = GNUNET_SCHEDULER_NO_TASK; + ac->delay_task = NULL; get_ac = NULL; while (1) { @@ -588,7 +657,7 @@ delayed_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } get_ac->nrefs++; ac->get_ac = get_ac; - DEBUG ("Doing a DHT GET for data of size %u\n", get_ac->put_data_size); + DEBUG ("GET_REQUEST_START key %s \n", GNUNET_h2s((struct GNUNET_HashCode *)ac->put_data)); ac->dht_get = GNUNET_DHT_get_start (ac->dht, GNUNET_BLOCK_TYPE_TEST, &get_ac->hash, @@ -605,10 +674,28 @@ delayed_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** - * Connect to DHT services of active peers + * Task to teardown the dht connection. We do it as a task because calling + * GNUNET_DHT_disconnect() from put_continutation_callback seems illegal (the + * put_continuation_callback() is getting called again synchronously). Also, + * only free the operation when we are not shutting down; the shutdown task will + * clear the operation during shutdown. + * + * @param cls the context + * @return tc scheduler task context. */ static void -start_profiling(); +teardown_dht_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct Context *ctx = cls; + struct GNUNET_TESTBED_Operation *op; + + if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) + return; + GNUNET_assert (NULL != ctx); + GNUNET_assert (NULL != (op = ctx->op)); + ctx->op = NULL; + GNUNET_TESTBED_operation_done (op); +} /** @@ -626,7 +713,6 @@ put_cont (void *cls, int success) { struct ActiveContext *ac = cls; struct Context *ctx = ac->ctx; - struct GNUNET_TESTBED_Operation *op; ac->dht_put = NULL; if (success) @@ -634,9 +720,7 @@ put_cont (void *cls, int success) else n_puts_fail++; GNUNET_assert (NULL != ctx); - op = ctx->op; - ctx->op = NULL; - GNUNET_TESTBED_operation_done (op); + (void) GNUNET_SCHEDULER_add_now (&teardown_dht_connection, ctx); } @@ -651,7 +735,7 @@ delayed_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ActiveContext *ac = cls; - ac->delay_task = GNUNET_SCHEDULER_NO_TASK; + ac->delay_task = NULL; /* Generate and DHT PUT some random data */ ac->put_data_size = 16; /* minimum */ ac->put_data_size += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, @@ -660,10 +744,10 @@ delayed_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ac->put_data, ac->put_data_size); GNUNET_CRYPTO_hash (ac->put_data, ac->put_data_size, &ac->hash); - DEBUG ("Doing a DHT PUT with data of size %u\n", ac->put_data_size); + DEBUG ("PUT_REQUEST_START key %s \n", GNUNET_h2s((struct GNUNET_HashCode *)ac->put_data)); ac->dht_put = GNUNET_DHT_put (ac->dht, &ac->hash, replication, - GNUNET_DHT_RO_NONE, + GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_BLOCK_TYPE_TEST, ac->put_data_size, ac->put_data, @@ -706,12 +790,25 @@ dht_connected (void *cls, switch (mode) { case MODE_PUT: - ac->delay_task = GNUNET_SCHEDULER_add_delayed (delay, &delayed_put, ac); + { + struct GNUNET_TIME_Relative peer_delay_put; + peer_delay_put.rel_value_us = + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, + delay_put.rel_value_us); + ac->delay_task = GNUNET_SCHEDULER_add_delayed (peer_delay_put, &delayed_put, ac); break; + } case MODE_GET: - ac->delay_task = GNUNET_SCHEDULER_add_delayed (delay, &delayed_get, ac); + { + struct GNUNET_TIME_Relative peer_delay_get; + peer_delay_get.rel_value_us = + delay_get.rel_value_us + + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, + delay_get.rel_value_us); + ac->delay_task = GNUNET_SCHEDULER_add_delayed (peer_delay_get, &delayed_get, ac); break; } + } } @@ -751,31 +848,44 @@ dht_disconnect (void *cls, void *op_result) n_dht--; if (0 != n_dht) return; - /* Start GETs if all PUTs have been made */ - if (MODE_PUT == mode) + if (GNUNET_YES == in_shutdown) + return; + switch (mode) { + case MODE_PUT: + if ((n_puts_ok + n_puts_fail) != n_active) + return; + /* Start GETs if all PUTs have been made */ mode = MODE_GET; + //(void) GNUNET_SCHEDULER_add_now (&call_start_profiling, NULL); start_profiling (); return; + case MODE_GET: + if ((n_gets_ok + n_gets_fail) != n_active) + return; + break; } - GNUNET_SCHEDULER_shutdown (); } - /** * Connect to DHT services of active peers */ static void start_profiling() { + struct Context *ctx; unsigned int i; + DEBUG("GNUNET_TESTBED_service_connect \n"); + GNUNET_break (GNUNET_YES != in_shutdown); for(i = 0; i < n_active; i++) { struct ActiveContext *ac = &a_ac[i]; - ac->ctx->op = - GNUNET_TESTBED_service_connect (ac->ctx, - ac->ctx->peer, + GNUNET_assert (NULL != (ctx = ac->ctx)); + GNUNET_assert (NULL == ctx->op); + ctx->op = + GNUNET_TESTBED_service_connect (ctx, + ctx->peer, "dht", &dht_connected, ac, &dht_connect, @@ -784,7 +894,156 @@ start_profiling() } } -static unsigned int tries; +#if ENABLE_MALICIOUS +/** + * Count of total number of malicious peers. + */ +static unsigned int count_malicious; + +/** + * Continuation of GNUNET_DHT_act_malicious + * @param cls Malicious context + * @param success #GNUNET_OK if the ACT_MALICIOUS was transmitted, + * #GNUNET_NO on timeout, + * #GNUNET_SYSERR on disconnect from service + * after the ACT_MALICIOUS message was transmitted + * (so we don't know if it was received or not) + */ +static void +act_malicious_cont (void *cls, int success) +{ + struct MaliciousContext *mc = cls; + struct Context *ctx = mc->ctx; + + GNUNET_TESTBED_operation_done (ctx->op); + ctx->op = NULL; + return; +} + + +/** + * Call malicious API for all the malicious peers. + * @param cls the malicious context. + * @param op the operation that has been finished + * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() + * @param emsg error message in case the operation has failed; will be NULL if + * operation has executed successfully. + */ +static void +dht_set_malicious(void *cls, + struct GNUNET_TESTBED_Operation *op, + void *ca_result, + const char *emsg) +{ + struct MaliciousContext *mc = cls; + struct Context *ctx = mc->ctx; + + GNUNET_assert (NULL != ctx); + GNUNET_assert (NULL != ctx->op); + GNUNET_assert (ctx->op == op); + mc->dht = (struct GNUNET_DHT_Handle *) ca_result; + if (NULL != emsg) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to DHT service failed: %s\n", emsg); + GNUNET_TESTBED_operation_done (ctx->op); /* Calls dht_disconnect_malicious() */ + ctx->op = NULL; + return; + } + mc->dht_malicious = GNUNET_DHT_act_malicious(mc->dht, 1, act_malicious_cont, mc); +} + + +/** + * Adapter function called to destroy a connection to + * a service. + * + * @param cls the active context + * @param op_result service handle returned from the connect adapter + */ +static void +dht_disconnect_malicious (void *cls, void *op_result) +{ + struct MaliciousContext *mc = cls; + count_malicious++; + GNUNET_assert (NULL != mc->dht); + GNUNET_assert (mc->dht == op_result); + GNUNET_DHT_disconnect (mc->dht); + mc->dht = NULL; + mc->ctx->op = NULL; + n_dht--; + + if (0 != n_dht) + return; + + if(n_malicious == count_malicious) + { + DEBUG("\n Call start_profiling()"); + start_profiling(); + } +} + + +/** + * Set the malicious variable in peer malicious context. + */ +static void +set_malicious() +{ + unsigned int i; + + DEBUG ("Setting %u peers malicious", + n_malicious); + for(i = 0; i < n_malicious; i++) + { + struct MaliciousContext *mc = &a_mc[i]; + mc->ctx->op = + GNUNET_TESTBED_service_connect (mc->ctx, + mc->ctx->peer, + "dht", + &dht_set_malicious, mc, + &dht_connect, + &dht_disconnect_malicious, + mc); + } +} + +#endif + + +/** + * Start collecting relevant statistics. If ENABLE_MALICIOUS set, first + * set the malicious peers. If not, then start with PUT operation on active + * peers. + */ +static void +start_func() +{ +#if ENABLE_MALICIOUS + set_malicious(); +#else + start_profiling(); +#endif +} + + +/** + * Remove entry from successor peer hashmap. + * @param cls closure + * @param key current public key + * @param value value in the hash map + * @return #GNUNET_YES if we should continue to iterate, + * #GNUNET_NO if not. + */ +static int +hashmap_iterate_remove(void *cls, + const struct GNUNET_HashCode *key, + void *value) +{ + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_remove(successor_peer_hashmap, key, value)); + return GNUNET_YES; +} + /** * Stats callback. Iterate over the hashmap and check if all th peers form @@ -796,78 +1055,91 @@ static unsigned int tries; * operation has executed successfully. */ static void -successor_stats_cont (void *cls, - struct GNUNET_TESTBED_Operation *op, +successor_stats_cont (void *cls, + struct GNUNET_TESTBED_Operation *op, const char *emsg) { struct GNUNET_HashCode *val; struct GNUNET_HashCode *start_val; struct GNUNET_HashCode *key; int count; - + /* Don't schedule the task till we are looking for circle here. */ - successor_stats_task = GNUNET_SCHEDULER_NO_TASK; + successor_stats_task = NULL; GNUNET_TESTBED_operation_done (successor_stats_op); successor_stats_op = NULL; - - start_val = - (struct GNUNET_HashCode *) GNUNET_CONTAINER_multihashmap_get(successor_peer_hashmap, - start_key); - val = GNUNET_new(struct GNUNET_HashCode); - key = GNUNET_new(struct GNUNET_HashCode); + if (0 == max_searches) + { + start_func(); + return; + } + + GNUNET_assert (NULL != start_key); + start_val = GNUNET_CONTAINER_multihashmap_get (successor_peer_hashmap, + start_key); + GNUNET_assert (NULL != start_val); val = start_val; for (count = 0; count < num_peers; count++) { key = val; val = GNUNET_CONTAINER_multihashmap_get (successor_peer_hashmap, key); - GNUNET_assert(NULL != val); + if (NULL == val) + break; /* Remove the entry from hashmap. This is done to take care of loop. */ - if (GNUNET_NO == - GNUNET_CONTAINER_multihashmap_remove (successor_peer_hashmap, - key, val)) + if (GNUNET_NO == + GNUNET_CONTAINER_multihashmap_remove (successor_peer_hashmap, + key, val)) { DEBUG ("Failed to remove entry from hashmap\n"); break; } /* If a peer has its own identity as its successor. */ - if (0 == memcmp(&key, &val, sizeof (struct GNUNET_HashCode))) - { + if (0 == memcmp(key, val, sizeof (struct GNUNET_HashCode))) break; - } } - + + GNUNET_assert (GNUNET_SYSERR != + GNUNET_CONTAINER_multihashmap_iterate (successor_peer_hashmap, + &hashmap_iterate_remove, + NULL)); + + successor_peer_hashmap = GNUNET_CONTAINER_multihashmap_create (num_peers, + GNUNET_NO); if ((start_val == val) && (count == num_peers)) { DEBUG("CIRCLE COMPLETED after %u tries", tries); - //FIXME: FREE HASHMAP. - if(GNUNET_SCHEDULER_NO_TASK == successor_stats_task) - start_profiling(); + if(NULL == successor_stats_task) + { + start_func(); + } return; } else { if (max_searches == ++tries) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Maximum tries %u exceeded while checking successor TOTAL TRIES %u" - " cirle formation. Exiting\n", + " circle formation. Exiting\n", max_searches,tries); - //FIXME: FREE HASHMAP - if (GNUNET_SCHEDULER_NO_TASK != successor_stats_task) + if (NULL != successor_stats_task) { - successor_stats_task = GNUNET_SCHEDULER_NO_TASK; + successor_stats_task = NULL; } - if(GNUNET_SCHEDULER_NO_TASK == successor_stats_task) + if(NULL == successor_stats_task) { - start_profiling(); + start_func(); } - + return; } - - flag = 0; - successor_stats_task = GNUNET_SCHEDULER_add_delayed (delay, &collect_stats, cls); + else + { + flag = 0; + successor_stats_task = GNUNET_SCHEDULER_add_delayed (delay_stats, + &collect_stats, cls); + } } } @@ -884,14 +1156,17 @@ successor_stats_cont (void *cls, * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int -successor_stats_iterator (void *cls, +successor_stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, - const char *subsystem, + const char *subsystem, const char *name, - uint64_t value, + uint64_t value, int is_persistent) { static const char *key_string = "XDHT"; + if (0 == max_searches) + return GNUNET_OK; + if (0 == strncmp (key_string, name, strlen (key_string))) { char *my_id_str; @@ -900,10 +1175,10 @@ successor_stats_iterator (void *cls, char truncated_successor_str[13]; struct GNUNET_HashCode *my_id_key; struct GNUNET_HashCode *succ_key; - + strtok((char *)name,":"); my_id_str = strtok(NULL,":"); - + strncpy(truncated_my_id_str, my_id_str, 12); truncated_my_id_str[12] = '\0'; my_id_key = GNUNET_new(struct GNUNET_HashCode); @@ -911,28 +1186,29 @@ successor_stats_iterator (void *cls, GNUNET_STRINGS_data_to_string(&value, sizeof(uint64_t), successor_str, 13); strncpy(truncated_successor_str, successor_str, 12); truncated_successor_str[12] ='\0'; - + succ_key = GNUNET_new(struct GNUNET_HashCode); GNUNET_CRYPTO_hash (truncated_successor_str, sizeof(truncated_successor_str),succ_key); - + if (0 == flag) { + GNUNET_assert(NULL != my_id_key); start_key = my_id_key; + GNUNET_assert(NULL != start_key); flag = 1; } - /* FIXME: GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE do not free the value - which is replaced, need to free it. */ GNUNET_CONTAINER_multihashmap_put (successor_peer_hashmap, my_id_key, (void *)succ_key, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); } + return GNUNET_OK; } -/* - * Task that collects peer and its corresponding successors. - * +/* + * Task that collects peer and its corresponding successors. + * * @param cls Closure (NULL). * @param tc Task Context. */ @@ -944,39 +1220,20 @@ collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start collecting statistics...\n"); GNUNET_assert(NULL != testbed_handles); - successor_stats_op = + + if (0 != max_searches) + successor_peer_hashmap = GNUNET_CONTAINER_multihashmap_create (num_peers, + GNUNET_NO); + successor_stats_op = GNUNET_TESTBED_get_statistics (num_peers, testbed_handles, "dht", NULL, - successor_stats_iterator, + successor_stats_iterator, successor_stats_cont, cls); - + GNUNET_assert(NULL != successor_stats_op); } -#if ENABLE_MALICIOUS -/** - * Set the malicious variable in peer malicious context. - */ -static void -set_malicious() -{ - unsigned int i; - DEBUG ("Setting %u peers malicious"); - for(i = 0; i < n_malicious; i++) - { - struct MaliciousContext *mc = &a_mc[i]; - mc->ctx->op = - GNUNET_TESTBED_service_connect (ac->ctx, - ac->ctx->peer, - "dht", - &dht_set_malicious, mc, - &dht_connect, - &dht_finish, - mc); - } -} -#endif /** * Callback called when DHT service on the peer is started * @@ -995,20 +1252,17 @@ service_started (void *cls, GNUNET_assert (NULL != ctx); GNUNET_assert (NULL != ctx->op); GNUNET_TESTBED_operation_done (ctx->op); + ctx->op = NULL; peers_started++; DEBUG("Peers Started = %d; num_peers = %d \n", peers_started, num_peers); - if (GNUNET_SCHEDULER_NO_TASK == successor_stats_task && peers_started == num_peers) + if (NULL == successor_stats_task && peers_started == num_peers) { -#if ENABLE_MALICIOUS - set_malicious(); -#endif DEBUG("successor_stats_task \n"); struct Collect_Stat_Context *collect_stat_cls = GNUNET_new(struct Collect_Stat_Context); collect_stat_cls->service_connect_ctx = cls; collect_stat_cls->op = op; - successor_peer_hashmap = GNUNET_CONTAINER_multihashmap_create (num_peers, - GNUNET_NO); - successor_stats_task = GNUNET_SCHEDULER_add_delayed (delay, + + successor_stats_task = GNUNET_SCHEDULER_add_delayed (delay_stats, &collect_stats, collect_stat_cls); } @@ -1035,8 +1289,7 @@ test_run (void *cls, { unsigned int cnt; unsigned int ac_cnt; - - testbed_handles = peers; + testbed_handles = peers; if (NULL == peers) { /* exit */ @@ -1053,39 +1306,58 @@ test_run (void *cls, GNUNET_free (a_ctx); return; } - -#if ENABLE_MALICIOUS - if(PUT_PROBABILITY + MALICIOUS_PEERS > 100) + a_ac = GNUNET_malloc (n_active * sizeof (struct ActiveContext)); + ac_cnt = 0; + +#if ENABLE_MALICIOUS + unsigned int malicious_peers; + if(PUT_PROBABILITY + MALICIOUS_PROBABILITY > 100) { DEBUG ("Reduce either number of malicious peer or active peers. "); GNUNET_SCHEDULER_shutdown (); GNUNET_free (a_ctx); return; } - + /* Select the peers which should act maliciously. */ - n_malicious = num_peers * MALICIOUS_PEERS / 100; - - /* Select n_malicious peers and ensure that those are not active peers. - keep all malicious peer at one place, and call act malicious for all - those peers. */ - + n_malicious = num_peers * MALICIOUS_PROBABILITY / 100; + + a_mc = GNUNET_malloc (n_malicious * sizeof (struct MaliciousContext)); + malicious_peers = 0; + + for (cnt = 0; cnt < num_peers && malicious_peers < n_malicious; cnt++) + { + if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100) >= + MALICIOUS_PROBABILITY) + continue; + a_ctx[cnt].mc = &a_mc[malicious_peers]; + a_mc[malicious_peers].ctx = &a_ctx[cnt]; + malicious_peers++; + } + n_malicious = malicious_peers; + INFO ("Malicious Peers: %u\n",malicious_peers); + #endif - + a_ac = GNUNET_malloc (n_active * sizeof (struct ActiveContext)); ac_cnt = 0; for (cnt = 0; cnt < num_peers && ac_cnt < n_active; cnt++) { - if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100) >= - PUT_PROBABILITY) + if ((GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100) >= + PUT_PROBABILITY)) + continue; + +#if ENABLE_MALICIOUS + if(a_ctx[ac_cnt].mc != NULL) continue; +#endif + a_ctx[cnt].ac = &a_ac[ac_cnt]; a_ac[ac_cnt].ctx = &a_ctx[cnt]; ac_cnt++; } n_active = ac_cnt; - a_ac = GNUNET_realloc (a_ac, n_active * sizeof (struct ActiveContext)); INFO ("Active peers: %u\n", n_active); /* start DHT service on all peers */ @@ -1146,19 +1418,25 @@ main (int argc, char *const *argv) gettext_noop ("number of peers to start"), 1, &GNUNET_GETOPT_set_uint, &num_peers}, {'s', "searches", "COUNT", - gettext_noop ("maximum number of times we try to search for successor circle formation (default is 1)"), + gettext_noop ("maximum number of times we try to search for successor circle formation (0 for R5N)"), 1, &GNUNET_GETOPT_set_uint, &max_searches}, {'H', "hosts", "FILENAME", gettext_noop ("name of the file with the login information for the testbed"), 1, &GNUNET_GETOPT_set_string, &hosts_file}, - {'d', "delay", "DELAY", - gettext_noop ("delay for starting DHT PUT and GET"), - 1, &GNUNET_GETOPT_set_relative_time, &delay}, + {'D', "delay", "DELAY", + gettext_noop ("delay between rounds for collecting statistics (default: 30 sec)"), + 1, &GNUNET_GETOPT_set_relative_time, &delay_stats}, + {'P', "PUT-delay", "DELAY", + gettext_noop ("delay to start doing PUTs (default: 1 sec)"), + 1, &GNUNET_GETOPT_set_relative_time, &delay_put}, + {'G', "GET-delay", "DELAY", + gettext_noop ("delay to start doing GETs (default: 5 min)"), + 1, &GNUNET_GETOPT_set_relative_time, &delay_get}, {'r', "replication", "DEGREE", gettext_noop ("replication degree for DHT PUTs"), 1, &GNUNET_GETOPT_set_uint, &replication}, {'t', "timeout", "TIMEOUT", - gettext_noop ("timeout for DHT PUT and GET requests"), + gettext_noop ("timeout for DHT PUT and GET requests (default: 1 min)"), 1, &GNUNET_GETOPT_set_relative_time, &timeout}, GNUNET_GETOPT_OPTION_END }; @@ -1166,8 +1444,11 @@ main (int argc, char *const *argv) max_searches = 5; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; - delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20); /* default delay */ - timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1); /* default timeout */ + /* set default delays */ + delay_stats = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); + delay_put = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); + delay_get = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); + timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); replication = 1; /* default replication */ rc = 0; if (GNUNET_OK !=