From: Matthias Wachs Date: Thu, 13 Dec 2012 13:46:49 +0000 (+0000) Subject: simplistic solver supports moving addresses between networks, test renamed X-Git-Tag: initial-import-from-subversion-38251~10439 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=00284d606dcff37fa25dba8780a78f54a03ca497;p=oweals%2Fgnunet.git simplistic solver supports moving addresses between networks, test renamed --- diff --git a/src/ats/Makefile.am b/src/ats/Makefile.am index cd434380a..7121f24e1 100644 --- a/src/ats/Makefile.am +++ b/src/ats/Makefile.am @@ -63,12 +63,12 @@ check_PROGRAMS = \ test_ats_api_scheduling_add_address \ test_ats_api_scheduling_add_session \ test_ats_api_scheduling_update_address \ - test_ats_api_scheduling_switch_network \ test_ats_api_scheduling_destroy_address \ test_ats_api_scheduling_destroy_session \ test_ats_api_scheduling_destroy_inbound_connection \ test_ats_api_scheduling_block_and_reset \ test_ats_simplistic \ + test_ats_simplistic_switch_networks \ test_ats_api_performance # $(GN_MLP_TEST) \ # $(GN_MLP_TEST_AVG) \ @@ -108,15 +108,6 @@ test_ats_api_scheduling_update_address_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la -test_ats_api_scheduling_switch_network_SOURCES = \ - test_ats_api_scheduling_switch_network.c test_ats_api_common.c -test_ats_api_scheduling_switch_network_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/ats/libgnunetats.la - - - test_ats_api_scheduling_destroy_address_SOURCES = \ test_ats_api_scheduling_destroy_address.c test_ats_api_common.c test_ats_api_scheduling_destroy_address_LDADD = \ @@ -161,6 +152,12 @@ test_ats_simplistic_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la +test_ats_simplistic_switch_networks_SOURCES = \ + test_ats_simplistic_switch_networks.c test_ats_api_common.c +test_ats_simplistic_switch_networks_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la if HAVE_LIBGLPK #test_ats_mlp_SOURCES = \ diff --git a/src/ats/gnunet-service-ats_addresses_simplistic.c b/src/ats/gnunet-service-ats_addresses_simplistic.c index 2c31359f5..0d3e0a08a 100644 --- a/src/ats/gnunet-service-ats_addresses_simplistic.c +++ b/src/ats/gnunet-service-ats_addresses_simplistic.c @@ -154,7 +154,7 @@ GAS_simplistic_init (const struct GNUNET_CONFIGURATION_Handle *cfg, int c; struct GAS_SIMPLISTIC_Handle *s = GNUNET_malloc (sizeof (struct GAS_SIMPLISTIC_Handle)); struct Network * cur; - char * net_str[GNUNET_ATS_NetworkTypeCount] = {"UNSPECIFIED", "LOOPBACK", "LAN", "WAN", "WLAN"}; + char * net_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; s->bw_changed = bw_changed_cb; s->bw_changed_cls = bw_changed_cb_cls; @@ -302,17 +302,17 @@ void GAS_simplistic_address_add (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address) { struct GAS_SIMPLISTIC_Handle *s = solver; - struct Network *cur = NULL; + struct Network *net = NULL; struct AddressWrapper *aw = NULL; GNUNET_assert (NULL != s); int c; for (c = 0; c < s->networks; c++) { - cur = &s->network_entries[c]; - if (address->atsp_network_type == cur->type) + net = &s->network_entries[c]; + if (address->atsp_network_type == net->type) break; } - if (NULL == cur) + if (NULL == net) { GNUNET_break (0); return; @@ -320,15 +320,16 @@ GAS_simplistic_address_add (void *solver, struct GNUNET_CONTAINER_MultiHashMap * aw = GNUNET_malloc (sizeof (struct AddressWrapper)); aw->addr = address; - GNUNET_CONTAINER_DLL_insert (cur->head, cur->tail, aw); - cur->total_addresses ++; + GNUNET_CONTAINER_DLL_insert (net->head, net->tail, aw); + net->total_addresses ++; s->total_addresses ++; - aw->addr->solver_information = cur; + aw->addr->solver_information = net; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Adding new address for network type `%s' (now %u total)\n", - cur->desc, - cur->active_addresses); + + LOG (GNUNET_ERROR_TYPE_DEBUG, "After adding address now total %u and active %u addresses in network `%s'\n", + net->total_addresses, + net->active_addresses, + net->desc); } /** @@ -397,6 +398,7 @@ GAS_simplistic_address_delete (void *solver, net->desc, net->total_addresses, net->active_addresses); } + if (GNUNET_YES == address->active) { /* Address was active, remove from network and update quotas*/ @@ -411,6 +413,23 @@ GAS_simplistic_address_delete (void *solver, s->active_addresses --; update_quota_per_network (s, net, NULL); } + LOG (GNUNET_ERROR_TYPE_DEBUG, "After deleting address now total %u and active %u addresses in network `%s'\n", + net->total_addresses, + net->active_addresses, + net->desc); + +} + +static struct Network * +find_network (struct GAS_SIMPLISTIC_Handle *s, uint32_t type) +{ + int c; + for (c = 0 ; c < s->networks; c++) + { + if (s->network_entries[c].type == type) + return &s->network_entries[c]; + } + return NULL; } /** @@ -433,9 +452,12 @@ GAS_simplistic_address_update (void *solver, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count) { + struct GAS_SIMPLISTIC_Handle *s = (struct GAS_SIMPLISTIC_Handle *) solver; int i; uint32_t value; uint32_t type; + int save_active = GNUNET_NO; + struct Network *new_net = NULL; for (i = 0; i < atsi_count; i++) { type = ntohl (atsi[i].type); @@ -474,20 +496,35 @@ GAS_simplistic_address_update (void *solver, if (address->atsp_network_type != value) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Network changed from `%s' to `%s'\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, "Network type changed, moving %s address from `%s' to `%s'\n", + (GNUNET_YES == address->active) ? "active" : "inactive", GNUNET_ATS_print_network_type(address->atsp_network_type), GNUNET_ATS_print_network_type(value)); -#if 0 - /* FIXME */ - int active = address->active; - address->atsp_network_type = value; - /* Remove address from old network */ + + save_active = address->active; + /* remove from old network */ GAS_simplistic_address_delete (solver, addresses, address, GNUNET_NO); - /* Add to new network */ + + /* set new network type */ + address->atsp_network_type = value; + new_net = find_network (solver, value); + address->solver_information = new_net; + if (address->solver_information == NULL) + { + GNUNET_break (0); + address->atsp_network_type = GNUNET_ATS_NET_UNSPECIFIED; + return; + } + + /* restore active state, add to new network and update*/ + address->active = save_active; GAS_simplistic_address_add (solver, addresses, address); - address->active = active; - update_quota_per_network(solver, address->solver_information, NULL); -#endif + if (GNUNET_YES == save_active) + { + s->active_addresses ++; + new_net->active_addresses ++; + update_quota_per_network (solver, new_net, NULL); + } } break; case GNUNET_ATS_ARRAY_TERMINATOR: diff --git a/src/ats/test_ats_api_scheduling_switch_network.c b/src/ats/test_ats_api_scheduling_switch_network.c deleted file mode 100644 index 4d0fc0ecc..000000000 --- a/src/ats/test_ats_api_scheduling_switch_network.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - 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/test_ats_api_scheduling_update_address.c - * @brief test updating networtk type of an address - * @author Christian Grothoff - * @author Matthias Wachs - */ -#include "platform.h" -#include "gnunet_ats_service.h" -#include "gnunet_testing_lib-new.h" -#include "ats.h" -#include "test_ats_api_common.h" - -#define BIG_M_STRING "unlimited" - - -static GNUNET_SCHEDULER_TaskIdentifier die_task; - -/** - * Scheduling handle - */ -static struct GNUNET_ATS_SchedulingHandle *sched_ats; - -/** - * Return value - */ -static int ret; - -/** - * Test address - */ -static struct Test_Address test_addr; - -/** - * Test peer - */ -static struct PeerContext p; - -/** - * HELLO test address - */ - -struct GNUNET_HELLO_Address test_hello_address; - -/** - * Test session - */ -static void *test_session; - -/** - * Test ats info - */ -struct GNUNET_ATS_Information test_ats_info[3]; - -/** - * Test ats count - */ -uint32_t test_ats_count; - -unsigned long long int quota_out[GNUNET_ATS_NetworkTypeCount]; -unsigned long long int quota_in[GNUNET_ATS_NetworkTypeCount]; - -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - die_task = GNUNET_SCHEDULER_NO_TASK; - - if (sched_ats != NULL) - GNUNET_ATS_scheduling_done (sched_ats); - free_test_address (&test_addr); - ret = GNUNET_SYSERR; -} - - -static void -end () -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); - if (die_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_ATS_scheduling_done (sched_ats); - sched_ats = NULL; - free_test_address (&test_addr); -} - -static uint32_t -find_ats_value (const struct GNUNET_ATS_Information *atsi, - uint32_t ats_count, - uint32_t value) -{ - int c; - for (c = 0; c < ats_count; c ++) - { - if (ntohl(atsi[c].type) == value) - return ntohl (atsi[c].value); - } - GNUNET_break (0); - return UINT32_MAX; -} - - -static void -address_suggest_cb (void *cls, const struct GNUNET_HELLO_Address *address, - struct Session *session, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, - const struct GNUNET_ATS_Information *atsi, - uint32_t ats_count) -{ - static int stage = 0; - int level; - char *text; - if (0 == stage) - { - GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); - if (GNUNET_OK == compare_addresses(address, session, &test_hello_address, test_session)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback for correct address `%s'\n", - stage, GNUNET_i2s (&address->peer)); - ret = 0; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect address `%s'\n", - stage, GNUNET_i2s (&address->peer)); - ret = 1; - GNUNET_SCHEDULER_add_now (&end, NULL); - return; - } - - if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info, test_ats_count)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n", stage); - ret = 1; - GNUNET_SCHEDULER_add_now (&end, NULL); - return; - } - - if (ntohl(bandwidth_out.value__) == quota_out[GNUNET_ATS_NET_WAN]) - { - level = GNUNET_ERROR_TYPE_DEBUG; - text = "correct"; - ret = 0; - } - else - { - level = GNUNET_ERROR_TYPE_ERROR; - text = "wrong"; - ret = 1; - } - - GNUNET_log (level, "Stage %u: WAN outbound quota out %s: Received %llu, configured %llu\n", - stage, - text, - (unsigned long long int) ntohl(bandwidth_out.value__), - quota_out[GNUNET_ATS_NET_WAN]); - - if (ntohl(bandwidth_in.value__) == quota_in[GNUNET_ATS_NET_WAN]) - { - level = GNUNET_ERROR_TYPE_DEBUG; - text = "correct"; - ret = 0; - } - else - { - level = GNUNET_ERROR_TYPE_ERROR; - text = "wrong"; - ret = 1; - } - - GNUNET_log (level, "Stage %u: WAN inbound quota out %s: Received %llu, configured %llu\n", - stage, - text, - (unsigned long long int) ntohl(bandwidth_out.value__), - quota_out[GNUNET_ATS_NET_WAN]); - - if (GNUNET_ATS_NET_WAN != find_ats_value (atsi, ats_count, GNUNET_ATS_NETWORK_TYPE)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Incorrect network type, exptected %s, got %s \n", - stage, - GNUNET_ATS_print_network_type(GNUNET_ATS_NET_WAN), - GNUNET_ATS_print_network_type(find_ats_value (atsi, ats_count, GNUNET_ATS_NETWORK_TYPE))); - ret = 1; - } - - if (1 == ret) - { - GNUNET_SCHEDULER_add_now (&end, NULL); - return; - } - - /* Update address */ - /* Prepare ATS Information: change network */ - test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); - test_ats_info[0].value = htonl(GNUNET_ATS_NET_LAN); - test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); - test_ats_info[1].value = htonl(3); - test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); - test_ats_info[1].value = htonl(30); - test_ats_count = 2; - - GNUNET_ATS_address_update (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); - - /* Request address */ - GNUNET_ATS_suggest_address (sched_ats, &p.id); - stage ++; - } - else if (1 == stage) - { - GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); - if (GNUNET_OK == compare_addresses(address, session, &test_hello_address, test_session)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with correct address `%s'\n", stage, - GNUNET_i2s (&address->peer)); - ret = 0; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect address `%s'\n", stage, - GNUNET_i2s (&address->peer)); - ret = 1; - } - - if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info, test_ats_count)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n"); - ret = 1; - GNUNET_SCHEDULER_add_now (&end, NULL); - return; - } - - if (ntohl(bandwidth_out.value__) == quota_out[GNUNET_ATS_NET_LAN]) - { - level = GNUNET_ERROR_TYPE_DEBUG; - text = "correct"; - ret = 0; - } - else - { - level = GNUNET_ERROR_TYPE_ERROR; - text = "wrong"; - ret = 1; - } - - GNUNET_log (level, "Stage %u: LAN outbound quota out %s: Received %llu, configured %llu\n", - stage, - text, - (unsigned long long int) ntohl(bandwidth_out.value__), - quota_out[GNUNET_ATS_NET_LAN]); - - if (ntohl(bandwidth_in.value__) == quota_in[GNUNET_ATS_NET_LAN]) - { - level = GNUNET_ERROR_TYPE_DEBUG; - text = "correct"; - ret = 0; - } - else - { - level = GNUNET_ERROR_TYPE_ERROR; - text = "wrong"; - ret = 1; - } - - GNUNET_log (level, "Stage %u: LAN inbound quota out %s: Received %llu, configured %llu\n", - stage, - text, - (unsigned long long int) ntohl(bandwidth_out.value__), - quota_out[GNUNET_ATS_NET_LAN]); - - if (GNUNET_ATS_NET_LAN != find_ats_value (atsi, ats_count, GNUNET_ATS_NETWORK_TYPE)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Incorrect network type, exptected %s, got %s \n", - stage, - GNUNET_ATS_print_network_type(GNUNET_ATS_NET_LAN), - GNUNET_ATS_print_network_type(find_ats_value (atsi, ats_count, GNUNET_ATS_NETWORK_TYPE))); - ret = 1; - } - - GNUNET_SCHEDULER_add_now (&end, NULL); - } -} - -static unsigned int -load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned long long *out_dest, unsigned long long *in_dest, int dest_length) -{ - int quotas[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType; - char * entry_in = NULL; - char * entry_out = NULL; - char * quota_out_str; - char * quota_in_str; - int c; - - for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++) - { - in_dest[c] = 0; - out_dest[c] = 0; - switch (quotas[c]) { - case GNUNET_ATS_NET_UNSPECIFIED: - entry_out = "UNSPECIFIED_QUOTA_OUT"; - entry_in = "UNSPECIFIED_QUOTA_IN"; - break; - case GNUNET_ATS_NET_LOOPBACK: - entry_out = "LOOPBACK_QUOTA_OUT"; - entry_in = "LOOPBACK_QUOTA_IN"; - break; - case GNUNET_ATS_NET_LAN: - entry_out = "LAN_QUOTA_OUT"; - entry_in = "LAN_QUOTA_IN"; - break; - case GNUNET_ATS_NET_WAN: - entry_out = "WAN_QUOTA_OUT"; - entry_in = "WAN_QUOTA_IN"; - break; - case GNUNET_ATS_NET_WLAN: - entry_out = "WLAN_QUOTA_OUT"; - entry_in = "WLAN_QUOTA_IN"; - break; - default: - break; - } - - if ((entry_in == NULL) || (entry_out == NULL)) - continue; - - /* quota out */ - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, "a_out_str)) - { - if (0 == strcmp(quota_out_str, BIG_M_STRING) || - (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c]))) - out_dest[c] = UINT32_MAX; - - GNUNET_free (quota_out_str); - quota_out_str = NULL; - } - else if (GNUNET_ATS_NET_UNSPECIFIED == quotas[c]) - out_dest[c] = UINT32_MAX; - else - out_dest[c] = UINT32_MAX; - - /* quota in */ - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, "a_in_str)) - { - if (0 == strcmp(quota_in_str, BIG_M_STRING) || - (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c]))) - in_dest[c] = UINT32_MAX; - - GNUNET_free (quota_in_str); - quota_in_str = NULL; - } - else if (GNUNET_ATS_NET_UNSPECIFIED == quotas[c]) - { - in_dest[c] = UINT32_MAX; - } - else - { - in_dest[c] = UINT32_MAX; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded quota: %s %u, %s %u\n", entry_in, in_dest[c], entry_out, out_dest[c]); - - } - return GNUNET_ATS_NetworkTypeCount; -} - -static void -run (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Peer *peer) -{ - die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); - - load_quotas (cfg, quota_out, quota_in, GNUNET_ATS_NetworkTypeCount); - - /* Connect to ATS scheduling */ - sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); - if (sched_ats == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); - ret = 1; - end (); - return; - } - - /* Set up peer */ - if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID0, &p.id.hashPubKey)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); - ret = GNUNET_SYSERR; - end (); - return; - } - - GNUNET_assert (0 == strcmp (PEERID0, GNUNET_i2s_full (&p.id))); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", - GNUNET_i2s_full(&p.id)); - - /* Prepare ATS Information */ - test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); - test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); - test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); - test_ats_info[1].value = htonl(1); - test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); - test_ats_info[1].value = htonl(10); - test_ats_count = 2; - - /* Adding address without session */ - test_session = &test_addr; - create_test_address (&test_addr, "test", &test_addr, "test", strlen ("test") + 1); - test_hello_address.peer = p.id; - test_hello_address.transport_name = test_addr.plugin; - test_hello_address.address = test_addr.addr; - test_hello_address.address_length = test_addr.addr_len; - GNUNET_ATS_address_add (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); - - /* Request address */ - GNUNET_ATS_suggest_address (sched_ats, &p.id); -} - - -int -main (int argc, char *argv[]) -{ - if (0 != GNUNET_TESTING_peer_run ("test_ats_api_scheduling_update_address", - "test_ats_api.conf", - &run, NULL)) - return 1; - return ret; -} - -/* end of file test_ats_api_scheduling_update_address.c */ diff --git a/src/ats/test_ats_simplistic_switch_networks.c b/src/ats/test_ats_simplistic_switch_networks.c new file mode 100644 index 000000000..4d0fc0ecc --- /dev/null +++ b/src/ats/test_ats_simplistic_switch_networks.c @@ -0,0 +1,451 @@ +/* + 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/test_ats_api_scheduling_update_address.c + * @brief test updating networtk type of an address + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib-new.h" +#include "ats.h" +#include "test_ats_api_common.h" + +#define BIG_M_STRING "unlimited" + + +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +/** + * Scheduling handle + */ +static struct GNUNET_ATS_SchedulingHandle *sched_ats; + +/** + * Return value + */ +static int ret; + +/** + * Test address + */ +static struct Test_Address test_addr; + +/** + * Test peer + */ +static struct PeerContext p; + +/** + * HELLO test address + */ + +struct GNUNET_HELLO_Address test_hello_address; + +/** + * Test session + */ +static void *test_session; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[3]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + +unsigned long long int quota_out[GNUNET_ATS_NetworkTypeCount]; +unsigned long long int quota_in[GNUNET_ATS_NetworkTypeCount]; + +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + + if (sched_ats != NULL) + GNUNET_ATS_scheduling_done (sched_ats); + free_test_address (&test_addr); + ret = GNUNET_SYSERR; +} + + +static void +end () +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); + if (die_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_ATS_scheduling_done (sched_ats); + sched_ats = NULL; + free_test_address (&test_addr); +} + +static uint32_t +find_ats_value (const struct GNUNET_ATS_Information *atsi, + uint32_t ats_count, + uint32_t value) +{ + int c; + for (c = 0; c < ats_count; c ++) + { + if (ntohl(atsi[c].type) == value) + return ntohl (atsi[c].value); + } + GNUNET_break (0); + return UINT32_MAX; +} + + +static void +address_suggest_cb (void *cls, const struct GNUNET_HELLO_Address *address, + struct Session *session, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, + const struct GNUNET_ATS_Information *atsi, + uint32_t ats_count) +{ + static int stage = 0; + int level; + char *text; + if (0 == stage) + { + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + if (GNUNET_OK == compare_addresses(address, session, &test_hello_address, test_session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback for correct address `%s'\n", + stage, GNUNET_i2s (&address->peer)); + ret = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect address `%s'\n", + stage, GNUNET_i2s (&address->peer)); + ret = 1; + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info, test_ats_count)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n", stage); + ret = 1; + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + if (ntohl(bandwidth_out.value__) == quota_out[GNUNET_ATS_NET_WAN]) + { + level = GNUNET_ERROR_TYPE_DEBUG; + text = "correct"; + ret = 0; + } + else + { + level = GNUNET_ERROR_TYPE_ERROR; + text = "wrong"; + ret = 1; + } + + GNUNET_log (level, "Stage %u: WAN outbound quota out %s: Received %llu, configured %llu\n", + stage, + text, + (unsigned long long int) ntohl(bandwidth_out.value__), + quota_out[GNUNET_ATS_NET_WAN]); + + if (ntohl(bandwidth_in.value__) == quota_in[GNUNET_ATS_NET_WAN]) + { + level = GNUNET_ERROR_TYPE_DEBUG; + text = "correct"; + ret = 0; + } + else + { + level = GNUNET_ERROR_TYPE_ERROR; + text = "wrong"; + ret = 1; + } + + GNUNET_log (level, "Stage %u: WAN inbound quota out %s: Received %llu, configured %llu\n", + stage, + text, + (unsigned long long int) ntohl(bandwidth_out.value__), + quota_out[GNUNET_ATS_NET_WAN]); + + if (GNUNET_ATS_NET_WAN != find_ats_value (atsi, ats_count, GNUNET_ATS_NETWORK_TYPE)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Incorrect network type, exptected %s, got %s \n", + stage, + GNUNET_ATS_print_network_type(GNUNET_ATS_NET_WAN), + GNUNET_ATS_print_network_type(find_ats_value (atsi, ats_count, GNUNET_ATS_NETWORK_TYPE))); + ret = 1; + } + + if (1 == ret) + { + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + /* Update address */ + /* Prepare ATS Information: change network */ + test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); + test_ats_info[0].value = htonl(GNUNET_ATS_NET_LAN); + test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); + test_ats_info[1].value = htonl(3); + test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); + test_ats_info[1].value = htonl(30); + test_ats_count = 2; + + GNUNET_ATS_address_update (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); + + /* Request address */ + GNUNET_ATS_suggest_address (sched_ats, &p.id); + stage ++; + } + else if (1 == stage) + { + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + if (GNUNET_OK == compare_addresses(address, session, &test_hello_address, test_session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with correct address `%s'\n", stage, + GNUNET_i2s (&address->peer)); + ret = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect address `%s'\n", stage, + GNUNET_i2s (&address->peer)); + ret = 1; + } + + if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info, test_ats_count)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n"); + ret = 1; + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + if (ntohl(bandwidth_out.value__) == quota_out[GNUNET_ATS_NET_LAN]) + { + level = GNUNET_ERROR_TYPE_DEBUG; + text = "correct"; + ret = 0; + } + else + { + level = GNUNET_ERROR_TYPE_ERROR; + text = "wrong"; + ret = 1; + } + + GNUNET_log (level, "Stage %u: LAN outbound quota out %s: Received %llu, configured %llu\n", + stage, + text, + (unsigned long long int) ntohl(bandwidth_out.value__), + quota_out[GNUNET_ATS_NET_LAN]); + + if (ntohl(bandwidth_in.value__) == quota_in[GNUNET_ATS_NET_LAN]) + { + level = GNUNET_ERROR_TYPE_DEBUG; + text = "correct"; + ret = 0; + } + else + { + level = GNUNET_ERROR_TYPE_ERROR; + text = "wrong"; + ret = 1; + } + + GNUNET_log (level, "Stage %u: LAN inbound quota out %s: Received %llu, configured %llu\n", + stage, + text, + (unsigned long long int) ntohl(bandwidth_out.value__), + quota_out[GNUNET_ATS_NET_LAN]); + + if (GNUNET_ATS_NET_LAN != find_ats_value (atsi, ats_count, GNUNET_ATS_NETWORK_TYPE)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Incorrect network type, exptected %s, got %s \n", + stage, + GNUNET_ATS_print_network_type(GNUNET_ATS_NET_LAN), + GNUNET_ATS_print_network_type(find_ats_value (atsi, ats_count, GNUNET_ATS_NETWORK_TYPE))); + ret = 1; + } + + GNUNET_SCHEDULER_add_now (&end, NULL); + } +} + +static unsigned int +load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned long long *out_dest, unsigned long long *in_dest, int dest_length) +{ + int quotas[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType; + char * entry_in = NULL; + char * entry_out = NULL; + char * quota_out_str; + char * quota_in_str; + int c; + + for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++) + { + in_dest[c] = 0; + out_dest[c] = 0; + switch (quotas[c]) { + case GNUNET_ATS_NET_UNSPECIFIED: + entry_out = "UNSPECIFIED_QUOTA_OUT"; + entry_in = "UNSPECIFIED_QUOTA_IN"; + break; + case GNUNET_ATS_NET_LOOPBACK: + entry_out = "LOOPBACK_QUOTA_OUT"; + entry_in = "LOOPBACK_QUOTA_IN"; + break; + case GNUNET_ATS_NET_LAN: + entry_out = "LAN_QUOTA_OUT"; + entry_in = "LAN_QUOTA_IN"; + break; + case GNUNET_ATS_NET_WAN: + entry_out = "WAN_QUOTA_OUT"; + entry_in = "WAN_QUOTA_IN"; + break; + case GNUNET_ATS_NET_WLAN: + entry_out = "WLAN_QUOTA_OUT"; + entry_in = "WLAN_QUOTA_IN"; + break; + default: + break; + } + + if ((entry_in == NULL) || (entry_out == NULL)) + continue; + + /* quota out */ + if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, "a_out_str)) + { + if (0 == strcmp(quota_out_str, BIG_M_STRING) || + (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c]))) + out_dest[c] = UINT32_MAX; + + GNUNET_free (quota_out_str); + quota_out_str = NULL; + } + else if (GNUNET_ATS_NET_UNSPECIFIED == quotas[c]) + out_dest[c] = UINT32_MAX; + else + out_dest[c] = UINT32_MAX; + + /* quota in */ + if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, "a_in_str)) + { + if (0 == strcmp(quota_in_str, BIG_M_STRING) || + (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c]))) + in_dest[c] = UINT32_MAX; + + GNUNET_free (quota_in_str); + quota_in_str = NULL; + } + else if (GNUNET_ATS_NET_UNSPECIFIED == quotas[c]) + { + in_dest[c] = UINT32_MAX; + } + else + { + in_dest[c] = UINT32_MAX; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded quota: %s %u, %s %u\n", entry_in, in_dest[c], entry_out, out_dest[c]); + + } + return GNUNET_ATS_NetworkTypeCount; +} + +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TESTING_Peer *peer) +{ + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + load_quotas (cfg, quota_out, quota_in, GNUNET_ATS_NetworkTypeCount); + + /* Connect to ATS scheduling */ + sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); + if (sched_ats == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); + ret = 1; + end (); + return; + } + + /* Set up peer */ + if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID0, &p.id.hashPubKey)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); + ret = GNUNET_SYSERR; + end (); + return; + } + + GNUNET_assert (0 == strcmp (PEERID0, GNUNET_i2s_full (&p.id))); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", + GNUNET_i2s_full(&p.id)); + + /* Prepare ATS Information */ + test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); + test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); + test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); + test_ats_info[1].value = htonl(1); + test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); + test_ats_info[1].value = htonl(10); + test_ats_count = 2; + + /* Adding address without session */ + test_session = &test_addr; + create_test_address (&test_addr, "test", &test_addr, "test", strlen ("test") + 1); + test_hello_address.peer = p.id; + test_hello_address.transport_name = test_addr.plugin; + test_hello_address.address = test_addr.addr; + test_hello_address.address_length = test_addr.addr_len; + GNUNET_ATS_address_add (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); + + /* Request address */ + GNUNET_ATS_suggest_address (sched_ats, &p.id); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_api_scheduling_update_address", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + +/* end of file test_ats_api_scheduling_update_address.c */