From 572e6cfded2bece750dc1a0e35432112e89f4467 Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Fri, 9 Sep 2011 15:06:53 +0000 Subject: [PATCH] fix in address update + testcase --- src/ats/Makefile.am | 10 +- src/ats/ats_api.c | 22 +- src/ats/test_ats_api_update_address.c | 298 ++++++++++++++++++++++++++ 3 files changed, 313 insertions(+), 17 deletions(-) create mode 100644 src/ats/test_ats_api_update_address.c diff --git a/src/ats/Makefile.am b/src/ats/Makefile.am index 652cc7462..d44f59e6f 100644 --- a/src/ats/Makefile.am +++ b/src/ats/Makefile.am @@ -28,7 +28,8 @@ libgnunetats_la_LIBADD = \ check_PROGRAMS = \ - test_ats_api + test_ats_api \ + test_ats_api_update_address if ENABLE_TEST_RUN TESTS = $(check_PROGRAMS) @@ -40,5 +41,8 @@ test_ats_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats/libgnunetats.la - - +test_ats_api_update_address_SOURCES = \ + test_ats_api_update_address.c +test_ats_api_update_address_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/ats/libgnunetats.la diff --git a/src/ats/ats_api.c b/src/ats/ats_api.c index e6013a84c..a411d4dcb 100644 --- a/src/ats/ats_api.c +++ b/src/ats/ats_api.c @@ -343,13 +343,6 @@ GNUNET_ATS_suggest_address (struct GNUNET_ATS_Handle *atc, GNUNET_CONTAINER_multihashmap_get_multiple (atc->peers, &peer->hashPubKey, &suggest_address, asc); -#if DEBUG_ATS - GNUNET_CONTAINER_multihashmap_iterate (atc->peers, &map_it, (void *) peer); - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-api", - "Addresses %u (of %i) processed, \n", count, - GNUNET_CONTAINER_multihashmap_size (atc->peers)); -#endif - if (NULL == asc->cb) { GNUNET_free (asc); @@ -531,7 +524,7 @@ update_session (void *cls, const GNUNET_HashCode * key, void *value) { #if DEBUG_ATS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Found type %u, old value=%u new value=%u\n", + "Found type %i, old value=%i new value=%i\n", ntohl (arold->ats[c_old].type), ntohl (arold->ats[c_old].value), ntohl (arnew->ats[c_new].value)); @@ -545,18 +538,18 @@ update_session (void *cls, const GNUNET_HashCode * key, void *value) if (found == GNUNET_NO) { #if DEBUG_ATS - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Added new value type %u, old value=%u new value=%u\n", + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added new type %i new value=%i\n", ntohl (arnew->ats[c_new].type), ntohl (arnew->ats[c_new].value)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Old array size: %u\n", arold->ats_count); #endif GNUNET_array_grow (arold->ats, arold->ats_count, arold->ats_count + 1); - arold->ats[arold->ats_count - 1].type = arnew->ats[c_new].type; - arold->ats[arold->ats_count - 1].value = arnew->ats[c_new].value; - arold->ats[arold->ats_count].type = htonl (0); - arold->ats[arold->ats_count].value = htonl (0); + GNUNET_assert (arold->ats_count >= 2); + arold->ats[arold->ats_count - 2].type = arnew->ats[c_new].type; + arold->ats[arold->ats_count - 2].value = arnew->ats[c_new].value; + arold->ats[arold->ats_count - 1].type = htonl (0); + arold->ats[arold->ats_count - 1].value = htonl (0); #if DEBUG_ATS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New array size: %i\n", arold->ats_count); @@ -780,6 +773,7 @@ notify_valid (void *cls, const GNUNET_HashCode * key, void *value) GNUNET_BANDWIDTH_value_init (asc->atc->total_bps / 32), ar->ats, ar->ats_count); GNUNET_ATS_suggest_address_cancel (asc); + asc = NULL; return GNUNET_OK; } diff --git a/src/ats/test_ats_api_update_address.c b/src/ats/test_ats_api_update_address.c new file mode 100644 index 000000000..1c6351fcd --- /dev/null +++ b/src/ats/test_ats_api_update_address.c @@ -0,0 +1,298 @@ +/* + This file is part of GNUnet. + (C) 2010,2011 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 + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + 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. +*/ +/** + * @file ats/ats_api.c + * @brief automatic transport selection API + * @author Christian Grothoff + * @author Matthias Wachs + * + * TODO: + * - write test case + * - extend API to get performance data + * - implement simplistic strategy based on say 'lowest latency' or strict ordering + * - extend API to get peer preferences, implement proportional bandwidth assignment + * - re-implement API against a real ATS service (!) + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_transport_service.h" + +#define VERBOSE GNUNET_NO + +#define VERBOSE_ARM GNUNET_NO + +#define START_ARM GNUNET_YES + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) + +#define VALID GNUNET_TIME_absolute_get_forever () + +static struct GNUNET_ATS_Handle *ats; + +static struct GNUNET_ATS_SuggestionContext *asc; + +static struct GNUNET_PeerIdentity peer; + +static GNUNET_SCHEDULER_TaskIdentifier end_task; + +static struct AllocationRecord *ar; + +static int result; + +struct ExpectedValues +{ + int expected_ats_count; + + int expected_ats_type; + + int expected_ats_value; + + int expected_in_index; +}; + +struct AllocationRecord +{ + + /** + * Performance information associated with this address (array). + */ + struct GNUNET_TRANSPORT_ATS_Information *ats; + + /** + * Name of the plugin + */ + char *plugin_name; + + /** + * Address this record represents, allocated at the end of this struct. + */ + const void *plugin_addr; + + /** + * Session associated with this record. + */ + struct Session *session; + + /** + * Number of bytes in plugin_addr. + */ + size_t plugin_addr_len; + + /** + * Number of entries in 'ats'. + */ + uint32_t ats_count; +}; + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown\n"); + if (asc != NULL) + { + GNUNET_ATS_suggest_address_cancel (asc); + asc = NULL; + } + GNUNET_ATS_shutdown (ats); + + GNUNET_array_grow (ar->ats, ar->ats_count, 0); + GNUNET_free (ar); +} + +void +suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, + const char *plugin_name, const void *plugin_addr, + size_t plugin_addr_len, struct Session *session, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth, + const struct GNUNET_TRANSPORT_ATS_Information *ats, + uint32_t ats_count) +{ + struct ExpectedValues *ex = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "ATS suggested address for peer `%s': `%s' `%s'\n", + GNUNET_i2s (peer), plugin_name, plugin_addr); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS count %u\n", ats_count); + + int c = 0; + + while (c < ats_count) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ats[%u]: type %u value %u\n", c, + ntohl (ats[c].type), ntohl (ats[c].value)); + + c++; + } + + if (ex->expected_ats_count != GNUNET_SYSERR) + GNUNET_assert (ex->expected_ats_count == ats_count); + + if ((ex->expected_ats_value != GNUNET_SYSERR) && + (ex->expected_in_index != GNUNET_SYSERR)) + GNUNET_assert (ex->expected_ats_value == + ntohl (ats[ex->expected_in_index].value)); + + if ((ex->expected_ats_type != GNUNET_SYSERR) && + (ex->expected_in_index != GNUNET_SYSERR)) + GNUNET_assert (ex->expected_ats_type == + ntohl (ats[ex->expected_in_index].type)); + + +} + +static void +check (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct ExpectedValues ex; + + GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, + &peer.hashPubKey); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Created peer identity `%s'\n", + GNUNET_i2s (&peer)); + + ats = GNUNET_ATS_init (cfg, NULL, NULL); + GNUNET_assert (ats != NULL); + + end_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end, NULL); + + ar = GNUNET_malloc (sizeof (struct AllocationRecord)); + + ar->plugin_name = "test"; + ar->session = NULL; + ar->plugin_addr = "address1"; + ar->plugin_addr_len = strlen (ar->plugin_addr) + 1; + ar->ats = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_ATS_Information)); + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Initial ATS information\n"); + ar->ats_count = 1; + ar->ats[0].type = htonl (0); + ar->ats[0].value = htonl (0); + + ex.expected_ats_count = 1; + ex.expected_ats_type = 0; + ex.expected_ats_value = 0; + ex.expected_in_index = 0; + + GNUNET_ATS_address_update (ats, &peer, VALID, ar->plugin_name, ar->session, + ar->plugin_addr, ar->plugin_addr_len, ar->ats, + ar->ats_count); + asc = GNUNET_ATS_suggest_address (ats, &peer, &suggest_cb, &ex); + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Extending empty ATS information\n"); + + GNUNET_array_grow (ar->ats, ar->ats_count, ar->ats_count + 1); + ar->ats[0].type = htonl (1); + ar->ats[0].value = htonl (1); + ar->ats[1].type = htonl (0); + ar->ats[1].value = htonl (0); + + ex.expected_ats_count = 2; + ex.expected_ats_type = 1; + ex.expected_ats_value = 1; + ex.expected_in_index = 0; + + GNUNET_ATS_address_update (ats, &peer, VALID, ar->plugin_name, ar->session, + ar->plugin_addr, ar->plugin_addr_len, ar->ats, + ar->ats_count); + asc = GNUNET_ATS_suggest_address (ats, &peer, &suggest_cb, &ex); + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updating existing ATS information\n"); + + ar->ats[0].type = htonl (1); + ar->ats[0].value = htonl (2); + ar->ats[1].type = htonl (0); + ar->ats[1].value = htonl (0); + + ex.expected_ats_count = 2; + ex.expected_ats_type = 1; + ex.expected_ats_value = 2; + ex.expected_in_index = 0; + + GNUNET_ATS_address_update (ats, &peer, VALID, ar->plugin_name, ar->session, + ar->plugin_addr, ar->plugin_addr_len, ar->ats, + ar->ats_count); + asc = GNUNET_ATS_suggest_address (ats, &peer, &suggest_cb, &ex); + + /* Extending existing ATS information */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Extending existing ATS information\n"); + + + ar->ats[0].type = htonl (2); + ar->ats[0].value = htonl (2); + ar->ats[1].type = htonl (0); + ar->ats[1].value = htonl (0); + + ex.expected_ats_count = 3; + ex.expected_ats_type = 2; + ex.expected_ats_value = 2; + ex.expected_in_index = 1; + + GNUNET_ATS_address_update (ats, &peer, VALID, ar->plugin_name, ar->session, + ar->plugin_addr, ar->plugin_addr_len, ar->ats, + ar->ats_count); + asc = GNUNET_ATS_suggest_address (ats, &peer, &suggest_cb, &ex); + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updating existing ATS information\n"); + + ar->ats[0].type = htonl (2); + ar->ats[0].value = htonl (3); + ar->ats[1].type = htonl (0); + ar->ats[1].value = htonl (0); + + ex.expected_ats_count = 3; + ex.expected_ats_type = 2; + ex.expected_ats_value = 3; + ex.expected_in_index = 1; + + GNUNET_ATS_address_update (ats, &peer, VALID, ar->plugin_name, ar->session, + ar->plugin_addr, ar->plugin_addr_len, ar->ats, + ar->ats_count); + asc = GNUNET_ATS_suggest_address (ats, &peer, &suggest_cb, &ex); + + if (end_task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_SCHEDULER_cancel (end_task); + end_task = GNUNET_SCHEDULER_add_now (&end, NULL); +} + +int +main (int argc, char *argv1[]) +{ + static char *const argv[] = { "test_ats_api_update_address", + "-c", + "test_ats_api.conf", +#if VERBOSE + "-L", "DEBUG", +#else + "-L", "WARNING", +#endif + NULL + }; + + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, + "test_ats_api_update_address", "nohelp", options, &check, + NULL); + + return result; +} -- 2.25.1