From f2678662372b0a43a6045ce2edb6cfe8f600a370 Mon Sep 17 00:00:00 2001 From: Supriti Singh Date: Mon, 25 Aug 2014 19:25:27 +0000 Subject: [PATCH] - Adding r5n profiler. - Changes in makefile for r5n profiler - Correctly adding the trail in add_trail - Passing correct trail id in PUT message routing lookup --- src/dht/Makefile.am | 13 +- src/dht/gnunet-service-xdht_neighbours.c | 71 +++++---- src/dht/gnunet_dht_profiler.c | 2 +- src/dht/gnunet_dht_r5n_profiler.c | 174 +++++++++++++++++++---- 4 files changed, 190 insertions(+), 70 deletions(-) diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am index f8918616f..b9e7c5d67 100644 --- a/src/dht/Makefile.am +++ b/src/dht/Makefile.am @@ -56,7 +56,8 @@ noinst_PROGRAMS = \ gnunet-dht-monitor \ gnunet-dht-get \ gnunet-dht-put \ - gnunet-dht-profiler + gnunet-dht-profiler\ + gnunet-dht-r5n-profiler gnunet_service_dht_SOURCES = \ gnunet-service-dht.c gnunet-service-dht.h \ @@ -139,6 +140,16 @@ gnunet_dht_profiler_LDADD = \ gnunet_dht_profiler_DEPENDENCIES = \ libgnunetdht.la +gnunet_dht_r5n_profiler_SOURCES = \ + gnunet_dht_r5n_profiler.c +gnunet_dht_r5n_profiler_LDADD = \ + $(top_builddir)/src/dht/libgnunetdht.la \ + $(top_builddir)/src/core/libgnunetcore.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testbed/libgnunettestbed.la +gnunet_dht_r5n_profiler_DEPENDENCIES = \ + libgnunetdht.la + if HAVE_TESTING noinst_LIBRARIES = libgnunetdhttest.a endif diff --git a/src/dht/gnunet-service-xdht_neighbours.c b/src/dht/gnunet-service-xdht_neighbours.c index dde456037..3d17a07fa 100644 --- a/src/dht/gnunet-service-xdht_neighbours.c +++ b/src/dht/gnunet-service-xdht_neighbours.c @@ -845,6 +845,16 @@ struct Closest_Peer unsigned int finger_table_index; }; +/** + * Context for send_verify_successor_task. + */ +struct VerifySuccessorContext +{ + /** + * Number of times this has been scheduled. + */ + unsigned int num_retries_scheduled; +}; /** * Task that sends FIND FINGER TRAIL requests. This task is started when we have @@ -3160,10 +3170,6 @@ add_new_finger (struct GNUNET_PeerIdentity finger_identity, return; } -struct VerifySuccessorContext -{ - unsigned int num_retries_scheduled; -}; /** * Periodic task to verify current successor. There can be multiple trails to reach @@ -3174,7 +3180,7 @@ struct VerifySuccessorContext */ static void send_verify_successor_message (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) + const struct GNUNET_SCHEDULER_TaskContext *tc) { struct FriendInfo *target_friend; struct GNUNET_HashCode trail_id; @@ -3184,6 +3190,8 @@ send_verify_successor_message (void *cls, unsigned int i = 0; struct FingerInfo *successor; + successor = &finger_table[0]; + /* This task will be scheduled when the result for Verify Successor is received. */ send_verify_successor_task = GNUNET_SCHEDULER_NO_TASK; @@ -3194,13 +3202,29 @@ send_verify_successor_message (void *cls, */ if (NULL == cls) { + /* FIXME: Here we are scheduling a new verify successor task, as we + got a new successor. But a send verify successor task may be in progress. + 1. We need to be sure that this is indeed a new successor. As this function + is called even if we add a new trail to reach t old successor. + 2. Assuming the new successor is different, then verify successor message + * to old successor may be following stages. + * --> Waiting for verify successor result. Don't wait anymore. there is + * no trail to reach from old successor to me, hence, routing + * lookup will fail. + * --> Waiting for notify confirmation. again don't wait for it. notify + * confirmation will not succeded. + */ if (send_verify_successor_retry_task != GNUNET_SCHEDULER_NO_TASK) { + /* FIXME: Are we scheduling retry task as soon as we send verify message. + If yes then here before making this task, first check if the message + is for the same peer again. */ struct VerifySuccessorContext *old_ctx = GNUNET_SCHEDULER_cancel(send_verify_successor_retry_task); /* old_ctx must not be NULL, as the retry task had been scheduled */ GNUNET_assert(NULL != old_ctx); GNUNET_free(old_ctx); + /* FIXME: Why don't we reset the task to NO_TASK here? */ } struct VerifySuccessorContext *ctx; @@ -3225,14 +3249,6 @@ send_verify_successor_message (void *cls, ctx); } - successor = &finger_table[0]; - /* We are waiting for a confirmation from the notify message and we have not - * crossed the wait time, then return. */ -// if ((1 == waiting_for_notify_confirmation) -// && (0 != GNUNET_TIME_absolute_get_remaining(successor->wait_notify_confirmation).rel_value_us)) -// { -// return; -// } /* Among all the trails to reach to successor, select first one which is present.*/ for (i = 0; i < successor->trails_count; i++) { @@ -3737,14 +3753,12 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_best_known_dest, &my_identity))) { - next_routing_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id, + next_routing_hop = GDS_ROUTING_get_next_hop (received_intermediate_trail_id, GDS_ROUTING_SRC_TO_DEST); if (NULL != next_routing_hop) { next_hop = next_routing_hop; intermediate_trail_id = received_intermediate_trail_id; - FPRINTF (stderr,_("\nSUPU %s, %s, %d,intermediate_trail_id=%s"),__FILE__, __func__,__LINE__,GNUNET_h2s(&intermediate_trail_id)); - best_known_dest = current_best_known_dest; } } @@ -3881,7 +3895,7 @@ handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, if (0 != (GNUNET_CRYPTO_cmp_peer_identity (¤t_best_known_dest, &my_identity))) { next_routing_hop = GDS_ROUTING_get_next_hop (received_intermediate_trail_id, - GDS_ROUTING_SRC_TO_DEST); + GDS_ROUTING_SRC_TO_DEST); if (NULL != next_routing_hop) { next_hop = next_routing_hop; @@ -5333,22 +5347,8 @@ handle_dht_p2p_notify_new_successor(void *cls, next_hop = new_successor; else next_hop = trail[my_index + 1]; - /* Add an entry in routing table for trail from source to its new successor. */ - /* TODO : Verify the logic below - * Removed th following error check because GNUNET_SYSERR is returned when - * route with trail_id was already in the routing table. This can happen, when - * notify_successor was being retried. This should not be an error, and should - * be ignored. - */ - GDS_ROUTING_add(trail_id, *peer, next_hop); -// if (GNUNET_SYSERR == GDS_ROUTING_add (trail_id, *peer, next_hop)) -// { -// -// GNUNET_break(0); -// return GNUNET_OK; -// -// } + GDS_ROUTING_add(trail_id, *peer, next_hop); target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop); if (NULL == target_friend) @@ -5731,10 +5731,6 @@ handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer, source_peer = add_trail->source_peer; trail_id = add_trail->trail_id; - //FIXME: add a check that sender peer is not malicious. Make it a generic - // function so that it can be used in all other functions where we need the - // same functionality. - /* I am not the destination of the trail. */ if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &destination_peer)) { @@ -5762,7 +5758,8 @@ handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer, next_hop = trail[my_index + 1]; } /* Add in your routing table. */ - GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, next_hop, *peer)); + GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, *peer, next_hop)); + //GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, next_hop, *peer)); GNUNET_assert (NULL != (target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop))); diff --git a/src/dht/gnunet_dht_profiler.c b/src/dht/gnunet_dht_profiler.c index 0dca21f2c..2e1447d35 100644 --- a/src/dht/gnunet_dht_profiler.c +++ b/src/dht/gnunet_dht_profiler.c @@ -577,7 +577,7 @@ get_iter (void *cls, 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 (); } } diff --git a/src/dht/gnunet_dht_r5n_profiler.c b/src/dht/gnunet_dht_r5n_profiler.c index 9921c0aed..95528b3f9 100644 --- a/src/dht/gnunet_dht_r5n_profiler.c +++ b/src/dht/gnunet_dht_r5n_profiler.c @@ -21,7 +21,7 @@ /** * @file dht/gnunet_dht_profiler.c * @brief Profiler for GNUnet DHT - * @author Sree Harsha Totakura + * @author Sree Harsha Totakura */ #include "platform.h" @@ -38,7 +38,7 @@ /** * Number of peers which should perform a PUT out of 100 peers */ -#define PUT_PROBABILITY 50 +#define PUT_PROBABILITY 100 /** * Configuration @@ -114,7 +114,7 @@ struct ActiveContext struct GNUNET_DHT_GetHandle *dht_get; /** - * The hash of the @put_data + * The hash of the @e put_data */ struct GNUNET_HashCode hash; @@ -124,7 +124,7 @@ struct ActiveContext GNUNET_SCHEDULER_TaskIdentifier delay_task; /** - * The size of the put_data + * The size of the @e put_data */ uint16_t put_data_size; @@ -200,7 +200,44 @@ static unsigned int n_gets_ok; */ static unsigned int n_gets_fail; +/** + * Replication degree + */ +static unsigned int replication; + +/** + * Testbed Operation (to get stats). + */ +static struct GNUNET_TESTBED_Operation *stats_op; + +/** + * Testbed peer handles. + */ +static struct GNUNET_TESTBED_Peer **testbed_handles; + +/** + * Total number of messages sent by peer. + */ +static uint64_t outgoing_bandwidth; + +/** + * Total number of messages received by peer. + */ +static uint64_t incoming_bandwidth; + +/** + * Average number of hops taken to do put. + */ +static unsigned int average_put_path_length; +/** + * Average number of hops taken to do get. + */ +static unsigned int average_get_path_length; + +static unsigned int total_put_path_length; + +static unsigned int total_get_path_length; /** * Shutdown task. Cleanup all resources and operations. * @@ -212,14 +249,14 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ActiveContext *ac; unsigned int cnt; - + 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); - + /* Cleanup active context if this peer is an active peer */ ac = a_ctx[cnt].ac; if (NULL == ac) @@ -236,10 +273,68 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_free (a_ctx); a_ctx = NULL; } + if(NULL != stats_op) + GNUNET_TESTBED_operation_done (stats_op); + stats_op = NULL; GNUNET_free_non_null (a_ac); } +/** + * Stats callback. Finish the stats testbed operation and when all stats have + * been iterated, shutdown the test. + * + * @param cls closure + * @param op the operation that has been finished + * @param emsg error message in case the operation has failed; will be NULL if + * operation has executed successfully. + */ +static void +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 (); +} + + +/** + * Process statistic values. + * + * @param cls closure + * @param peer the peer the statistic belong to + * @param subsystem name of subsystem that created the statistic + * @param name the name of the datum + * @param value the current value + * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not + * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration + */ +static int +bandwidth_stats_iterator (void *cls, + const struct GNUNET_TESTBED_Peer *peer, + const char *subsystem, + const char *name, + uint64_t value, + int is_persistent) +{ + static const char *s_sent = "# Bytes transmitted to other peers"; + static const char *s_recv = "# Bytes received from other peers"; + + if (0 == strncmp (s_sent, name, strlen (s_sent))) + outgoing_bandwidth = outgoing_bandwidth + value; + else if (0 == strncmp(s_recv, name, strlen (s_recv))) + incoming_bandwidth = incoming_bandwidth + value; + else + return GNUNET_OK; + DEBUG ("Bandwith - Out: %lu; In: %lu\n", + (unsigned long) outgoing_bandwidth, + (unsigned long) incoming_bandwidth); + return GNUNET_OK; +} + + static void summarize () { @@ -249,7 +344,19 @@ summarize () INFO ("# GETS made: %u\n", n_gets); INFO ("# GETS succeeded: %u\n", n_gets_ok); INFO ("# GETS failed: %u\n", n_gets_fail); - GNUNET_SCHEDULER_shutdown (); + INFO ("# average_put_path_length: %u\n", average_put_path_length); + INFO ("# average_get_path_length: %u\n", average_get_path_length); + + if (NULL == testbed_handles) + { + INFO ("No peers found\n"); + return; + } + /* Collect Stats*/ + stats_op = GNUNET_TESTBED_get_statistics (n_active, testbed_handles, + "dht", NULL, + bandwidth_stats_iterator, + bandwidth_stats_cont, NULL); } @@ -271,8 +378,9 @@ cancel_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) n_gets_fail++; /* If profiling is complete, summarize */ - if (n_gets == n_gets_fail + n_gets_ok) + if (n_active == n_gets_fail + n_gets_ok) summarize (); + } @@ -293,7 +401,7 @@ cancel_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @param size number of bytes in @a data * @param data pointer to the result data */ -static void +static void get_iter (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, @@ -306,18 +414,9 @@ get_iter (void *cls, { struct ActiveContext *ac = cls; struct ActiveContext *get_ac = ac->get_ac; - - if (get_ac->put_data_size != size) - { - DEBUG ("Found a GET with incorrect data length (this may happen, but very unlikely)\n"); - return; - } - if (0 != memcmp (data, get_ac->put_data, size)) - { - DEBUG ("Found a GET with incorrect data (this may happen, but very unlikely)\n"); - return; - } + /* 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)); n_gets_ok++; @@ -326,10 +425,17 @@ get_iter (void *cls, ac->dht_get = NULL; GNUNET_SCHEDULER_cancel (ac->delay_task); ac->delay_task = GNUNET_SCHEDULER_NO_TASK; - + + total_put_path_length = total_put_path_length + put_path_length; + total_get_path_length = total_get_path_length + get_path_length; + /* Summarize if profiling is complete */ - if (n_gets == n_gets_fail + n_gets_ok) + if (n_active == n_gets_fail + n_gets_ok) + { + average_put_path_length = total_put_path_length/n_active; + average_get_path_length = total_get_path_length/n_active; summarize (); + } } @@ -357,9 +463,10 @@ 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); ac->dht_get = GNUNET_DHT_get_start (ac->dht, GNUNET_BLOCK_TYPE_TEST, - &ac->hash, + &get_ac->hash, 1, /* replication level */ GNUNET_DHT_RO_NONE, NULL, 0, /* extended query and size */ @@ -413,12 +520,12 @@ delayed_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) ac->put_data_size += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, (63*1024)); ac->put_data = GNUNET_malloc (ac->put_data_size); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, + 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); ac->dht_put = GNUNET_DHT_put (ac->dht, &ac->hash, - 1, /* replication level */ + replication, GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_TEST, ac->put_data_size, @@ -487,7 +594,7 @@ dht_connect (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) * @param cls the active context * @param op_result service handle returned from the connect adapter */ -static void +static void dht_disconnect (void *cls, void *op_result) { struct ActiveContext *ac = cls; @@ -552,7 +659,8 @@ test_run (void *cls, { unsigned int cnt; unsigned int ac_cnt; - + + testbed_handles = peers; if (NULL == peers) { /* exit */ @@ -560,7 +668,7 @@ test_run (void *cls, } INFO ("%u peers started\n", num_peers); a_ctx = GNUNET_malloc (sizeof (struct Context) * num_peers); - + /* select the peers which actively participate in profiling */ n_active = num_peers * PUT_PROBABILITY / 100; if (0 == n_active) @@ -611,7 +719,7 @@ run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { uint64_t event_mask; - + if (0 == num_peers) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Exiting as the number of peers is %u\n"), @@ -647,6 +755,9 @@ main (int argc, char *const *argv) {'d', "delay", "DELAY", gettext_noop ("delay for starting DHT PUT and GET"), 1, &GNUNET_GETOPT_set_relative_time, &delay}, + {'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"), 1, &GNUNET_GETOPT_set_relative_time, &timeout}, @@ -655,8 +766,9 @@ main (int argc, char *const *argv) if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; - delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3); /* default delay */ - timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3); /* default timeout */ + delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30); /* default delay */ + timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1); /* default timeout */ + replication = 1; /* default replication */ rc = 0; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "dht-profiler", -- 2.25.1