diff options
| author | David Barksdale <amatus.amongus@gmail.com> | 2013-07-22 08:26:16 -0500 |
|---|---|---|
| committer | David Barksdale <amatus.amongus@gmail.com> | 2013-07-22 08:26:16 -0500 |
| commit | 7450bd0b6c6c05ee6425e2c63e9b79beb94bfbfa (patch) | |
| tree | dfde89b41437def7ce23af24db53a11a9b5f1075 /src/ats | |
| parent | 740b30688bd745a527f96f9116c19acb3480971a (diff) | |
Imported Upstream version 0.9.5aupstream
Diffstat (limited to 'src/ats')
41 files changed, 9693 insertions, 2406 deletions
diff --git a/src/ats/Makefile.am b/src/ats/Makefile.am index 2e85848..f9a1ec4 100644 --- a/src/ats/Makefile.am +++ b/src/ats/Makefile.am @@ -2,6 +2,8 @@ INCLUDES = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ +libexecdir= $(pkglibdir)/libexec/ + pkgcfg_DATA = \ ats.conf @@ -28,19 +30,21 @@ libgnunetats_la_SOURCES = \ ats_api_performance.c libgnunetats_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la + $(top_builddir)/src/util/libgnunetutil.la \ + $(LTLIBINTL) libgnunetats_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ - -version-info 2:0:2 + -version-info 4:0:0 -bin_PROGRAMS = \ +libexec_PROGRAMS = \ gnunet-service-ats gnunet_service_ats_SOURCES = \ gnunet-service-ats.c gnunet-service-ats.h\ gnunet-service-ats_addresses.c gnunet-service-ats_addresses.h \ + gnunet-service-ats_addresses_simplistic.c gnunet-service-ats_addresses_simplistic.h \ $(GN_MLP_SRC) \ gnunet-service-ats_performance.c gnunet-service-ats_performance.h \ gnunet-service-ats_scheduling.c gnunet-service-ats_scheduling.h \ @@ -48,16 +52,31 @@ gnunet_service_ats_SOURCES = \ gnunet_service_ats_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetats.la \ $(GN_LIBGLPK) \ $(GN_LIBINTL) - +gnunet_service_ats_DEPENDENCIES = \ + libgnunetats.la check_PROGRAMS = \ - test_ats_api_scheduling \ - test_ats_api_reset_backoff \ - $(GN_MLP_TEST) \ - $(GN_MLP_TEST_AVG) \ - $(GN_MLP_PERF) + test_ats_api_scheduling_init \ + test_ats_api_scheduling_add_address \ + test_ats_api_scheduling_add_session \ + test_ats_api_scheduling_min_bw \ + test_ats_api_scheduling_check_min_bw_alt \ + test_ats_api_scheduling_update_address \ + 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_simplistic_change_preference \ + test_ats_simplistic_pref_aging \ + test_ats_api_performance +# $(GN_MLP_TEST) \ +# $(GN_MLP_TEST_AVG) \ +# $(GN_MLP_PERF) # test_ats_api_scheduling_get_type # test_ats_api_bandwidth_consumption @@ -65,60 +84,147 @@ if ENABLE_TEST_RUN TESTS = $(check_PROGRAMS) endif -if HAVE_LIBGLPK -test_ats_mlp_SOURCES = \ - $(GN_MLP_SRC) \ - test_ats_mlp.c -test_ats_mlp_LDADD = \ - $(GN_LIBGLPK) \ +test_ats_api_scheduling_init_SOURCES = \ + test_ats_api_scheduling_init.c \ + test_ats_api_common.c test_ats_api_common.h +test_ats_api_scheduling_init_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/statistics/libgnunetstatistics.la + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la -test_ats_mlp_averaging_SOURCES = \ - $(GN_MLP_SRC) \ - test_ats_mlp_averaging.c -test_ats_mlp_averaging_LDADD = \ - $(GN_LIBGLPK) \ +test_ats_api_scheduling_add_address_SOURCES = \ + test_ats_api_scheduling_add_address.c \ + test_ats_api_common.c test_ats_api_common.h +test_ats_api_scheduling_add_address_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/statistics/libgnunetstatistics.la + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la -perf_ats_mlp_SOURCES = \ - $(GN_MLP_SRC) \ - perf_ats_mlp.c -perf_ats_mlp_LDADD = \ - $(GN_LIBGLPK) \ +test_ats_api_scheduling_add_session_SOURCES = \ + test_ats_api_scheduling_add_session.c test_ats_api_common.c +test_ats_api_scheduling_add_session_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/statistics/libgnunetstatistics.la -endif + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_api_scheduling_min_bw_SOURCES = \ + test_ats_api_scheduling_min_bw.c test_ats_api_common.c +test_ats_api_scheduling_min_bw_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_api_scheduling_check_min_bw_alt_SOURCES = \ + test_ats_api_scheduling_check_min_bw_alt.c test_ats_api_common.c +test_ats_api_scheduling_check_min_bw_alt_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + + +test_ats_api_scheduling_update_address_SOURCES = \ + test_ats_api_scheduling_update_address.c test_ats_api_common.c +test_ats_api_scheduling_update_address_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la -test_ats_api_scheduling_SOURCES = \ - test_ats_api_scheduling.c -test_ats_api_scheduling_LDADD = \ +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 = \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la -test_ats_api_reset_backoff_SOURCES = \ - test_ats_api_reset_backoff.c -test_ats_api_reset_backoff_LDADD = \ +test_ats_api_scheduling_destroy_session_SOURCES = \ + test_ats_api_scheduling_destroy_session.c test_ats_api_common.c +test_ats_api_scheduling_destroy_session_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_api_scheduling_destroy_inbound_connection_SOURCES = \ + test_ats_api_scheduling_destroy_inbound_connection.c test_ats_api_common.c +test_ats_api_scheduling_destroy_inbound_connection_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_api_scheduling_block_and_reset_SOURCES = \ + test_ats_api_scheduling_block_and_reset.c test_ats_api_common.c +test_ats_api_scheduling_block_and_reset_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_api_performance_SOURCES = \ + test_ats_api_performance.c +test_ats_api_performance_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/hello/libgnunethello.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_simplistic_SOURCES = \ + test_ats_simplistic.c test_ats_api_common.c +test_ats_simplistic_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(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 + +test_ats_simplistic_change_preference_SOURCES = \ + test_ats_simplistic_change_preference.c test_ats_api_common.c +test_ats_simplistic_change_preference_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_simplistic_pref_aging_SOURCES = \ + test_ats_simplistic_pref_aging.c test_ats_api_common.c +test_ats_simplistic_pref_aging_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la -#test_ats_api_scheduling_get_type_SOURCES = \ -# test_ats_api_scheduling_get_type.c -#test_ats_api_scheduling_get_type_LDADD = \ +if HAVE_LIBGLPK +#test_ats_mlp_SOURCES = \ +# $(GN_MLP_SRC) \ +# test_ats_mlp.c +#test_ats_mlp_LDADD = \ +# $(GN_LIBGLPK) \ # $(top_builddir)/src/util/libgnunetutil.la \ -# $(top_builddir)/src/ats/libgnunetats.la +# $(top_builddir)/src/statistics/libgnunetstatistics.la + +#test_ats_mlp_averaging_SOURCES = \ +# $(GN_MLP_SRC) \ +# test_ats_mlp_averaging.c +#test_ats_mlp_averaging_LDADD = \ +# $(GN_LIBGLPK) \ +# $(top_builddir)/src/util/libgnunetutil.la \ +# $(top_builddir)/src/statistics/libgnunetstatistics.la + +#perf_ats_mlp_SOURCES = \ +# $(GN_MLP_SRC) \ +# perf_ats_mlp.c +#perf_ats_mlp_LDADD = \ +# $(GN_LIBGLPK) \ +# $(top_builddir)/src/util/libgnunetutil.la \ +# $(top_builddir)/src/statistics/libgnunetstatistics.la +endif #test_ats_api_bandwidth_consumption_SOURCES = \ # test_ats_api_bandwidth_consumption.c #test_ats_api_bandwidth_consumption_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/testing/libgnunettesting.la \ # $(top_builddir)/src/ats/libgnunetats.la diff --git a/src/ats/Makefile.in b/src/ats/Makefile.in index 7f74064..e9a1c3a 100644 --- a/src/ats/Makefile.in +++ b/src/ats/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -18,6 +18,23 @@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -37,24 +54,37 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -bin_PROGRAMS = gnunet-service-ats$(EXEEXT) -check_PROGRAMS = test_ats_api_scheduling$(EXEEXT) \ - test_ats_api_reset_backoff$(EXEEXT) $(am__EXEEXT_1) \ - $(am__EXEEXT_2) $(am__EXEEXT_3) +libexec_PROGRAMS = gnunet-service-ats$(EXEEXT) +check_PROGRAMS = test_ats_api_scheduling_init$(EXEEXT) \ + test_ats_api_scheduling_add_address$(EXEEXT) \ + test_ats_api_scheduling_add_session$(EXEEXT) \ + test_ats_api_scheduling_min_bw$(EXEEXT) \ + test_ats_api_scheduling_check_min_bw_alt$(EXEEXT) \ + test_ats_api_scheduling_update_address$(EXEEXT) \ + test_ats_api_scheduling_destroy_address$(EXEEXT) \ + test_ats_api_scheduling_destroy_session$(EXEEXT) \ + test_ats_api_scheduling_destroy_inbound_connection$(EXEEXT) \ + test_ats_api_scheduling_block_and_reset$(EXEEXT) \ + test_ats_simplistic$(EXEEXT) \ + test_ats_simplistic_switch_networks$(EXEEXT) \ + test_ats_simplistic_change_preference$(EXEEXT) \ + test_ats_simplistic_pref_aging$(EXEEXT) \ + test_ats_api_performance$(EXEEXT) subdir = src/ats DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/ats.conf.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/argz.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libcurl.m4 \ - $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/libunistring.m4 $(top_srcdir)/m4/ltdl.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glib-2.0.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libcurl.m4 $(top_srcdir)/m4/libgcrypt.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ + $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -84,28 +114,35 @@ am__nobase_list = $(am__nobase_strip_setup); \ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = libgnunetats_la_DEPENDENCIES = \ - $(top_builddir)/src/util/libgnunetutil.la + $(top_builddir)/src/util/libgnunetutil.la \ + $(am__DEPENDENCIES_1) am_libgnunetats_la_OBJECTS = ats_api_scheduling.lo \ ats_api_performance.lo libgnunetats_la_OBJECTS = $(am_libgnunetats_la_OBJECTS) -AM_V_lt = $(am__v_lt_$(V)) -am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent libgnunetats_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetats_la_LDFLAGS) $(LDFLAGS) \ -o $@ -@HAVE_LIBGLPK_TRUE@am__EXEEXT_1 = test_ats_mlp$(EXEEXT) -@HAVE_LIBGLPK_TRUE@am__EXEEXT_2 = test_ats_mlp_averaging$(EXEEXT) -@HAVE_LIBGLPK_TRUE@am__EXEEXT_3 = perf_ats_mlp$(EXEEXT) -PROGRAMS = $(bin_PROGRAMS) +PROGRAMS = $(libexec_PROGRAMS) am__gnunet_service_ats_SOURCES_DIST = gnunet-service-ats.c \ gnunet-service-ats.h gnunet-service-ats_addresses.c \ gnunet-service-ats_addresses.h \ + gnunet-service-ats_addresses_simplistic.c \ + gnunet-service-ats_addresses_simplistic.h \ gnunet-service-ats_addresses_mlp.c \ gnunet-service-ats_addresses_mlp.h \ gnunet-service-ats_performance.c \ @@ -117,57 +154,145 @@ am__gnunet_service_ats_SOURCES_DIST = gnunet-service-ats.c \ @HAVE_LIBGLPK_TRUE@am__objects_1 = \ @HAVE_LIBGLPK_TRUE@ gnunet-service-ats_addresses_mlp.$(OBJEXT) am_gnunet_service_ats_OBJECTS = gnunet-service-ats.$(OBJEXT) \ - gnunet-service-ats_addresses.$(OBJEXT) $(am__objects_1) \ - gnunet-service-ats_performance.$(OBJEXT) \ + gnunet-service-ats_addresses.$(OBJEXT) \ + gnunet-service-ats_addresses_simplistic.$(OBJEXT) \ + $(am__objects_1) gnunet-service-ats_performance.$(OBJEXT) \ gnunet-service-ats_scheduling.$(OBJEXT) \ gnunet-service-ats_reservations.$(OBJEXT) gnunet_service_ats_OBJECTS = $(am_gnunet_service_ats_OBJECTS) -am__DEPENDENCIES_1 = -gnunet_service_ats_DEPENDENCIES = \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ +am_test_ats_api_performance_OBJECTS = \ + test_ats_api_performance.$(OBJEXT) +test_ats_api_performance_OBJECTS = \ + $(am_test_ats_api_performance_OBJECTS) +test_ats_api_performance_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am__perf_ats_mlp_SOURCES_DIST = gnunet-service-ats_addresses_mlp.c \ - gnunet-service-ats_addresses_mlp.h perf_ats_mlp.c -@HAVE_LIBGLPK_TRUE@am_perf_ats_mlp_OBJECTS = $(am__objects_1) \ -@HAVE_LIBGLPK_TRUE@ perf_ats_mlp.$(OBJEXT) -perf_ats_mlp_OBJECTS = $(am_perf_ats_mlp_OBJECTS) -@HAVE_LIBGLPK_TRUE@perf_ats_mlp_DEPENDENCIES = $(am__DEPENDENCIES_1) \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la -am_test_ats_api_reset_backoff_OBJECTS = \ - test_ats_api_reset_backoff.$(OBJEXT) -test_ats_api_reset_backoff_OBJECTS = \ - $(am_test_ats_api_reset_backoff_OBJECTS) -test_ats_api_reset_backoff_DEPENDENCIES = \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/hello/libgnunethello.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_api_scheduling_add_address_OBJECTS = \ + test_ats_api_scheduling_add_address.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_api_scheduling_add_address_OBJECTS = \ + $(am_test_ats_api_scheduling_add_address_OBJECTS) +test_ats_api_scheduling_add_address_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la -am_test_ats_api_scheduling_OBJECTS = \ - test_ats_api_scheduling.$(OBJEXT) -test_ats_api_scheduling_OBJECTS = \ - $(am_test_ats_api_scheduling_OBJECTS) -test_ats_api_scheduling_DEPENDENCIES = \ +am_test_ats_api_scheduling_add_session_OBJECTS = \ + test_ats_api_scheduling_add_session.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_api_scheduling_add_session_OBJECTS = \ + $(am_test_ats_api_scheduling_add_session_OBJECTS) +test_ats_api_scheduling_add_session_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_api_scheduling_block_and_reset_OBJECTS = \ + test_ats_api_scheduling_block_and_reset.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_api_scheduling_block_and_reset_OBJECTS = \ + $(am_test_ats_api_scheduling_block_and_reset_OBJECTS) +test_ats_api_scheduling_block_and_reset_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_api_scheduling_check_min_bw_alt_OBJECTS = \ + test_ats_api_scheduling_check_min_bw_alt.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_api_scheduling_check_min_bw_alt_OBJECTS = \ + $(am_test_ats_api_scheduling_check_min_bw_alt_OBJECTS) +test_ats_api_scheduling_check_min_bw_alt_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_api_scheduling_destroy_address_OBJECTS = \ + test_ats_api_scheduling_destroy_address.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_api_scheduling_destroy_address_OBJECTS = \ + $(am_test_ats_api_scheduling_destroy_address_OBJECTS) +test_ats_api_scheduling_destroy_address_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_api_scheduling_destroy_inbound_connection_OBJECTS = \ + test_ats_api_scheduling_destroy_inbound_connection.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_api_scheduling_destroy_inbound_connection_OBJECTS = $(am_test_ats_api_scheduling_destroy_inbound_connection_OBJECTS) +test_ats_api_scheduling_destroy_inbound_connection_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_api_scheduling_destroy_session_OBJECTS = \ + test_ats_api_scheduling_destroy_session.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_api_scheduling_destroy_session_OBJECTS = \ + $(am_test_ats_api_scheduling_destroy_session_OBJECTS) +test_ats_api_scheduling_destroy_session_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_api_scheduling_init_OBJECTS = \ + test_ats_api_scheduling_init.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_api_scheduling_init_OBJECTS = \ + $(am_test_ats_api_scheduling_init_OBJECTS) +test_ats_api_scheduling_init_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_api_scheduling_min_bw_OBJECTS = \ + test_ats_api_scheduling_min_bw.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_api_scheduling_min_bw_OBJECTS = \ + $(am_test_ats_api_scheduling_min_bw_OBJECTS) +test_ats_api_scheduling_min_bw_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_api_scheduling_update_address_OBJECTS = \ + test_ats_api_scheduling_update_address.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_api_scheduling_update_address_OBJECTS = \ + $(am_test_ats_api_scheduling_update_address_OBJECTS) +test_ats_api_scheduling_update_address_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_simplistic_OBJECTS = test_ats_simplistic.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_simplistic_OBJECTS = $(am_test_ats_simplistic_OBJECTS) +test_ats_simplistic_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/hello/libgnunethello.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_simplistic_change_preference_OBJECTS = \ + test_ats_simplistic_change_preference.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_simplistic_change_preference_OBJECTS = \ + $(am_test_ats_simplistic_change_preference_OBJECTS) +test_ats_simplistic_change_preference_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_simplistic_pref_aging_OBJECTS = \ + test_ats_simplistic_pref_aging.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_simplistic_pref_aging_OBJECTS = \ + $(am_test_ats_simplistic_pref_aging_OBJECTS) +test_ats_simplistic_pref_aging_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la +am_test_ats_simplistic_switch_networks_OBJECTS = \ + test_ats_simplistic_switch_networks.$(OBJEXT) \ + test_ats_api_common.$(OBJEXT) +test_ats_simplistic_switch_networks_OBJECTS = \ + $(am_test_ats_simplistic_switch_networks_OBJECTS) +test_ats_simplistic_switch_networks_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la -am__test_ats_mlp_SOURCES_DIST = gnunet-service-ats_addresses_mlp.c \ - gnunet-service-ats_addresses_mlp.h test_ats_mlp.c -@HAVE_LIBGLPK_TRUE@am_test_ats_mlp_OBJECTS = $(am__objects_1) \ -@HAVE_LIBGLPK_TRUE@ test_ats_mlp.$(OBJEXT) -test_ats_mlp_OBJECTS = $(am_test_ats_mlp_OBJECTS) -@HAVE_LIBGLPK_TRUE@test_ats_mlp_DEPENDENCIES = $(am__DEPENDENCIES_1) \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la -am__test_ats_mlp_averaging_SOURCES_DIST = \ - gnunet-service-ats_addresses_mlp.c \ - gnunet-service-ats_addresses_mlp.h test_ats_mlp_averaging.c -@HAVE_LIBGLPK_TRUE@am_test_ats_mlp_averaging_OBJECTS = \ -@HAVE_LIBGLPK_TRUE@ $(am__objects_1) \ -@HAVE_LIBGLPK_TRUE@ test_ats_mlp_averaging.$(OBJEXT) -test_ats_mlp_averaging_OBJECTS = $(am_test_ats_mlp_averaging_OBJECTS) -@HAVE_LIBGLPK_TRUE@test_ats_mlp_averaging_DEPENDENCIES = \ -@HAVE_LIBGLPK_TRUE@ $(am__DEPENDENCIES_1) \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -178,33 +303,60 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_$(V)) -am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_$(V)) -am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libgnunetats_la_SOURCES) $(gnunet_service_ats_SOURCES) \ - $(perf_ats_mlp_SOURCES) $(test_ats_api_reset_backoff_SOURCES) \ - $(test_ats_api_scheduling_SOURCES) $(test_ats_mlp_SOURCES) \ - $(test_ats_mlp_averaging_SOURCES) + $(test_ats_api_performance_SOURCES) \ + $(test_ats_api_scheduling_add_address_SOURCES) \ + $(test_ats_api_scheduling_add_session_SOURCES) \ + $(test_ats_api_scheduling_block_and_reset_SOURCES) \ + $(test_ats_api_scheduling_check_min_bw_alt_SOURCES) \ + $(test_ats_api_scheduling_destroy_address_SOURCES) \ + $(test_ats_api_scheduling_destroy_inbound_connection_SOURCES) \ + $(test_ats_api_scheduling_destroy_session_SOURCES) \ + $(test_ats_api_scheduling_init_SOURCES) \ + $(test_ats_api_scheduling_min_bw_SOURCES) \ + $(test_ats_api_scheduling_update_address_SOURCES) \ + $(test_ats_simplistic_SOURCES) \ + $(test_ats_simplistic_change_preference_SOURCES) \ + $(test_ats_simplistic_pref_aging_SOURCES) \ + $(test_ats_simplistic_switch_networks_SOURCES) DIST_SOURCES = $(libgnunetats_la_SOURCES) \ $(am__gnunet_service_ats_SOURCES_DIST) \ - $(am__perf_ats_mlp_SOURCES_DIST) \ - $(test_ats_api_reset_backoff_SOURCES) \ - $(test_ats_api_scheduling_SOURCES) \ - $(am__test_ats_mlp_SOURCES_DIST) \ - $(am__test_ats_mlp_averaging_SOURCES_DIST) + $(test_ats_api_performance_SOURCES) \ + $(test_ats_api_scheduling_add_address_SOURCES) \ + $(test_ats_api_scheduling_add_session_SOURCES) \ + $(test_ats_api_scheduling_block_and_reset_SOURCES) \ + $(test_ats_api_scheduling_check_min_bw_alt_SOURCES) \ + $(test_ats_api_scheduling_destroy_address_SOURCES) \ + $(test_ats_api_scheduling_destroy_inbound_connection_SOURCES) \ + $(test_ats_api_scheduling_destroy_session_SOURCES) \ + $(test_ats_api_scheduling_init_SOURCES) \ + $(test_ats_api_scheduling_min_bw_SOURCES) \ + $(test_ats_api_scheduling_update_address_SOURCES) \ + $(test_ats_simplistic_SOURCES) \ + $(test_ats_simplistic_change_preference_SOURCES) \ + $(test_ats_simplistic_pref_aging_SOURCES) \ + $(test_ats_simplistic_switch_networks_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac DATA = $(pkgcfg_DATA) ETAGS = etags CTAGS = ctags @@ -246,6 +398,10 @@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ @@ -256,6 +412,7 @@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GN_USER_HOME_DIR = @GN_USER_HOME_DIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ GREP = @GREP@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INCLTDL = @INCLTDL@ @@ -278,6 +435,8 @@ LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBGTOP_CFLAGS = @LIBGTOP_CFLAGS@ +LIBGTOP_LIBS = @LIBGTOP_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBLTDL = @LIBLTDL@ @@ -299,6 +458,7 @@ LT_CONFIG_H = @LT_CONFIG_H@ LT_DLLOADERS = @LT_DLLOADERS@ LT_DLPREOPEN = @LT_DLPREOPEN@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ @@ -308,6 +468,7 @@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ +NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ @@ -323,6 +484,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ @@ -354,6 +516,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ @@ -376,6 +539,7 @@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -386,10 +550,9 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ -libexecdir = @libexecdir@ +libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ ltdl_LIBOBJS = @ltdl_LIBOBJS@ ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@ mandir = @mandir@ @@ -407,6 +570,7 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ +svnversioncommand = @svnversioncommand@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ @@ -435,15 +599,17 @@ libgnunetats_la_SOURCES = \ ats_api_performance.c libgnunetats_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la + $(top_builddir)/src/util/libgnunetutil.la \ + $(LTLIBINTL) libgnunetats_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ - -version-info 2:0:2 + -version-info 4:0:0 gnunet_service_ats_SOURCES = \ gnunet-service-ats.c gnunet-service-ats.h\ gnunet-service-ats_addresses.c gnunet-service-ats_addresses.h \ + gnunet-service-ats_addresses_simplistic.c gnunet-service-ats_addresses_simplistic.h \ $(GN_MLP_SRC) \ gnunet-service-ats_performance.c gnunet-service-ats_performance.h \ gnunet-service-ats_scheduling.c gnunet-service-ats_scheduling.h \ @@ -452,70 +618,173 @@ gnunet_service_ats_SOURCES = \ gnunet_service_ats_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ + libgnunetats.la \ $(GN_LIBGLPK) \ $(GN_LIBINTL) +gnunet_service_ats_DEPENDENCIES = \ + libgnunetats.la + +# $(GN_MLP_TEST) \ +# $(GN_MLP_TEST_AVG) \ +# $(GN_MLP_PERF) # test_ats_api_scheduling_get_type # test_ats_api_bandwidth_consumption @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) -@HAVE_LIBGLPK_TRUE@test_ats_mlp_SOURCES = \ -@HAVE_LIBGLPK_TRUE@ $(GN_MLP_SRC) \ -@HAVE_LIBGLPK_TRUE@ test_ats_mlp.c +test_ats_api_scheduling_init_SOURCES = \ + test_ats_api_scheduling_init.c \ + test_ats_api_common.c test_ats_api_common.h -@HAVE_LIBGLPK_TRUE@test_ats_mlp_LDADD = \ -@HAVE_LIBGLPK_TRUE@ $(GN_LIBGLPK) \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la +test_ats_api_scheduling_init_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la -@HAVE_LIBGLPK_TRUE@test_ats_mlp_averaging_SOURCES = \ -@HAVE_LIBGLPK_TRUE@ $(GN_MLP_SRC) \ -@HAVE_LIBGLPK_TRUE@ test_ats_mlp_averaging.c +test_ats_api_scheduling_add_address_SOURCES = \ + test_ats_api_scheduling_add_address.c \ + test_ats_api_common.c test_ats_api_common.h -@HAVE_LIBGLPK_TRUE@test_ats_mlp_averaging_LDADD = \ -@HAVE_LIBGLPK_TRUE@ $(GN_LIBGLPK) \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la +test_ats_api_scheduling_add_address_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la -@HAVE_LIBGLPK_TRUE@perf_ats_mlp_SOURCES = \ -@HAVE_LIBGLPK_TRUE@ $(GN_MLP_SRC) \ -@HAVE_LIBGLPK_TRUE@ perf_ats_mlp.c +test_ats_api_scheduling_add_session_SOURCES = \ + test_ats_api_scheduling_add_session.c test_ats_api_common.c -@HAVE_LIBGLPK_TRUE@perf_ats_mlp_LDADD = \ -@HAVE_LIBGLPK_TRUE@ $(GN_LIBGLPK) \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ -@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la +test_ats_api_scheduling_add_session_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la -test_ats_api_scheduling_SOURCES = \ - test_ats_api_scheduling.c +test_ats_api_scheduling_min_bw_SOURCES = \ + test_ats_api_scheduling_min_bw.c test_ats_api_common.c -test_ats_api_scheduling_LDADD = \ +test_ats_api_scheduling_min_bw_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la -test_ats_api_reset_backoff_SOURCES = \ - test_ats_api_reset_backoff.c +test_ats_api_scheduling_check_min_bw_alt_SOURCES = \ + test_ats_api_scheduling_check_min_bw_alt.c test_ats_api_common.c + +test_ats_api_scheduling_check_min_bw_alt_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_api_scheduling_update_address_SOURCES = \ + test_ats_api_scheduling_update_address.c test_ats_api_common.c + +test_ats_api_scheduling_update_address_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 = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_api_scheduling_destroy_session_SOURCES = \ + test_ats_api_scheduling_destroy_session.c test_ats_api_common.c + +test_ats_api_scheduling_destroy_session_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_api_scheduling_destroy_inbound_connection_SOURCES = \ + test_ats_api_scheduling_destroy_inbound_connection.c test_ats_api_common.c + +test_ats_api_scheduling_destroy_inbound_connection_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_api_scheduling_block_and_reset_SOURCES = \ + test_ats_api_scheduling_block_and_reset.c test_ats_api_common.c + +test_ats_api_scheduling_block_and_reset_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_api_performance_SOURCES = \ + test_ats_api_performance.c + +test_ats_api_performance_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/hello/libgnunethello.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_simplistic_SOURCES = \ + test_ats_simplistic.c test_ats_api_common.c + +test_ats_simplistic_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(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_api_reset_backoff_LDADD = \ +test_ats_simplistic_switch_networks_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_simplistic_change_preference_SOURCES = \ + test_ats_simplistic_change_preference.c test_ats_api_common.c + +test_ats_simplistic_change_preference_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/ats/libgnunetats.la + +test_ats_simplistic_pref_aging_SOURCES = \ + test_ats_simplistic_pref_aging.c test_ats_api_common.c + +test_ats_simplistic_pref_aging_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la -#test_ats_api_scheduling_get_type_SOURCES = \ -# test_ats_api_scheduling_get_type.c -#test_ats_api_scheduling_get_type_LDADD = \ +#test_ats_mlp_SOURCES = \ +# $(GN_MLP_SRC) \ +# test_ats_mlp.c +#test_ats_mlp_LDADD = \ +# $(GN_LIBGLPK) \ # $(top_builddir)/src/util/libgnunetutil.la \ -# $(top_builddir)/src/ats/libgnunetats.la +# $(top_builddir)/src/statistics/libgnunetstatistics.la + +#test_ats_mlp_averaging_SOURCES = \ +# $(GN_MLP_SRC) \ +# test_ats_mlp_averaging.c +#test_ats_mlp_averaging_LDADD = \ +# $(GN_LIBGLPK) \ +# $(top_builddir)/src/util/libgnunetutil.la \ +# $(top_builddir)/src/statistics/libgnunetstatistics.la + +#perf_ats_mlp_SOURCES = \ +# $(GN_MLP_SRC) \ +# perf_ats_mlp.c +#perf_ats_mlp_LDADD = \ +# $(GN_LIBGLPK) \ +# $(top_builddir)/src/util/libgnunetutil.la \ +# $(top_builddir)/src/statistics/libgnunetstatistics.la #test_ats_api_bandwidth_consumption_SOURCES = \ # test_ats_api_bandwidth_consumption.c #test_ats_api_bandwidth_consumption_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/testing/libgnunettesting.la \ # $(top_builddir)/src/ats/libgnunetats.la EXTRA_DIST = \ ats.h \ @@ -559,7 +828,6 @@ ats.conf: $(top_builddir)/config.status $(srcdir)/ats.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -567,6 +835,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } @@ -588,12 +858,24 @@ clean-libLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libgnunetats.la: $(libgnunetats_la_OBJECTS) $(libgnunetats_la_DEPENDENCIES) +libgnunetats.la: $(libgnunetats_la_OBJECTS) $(libgnunetats_la_DEPENDENCIES) $(EXTRA_libgnunetats_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetats_la_LINK) -rpath $(libdir) $(libgnunetats_la_OBJECTS) $(libgnunetats_la_LIBADD) $(LIBS) -install-binPROGRAMS: $(bin_PROGRAMS) + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) - test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" - @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ @@ -610,56 +892,77 @@ install-binPROGRAMS: $(bin_PROGRAMS) while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ - echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ - $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done -uninstall-binPROGRAMS: +uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) - @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ - echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(bindir)" && rm -f $$files + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files -clean-binPROGRAMS: - @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list - -clean-checkPROGRAMS: - @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list -gnunet-service-ats$(EXEEXT): $(gnunet_service_ats_OBJECTS) $(gnunet_service_ats_DEPENDENCIES) +gnunet-service-ats$(EXEEXT): $(gnunet_service_ats_OBJECTS) $(gnunet_service_ats_DEPENDENCIES) $(EXTRA_gnunet_service_ats_DEPENDENCIES) @rm -f gnunet-service-ats$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_ats_OBJECTS) $(gnunet_service_ats_LDADD) $(LIBS) -perf_ats_mlp$(EXEEXT): $(perf_ats_mlp_OBJECTS) $(perf_ats_mlp_DEPENDENCIES) - @rm -f perf_ats_mlp$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(perf_ats_mlp_OBJECTS) $(perf_ats_mlp_LDADD) $(LIBS) -test_ats_api_reset_backoff$(EXEEXT): $(test_ats_api_reset_backoff_OBJECTS) $(test_ats_api_reset_backoff_DEPENDENCIES) - @rm -f test_ats_api_reset_backoff$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_ats_api_reset_backoff_OBJECTS) $(test_ats_api_reset_backoff_LDADD) $(LIBS) -test_ats_api_scheduling$(EXEEXT): $(test_ats_api_scheduling_OBJECTS) $(test_ats_api_scheduling_DEPENDENCIES) - @rm -f test_ats_api_scheduling$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_OBJECTS) $(test_ats_api_scheduling_LDADD) $(LIBS) -test_ats_mlp$(EXEEXT): $(test_ats_mlp_OBJECTS) $(test_ats_mlp_DEPENDENCIES) - @rm -f test_ats_mlp$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_ats_mlp_OBJECTS) $(test_ats_mlp_LDADD) $(LIBS) -test_ats_mlp_averaging$(EXEEXT): $(test_ats_mlp_averaging_OBJECTS) $(test_ats_mlp_averaging_DEPENDENCIES) - @rm -f test_ats_mlp_averaging$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(test_ats_mlp_averaging_OBJECTS) $(test_ats_mlp_averaging_LDADD) $(LIBS) +test_ats_api_performance$(EXEEXT): $(test_ats_api_performance_OBJECTS) $(test_ats_api_performance_DEPENDENCIES) $(EXTRA_test_ats_api_performance_DEPENDENCIES) + @rm -f test_ats_api_performance$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_performance_OBJECTS) $(test_ats_api_performance_LDADD) $(LIBS) +test_ats_api_scheduling_add_address$(EXEEXT): $(test_ats_api_scheduling_add_address_OBJECTS) $(test_ats_api_scheduling_add_address_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_add_address_DEPENDENCIES) + @rm -f test_ats_api_scheduling_add_address$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_add_address_OBJECTS) $(test_ats_api_scheduling_add_address_LDADD) $(LIBS) +test_ats_api_scheduling_add_session$(EXEEXT): $(test_ats_api_scheduling_add_session_OBJECTS) $(test_ats_api_scheduling_add_session_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_add_session_DEPENDENCIES) + @rm -f test_ats_api_scheduling_add_session$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_add_session_OBJECTS) $(test_ats_api_scheduling_add_session_LDADD) $(LIBS) +test_ats_api_scheduling_block_and_reset$(EXEEXT): $(test_ats_api_scheduling_block_and_reset_OBJECTS) $(test_ats_api_scheduling_block_and_reset_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_block_and_reset_DEPENDENCIES) + @rm -f test_ats_api_scheduling_block_and_reset$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_block_and_reset_OBJECTS) $(test_ats_api_scheduling_block_and_reset_LDADD) $(LIBS) +test_ats_api_scheduling_check_min_bw_alt$(EXEEXT): $(test_ats_api_scheduling_check_min_bw_alt_OBJECTS) $(test_ats_api_scheduling_check_min_bw_alt_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_check_min_bw_alt_DEPENDENCIES) + @rm -f test_ats_api_scheduling_check_min_bw_alt$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_check_min_bw_alt_OBJECTS) $(test_ats_api_scheduling_check_min_bw_alt_LDADD) $(LIBS) +test_ats_api_scheduling_destroy_address$(EXEEXT): $(test_ats_api_scheduling_destroy_address_OBJECTS) $(test_ats_api_scheduling_destroy_address_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_destroy_address_DEPENDENCIES) + @rm -f test_ats_api_scheduling_destroy_address$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_destroy_address_OBJECTS) $(test_ats_api_scheduling_destroy_address_LDADD) $(LIBS) +test_ats_api_scheduling_destroy_inbound_connection$(EXEEXT): $(test_ats_api_scheduling_destroy_inbound_connection_OBJECTS) $(test_ats_api_scheduling_destroy_inbound_connection_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_destroy_inbound_connection_DEPENDENCIES) + @rm -f test_ats_api_scheduling_destroy_inbound_connection$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_destroy_inbound_connection_OBJECTS) $(test_ats_api_scheduling_destroy_inbound_connection_LDADD) $(LIBS) +test_ats_api_scheduling_destroy_session$(EXEEXT): $(test_ats_api_scheduling_destroy_session_OBJECTS) $(test_ats_api_scheduling_destroy_session_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_destroy_session_DEPENDENCIES) + @rm -f test_ats_api_scheduling_destroy_session$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_destroy_session_OBJECTS) $(test_ats_api_scheduling_destroy_session_LDADD) $(LIBS) +test_ats_api_scheduling_init$(EXEEXT): $(test_ats_api_scheduling_init_OBJECTS) $(test_ats_api_scheduling_init_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_init_DEPENDENCIES) + @rm -f test_ats_api_scheduling_init$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_init_OBJECTS) $(test_ats_api_scheduling_init_LDADD) $(LIBS) +test_ats_api_scheduling_min_bw$(EXEEXT): $(test_ats_api_scheduling_min_bw_OBJECTS) $(test_ats_api_scheduling_min_bw_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_min_bw_DEPENDENCIES) + @rm -f test_ats_api_scheduling_min_bw$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_min_bw_OBJECTS) $(test_ats_api_scheduling_min_bw_LDADD) $(LIBS) +test_ats_api_scheduling_update_address$(EXEEXT): $(test_ats_api_scheduling_update_address_OBJECTS) $(test_ats_api_scheduling_update_address_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_update_address_DEPENDENCIES) + @rm -f test_ats_api_scheduling_update_address$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_update_address_OBJECTS) $(test_ats_api_scheduling_update_address_LDADD) $(LIBS) +test_ats_simplistic$(EXEEXT): $(test_ats_simplistic_OBJECTS) $(test_ats_simplistic_DEPENDENCIES) $(EXTRA_test_ats_simplistic_DEPENDENCIES) + @rm -f test_ats_simplistic$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_simplistic_OBJECTS) $(test_ats_simplistic_LDADD) $(LIBS) +test_ats_simplistic_change_preference$(EXEEXT): $(test_ats_simplistic_change_preference_OBJECTS) $(test_ats_simplistic_change_preference_DEPENDENCIES) $(EXTRA_test_ats_simplistic_change_preference_DEPENDENCIES) + @rm -f test_ats_simplistic_change_preference$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_simplistic_change_preference_OBJECTS) $(test_ats_simplistic_change_preference_LDADD) $(LIBS) +test_ats_simplistic_pref_aging$(EXEEXT): $(test_ats_simplistic_pref_aging_OBJECTS) $(test_ats_simplistic_pref_aging_DEPENDENCIES) $(EXTRA_test_ats_simplistic_pref_aging_DEPENDENCIES) + @rm -f test_ats_simplistic_pref_aging$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_simplistic_pref_aging_OBJECTS) $(test_ats_simplistic_pref_aging_LDADD) $(LIBS) +test_ats_simplistic_switch_networks$(EXEEXT): $(test_ats_simplistic_switch_networks_OBJECTS) $(test_ats_simplistic_switch_networks_DEPENDENCIES) $(EXTRA_test_ats_simplistic_switch_networks_DEPENDENCIES) + @rm -f test_ats_simplistic_switch_networks$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ats_simplistic_switch_networks_OBJECTS) $(test_ats_simplistic_switch_networks_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -672,38 +975,47 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_addresses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_addresses_mlp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_addresses_simplistic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_performance.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_reservations.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_scheduling.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_ats_mlp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_reset_backoff.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_mlp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_mlp_averaging.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_performance.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_add_address.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_add_session.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_block_and_reset.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_check_min_bw_alt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_destroy_address.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_destroy_inbound_connection.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_destroy_session.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_min_bw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_update_address.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_simplistic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_simplistic_change_preference.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_simplistic_pref_aging.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_simplistic_switch_networks.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo @@ -712,8 +1024,11 @@ clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) - test -z "$(pkgcfgdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -727,9 +1042,7 @@ uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(pkgcfgdir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(pkgcfgdir)" && rm -f $$files + dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -864,14 +1177,15 @@ check-TESTS: $(TESTS) fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ - echo "$$grn$$dashes"; \ + col="$$grn"; \ else \ - echo "$$red$$dashes"; \ + col="$$red"; \ fi; \ - echo "$$banner"; \ - test -z "$$skipped" || echo "$$skipped"; \ - test -z "$$report" || echo "$$report"; \ - echo "$$dashes$$std"; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi @@ -910,10 +1224,8 @@ check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) -install-binPROGRAMS: install-libLTLIBRARIES - installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)"; do \ + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -926,10 +1238,15 @@ install-am: all-am installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: @@ -943,8 +1260,8 @@ maintainer-clean-generic: @echo "it deletes files that may require special tools to rebuild." clean: clean-am -clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ - clean-libLTLIBRARIES clean-libtool mostlyclean-am +clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libexecPROGRAMS clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) @@ -970,7 +1287,7 @@ install-dvi: install-dvi-am install-dvi-am: -install-exec-am: install-binPROGRAMS install-libLTLIBRARIES +install-exec-am: install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-am @@ -1010,27 +1327,27 @@ ps: ps-am ps-am: -uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ +uninstall-am: uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ - clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ - clean-libLTLIBRARIES clean-libtool ctags distclean \ + clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libexecPROGRAMS clean-libtool ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-binPROGRAMS install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-libLTLIBRARIES install-man install-pdf \ - install-pdf-am install-pkgcfgDATA install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am \ - uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ - uninstall-pkgcfgDATA + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-libexecPROGRAMS install-man \ + install-pdf install-pdf-am install-pkgcfgDATA install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-libLTLIBRARIES \ + uninstall-libexecPROGRAMS uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/src/ats/ats.conf.in b/src/ats/ats.conf.in index f81016e..bdc064e 100644 --- a/src/ats/ats.conf.in +++ b/src/ats/ats.conf.in @@ -3,7 +3,6 @@ AUTOSTART = YES @UNIXONLY@ PORT = 2098 HOSTNAME = localhost HOME = $SERVICEHOME -CONFIG = $DEFAULTCONFIG BINARY = gnunet-service-ats ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; @@ -11,9 +10,12 @@ UNIXPATH = /tmp/gnunet-service-ats.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES -# Enable MLP mode (default: NO) -MLP = NO +# Designated assigment mode: simplistic / MLP +MODE = simplistic + # Network specific inbound/outbound quotas +UNSPECIFIED_QUOTA_IN = 64 KiB +UNSPECIFIED_QUOTA_OUT = 64 KiB # LOOPBACK LOOPBACK_QUOTA_IN = unlimited LOOPBACK_QUOTA_OUT = unlimited @@ -28,6 +30,13 @@ WLAN_QUOTA_IN = 1 MiB WLAN_QUOTA_OUT = 1 MiB # ATS options + +# MLP specific settings +# MAX_DURATION = 3 s +# MAX_ITERATIONS = 1024 + + + DUMP_MLP = NO DUMP_SOLUTION = NO DUMP_OVERWRITE = NO diff --git a/src/ats/ats.h b/src/ats/ats.h index f4c3d9f..70b8826 100644 --- a/src/ats/ats.h +++ b/src/ats/ats.h @@ -170,6 +170,10 @@ struct PeerInformationMessage uint32_t ats_count GNUNET_PACKED; + uint32_t address_active GNUNET_PACKED; + + uint32_t id GNUNET_PACKED; + struct GNUNET_PeerIdentity peer; uint16_t address_length GNUNET_PACKED; @@ -188,6 +192,17 @@ struct PeerInformationMessage }; +struct AddressListRequestMessage +{ + struct GNUNET_MessageHeader header; + + uint32_t id GNUNET_PACKED; + + int32_t all GNUNET_PACKED; + + struct GNUNET_PeerIdentity peer; +}; + struct ReservationRequestMessage { diff --git a/src/ats/ats_api_performance.c b/src/ats/ats_api_performance.c index c98e1c2..25b4926 100644 --- a/src/ats/ats_api_performance.c +++ b/src/ats/ats_api_performance.c @@ -106,6 +106,58 @@ struct GNUNET_ATS_ReservationContext /** + * Linked list of pending reservations. + */ +struct GNUNET_ATS_AddressListHandle +{ + + /** + * Kept in a DLL. + */ + struct GNUNET_ATS_AddressListHandle *next; + + /** + * Kept in a DLL. + */ + struct GNUNET_ATS_AddressListHandle *prev; + + /** + * Performance handle + */ + struct GNUNET_ATS_PerformanceHandle *ph; + + /** + * Callback + */ + GNUNET_ATS_PeerInformationCallback cb; + + /** + * Callback closure + */ + void *cb_cls; + + /** + * Target peer. + */ + struct GNUNET_PeerIdentity peer; + + /** + * Return all or specific peer only + */ + int all_peers; + + /** + * Return all or used address only + */ + int all_addresses; + + /** + * Request multiplexing + */ + uint32_t id; +}; + +/** * ATS Handle to obtain and/or modify performance information. */ struct GNUNET_ATS_PerformanceHandle @@ -152,6 +204,16 @@ struct GNUNET_ATS_PerformanceHandle struct GNUNET_ATS_ReservationContext *reservation_tail; /** + * Head of linked list of pending address list requests. + */ + struct GNUNET_ATS_AddressListHandle *addresslist_head; + + /** + * Tail of linked list of pending address list requests. + */ + struct GNUNET_ATS_AddressListHandle *addresslist_tail; + + /** * Current request for transmission to ATS. */ struct GNUNET_CLIENT_TransmitHandle *th; @@ -161,6 +223,10 @@ struct GNUNET_ATS_PerformanceHandle */ GNUNET_SCHEDULER_TaskIdentifier task; + /** + * Request multiplexing + */ + uint32_t id; }; @@ -276,16 +342,12 @@ process_pi_message (struct GNUNET_ATS_PerformanceHandle *ph, uint16_t plugin_name_length; uint32_t ats_count; - if (ph->infocb == NULL) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } if (ntohs (msg->size) < sizeof (struct PeerInformationMessage)) { GNUNET_break (0); return GNUNET_SYSERR; } + pi = (const struct PeerInformationMessage *) msg; ats_count = ntohl (pi->ats_count); plugin_address_length = ntohs (pi->address_length); @@ -303,6 +365,11 @@ process_pi_message (struct GNUNET_ATS_PerformanceHandle *ph, GNUNET_break (0); return GNUNET_SYSERR; } + if (ph->infocb == NULL) + { + return GNUNET_OK; + } + address.peer = pi->peer; address.address = plugin_address; address.address_length = plugin_address_length; @@ -364,6 +431,110 @@ process_rr_message (struct GNUNET_ATS_PerformanceHandle *ph, /** + * We received a reservation result message. Validate and process it. + * + * @param ph our context with the callback + * @param msg the message + * @return GNUNET_OK if the message was well-formed + */ +static int +process_ar_message (struct GNUNET_ATS_PerformanceHandle *ph, + const struct GNUNET_MessageHeader *msg) +{ + const struct PeerInformationMessage *pi; + struct GNUNET_ATS_AddressListHandle *alh; + struct GNUNET_ATS_AddressListHandle *next; + const struct GNUNET_ATS_Information *atsi; + const char *plugin_address; + const char *plugin_name; + struct GNUNET_HELLO_Address address; + struct GNUNET_PeerIdentity allzeros; + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_zero; + uint16_t plugin_address_length; + uint16_t plugin_name_length; + uint32_t ats_count; + uint32_t active; + uint32_t id; + + if (ntohs (msg->size) < sizeof (struct PeerInformationMessage)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Received %s message\n"), "ATS_ADDRESSLIST_RESPONSE"); + + pi = (const struct PeerInformationMessage *) msg; + id = ntohl (pi->id); + ats_count = ntohl (pi->ats_count); + active = ntohl (pi->address_active); + plugin_address_length = ntohs (pi->address_length); + plugin_name_length = ntohs (pi->plugin_name_length); + atsi = (const struct GNUNET_ATS_Information *) &pi[1]; + plugin_address = (const char *) &atsi[ats_count]; + plugin_name = &plugin_address[plugin_address_length]; + if ((plugin_address_length + plugin_name_length + + ats_count * sizeof (struct GNUNET_ATS_Information) + + sizeof (struct PeerInformationMessage) != ntohs (msg->size)) || + (ats_count > + GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)) + || (plugin_name[plugin_name_length - 1] != '\0')) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + next = ph->addresslist_head; + while (NULL != (alh = next)) + { + next = alh->next; + if (alh->id == id) + break; + } + if (NULL == alh) + { + /* was canceled */ + return GNUNET_SYSERR; + } + + memset (&allzeros, '\0', sizeof (allzeros)); + if ((0 == memcmp (&allzeros, &pi->peer, sizeof (allzeros))) && + (0 == plugin_name_length) && + (0 == plugin_address_length) && + (0 == ats_count)) + { + /* Done */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Received last message for %s \n"), "ATS_ADDRESSLIST_RESPONSE"); + bandwidth_zero.value__ = htonl (0); + if (NULL != alh->cb) + alh->cb (ph->infocb_cls, + NULL, + bandwidth_zero, bandwidth_zero, + NULL, 0); + GNUNET_CONTAINER_DLL_remove (ph->addresslist_head, ph->addresslist_tail, alh); + GNUNET_free (alh); + return GNUNET_OK; + } + + address.peer = pi->peer; + address.address = plugin_address; + address.address_length = plugin_address_length; + address.transport_name = plugin_name; + + if ((GNUNET_YES == alh->all_addresses) || (GNUNET_YES == active)) + { + if (NULL != alh->cb) + alh->cb (ph->infocb_cls, + &address, + pi->bandwidth_out, pi->bandwidth_in, + atsi, ats_count); + } + return GNUNET_OK; +} + + +/** * Type of a function to call when we receive a message * from the service. * @@ -387,6 +558,10 @@ process_ats_message (void *cls, const struct GNUNET_MessageHeader *msg) if (GNUNET_OK != process_rr_message (ph, msg)) goto reconnect; break; + case GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE: + if (GNUNET_OK != process_ar_message (ph, msg)) + goto reconnect; + break; default: GNUNET_break (0); goto reconnect; @@ -395,6 +570,11 @@ process_ats_message (void *cls, const struct GNUNET_MessageHeader *msg) GNUNET_TIME_UNIT_FOREVER_REL); return; reconnect: + if (NULL != ph->th) + { + GNUNET_CLIENT_notify_transmit_ready_cancel (ph->th); + ph->th = NULL; + } GNUNET_CLIENT_disconnect (ph->client); ph->client = NULL; ph->task = @@ -458,6 +638,7 @@ GNUNET_ATS_performance_init (const struct GNUNET_CONFIGURATION_Handle *cfg, ph->cfg = cfg; ph->infocb = infocb; ph->infocb_cls = infocb_cls; + ph->id = 0; reconnect (ph); return ph; } @@ -473,12 +654,19 @@ GNUNET_ATS_performance_done (struct GNUNET_ATS_PerformanceHandle *ph) { struct PendingMessage *p; struct GNUNET_ATS_ReservationContext *rc; + struct GNUNET_ATS_AddressListHandle *alh; while (NULL != (p = ph->pending_head)) { GNUNET_CONTAINER_DLL_remove (ph->pending_head, ph->pending_tail, p); GNUNET_free (p); } + while (NULL != (alh = ph->addresslist_head)) + { + GNUNET_CONTAINER_DLL_remove (ph->addresslist_head, ph->addresslist_tail, + alh); + GNUNET_free (alh); + } while (NULL != (rc = ph->reservation_head)) { GNUNET_CONTAINER_DLL_remove (ph->reservation_head, ph->reservation_tail, @@ -560,6 +748,102 @@ GNUNET_ATS_reserve_bandwidth_cancel (struct GNUNET_ATS_ReservationContext *rc) rc->rcb = NULL; } +/** + * Get information about addresses known to the ATS subsystem. + * + * @param handle the performance handle to use + * @param peer peer idm can be NULL for all peers + * @param all GNUNET_YES to get information about all addresses or GNUNET_NO to + * get only address currently used + * @param infocb callback to call with the addresses, + * will callback with address == NULL when done + * @param infocb_cls closure for infocb + * @return ats performance context + */ +struct GNUNET_ATS_AddressListHandle* +GNUNET_ATS_performance_list_addresses (struct GNUNET_ATS_PerformanceHandle *handle, + const struct GNUNET_PeerIdentity *peer, + int all, + GNUNET_ATS_PeerInformationCallback infocb, + void *infocb_cls) +{ + struct GNUNET_ATS_AddressListHandle *alh; + struct PendingMessage *p; + struct AddressListRequestMessage *m; + + GNUNET_assert (NULL != handle); + if (NULL == infocb) + return NULL; + + alh = GNUNET_malloc (sizeof (struct GNUNET_ATS_AddressListHandle)); + alh->id = handle->id; + handle->id ++; + alh->cb = infocb; + alh->cb_cls = infocb_cls; + alh->ph = handle; + alh->all_addresses = all; + if (NULL == peer) + alh->all_peers = GNUNET_YES; + else + { + alh->all_peers = GNUNET_NO; + alh->peer = (*peer); + } + + GNUNET_CONTAINER_DLL_insert (handle->addresslist_head, handle->addresslist_tail, alh); + + p = GNUNET_malloc (sizeof (struct PendingMessage) + + sizeof (struct AddressListRequestMessage)); + p->size = sizeof (struct AddressListRequestMessage); + m = (struct AddressListRequestMessage *) &p[1]; + m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST); + m->header.size = htons (sizeof (struct AddressListRequestMessage)); + m->all = htonl (all); + m->id = htonl (alh->id); + if (NULL != peer) + m->peer = *peer; + else + { + memset (&m->peer, '\0', sizeof (struct GNUNET_PeerIdentity)); + } + GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail, p); + + do_transmit (handle); + + return alh; +} + + +/** + * Cancel a pending address listing operation + * + * @param handle the GNUNET_ATS_AddressListHandle handle to cancel + */ +void +GNUNET_ATS_performance_list_addresses_cancel (struct GNUNET_ATS_AddressListHandle *handle) +{ + GNUNET_assert (NULL != handle); + + GNUNET_CONTAINER_DLL_remove (handle->ph->addresslist_head, handle->ph->addresslist_tail, handle); + GNUNET_free (handle); +} + + +/** + * Convert a GNUNET_ATS_PreferenceType to a string + * + * @param type the preference type + * @return a string or NULL if invalid + */ +const char * +GNUNET_ATS_print_preference_type (uint32_t type) +{ + char *prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString; + if (type < GNUNET_ATS_PreferenceCount) + return prefs[type]; + return NULL; +} + /** * Change preferences for the given peer. Preference changes are forgotten if peers diff --git a/src/ats/ats_api_scheduling.c b/src/ats/ats_api_scheduling.c index 5a4e883..dce267e 100644 --- a/src/ats/ats_api_scheduling.c +++ b/src/ats/ats_api_scheduling.c @@ -30,6 +30,8 @@ #define INTERFACE_PROCESSING_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) +#define NOT_FOUND 0 + /** * Message in linked list we should send to the ATS service. The * actual binary message follows this struct. @@ -92,6 +94,15 @@ struct ATS_Network socklen_t length; }; +/** + * Handle for address suggestions + */ +struct GNUNET_ATS_SuggestHandle +{ + struct GNUNET_ATS_SuggestHandle *prev; + struct GNUNET_ATS_SuggestHandle *next; + struct GNUNET_PeerIdentity id; +}; /** @@ -116,6 +127,16 @@ struct GNUNET_ATS_SchedulingHandle void *suggest_cb_cls; /** + * DLL for suggestions head + */ + struct GNUNET_ATS_SuggestHandle *sug_head; + + /** + * DLL for suggestions tail + */ + struct GNUNET_ATS_SuggestHandle *sug_tail; + + /** * Connection to ATS service. */ struct GNUNET_CLIENT_Connection *client; @@ -344,13 +365,28 @@ find_session (struct GNUNET_ATS_SchedulingHandle *sh, uint32_t session_id, sh->reconnect = GNUNET_YES; return NULL; } + /* This check exploits the fact that first field of a session object + * is peer identity. + */ + if (0 != + memcmp (peer, sh->session_array[session_id].session, + sizeof (struct GNUNET_PeerIdentity))) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", + "Session %p belongs to peer `%s'\n", + sh->session_array[session_id].session, GNUNET_i2s_full ((struct GNUNET_PeerIdentity *) &sh->session_array[session_id].peer)); +/* + GNUNET_break (0); + sh->reconnect = GNUNET_YES; + return NULL; +*/ + } return sh->session_array[session_id].session; } /** - * Get the ID for the given session object. If we do not have an ID for - * the given session object, allocate one. + * Get an available session ID for the given session object. * * @param sh our handle * @param session session object @@ -358,29 +394,21 @@ find_session (struct GNUNET_ATS_SchedulingHandle *sh, uint32_t session_id, * @return the session id */ static uint32_t -get_session_id (struct GNUNET_ATS_SchedulingHandle *sh, struct Session *session, +find_empty_session_slot (struct GNUNET_ATS_SchedulingHandle *sh, struct Session *session, const struct GNUNET_PeerIdentity *peer) { unsigned int i; unsigned int f; - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "Get session ID for session %p from peer %s in %p\n", session, GNUNET_i2s (peer), sh); if (NULL == session) - return 0; + return NOT_FOUND; f = 0; for (i = 1; i < sh->session_array_size; i++) { - if (session == sh->session_array[i].session) - { - GNUNET_assert (0 == - memcmp (peer, &sh->session_array[i].peer, - sizeof (struct GNUNET_PeerIdentity))); - return i; - } if ((f == 0) && (sh->session_array[i].slot_used == GNUNET_NO)) f = i; } @@ -404,6 +432,48 @@ get_session_id (struct GNUNET_ATS_SchedulingHandle *sh, struct Session *session, /** + * Get the ID for the given session object. + * + * @param sh our handle + * @param session session object + * @param peer peer the session belongs to + * @return the session id or NOT_FOUND for error + */ +static uint32_t +find_session_id (struct GNUNET_ATS_SchedulingHandle *sh, struct Session *session, + const struct GNUNET_PeerIdentity *peer) +{ + unsigned int i; + char * p2; + + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", + "Get session ID for session %p from peer %s in %p\n", session, + GNUNET_i2s (peer), sh); + + if (NULL == session) + return NOT_FOUND; + for (i = 1; i < sh->session_array_size; i++) + { + if (session == sh->session_array[i].session) + { + if (0 != memcmp (peer, &sh->session_array[i].peer, + sizeof (struct GNUNET_PeerIdentity))) + { + p2 = strdup (GNUNET_i2s (&sh->session_array[i].peer)); + GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "ats-scheduling-api", + "Session %p did not match: old session was for peer `%s' new session is for `%s'\n", + session, GNUNET_i2s (peer), p2); + GNUNET_free (p2); + return NOT_FOUND; + } + return i; + } + } + return NOT_FOUND; +} + + +/** * Remove the session of the given session ID from the session * table (it is no longer valid). * @@ -424,12 +494,19 @@ remove_session (struct GNUNET_ATS_SchedulingHandle *sh, uint32_t session_id, if (0 == session_id) return; + GNUNET_assert (session_id < sh->session_array_size); GNUNET_assert (GNUNET_YES == sh->session_array[session_id].slot_used); - GNUNET_assert (0 == - memcmp (peer, &sh->session_array[session_id].peer, - sizeof (struct GNUNET_PeerIdentity))); + GNUNET_assert (0 == memcmp (peer, + &sh->session_array[session_id].peer, + sizeof (struct GNUNET_PeerIdentity))); + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", + "Session %p for peer `%s' removed from slot %u \n", + sh->session_array[session_id].session, + GNUNET_i2s (peer), + session_id); sh->session_array[session_id].session = NULL; + } @@ -750,6 +827,21 @@ get_addresses (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) sh); } +/** + * Convert a GNUNET_ATS_NetworkType to a string + * + * @param net the network type + * @return a string or NULL if invalid + */ +const char * +GNUNET_ATS_print_network_type (uint32_t net) +{ + char *networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; + if (net < GNUNET_ATS_NetworkTypeCount) + return networks[net]; + return NULL; +} + /** * Returns where the address is located: LAN or WAN or ... @@ -763,9 +855,10 @@ struct GNUNET_ATS_Information GNUNET_ATS_address_get_type (struct GNUNET_ATS_SchedulingHandle * sh, const struct sockaddr * addr, socklen_t addrlen) { GNUNET_assert (sh != NULL); - struct GNUNET_ATS_Information ats; struct ATS_Network * cur = sh->net_head; + int type = GNUNET_ATS_NET_UNSPECIFIED; + struct GNUNET_ATS_Information ats; if (addr->sa_family == AF_UNIX) { @@ -804,15 +897,7 @@ GNUNET_ATS_address_get_type (struct GNUNET_ATS_SchedulingHandle * sh, const stru struct sockaddr_in * mask4 = (struct sockaddr_in *) cur->netmask; if (((a4->sin_addr.s_addr & mask4->sin_addr.s_addr)) == net4->sin_addr.s_addr) - { - char * net = GNUNET_strdup (GNUNET_a2s ((const struct sockaddr *) net4, addrlen)); - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", - "`%s' is in network `%s'\n", - GNUNET_a2s ((const struct sockaddr *)a4, addrlen), - net); - GNUNET_free (net); type = GNUNET_ATS_NET_LAN; - } } if (addr->sa_family == AF_INET6) { @@ -830,14 +915,7 @@ GNUNET_ATS_address_get_type (struct GNUNET_ATS_SchedulingHandle * sh, const stru res = GNUNET_NO; if (res == GNUNET_YES) - { - char * net = GNUNET_strdup (GNUNET_a2s ((const struct sockaddr *) net6, addrlen)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' is in network `%s'\n", - GNUNET_a2s ((const struct sockaddr *) a6, addrlen), - net); - GNUNET_free (net); type = GNUNET_ATS_NET_LAN; - } } cur = cur->next; } @@ -847,7 +925,12 @@ GNUNET_ATS_address_get_type (struct GNUNET_ATS_SchedulingHandle * sh, const stru type = GNUNET_ATS_NET_WAN; ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); ats.value = htonl (type); - return (const struct GNUNET_ATS_Information) ats; + + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", + "`%s' is in network `%s'\n", + GNUNET_a2s ((const struct sockaddr *) addr, addrlen), + GNUNET_ATS_print_network_type(type)); + return ats; } @@ -889,7 +972,8 @@ void GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh) { struct PendingMessage *p; - + struct GNUNET_ATS_SuggestHandle *cur; + struct GNUNET_ATS_SuggestHandle *next; while (NULL != (p = sh->pending_head)) { GNUNET_CONTAINER_DLL_remove (sh->pending_head, sh->pending_tail, p); @@ -906,6 +990,14 @@ GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh) sh->task = GNUNET_SCHEDULER_NO_TASK; } + next = sh->sug_head; + while (NULL != (cur = next)) + { + next = cur->next; + GNUNET_CONTAINER_DLL_remove (sh->sug_head, sh->sug_tail, cur); + GNUNET_free (cur); + } + delete_networks (sh); if (sh->interface_task != GNUNET_SCHEDULER_NO_TASK) { @@ -950,13 +1042,15 @@ GNUNET_ATS_reset_backoff (struct GNUNET_ATS_SchedulingHandle *sh, * * @param sh handle * @param peer identity of the peer we need an address for + * @return suggest handle */ -void +struct GNUNET_ATS_SuggestHandle * GNUNET_ATS_suggest_address (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_PeerIdentity *peer) { struct PendingMessage *p; struct RequestAddressMessage *m; + struct GNUNET_ATS_SuggestHandle *s; // FIXME: ATS needs to remember this in case of // a disconnect! @@ -971,6 +1065,10 @@ GNUNET_ATS_suggest_address (struct GNUNET_ATS_SchedulingHandle *sh, m->peer = *peer; GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); + s = GNUNET_malloc (sizeof (struct GNUNET_ATS_SuggestHandle)); + s->id = (*peer); + GNUNET_CONTAINER_DLL_insert_tail (sh->sug_head, sh->sug_tail, s); + return s; } @@ -986,6 +1084,21 @@ GNUNET_ATS_suggest_address_cancel (struct GNUNET_ATS_SchedulingHandle *sh, { struct PendingMessage *p; struct RequestAddressMessage *m; + struct GNUNET_ATS_SuggestHandle *s; + + for (s = sh->sug_head; NULL != s; s = s->next) + if (0 == memcmp(peer, &s->id, sizeof (s->id))) + break; + if (NULL == s) + { + GNUNET_break (0); + return; + } + else + { + GNUNET_CONTAINER_DLL_remove (sh->sug_head, sh->sug_tail, s); + GNUNET_free (s); + } p = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct RequestAddressMessage)); @@ -1002,6 +1115,101 @@ GNUNET_ATS_suggest_address_cancel (struct GNUNET_ATS_SchedulingHandle *sh, /** + * We have a new address ATS should know. Addresses have to be added with this + * function before they can be: updated, set in use and destroyed + * + * @param sh handle + * @param address the address + * @param session session handle, can be NULL + * @param ats performance data for the address + * @param ats_count number of performance records in 'ats' + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_ATS_address_add (struct GNUNET_ATS_SchedulingHandle *sh, + const struct GNUNET_HELLO_Address *address, + struct Session *session, + const struct GNUNET_ATS_Information *ats, + uint32_t ats_count) +{ + + struct PendingMessage *p; + struct AddressUpdateMessage *m; + struct GNUNET_ATS_Information *am; + char *pm; + size_t namelen; + size_t msize; + uint32_t s = 0; + + if (address == NULL) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + namelen = + (address->transport_name == + NULL) ? 0 : strlen (address->transport_name) + 1; + msize = + sizeof (struct AddressUpdateMessage) + address->address_length + + ats_count * sizeof (struct GNUNET_ATS_Information) + namelen; + if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || + (address->address_length >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || + (namelen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || + (ats_count >= + GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information))) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + if (NULL != session) + { + s = find_session_id (sh, session, &address->peer); + if (NOT_FOUND != s) + { + /* Already existing, nothing todo */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding duplicate address for peer `%s', plugin `%s', session %p id %u\n", + GNUNET_i2s (&address->peer), + address->transport_name, session, s); + return GNUNET_SYSERR; + } + s = find_empty_session_slot (sh, session, &address->peer); + GNUNET_break (NOT_FOUND != s); + } + + p = GNUNET_malloc (sizeof (struct PendingMessage) + msize); + p->size = msize; + p->is_init = GNUNET_NO; + m = (struct AddressUpdateMessage *) &p[1]; + m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD); + m->header.size = htons (msize); + m->ats_count = htonl (ats_count); + m->peer = address->peer; + m->address_length = htons (address->address_length); + m->plugin_name_length = htons (namelen); + m->session_id = htonl (s); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding address for peer `%s', plugin `%s', session %p id %u\n", + GNUNET_i2s (&address->peer), + address->transport_name, session, s); + + am = (struct GNUNET_ATS_Information *) &m[1]; + memcpy (am, ats, ats_count * sizeof (struct GNUNET_ATS_Information)); + pm = (char *) &am[ats_count]; + memcpy (pm, address->address, address->address_length); + if (NULL != address->transport_name) + memcpy (&pm[address->address_length], address->transport_name, namelen); + GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); + do_transmit (sh); + return GNUNET_OK; + +} + + +/** * We have updated performance statistics for a given address. Note * that this function can be called for addresses that are currently * in use as well as addresses that are valid but not actively in use. @@ -1011,7 +1219,7 @@ GNUNET_ATS_suggest_address_cancel (struct GNUNET_ATS_SchedulingHandle *sh, * * @param sh handle * @param address the address - * @param session session handle (if available) + * @param session session handle, can be NULL * @param ats performance data for the address * @param ats_count number of performance records in 'ats' */ @@ -1028,17 +1236,13 @@ GNUNET_ATS_address_update (struct GNUNET_ATS_SchedulingHandle *sh, char *pm; size_t namelen; size_t msize; + uint32_t s = 0; if (address == NULL) { GNUNET_break (0); return; } - if ((address == NULL) && (session == NULL)) - { - GNUNET_break (0); - return; - } namelen = (address->transport_name == @@ -1056,6 +1260,21 @@ GNUNET_ATS_address_update (struct GNUNET_ATS_SchedulingHandle *sh, return; } + if (NULL != session) + { + s = find_session_id (sh, session, &address->peer); + if (NOT_FOUND == s) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Update for unknown address for peer `%s', plugin `%s', session %p id %u\n", + GNUNET_i2s (&address->peer), + address->transport_name, session, s); + + GNUNET_break (0); + return; + } + } + p = GNUNET_malloc (sizeof (struct PendingMessage) + msize); p->size = msize; p->is_init = GNUNET_NO; @@ -1066,7 +1285,14 @@ GNUNET_ATS_address_update (struct GNUNET_ATS_SchedulingHandle *sh, m->peer = address->peer; m->address_length = htons (address->address_length); m->plugin_name_length = htons (namelen); - m->session_id = htonl (get_session_id (sh, session, &address->peer)); + + m->session_id = htonl (s); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Updating address for peer `%s', plugin `%s', session %p id %u\n", + GNUNET_i2s (&address->peer), + address->transport_name, session, s); + am = (struct GNUNET_ATS_Information *) &m[1]; memcpy (am, ats, ats_count * sizeof (struct GNUNET_ATS_Information)); pm = (char *) &am[ats_count]; @@ -1074,6 +1300,7 @@ GNUNET_ATS_address_update (struct GNUNET_ATS_SchedulingHandle *sh, memcpy (&pm[address->address_length], address->transport_name, namelen); GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); + return; } @@ -1082,7 +1309,7 @@ GNUNET_ATS_address_update (struct GNUNET_ATS_SchedulingHandle *sh, * * @param sh handle * @param address the address - * @param session session handle + * @param session session handle, can be NULL * @param in_use GNUNET_YES if this address is now used, GNUNET_NO * if address is not used any more */ @@ -1096,6 +1323,7 @@ GNUNET_ATS_address_in_use (struct GNUNET_ATS_SchedulingHandle *sh, char *pm; size_t namelen; size_t msize; + uint32_t s = 0; GNUNET_assert (NULL != address); namelen = @@ -1110,6 +1338,26 @@ GNUNET_ATS_address_in_use (struct GNUNET_ATS_SchedulingHandle *sh, return; } + if (session != NULL) + { + s = find_session_id (sh, session, &address->peer); + if ((s == NOT_FOUND) && (GNUNET_NO == in_use)) + { + /* trying to set unknown address to NO */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Trying to set unknown address to unused for peer `%s', plugin `%s', session %p\n", + GNUNET_i2s (&address->peer), address->transport_name, session); + GNUNET_break (0); + return; + } + if ((s == NOT_FOUND) && (GNUNET_YES == in_use)) + { + /* trying to set new address to YES */ + s = find_empty_session_slot (sh, session, &address->peer); + GNUNET_assert (NOT_FOUND != s); + } + } + p = GNUNET_malloc (sizeof (struct PendingMessage) + msize); p->size = msize; p->is_init = GNUNET_NO; @@ -1120,12 +1368,19 @@ GNUNET_ATS_address_in_use (struct GNUNET_ATS_SchedulingHandle *sh, m->in_use = htons (in_use); m->address_length = htons (address->address_length); m->plugin_name_length = htons (namelen); - m->session_id = htonl (get_session_id (sh, session, &address->peer)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Setting address used to %s for peer `%s', plugin `%s', session %p\n", + (GNUNET_YES == in_use) ? "YES" : "NO", + GNUNET_i2s (&address->peer), address->transport_name, session); + + m->session_id = htonl (s); pm = (char *) &m[1]; memcpy (pm, address->address, address->address_length); memcpy (&pm[address->address_length], address->transport_name, namelen); GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); + return; } @@ -1134,7 +1389,7 @@ GNUNET_ATS_address_in_use (struct GNUNET_ATS_SchedulingHandle *sh, * * @param sh handle * @param address the address - * @param session session handle that is no longer valid + * @param session session handle that is no longer valid, can be NULL */ void GNUNET_ATS_address_destroyed (struct GNUNET_ATS_SchedulingHandle *sh, @@ -1146,7 +1401,13 @@ GNUNET_ATS_address_destroyed (struct GNUNET_ATS_SchedulingHandle *sh, char *pm; size_t namelen; size_t msize; - uint32_t session_id; + uint32_t s = 0; + + if (address == NULL) + { + GNUNET_break (0); + return; + } GNUNET_assert (address->transport_name != NULL); namelen = strlen (address->transport_name) + 1; @@ -1162,6 +1423,16 @@ GNUNET_ATS_address_destroyed (struct GNUNET_ATS_SchedulingHandle *sh, return; } + s = find_session_id (sh, session, &address->peer); + if ((NULL != session) && (NOT_FOUND == s)) + { + /* trying to delete unknown address */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to delete unknown address for peer `%s', plugin `%s', session %p\n", + GNUNET_i2s (&address->peer), address->transport_name, session); + return; + } + p = GNUNET_malloc (sizeof (struct PendingMessage) + msize); p->size = msize; p->is_init = GNUNET_NO; @@ -1172,14 +1443,18 @@ GNUNET_ATS_address_destroyed (struct GNUNET_ATS_SchedulingHandle *sh, m->peer = address->peer; m->address_length = htons (address->address_length); m->plugin_name_length = htons (namelen); - session_id = get_session_id (sh, session, &address->peer); - m->session_id = htonl (session_id); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Deleting address for peer `%s', plugin `%s', session %p\n", + GNUNET_i2s (&address->peer), address->transport_name, session); + + m->session_id = htonl (s); pm = (char *) &m[1]; memcpy (pm, address->address, address->address_length); memcpy (&pm[address->address_length], address->transport_name, namelen); GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); - remove_session (sh, session_id, &address->peer); + remove_session (sh, s, &address->peer); } /* end of ats_api_scheduling.c */ diff --git a/src/ats/gnunet-service-ats.c b/src/ats/gnunet-service-ats.c index aef72f1..3218769 100644 --- a/src/ats/gnunet-service-ats.c +++ b/src/ats/gnunet-service-ats.c @@ -41,6 +41,7 @@ struct GNUNET_STATISTICS_Handle *GSA_stats; static struct GNUNET_SERVER_Handle *GSA_server; +struct GAS_Addresses_Handle *GSA_addresses; /** * We have received a 'ClientStartMessage' from a client. Find out which @@ -109,7 +110,7 @@ client_disconnect_handler (void *cls, struct GNUNET_SERVER_Client *client) static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - GAS_addresses_done (); + GAS_addresses_done (GSA_addresses); GAS_scheduling_done (); GAS_performance_done (); GAS_reservations_done (); @@ -142,6 +143,11 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, {&GAS_handle_request_address_cancel, NULL, GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL, sizeof (struct RequestAddressMessage)}, + {&GAS_handle_request_address_list, NULL, + GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST, + sizeof (struct AddressListRequestMessage)}, + {&GAS_handle_address_add, NULL, + GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD, 0}, {&GAS_handle_address_update, NULL, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE, 0}, {&GAS_handle_address_in_use, NULL, @@ -161,9 +167,10 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GSA_server = server; GSA_stats = GNUNET_STATISTICS_create ("ats", cfg); GAS_reservations_init (); - GAS_performance_init (server); - GAS_scheduling_init (server); - GAS_addresses_init (cfg, GSA_stats); + GSA_addresses = GAS_addresses_init (cfg, GSA_stats); + GAS_performance_init (server, GSA_addresses); + GAS_scheduling_init (server, GSA_addresses); + GNUNET_SERVER_disconnect_notify (server, &client_disconnect_handler, NULL); GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, diff --git a/src/ats/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c index 9bf5ca6..e890aaa 100644 --- a/src/ats/gnunet-service-ats_addresses.c +++ b/src/ats/gnunet-service-ats_addresses.c @@ -34,104 +34,244 @@ #if HAVE_LIBGLPK #include "gnunet-service-ats_addresses_mlp.h" #endif +#include "gnunet-service-ats_addresses_simplistic.h" -#define VERBOSE GNUNET_NO +/** + * ATS address management + * + * Adding addresses: + * + * - If you add a new address without a session, a new address will be added + * - If you add this address again now with a session a, the existing address + * will be updated with this session + * - If you add this address again now with a session b, a new address object + * with this session will be added -#define ATS_BLOCKING_DELTA GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 100) + * Destroying addresses: + * + * - If you destroy an address without a session, the address itself and all + * address instances with an session will be removed + * - If you destroy an address with a session, the session for this address + * will be removed + * + * Conclusion + * Addresses without a session will be updated with a new session and if the + * the session is destroyed the session is removed and address itself still + * exists for suggestion + * + */ + +/** + * Available ressource assignment modes + */ enum ATS_Mode { /* + * Simplistic mode: + * * Assign each peer an equal amount of bandwidth (bw) * * bw_per_peer = bw_total / #active addresses */ - SIMPLE, + MODE_SIMPLISTIC, /* - * Use MLP solver to assign bandwidth + * MLP mode: + * + * Solve ressource assignment as an optimization problem + * Uses an mixed integer programming solver */ - MLP + MODE_MLP }; -static struct GNUNET_CONTAINER_MultiHashMap *addresses; +/** + * Pending Address suggestion requests + */ +struct GAS_Addresses_Suggestion_Requests +{ + /** + * Next in DLL + */ + struct GAS_Addresses_Suggestion_Requests *next; -#if HAVE_LIBGLPK -static struct GAS_MLP_Handle *mlp; -#endif + /** + * Previous in DLL + */ + struct GAS_Addresses_Suggestion_Requests *prev; -static unsigned long long wan_quota_in; + /** + * Peer ID + */ + struct GNUNET_PeerIdentity id; +}; -static unsigned long long wan_quota_out; +/** + * Handle for ATS address component + */ +struct GAS_Addresses_Handle +{ + /** + * + */ + struct GNUNET_STATISTICS_Handle *stat; -static unsigned int active_addr_count; + /** + * A multihashmap to store all addresses + */ + struct GNUNET_CONTAINER_MultiHashMap *addresses; -static int ats_mode; + /** + * Configure WAN quota in + */ + unsigned long long wan_quota_in; -static int running; + /** + * Configure WAN quota out + */ + unsigned long long wan_quota_out; + /** + * Is ATS addresses running + */ + int running; -static void -send_bw_notification (struct ATS_Address *aa) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New bandwidth for peer %s is %u/%u\n", - GNUNET_i2s (&aa->peer), ntohl (aa->assigned_bw_in.value__), - ntohl (aa->assigned_bw_out.value__)); - GAS_scheduling_transmit_address_suggestion (&aa->peer, aa->plugin, aa->addr, - aa->addr_len, aa->session_id, - aa->ats, aa->ats_count, - aa->assigned_bw_out, - aa->assigned_bw_in); - GAS_reservations_set_bandwidth (&aa->peer, aa->assigned_bw_in); - GAS_performance_notify_clients (&aa->peer, aa->plugin, aa->addr, aa->addr_len, - aa->ats, aa->ats_count, aa->assigned_bw_out, - aa->assigned_bw_in); -} + /** + * Configured ATS solver + */ + int ats_mode; -/** - * Update a bandwidth assignment for a peer. This trivial method currently - * simply assigns the same share to all active connections. - * - * @param cls unused - * @param key unused - * @param value the 'struct ATS_Address' - * @return GNUNET_OK (continue to iterate) - */ -static int -update_bw_simple_it (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct ATS_Address *aa = value; + /** + * Solver handle + */ + void *solver; + + /** + * Address suggestion requests DLL head + */ + struct GAS_Addresses_Suggestion_Requests *r_head; + + /** + * Address suggestion requests DLL tail + */ + struct GAS_Addresses_Suggestion_Requests *r_tail; + + /* Solver functions */ - if (GNUNET_YES != aa->active) - return GNUNET_OK; - GNUNET_assert (active_addr_count > 0); + /** + * Initialize solver + */ + GAS_solver_init s_init; + /** + * Add an address to the solver + */ + GAS_solver_address_add s_add; - /* Simple method */ - aa->assigned_bw_in.value__ = htonl (wan_quota_in / active_addr_count); - aa->assigned_bw_out.value__ = htonl (wan_quota_out / active_addr_count); + /** + * Update address in solver + */ + GAS_solver_address_update s_update; - send_bw_notification (aa); + /** + * Get address from solver + */ + GAS_solver_get_preferred_address s_get; - return GNUNET_OK; -} + /** + * Delete address in solver + */ + GAS_solver_address_delete s_del; + /** + * Change preference for quality in solver + */ + GAS_solver_address_change_preference s_pref; -/** - * Some (significant) input changed, recalculate bandwidth assignment - * for all peers. - */ -static void -recalculate_assigned_bw () + /** + * Shutdown solver + */ + GAS_solver_done s_done; +}; + + +static unsigned int +assemble_ats_information (const struct ATS_Address *aa, struct GNUNET_ATS_Information **dest) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Recalculating bandwidth for all active connections\n"); - GNUNET_STATISTICS_update (GSA_stats, "# bandwidth recalculations performed", - 1, GNUNET_NO); - GNUNET_STATISTICS_set (GSA_stats, "# active addresses", active_addr_count, - GNUNET_NO); + unsigned int ats_count = GNUNET_ATS_PropertyCount - 1; + struct GNUNET_ATS_Information *ats = GNUNET_malloc (ats_count * sizeof (struct GNUNET_ATS_Information)); + (*dest) = ats; + + ats[0].type = ntohl(GNUNET_ATS_UTILIZATION_UP); + ats[0].value = aa->atsp_utilization_out.value__; + ats[1].type = ntohl(GNUNET_ATS_UTILIZATION_DOWN); + ats[1].value = aa->atsp_utilization_in.value__; + ats[2].type = ntohl(GNUNET_ATS_NETWORK_TYPE); + ats[2].value = ntohl(aa->atsp_network_type); + ats[3].type = ntohl(GNUNET_ATS_QUALITY_NET_DELAY); + ats[3].value = ntohl(aa->atsp_latency.rel_value); + ats[4].type = ntohl(GNUNET_ATS_QUALITY_NET_DISTANCE); + ats[4].value = ntohl(aa->atsp_distance); + ats[5].type = ntohl(GNUNET_ATS_COST_WAN); + ats[5].value = ntohl (aa->atsp_cost_wan); + ats[6].type = ntohl(GNUNET_ATS_COST_LAN); + ats[6].value = ntohl (aa->atsp_cost_lan); + ats[7].type = ntohl(GNUNET_ATS_COST_WLAN); + ats[7].value = ntohl (aa->atsp_cost_wlan); + return ats_count; +} - GNUNET_CONTAINER_multihashmap_iterate (addresses, &update_bw_simple_it, NULL); +static unsigned int +disassemble_ats_information (const struct GNUNET_ATS_Information *src, + uint32_t ats_count, + struct ATS_Address *dest) +{ + int i; + int res = 0; + for (i = 0; i < ats_count; i++) + switch (ntohl (src[i].type)) + { + case GNUNET_ATS_UTILIZATION_UP: + dest->atsp_utilization_out.value__ = src[i].value; + res ++; + break; + case GNUNET_ATS_UTILIZATION_DOWN: + dest->atsp_utilization_in.value__ = src[i].value; + res ++; + break; + case GNUNET_ATS_QUALITY_NET_DELAY: + dest->atsp_latency.rel_value = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_QUALITY_NET_DISTANCE: + dest->atsp_distance = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_COST_WAN: + dest->atsp_cost_wan = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_COST_LAN: + dest->atsp_cost_lan = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_COST_WLAN: + dest->atsp_cost_wlan = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_NETWORK_TYPE: + dest->atsp_network_type = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_ARRAY_TERMINATOR: + break; + default: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Received unsupported ATS type %u\n", ntohl (src[i].type)); + GNUNET_break (0); + break; + } + return res; } /** @@ -141,7 +281,6 @@ recalculate_assigned_bw () static void free_address (struct ATS_Address *addr) { - GNUNET_free_non_null (addr->ats); GNUNET_free (addr->plugin); GNUNET_free (addr); } @@ -170,6 +309,11 @@ create_address (const struct GNUNET_PeerIdentity *peer, memcpy (&aa[1], plugin_addr, plugin_addr_len); aa->plugin = GNUNET_strdup (plugin_name); aa->session_id = session_id; + aa->active = GNUNET_NO; + aa->used = GNUNET_NO; + aa->solver_information = NULL; + aa->assigned_bw_in = GNUNET_BANDWIDTH_value_init(0); + aa->assigned_bw_out = GNUNET_BANDWIDTH_value_init(0); return aa; } @@ -177,31 +321,20 @@ create_address (const struct GNUNET_PeerIdentity *peer, /** * Destroy the given address. * + * @param handle the address handle * @param addr address to destroy * @return GNUNET_YES if bandwidth allocations should be recalcualted */ static int -destroy_address (struct ATS_Address *addr) +destroy_address (struct GAS_Addresses_Handle *handle, struct ATS_Address *addr) { int ret; ret = GNUNET_NO; GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (addresses, + GNUNET_CONTAINER_multihashmap_remove (handle->addresses, &addr->peer.hashPubKey, addr)); - -#if HAVE_LIBGLPK - if (ats_mode == MLP) - GAS_mlp_address_delete (mlp, addresses, addr); -#endif - - if (GNUNET_YES == addr->active) - { - active_addr_count--; - addr->active = GNUNET_NO; - ret = GNUNET_YES; - } free_address (addr); return ret; } @@ -219,39 +352,68 @@ struct CompareAddressContext static int -compare_address_it (void *cls, const GNUNET_HashCode * key, void *value) +compare_address_it (void *cls, const struct GNUNET_HashCode * key, void *value) { struct CompareAddressContext *cac = cls; struct ATS_Address *aa = value; -/* - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Comparing to: %s %s %u session %u\n", - GNUNET_i2s (&aa->peer), aa->plugin, aa->addr_len, aa->session_id); -*/ - /* find an exact matching address: aa->addr == cac->search->addr && aa->session == cac->search->session */ + /* Find an matching exact address: + * + * Compare by: + * aa->addr_len == cac->search->addr_len + * aa->plugin == cac->search->plugin + * aa->addr == cac->search->addr + * aa->session == cac->search->session + * + * return as exact address + */ if ((aa->addr_len == cac->search->addr_len) && (0 == strcmp (aa->plugin, cac->search->plugin))) { if ((0 == memcmp (aa->addr, cac->search->addr, aa->addr_len)) && (aa->session_id == cac->search->session_id)) - { cac->exact_address = aa; - } } - /* find an matching address: aa->addr == cac->search->addr && aa->session == 0 */ - /* this address can be used to be updated */ + /* Find an matching base address: + * + * Properties: + * + * aa->session_id == 0 + * + * Compare by: + * aa->addr_len == cac->search->addr_len + * aa->plugin == cac->search->plugin + * aa->addr == cac->search->addr + * + * return as base address + */ if ((aa->addr_len == cac->search->addr_len) && (0 == strcmp (aa->plugin, cac->search->plugin))) { if ((0 == memcmp (aa->addr, cac->search->addr, aa->addr_len)) && (aa->session_id == 0)) - { cac->base_address = aa; - } + } + + /* Find an matching exact address based on session: + * + * Properties: + * + * cac->search->addr_len == 0 + * + * Compare by: + * aa->plugin == cac->search->plugin + * aa->session_id == cac->search->session_id + * + * return as exact address + */ + if (0 == cac->search->addr_len) + { + if ((0 == strcmp (aa->plugin, cac->search->plugin)) && (aa->session_id == cac->search->session_id)) + cac->exact_address = aa; } if (cac->exact_address == NULL) - return GNUNET_YES; + return GNUNET_YES; /* Continue iteration to find exact address */ else - return GNUNET_NO; + return GNUNET_NO; /* Stop iteration since we have an exact address */ } @@ -260,177 +422,204 @@ compare_address_it (void *cls, const GNUNET_HashCode * key, void *value) * Compares by peer identity and network address OR by session ID * (one of the two must match). * + * @param handle the address handle * @param peer peer to lookup addresses for * @param addr existing address record * @return existing address record, NULL for none */ struct ATS_Address * -find_address (const struct GNUNET_PeerIdentity *peer, - const struct ATS_Address *addr) +find_equivalent_address (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, + const struct ATS_Address *addr) { struct CompareAddressContext cac; cac.exact_address = NULL; cac.base_address = NULL; cac.search = addr; - GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey, + GNUNET_CONTAINER_multihashmap_get_multiple (handle->addresses, &peer->hashPubKey, &compare_address_it, &cac); -/* - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "exact address: %s base address: %s\n", - (cac.exact_address != NULL) ? "YES" : "NO", - (cac.base_address != NULL) ? "YES" : "NO"); -*/ if (cac.exact_address == NULL) return cac.base_address; return cac.exact_address; } -static int -compare_address_session_it (void *cls, const GNUNET_HashCode * key, void *value) +static struct ATS_Address * +lookup_address (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, + const char *plugin_name, + const void *plugin_addr, + size_t plugin_addr_len, + uint32_t session_id, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count) { - struct CompareAddressContext *cac = cls; - struct ATS_Address *aa = value; + struct ATS_Address *aa; + struct ATS_Address *ea; - if ((aa->addr_len == cac->search->addr_len) && (0 == strcmp (aa->plugin, cac->search->plugin))) + aa = create_address (peer, + plugin_name, + plugin_addr, plugin_addr_len, + session_id); + + /* Get existing address or address with session == 0 */ + ea = find_equivalent_address (handle, peer, aa); + free_address (aa); + if (ea == NULL) { - if ((0 == memcmp (aa->addr, cac->search->addr, aa->addr_len)) && (aa->session_id == cac->search->session_id)) - { - cac->exact_address = aa; - return GNUNET_NO; - } + return NULL; } - return GNUNET_YES; + else if (ea->session_id != session_id) + { + return NULL; + } + return ea; } -/** - * Find an existing equivalent address record. - * Compares by peer identity and network address AND by session ID - * (one of the two must match). - * - * @param peer peer to lookup addresses for - * @param addr existing address record - * @return existing address record, NULL for none - */ -struct ATS_Address * -find_exact_address (const struct GNUNET_PeerIdentity *peer, - const struct ATS_Address *addr) +void +GAS_addresses_add (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, + const char *plugin_name, const void *plugin_addr, + size_t plugin_addr_len, uint32_t session_id, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count) { - struct CompareAddressContext cac; + struct ATS_Address *aa; + struct ATS_Address *ea; + unsigned int ats_res; - cac.exact_address = NULL; - cac.search = addr; - GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey, - &compare_address_session_it, &cac); - return cac.exact_address; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' for peer `%s'\n", + "ADDRESS ADD", + GNUNET_i2s (peer)); + + if (GNUNET_NO == handle->running) + return; + + GNUNET_assert (NULL != handle->addresses); + + aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, + session_id); + if (atsi_count != (ats_res = disassemble_ats_information(atsi, atsi_count, aa))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "While adding address: had %u ATS elements to add, could only add %u\n", + atsi_count, ats_res); + } + + /* Get existing address or address with session == 0 */ + ea = find_equivalent_address (handle, peer, aa); + if (ea == NULL) + { + /* We have a new address */ + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multihashmap_put (handle->addresses, + &peer->hashPubKey, aa, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added new address for peer `%s' session id %u, %p\n", + GNUNET_i2s (peer), session_id, aa); + /* Tell solver about new address */ + handle->s_add (handle->solver, handle->addresses, aa); + return; + } + GNUNET_free (aa->plugin); + GNUNET_free (aa); + + if (ea->session_id != 0) + { + /* This address with the same session is already existing + * Should not happen */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Added already existing address for peer `%s' `%s' %p with new session %u\n", + GNUNET_i2s (peer), plugin_name, session_id); + GNUNET_break (0); + return; + } + + /* We have an address without an session, update this address */ + + /* Notify solver about update with atsi information and session */ + handle->s_update (handle->solver, handle->addresses, ea, session_id, ea->used, atsi, atsi_count); + + /* Do the update */ + ea->session_id = session_id; + if (atsi_count != (ats_res = disassemble_ats_information(atsi, atsi_count, ea))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "While updating address: had %u ATS elements to add, could only add %u\n", + atsi_count, ats_res); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Updated existing address for peer `%s' %p with new session %u\n", + GNUNET_i2s (peer), ea, session_id); } void -GAS_addresses_update (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_update (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count) { struct ATS_Address *aa; - struct ATS_Address *old; - uint32_t i; + uint32_t ats_res; - if (GNUNET_NO == running) + if (GNUNET_NO == handle->running) return; - GNUNET_assert (NULL != addresses); + GNUNET_assert (NULL != handle->addresses); - aa = create_address (peer, - plugin_name, - plugin_addr, plugin_addr_len, - session_id); + /* Get existing address */ + aa = lookup_address (handle, peer, plugin_name, plugin_addr, plugin_addr_len, + session_id, atsi, atsi_count); + if (aa == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Tried to update unknown address for peer `%s' `%s' session id %u\n", + GNUNET_i2s (peer), plugin_name, session_id); + GNUNET_break (0); + return; + } - aa->mlp_information = NULL; - aa->ats = GNUNET_malloc (atsi_count * sizeof (struct GNUNET_ATS_Information)); - aa->ats_count = atsi_count; - memcpy (aa->ats, atsi, atsi_count * sizeof (struct GNUNET_ATS_Information)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' for peer `%s' address \n", + "ADDRESS UPDATE", + GNUNET_i2s (peer), aa); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating address for peer `%s' %u\n", - GNUNET_i2s (peer), - session_id); + /* Tell solver about update */ + handle->s_update (handle->solver, handle->addresses, aa, session_id, aa->used, atsi, atsi_count); - /* Get existing address or address with session == 0 */ - old = find_address (peer, aa); - if (old == NULL) + /* Update address */ + if (atsi_count != (ats_res = disassemble_ats_information (atsi, atsi_count, aa))) { - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (addresses, - &peer->hashPubKey, aa, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); -#if DEBUG_ATS - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added new address for peer `%s' %X\n", - GNUNET_i2s (peer), aa); -#endif - old = aa; - } - else - { -#if DEBUG_ATS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Updated existing address for peer `%s' %p old session %u new session %u\n", - GNUNET_i2s (peer), old, - old->session_id, session_id); -#endif - GNUNET_free_non_null (old->ats); - old->session_id = session_id; - old->ats = NULL; - old->ats_count = 0; - old->ats = aa->ats; - old->ats_count = aa->ats_count; - GNUNET_free (aa->plugin); - GNUNET_free (aa); - } - for (i = 0; i < atsi_count; i++) - switch (ntohl (atsi[i].type)) - { - case GNUNET_ATS_UTILIZATION_UP: - old->atsp_utilization_out.value__ = atsi[i].value; - break; - case GNUNET_ATS_UTILIZATION_DOWN: - old->atsp_utilization_in.value__ = atsi[i].value; - break; - case GNUNET_ATS_QUALITY_NET_DELAY: - old->atsp_latency.rel_value = ntohl (atsi[i].value); - break; - case GNUNET_ATS_QUALITY_NET_DISTANCE: - old->atsp_distance = ntohl (atsi[i].value); - break; - case GNUNET_ATS_COST_WAN: - old->atsp_cost_wan = ntohl (atsi[i].value); - break; - case GNUNET_ATS_COST_LAN: - old->atsp_cost_lan = ntohl (atsi[i].value); - break; - case GNUNET_ATS_COST_WLAN: - old->atsp_cost_wlan = ntohl (atsi[i].value); - break; - case GNUNET_ATS_NETWORK_TYPE: - old->atsp_network_type = ntohl (atsi[i].value); - break; - - default: - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Received unsupported ATS type %u\n", ntohl (atsi[i].type)); - GNUNET_break (0); - break; - } -#if HAVE_LIBGLPK - if (ats_mode == MLP) - GAS_mlp_address_update (mlp, addresses, old); -#endif + "While adding address: had %u ATS elements to add, could only add %u\n", + atsi_count, ats_res); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Updated %u ATS elements for address %p\n", + ats_res, aa); } +struct DestroyContext +{ + struct ATS_Address *aa; + + struct GAS_Addresses_Handle *handle; + + /** + * GNUNET_NO : full address + * GNUNET_YES : just session + */ + int result; +}; + + /** * Delete an address * @@ -444,453 +633,576 @@ GAS_addresses_update (const struct GNUNET_PeerIdentity *peer, * @return GNUNET_OK (continue to iterate) */ static int -destroy_by_session_id (void *cls, const GNUNET_HashCode * key, void *value) +destroy_by_session_id (void *cls, const struct GNUNET_HashCode * key, void *value) { - const struct ATS_Address *info = cls; + struct DestroyContext *dc = cls; + struct GAS_Addresses_Handle *handle = dc->handle; + const struct ATS_Address *des = dc->aa; struct ATS_Address *aa = value; - GNUNET_assert (0 == - memcmp (&aa->peer, &info->peer, - sizeof (struct GNUNET_PeerIdentity))); - /* session == 0, remove full address */ - if ((info->session_id == 0) && (0 == strcmp (info->plugin, aa->plugin)) && - (aa->addr_len == info->addr_len) && - (0 == memcmp (info->addr, aa->addr, aa->addr_len))) - { + GNUNET_assert (0 == memcmp (&aa->peer, &des->peer, + sizeof (struct GNUNET_PeerIdentity))); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Deleting address for peer `%s': `%s' %u\n", - GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); - - if (GNUNET_YES == destroy_address (aa)) - recalculate_assigned_bw (); - return GNUNET_OK; - } - /* session != 0, just remove session */ - if (aa->session_id != info->session_id) - return GNUNET_OK; /* irrelevant */ - if (aa->session_id != 0) - GNUNET_break (0 == strcmp (info->plugin, aa->plugin)); - /* session died */ -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Deleting session for peer `%s': `%s' %u\n", - GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); -#endif - aa->session_id = 0; - if (GNUNET_YES == aa->active) + if (des->session_id == 0) { - aa->active = GNUNET_NO; - active_addr_count--; - recalculate_assigned_bw (); - } + /* Session == 0, remove full address */ + if ((0 == strcmp (des->plugin, aa->plugin)) && + (aa->addr_len == des->addr_len) && + (0 == memcmp (des->addr, aa->addr, aa->addr_len))) + { - /* session == 0 and addrlen == 0 : destroy address */ - if (aa->addr_len == 0) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Deleting session and address for peer `%s': `%s' %u\n", - GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); -#endif - (void) destroy_address (aa); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Deleting full address for peer `%s' session %u %p\n", + GNUNET_i2s (&aa->peer), aa->session_id, aa); + + /* Notify solver about deletion */ + handle->s_del (handle->solver, handle->addresses, aa, GNUNET_NO); + destroy_address (handle, aa); + dc->result = GNUNET_NO; + return GNUNET_OK; /* Continue iteration */ + } } else { - /* session was set to 0, update address */ -#if HAVE_LIBGLPK - if (ats_mode == MLP) - GAS_mlp_address_update (mlp, addresses, aa); -#endif - } + /* Session != 0, just remove session */ + if (aa->session_id != des->session_id) + return GNUNET_OK; /* irrelevant */ + if ((aa->session_id != 0) && + (0 != strcmp (des->plugin, aa->plugin))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Different plugins during removal: `%s' vs `%s' \n", + des->plugin, aa->plugin); + GNUNET_break (0); + return GNUNET_OK; + } + + if (aa->addr_len == 0) + { + /* Inbound connection died, delete full address */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Deleting inbound address for peer `%s': `%s' session %u\n", + GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); + + /* Notify solver about deletion */ + handle->s_del (handle->solver, handle->addresses, aa, GNUNET_NO); + destroy_address (handle, aa); + dc->result = GNUNET_NO; + return GNUNET_OK; /* Continue iteration */ + } + else + { + /* Session died */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Deleting session for peer `%s': `%s' %u\n", + GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); + /* Notify solver to delete session */ + handle->s_del (handle->solver, handle->addresses, aa, GNUNET_YES); + aa->session_id = 0; + return GNUNET_OK; + } + } return GNUNET_OK; } void -GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_destroy (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id) { - struct ATS_Address *aa; + struct ATS_Address *ea; + struct DestroyContext dc; - if (GNUNET_NO == running) + if (GNUNET_NO == handle->running) return; - GNUNET_break (0 < strlen (plugin_name)); - aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id); - - GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey, - &destroy_by_session_id, aa); - - free_address (aa); -} - - -/** - * Find a "good" address to use for a peer. If we already have an existing - * address, we stick to it. Otherwise, we pick by lowest distance and then - * by lowest latency. - * - * @param cls the 'struct ATS_Address**' where we store the result - * @param key unused - * @param value another 'struct ATS_Address*' to consider using - * @return GNUNET_OK (continue to iterate) - */ -static int -find_address_it (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct ATS_Address **ap = cls; - struct ATS_Address *aa = (struct ATS_Address *) value; - struct ATS_Address *ab = *ap; - struct GNUNET_TIME_Absolute now; - - now = GNUNET_TIME_absolute_get(); - - if (aa->blocked_until.abs_value == GNUNET_TIME_absolute_max (now, aa->blocked_until).abs_value) - { - /* This address is blocked for suggestion */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Address %p blocked for suggestion for %llu ms \n", - aa, - GNUNET_TIME_absolute_get_difference(now, aa->blocked_until).rel_value); - return GNUNET_OK; - } - - aa->block_interval = GNUNET_TIME_relative_add (aa->block_interval, ATS_BLOCKING_DELTA); - aa->blocked_until = GNUNET_TIME_absolute_add (now, aa->block_interval); + /* Get existing address */ + ea = lookup_address (handle, peer, plugin_name, plugin_addr, plugin_addr_len, + session_id, NULL, 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Address %p ready for suggestion, block interval now %llu \n", aa, aa->block_interval); + "Received `%s' for peer `%s' address %p session %u\n", + "ADDRESS DESTROY", + GNUNET_i2s (peer), ea, session_id); - /* FIXME this is a hack */ - - - if (NULL != ab) + if (ea == NULL) { - if ((0 == strcmp (ab->plugin, "tcp")) && - (0 == strcmp (aa->plugin, "tcp"))) - { - if ((0 != ab->addr_len) && - (0 == aa->addr_len)) - { - /* saved address was an outbound address, but we have an inbound address */ - *ap = aa; - return GNUNET_OK; - } - if (0 == ab->addr_len) - { - /* saved address was an inbound address, so do not overwrite */ - return GNUNET_OK; - } - } + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tried to destroy unknown address for peer `%s' `%s' session id %u\n", + GNUNET_i2s (peer), plugin_name, session_id); + return; } - /* FIXME end of hack */ - if (NULL == ab) - { - *ap = aa; - return GNUNET_OK; - } - if ((ntohl (ab->assigned_bw_in.value__) == 0) && - (ntohl (aa->assigned_bw_in.value__) > 0)) - { - /* stick to existing connection */ - *ap = aa; - return GNUNET_OK; - } - if (ab->atsp_distance > aa->atsp_distance) - { - /* user shorter distance */ - *ap = aa; - return GNUNET_OK; - } - if (ab->atsp_latency.rel_value > aa->atsp_latency.rel_value) - { - /* user lower latency */ - *ap = aa; - return GNUNET_OK; - } - /* don't care */ - return GNUNET_OK; + GNUNET_break (0 < strlen (plugin_name)); + dc.handle = handle; + dc.aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id); + + GNUNET_CONTAINER_multihashmap_get_multiple (handle->addresses, &peer->hashPubKey, + &destroy_by_session_id, &dc); + free_address (dc.aa); } int -GAS_addresses_in_use (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_in_use (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id, int in_use) { -#if DEBUG_ATS - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received `%s' message for peer `%s': %i\n", "ADDRESS_IN_USE", - GNUNET_i2s (peer), in_use); -#endif + struct ATS_Address *ea; - struct ATS_Address *aa; - struct ATS_Address *old; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' for peer `%s'\n", + "ADDRESS IN USE", + GNUNET_i2s (peer)); - if (GNUNET_NO == running) + if (GNUNET_NO == handle->running) return GNUNET_SYSERR; - aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id); - old = find_exact_address (peer, aa); - free_address (aa); - - if (NULL == old) + ea = lookup_address (handle, peer, plugin_name, + plugin_addr, plugin_addr_len, + session_id, NULL, 0); + if (NULL == ea) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Trying to set unknown address `%s', %s %u %s \n", + GNUNET_i2s (peer), + plugin_name, session_id, + (GNUNET_NO == in_use) ? "NO" : "YES"); GNUNET_break (0); return GNUNET_SYSERR; } - if (old->used == in_use) + if (ea->used == in_use) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Address in use called multiple times for peer `%s': %s -> %s \n", GNUNET_i2s (peer), - (GNUNET_NO == old->used) ? "NO" : "YES", + (GNUNET_NO == ea->used) ? "NO" : "YES", (GNUNET_NO == in_use) ? "NO" : "YES"); return GNUNET_SYSERR; } - old->used = in_use; -#if HAVE_LIBGLPK - if (ats_mode == MLP) - GAS_mlp_address_update (mlp, addresses, old); -#endif + + /* Tell solver about update */ + handle->s_update (handle->solver, handle->addresses, ea, session_id, in_use, NULL, 0); + ea->used = in_use; + return GNUNET_OK; } -void request_address_mlp (const struct GNUNET_PeerIdentity *peer) +/** + * Cancel address suggestions for a peer + * + * @param handle the address handle + * @param peer the respective peer + */ +void +GAS_addresses_request_address_cancel (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer) { - struct ATS_Address *aa; - aa = NULL; - -#if HAVE_GLPK - /* Get preferred address from MLP */ - struct ATS_PreferedAddress * paddr = NULL; - paddr = GAS_mlp_get_preferred_address (mlp, addresses, peer); - aa = paddr->address; - aa->assigned_bw_out = GNUNET_BANDWIDTH_value_init(paddr->bandwidth_out); - /* FIXME use bw in value */ - paddr->bandwidth_in = paddr->bandwidth_out; - aa->assigned_bw_in = GNUNET_BANDWIDTH_value_init (paddr->bandwidth_in); - GNUNET_free (paddr); -#endif + struct GAS_Addresses_Suggestion_Requests *cur = handle->r_head; - if (aa == NULL) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received request: `%s' for peer %s\n", "request_address_cancel", GNUNET_i2s (peer)); + + while (NULL != cur) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, - "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer)); - return; + if (0 == memcmp (peer, &cur->id, sizeof (cur->id))) + break; /* found */ + cur = cur->next; } - if (aa->active == GNUNET_NO) - { - aa->active = GNUNET_YES; - active_addr_count++; - send_bw_notification (aa); - } - else + if (NULL == cur) { - /* just to be sure... */ - GAS_scheduling_transmit_address_suggestion (peer, aa->plugin, aa->addr, - aa->addr_len, aa->session_id, - aa->ats, aa->ats_count, - aa->assigned_bw_out, - aa->assigned_bw_in); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "No address requests pending for peer `%s', cannot remove!\n", GNUNET_i2s (peer)); + return; } - + GAS_addresses_handle_backoff_reset (handle, peer); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Removed request pending for peer `%s\n", GNUNET_i2s (peer)); + GNUNET_CONTAINER_DLL_remove (handle->r_head, handle->r_tail, cur); + GNUNET_free (cur); } -void request_address_simple (const struct GNUNET_PeerIdentity *peer) + +/** + * Add an address suggestions for a peer + * + * @param handle the address handle + * @param peer the respective peer + */ +void +GAS_addresses_request_address (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer) { + struct GAS_Addresses_Suggestion_Requests *cur = handle->r_head; struct ATS_Address *aa; - aa = NULL; + struct GNUNET_ATS_Information *ats; + unsigned int ats_count; - /* Get address with: stick to current address, lower distance, lower latency */ - GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey, - &find_address_it, &aa); - if (aa == NULL) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' for peer `%s'\n", + "REQUEST ADDRESS", + GNUNET_i2s (peer)); + + if (GNUNET_NO == handle->running) + return; + while (NULL != cur) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, + if (0 == memcmp (peer, &cur->id, sizeof (cur->id))) + break; /* already suggesting */ + cur = cur->next; + } + if (NULL == cur) + { + cur = GNUNET_malloc (sizeof (struct GAS_Addresses_Suggestion_Requests)); + cur->id = (*peer); + GNUNET_CONTAINER_DLL_insert (handle->r_head, handle->r_tail, cur); + } + + /* Get prefered address from solver */ + aa = (struct ATS_Address *) handle->s_get (handle->solver, handle->addresses, peer); + if (NULL == aa) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer)); return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggesting address %p for peer `%s'\n", aa, GNUNET_i2s (peer)); - if (aa->active == GNUNET_NO) - { - aa->active = GNUNET_YES; - active_addr_count++; - if (ats_mode == SIMPLE) - { - recalculate_assigned_bw (); - } - } - else - { - /* just to be sure... */ - GAS_scheduling_transmit_address_suggestion (peer, aa->plugin, aa->addr, - aa->addr_len, aa->session_id, - aa->ats, aa->ats_count, - aa->assigned_bw_out, - aa->assigned_bw_in); - } -} + ats_count = assemble_ats_information (aa, &ats); + GAS_scheduling_transmit_address_suggestion (peer, + aa->plugin, + aa->addr, aa->addr_len, + aa->session_id, + ats, ats_count, + aa->assigned_bw_out, + aa->assigned_bw_in); + aa->block_interval = GNUNET_TIME_relative_add (aa->block_interval, ATS_BLOCKING_DELTA); + aa->blocked_until = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), aa->block_interval); -void -GAS_addresses_request_address (const struct GNUNET_PeerIdentity *peer) -{ - if (GNUNET_NO == running) - return; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Address %p ready for suggestion, block interval now %llu \n", + aa, aa->block_interval); - if (ats_mode == SIMPLE) - { - request_address_simple (peer); - } - if (ats_mode == MLP) - { - request_address_mlp(peer); - } + GNUNET_free (ats); } static int -reset_address_it (void *cls, const GNUNET_HashCode * key, void *value) +reset_address_it (void *cls, const struct GNUNET_HashCode * key, void *value) { struct ATS_Address *aa = value; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Resetting interval for peer `%s' address %p from %llu to 0\n", GNUNET_i2s (&aa->peer), aa, aa->block_interval); + "Resetting interval for peer `%s' address %p from %llu to 0\n", + GNUNET_i2s (&aa->peer), aa, aa->block_interval); aa->blocked_until = GNUNET_TIME_UNIT_ZERO_ABS; aa->block_interval = GNUNET_TIME_UNIT_ZERO; return GNUNET_OK; } + void -GAS_addresses_handle_backoff_reset (const struct GNUNET_PeerIdentity *peer) +GAS_addresses_handle_backoff_reset (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer) { - GNUNET_break (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_get_multiple (addresses, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' for peer `%s'\n", + "RESET BACKOFF", + GNUNET_i2s (peer)); + + GNUNET_break (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_get_multiple (handle->addresses, &peer->hashPubKey, &reset_address_it, NULL)); } - -// FIXME: this function should likely end up in the LP-subsystem and -// not with 'addresses' in the future... void -GAS_addresses_change_preference (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_change_preference (struct GAS_Addresses_Handle *handle, + void *client, + const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, float score) { - if (GNUNET_NO == running) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' for peer `%s' for client %p\n", + "CHANGE PREFERENCE", + GNUNET_i2s (peer), client); + + if (GNUNET_NO == handle->running) return; -#if HAVE_LIBGLPK - if (ats_mode == MLP) - GAS_mlp_address_change_preference (mlp, peer, kind, score); -#endif -} + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->addresses, + &peer->hashPubKey)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Received `%s' for unknown peer `%s' from client %p\n", + "CHANGE PREFERENCE", + GNUNET_i2s (peer), client); + return; + } + /* Tell solver about update */ + handle->s_pref (handle->solver, client, peer, kind, score); +} -/** - * Initialize address subsystem. - * - * @param cfg configuration to use - * @param stats the statistics handle to use - */ -void -GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_STATISTICS_Handle *stats) +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 mode; + char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; + char * entry_in = NULL; + char * entry_out = NULL; + char * quota_out_str; + char * quota_in_str; + int c; + int res; + + for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++) + { + in_dest[c] = 0; + out_dest[c] = 0; + GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]); + GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]); - char *quota_wan_in_str; - char *quota_wan_out_str; + /* quota out */ + if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, "a_out_str)) + { + res = GNUNET_NO; + if (0 == strcmp(quota_out_str, BIG_M_STRING)) + { + out_dest[c] = GNUNET_ATS_MaxBandwidth; + res = GNUNET_YES; + } + if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c]))) + res = GNUNET_YES; + if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out, &out_dest[c]))) + res = GNUNET_YES; - running = GNUNET_NO; + if (GNUNET_NO == res) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s': `%s', assigning default bandwidth %llu\n"), + network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth); + out_dest[c] = GNUNET_ATS_DefaultBandwidth; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Outbound quota configure for network `%s' is %llu\n"), + network_str[c], out_dest[c]); + } + GNUNET_free (quota_out_str); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"), + network_str[c], GNUNET_ATS_DefaultBandwidth); + out_dest[c] = GNUNET_ATS_DefaultBandwidth; + } - addresses = GNUNET_CONTAINER_multihashmap_create (128); - GNUNET_assert (NULL != addresses); + /* quota in */ + if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, "a_in_str)) + { + res = GNUNET_NO; + if (0 == strcmp(quota_in_str, BIG_M_STRING)) + { + in_dest[c] = GNUNET_ATS_MaxBandwidth; + res = GNUNET_YES; + } + if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c]))) + res = GNUNET_YES; + if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in, &in_dest[c]))) + res = GNUNET_YES; - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_IN", "a_wan_in_str)) - { - if (0 == strcmp(quota_wan_in_str, "unlimited") || - (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_wan_in_str, &wan_quota_in))) - wan_quota_in = (UINT32_MAX) /10; + if (GNUNET_NO == res) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s': `%s', assigning default bandwidth %llu\n"), + network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth); + in_dest[c] = GNUNET_ATS_DefaultBandwidth; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Inbound quota configured for network `%s' is %llu\n"), + network_str[c], in_dest[c]); + } + GNUNET_free (quota_in_str); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"), + network_str[c], GNUNET_ATS_DefaultBandwidth); + out_dest[c] = GNUNET_ATS_DefaultBandwidth; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded quota for network `%s' (in/out): %llu %llu\n", network_str[c], in_dest[c], out_dest[c]); + GNUNET_free (entry_out); + GNUNET_free (entry_in); + } + return GNUNET_ATS_NetworkTypeCount; +} + + +static void +bandwidth_changed_cb (void *cls, struct ATS_Address *address) +{ + struct GAS_Addresses_Handle *handle = cls; + struct GAS_Addresses_Suggestion_Requests *cur; + + GNUNET_assert (handle != NULL); + GNUNET_assert (address != NULL); - GNUNET_free (quota_wan_in_str); - quota_wan_in_str = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bandwidth assignment changed for peer %s \n", GNUNET_i2s(&address->peer)); + struct GNUNET_ATS_Information *ats; + unsigned int ats_count; + + cur = handle->r_head; + while (NULL != cur) + { + if (0 == memcmp (&address->peer, &cur->id, sizeof (cur->id))) + break; /* we have an address request pending*/ + cur = cur->next; } - else + if (NULL == cur) { - wan_quota_in = (UINT32_MAX) /10; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Nobody is interested in peer `%s' :(\n",GNUNET_i2s (&address->peer)); + return; } - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_OUT", "a_wan_out_str)) - { - if (0 == strcmp(quota_wan_out_str, "unlimited") || - (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_wan_out_str, &wan_quota_out))) - wan_quota_out = (UINT32_MAX) /10; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending bandwidth update for peer `%s'\n",GNUNET_i2s (&address->peer)); + + ats_count = assemble_ats_information (address, &ats); + GAS_scheduling_transmit_address_suggestion (&address->peer, + address->plugin, + address->addr, address->addr_len, + address->session_id, + ats, ats_count, + address->assigned_bw_out, + address->assigned_bw_in); + GNUNET_free (ats); +} - GNUNET_free (quota_wan_out_str); - quota_wan_out_str = NULL; - } - else + +/** + * Initialize address subsystem. + * + * @param cfg configuration to use + * @param stats the statistics handle to use + */ +struct GAS_Addresses_Handle * +GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_STATISTICS_Handle *stats) +{ + struct GAS_Addresses_Handle *ah; + int quotas[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType; + unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount]; + unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount]; + int quota_count; + char *mode_str; + int c; + + ah = GNUNET_malloc (sizeof (struct GAS_Addresses_Handle)); + ah->running = GNUNET_NO; + + ah->stat = (struct GNUNET_STATISTICS_Handle *) stats; + /* Initialize the addresses database */ + ah->addresses = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO); + GNUNET_assert (NULL != ah->addresses); + + /* Figure out configured solution method */ + if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "ats", "MODE", &mode_str)) { - wan_quota_out = (UINT32_MAX) /10; + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "No ressource assignment method configured, using simplistic approch\n"); + ah->ats_mode = MODE_SIMPLISTIC; } - - mode = GNUNET_CONFIGURATION_get_value_yesno (cfg, "ats", "MLP"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MLP mode %u", mode); - switch (mode) + else { - /* MLP = YES */ - case GNUNET_YES: -#if HAVE_LIBGLPK - ats_mode = MLP; - /* Init the MLP solver with default values */ - mlp = GAS_mlp_init (cfg, stats, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS); - if (NULL == mlp) + for (c = 0; c < strlen (mode_str); c++) + mode_str[c] = toupper (mode_str[c]); + if (0 == strcmp (mode_str, "SIMPLISTIC")) + { + ah->ats_mode = MODE_SIMPLISTIC; + } + else if (0 == strcmp (mode_str, "MLP")) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP mode was configured, but libglpk is not installed, switching to simple mode\n"); - GNUNET_STATISTICS_update (GSA_stats, "MLP mode enabled", 0, GNUNET_NO); - break; + ah->ats_mode = MODE_MLP; +#if !HAVE_LIBGLPK + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Assignment method `%s' configured, but GLPK is not availabe, please install \n", mode_str); + ah->ats_mode = MODE_SIMPLISTIC; +#endif } else { - GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 1, GNUNET_NO); - break; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid ressource assignment method `%s' configured, using simplistic approch\n", mode_str); + ah->ats_mode = MODE_SIMPLISTIC; } + GNUNET_free (mode_str); + } + /* Start configured solution method */ + switch (ah->ats_mode) + { + case MODE_MLP: + /* Init the MLP solver with default values */ +#if HAVE_LIBGLPK + ah->ats_mode = MODE_MLP; + ah->s_init = &GAS_mlp_init; + ah->s_add = &GAS_mlp_address_add; + ah->s_update = &GAS_mlp_address_update; + ah->s_get = &GAS_mlp_get_preferred_address; + ah->s_pref = &GAS_mlp_address_change_preference; + ah->s_del = &GAS_mlp_address_delete; + ah->s_done = &GAS_mlp_done; #else - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP mode was configured, but libglpk is not installed, switching to simple mode"); - GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 0, GNUNET_NO); - ats_mode = SIMPLE; - break; + GNUNET_free (ah); + return NULL; #endif - /* MLP = NO */ - case GNUNET_NO: - GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 0, GNUNET_NO); - ats_mode = SIMPLE; break; - /* No configuration value */ - case GNUNET_SYSERR: - GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 0, GNUNET_NO); - ats_mode = SIMPLE; + case MODE_SIMPLISTIC: + /* Init the simplistic solver with default values */ + ah->ats_mode = MODE_SIMPLISTIC; + ah->s_init = &GAS_simplistic_init; + ah->s_add = &GAS_simplistic_address_add; + ah->s_update = &GAS_simplistic_address_update; + ah->s_get = &GAS_simplistic_get_preferred_address; + ah->s_pref = &GAS_simplistic_address_change_preference; + ah->s_del = &GAS_simplistic_address_delete; + ah->s_done = &GAS_simplistic_done; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS started in %s mode\n", "SIMPLISTIC"); break; default: + return NULL; break; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS started with %s mode\n", (SIMPLE == ats_mode) ? "SIMPLE" : "MLP"); - running = GNUNET_YES; + + GNUNET_assert (NULL != ah->s_init); + GNUNET_assert (NULL != ah->s_add); + GNUNET_assert (NULL != ah->s_update); + GNUNET_assert (NULL != ah->s_get); + GNUNET_assert (NULL != ah->s_pref); + GNUNET_assert (NULL != ah->s_del); + GNUNET_assert (NULL != ah->s_done); + + quota_count = load_quotas(cfg, quotas_in, quotas_out, GNUNET_ATS_NetworkTypeCount); + + ah->solver = ah->s_init (cfg, stats, quotas, quotas_in, quotas_out, quota_count, &bandwidth_changed_cb, ah); + if (NULL == ah->solver) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to initialize solver!\n"); + GNUNET_free (ah); + return NULL; + } + + /* up and running */ + ah->running = GNUNET_YES; + return ah; } @@ -903,24 +1215,28 @@ GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg, * @return GNUNET_OK (continue to iterate) */ static int -free_address_it (void *cls, const GNUNET_HashCode * key, void *value) +free_address_it (void *cls, const struct GNUNET_HashCode * key, void *value) { + struct GAS_Addresses_Handle *handle = cls; struct ATS_Address *aa = value; - - destroy_address (aa); + handle->s_del (handle->solver, handle->addresses, aa, GNUNET_NO); + destroy_address (handle, aa); return GNUNET_OK; } void -GAS_addresses_destroy_all () +GAS_addresses_destroy_all (struct GAS_Addresses_Handle *handle) { - if (GNUNET_NO == running) + if (GNUNET_NO == handle->running) return; - if (addresses != NULL) - GNUNET_CONTAINER_multihashmap_iterate (addresses, &free_address_it, NULL); - GNUNET_assert (active_addr_count == 0); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s'\n", + "DESTROY ALL"); + + if (handle->addresses != NULL) + GNUNET_CONTAINER_multihashmap_iterate (handle->addresses, &free_address_it, handle); } @@ -928,18 +1244,147 @@ GAS_addresses_destroy_all () * Shutdown address subsystem. */ void -GAS_addresses_done () +GAS_addresses_done (struct GAS_Addresses_Handle *handle) { - GAS_addresses_destroy_all (); - running = GNUNET_NO; - GNUNET_CONTAINER_multihashmap_destroy (addresses); - addresses = NULL; -#if HAVE_LIBGLPK - if (ats_mode == MLP) + struct GAS_Addresses_Suggestion_Requests *cur; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Shutting down addresses\n"); + GNUNET_assert (NULL != handle); + GAS_addresses_destroy_all (handle); + handle->running = GNUNET_NO; + GNUNET_CONTAINER_multihashmap_destroy (handle->addresses); + handle->addresses = NULL; + while (NULL != (cur = handle->r_head)) { - GAS_mlp_done (mlp); + GNUNET_CONTAINER_DLL_remove (handle->r_head, handle->r_tail, cur); + GNUNET_free (cur); } -#endif + handle->s_done (handle->solver); + GNUNET_free (handle); + /* Stop configured solution method */ + +} + +struct PeerIteratorContext +{ + GNUNET_ATS_Peer_Iterator it; + void *it_cls; + struct GNUNET_CONTAINER_MultiHashMap *peers_returned; +}; + +static int +peer_it (void *cls, + const struct GNUNET_HashCode * key, + void *value) +{ + struct PeerIteratorContext *ip_ctx = cls; + struct GNUNET_PeerIdentity tmp; + + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(ip_ctx->peers_returned, key)) + { + GNUNET_CONTAINER_multihashmap_put(ip_ctx->peers_returned, key, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); + tmp.hashPubKey = (*key); + ip_ctx->it (ip_ctx->it_cls, &tmp); + } + + return GNUNET_OK; +} + +/** + * Return all peers currently known to ATS + * + * @param handle the address handle + * @param p_it the iterator to call for every peer, callbach with id == NULL + * when done + * @param p_it_cls the closure for the iterator + */ +void +GAS_addresses_iterate_peers (struct GAS_Addresses_Handle *handle, GNUNET_ATS_Peer_Iterator p_it, void *p_it_cls) +{ + struct PeerIteratorContext ip_ctx; + unsigned int size; + + if (NULL == p_it) + return; + GNUNET_assert (NULL != handle->addresses); + + size = GNUNET_CONTAINER_multihashmap_size(handle->addresses); + if (0 != size) + { + ip_ctx.it = p_it; + ip_ctx.it_cls = p_it_cls; + ip_ctx.peers_returned = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_NO); + GNUNET_CONTAINER_multihashmap_iterate (handle->addresses, &peer_it, &ip_ctx); + GNUNET_CONTAINER_multihashmap_destroy (ip_ctx.peers_returned); + } + p_it (p_it_cls, NULL); +} + +struct PeerInfoIteratorContext +{ + GNUNET_ATS_PeerInfo_Iterator it; + void *it_cls; +}; + + +static int +peerinfo_it (void *cls, + const struct GNUNET_HashCode * key, + void *value) +{ + struct PeerInfoIteratorContext *pi_ctx = cls; + struct ATS_Address *addr = (struct ATS_Address *) value; + struct GNUNET_ATS_Information *ats; + uint32_t ats_count; + + if (NULL != pi_ctx->it) + { + ats_count = assemble_ats_information (addr, &ats); + + pi_ctx->it (pi_ctx->it_cls, + &addr->peer, + addr->plugin, + addr->addr, addr->addr_len, + addr->active, + ats, ats_count, + addr->assigned_bw_out, + addr->assigned_bw_in); + GNUNET_free (ats); + } + return GNUNET_YES; +} + + +/** + * Return all peers currently known to ATS + * + * @param handle the address handle + * @param peer the respective peer + * @param pi_it the iterator to call for every peer + * @param pi_it_cls the closure for the iterator + */ +void +GAS_addresses_get_peer_info (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, + GNUNET_ATS_PeerInfo_Iterator pi_it, + void *pi_it_cls) +{ + struct PeerInfoIteratorContext pi_ctx; + struct GNUNET_BANDWIDTH_Value32NBO zero_bw; + GNUNET_assert (NULL != peer); + GNUNET_assert (NULL != handle->addresses); + if (NULL == pi_it) + return; /* does not make sense without callback */ + + zero_bw = GNUNET_BANDWIDTH_value_init (0); + pi_ctx.it = pi_it; + pi_ctx.it_cls = pi_it_cls; + + GNUNET_CONTAINER_multihashmap_get_multiple (handle->addresses, &peer->hashPubKey, &peerinfo_it, &pi_ctx); + + if (NULL != pi_it) + pi_it (pi_it_cls, NULL, NULL, NULL, 0, GNUNET_NO, NULL, 0, zero_bw, zero_bw); } diff --git a/src/ats/gnunet-service-ats_addresses.h b/src/ats/gnunet-service-ats_addresses.h index fe07563..b774cff 100644 --- a/src/ats/gnunet-service-ats_addresses.h +++ b/src/ats/gnunet-service-ats_addresses.h @@ -32,46 +32,88 @@ #include "gnunet_statistics_service.h" #include "ats.h" +#define ATS_BLOCKING_DELTA GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 100) + +struct GAS_Addresses_Handle; + +/** + * Address with additional information + */ struct ATS_Address { + /** + * Next element in DLL + */ struct ATS_Address *next; + /** + * Previous element in DLL + */ struct ATS_Address *prev; + /** + * Peer ID + */ struct GNUNET_PeerIdentity peer; - size_t addr_len; - + /** + * Session ID, 0 if no session is given + */ uint32_t session_id; - uint32_t ats_count; - + /** + * Address + */ const void *addr; - char *plugin; + /** + * Address length + */ + size_t addr_len; - void *mlp_information; + /** + * Plugin name + */ + char *plugin; - struct GNUNET_ATS_Information *ats; + /** + * Solver specific information for this address + */ + void *solver_information; + /* CHECK USAGE */ struct GNUNET_TIME_Relative atsp_latency; + /* CHECK USAGE */ struct GNUNET_BANDWIDTH_Value32NBO atsp_utilization_in; + /* CHECK USAGE */ struct GNUNET_BANDWIDTH_Value32NBO atsp_utilization_out; + + /* CHECK USAGE */ uint32_t atsp_distance; + /* CHECK USAGE */ uint32_t atsp_cost_wan; + /* CHECK USAGE */ uint32_t atsp_cost_lan; + /* CHECK USAGE */ uint32_t atsp_cost_wlan; + /* CHECK USAGE */ uint32_t atsp_network_type; + /** + * Inbound bandwidth assigned by solver in NBO + */ struct GNUNET_BANDWIDTH_Value32NBO assigned_bw_in; + /** + * Outbound bandwidth assigned by solver in NBO + */ struct GNUNET_BANDWIDTH_Value32NBO assigned_bw_out; /** @@ -95,36 +137,128 @@ struct ATS_Address int used; }; + +/** + * Callback to call from solver when bandwidth for address has changed + * + * @param address the with changed bandwidth assigned + */ + +typedef void + (*GAS_bandwidth_changed_cb) (void *cls, struct ATS_Address *address); + +/** + * Init the simplistic problem solving component + * + * Quotas: + * network[i] contains the network type as type GNUNET_ATS_NetworkType[i] + * out_quota[i] contains outbound quota for network type i + * in_quota[i] contains inbound quota for network type i + * + * Example + * network = {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN} + * network[2] == GNUNET_ATS_NET_LAN + * out_quota[2] == 65353 + * in_quota[2] == 65353 + * + * @param cfg configuration handle + * @param stats the GNUNET_STATISTICS handle + * @param network array of GNUNET_ATS_NetworkType with length dest_length + * @param out_quota array of outbound quotas + * @param in_quota array of outbound quota + * @param bw_changed_cb callback to call when assigned changes + * @return handle for the solver on success, NULL on fail + */ +typedef void * + (*GAS_solver_init) (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_STATISTICS_Handle *stats, + int *network, + unsigned long long *out_quota, + unsigned long long *in_quota, + int dest_length, + GAS_bandwidth_changed_cb bw_changed_cb, + void *bw_changed_cb_cls); + + +typedef void +(*GAS_solver_address_change_preference) (void *solver, + void *client, + const struct GNUNET_PeerIdentity *peer, + enum GNUNET_ATS_PreferenceKind kind, + float score); + +/** + * Add a single address to the solver + * + * @param solver the solver Handle + * @param addresses the address hashmap containing all addresses + * @param address the address to add + */ +typedef void +(*GAS_solver_address_add) (void *solver, + struct GNUNET_CONTAINER_MultiHashMap * addresses, + struct ATS_Address *address); + + + +typedef void + (*GAS_solver_address_delete) (void *solver, + struct GNUNET_CONTAINER_MultiHashMap *addresses, + struct ATS_Address *address, + int session_only); + +typedef void +(*GAS_solver_address_update) (void *solver, + struct GNUNET_CONTAINER_MultiHashMap *addresses, + struct ATS_Address *address, + uint32_t session, + int in_use, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count); + + +typedef const struct ATS_Address * +(*GAS_solver_get_preferred_address) (void *solver, + struct GNUNET_CONTAINER_MultiHashMap *addresses, + const struct GNUNET_PeerIdentity *peer); + + +typedef void + (*GAS_solver_done) (void *solver); + + /** * Initialize address subsystem. * * @param cfg configuration to use * @param stats the statistics handle to use */ -void +struct GAS_Addresses_Handle * GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_STATISTICS_Handle *stats); - /** * Shutdown address subsystem. */ void -GAS_addresses_done (void); +GAS_addresses_done (struct GAS_Addresses_Handle *handle); void -GAS_addresses_handle_backoff_reset (const struct GNUNET_PeerIdentity *peer); +GAS_addresses_handle_backoff_reset (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer); /** * This address is now used or not used anymore */ int -GAS_addresses_in_use (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_in_use (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id, int in_use); void -GAS_addresses_update (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_update (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, @@ -132,32 +266,82 @@ GAS_addresses_update (const struct GNUNET_PeerIdentity *peer, void -GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_destroy (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id); void -GAS_addresses_destroy_all (void); +GAS_addresses_destroy_all (struct GAS_Addresses_Handle *handle); -// FIXME: this function should likely end up in the LP-subsystem and -// not with 'addresses' in the future... -// Note: this call should trigger an address suggestion -// (GAS_scheduling_transmit_address_suggestion) +/** + * Cancel address suggestions for a peer + * + * @param peer the respective peer + */ void -GAS_addresses_request_address (const struct GNUNET_PeerIdentity *peer); +GAS_addresses_request_address_cancel (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer); +void +GAS_addresses_request_address (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer); -// FIXME: this function should likely end up in the LP-subsystem and -// not with 'addresses' in the future... void -GAS_addresses_change_preference (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_change_preference (struct GAS_Addresses_Handle *handle, + void *client, + const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, float score); +void +GAS_addresses_add (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, + const char *plugin_name, const void *plugin_addr, + size_t plugin_addr_len, uint32_t session_id, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count); + + +typedef void (*GNUNET_ATS_Peer_Iterator) (void *p_it_cls, + const struct GNUNET_PeerIdentity *id); -/* FIXME: add performance request API */ +/** + * Return all peers currently known to ATS + * + * @param p_it the iterator to call for every peer + * @param p_it_cls the closure for the iterator + */ +void +GAS_addresses_iterate_peers (struct GAS_Addresses_Handle *handle, + GNUNET_ATS_Peer_Iterator p_it, + void *p_it_cls); + +typedef void (*GNUNET_ATS_PeerInfo_Iterator) (void *p_it_cls, + const struct GNUNET_PeerIdentity *id, + const char *plugin_name, + const void *plugin_addr, size_t plugin_addr_len, + const int address_active, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count, + struct GNUNET_BANDWIDTH_Value32NBO + bandwidth_out, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in); + +/** + * Return information all peers currently known to ATS + * + * @param peer the respective peer + * @param pi_it the iterator to call for every peer + * @param pi_it_cls the closure for the iterator + */ +void +GAS_addresses_get_peer_info (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, + GNUNET_ATS_PeerInfo_Iterator pi_it, + void *pi_it_cls); #endif diff --git a/src/ats/gnunet-service-ats_addresses_mlp.c b/src/ats/gnunet-service-ats_addresses_mlp.c index 8bfa010..98a77ae 100644 --- a/src/ats/gnunet-service-ats_addresses_mlp.c +++ b/src/ats/gnunet-service-ats_addresses_mlp.c @@ -31,6 +31,8 @@ #include "gnunet_statistics_service.h" #include "glpk.h" +#define LOG(kind,...) GNUNET_log_from (kind, "ats-mlp",__VA_ARGS__) + #define WRITE_MLP GNUNET_NO #define DEBUG_ATS GNUNET_NO #define VERBOSE_GLPK GNUNET_NO @@ -48,68 +50,46 @@ mlp_solve_to_string (int retcode) switch (retcode) { case 0: return "ok"; - break; case GLP_EBADB: return "invalid basis"; - break; case GLP_ESING: return "singular matrix"; - break; case GLP_ECOND: return "ill-conditioned matrix"; - break; case GLP_EBOUND: return "invalid bounds"; - break; case GLP_EFAIL: return "solver failed"; - break; case GLP_EOBJLL: return "objective lower limit reached"; - break; case GLP_EOBJUL: return "objective upper limit reached"; - break; case GLP_EITLIM: return "iteration limit exceeded"; - break; case GLP_ETMLIM: return "time limit exceeded"; - break; case GLP_ENOPFS: return "no primal feasible solution"; - break; case GLP_EROOT: return "root LP optimum not provided"; - break; case GLP_ESTOP: return "search terminated by application"; - break; case GLP_EMIPGAP: return "relative mip gap tolerance reached"; - break; case GLP_ENOFEAS: return "no dual feasible solution"; - break; case GLP_ENOCVG: return "no convergence"; - break; case GLP_EINSTAB: return "numerical instability"; - break; case GLP_EDATA: return "invalid data"; - break; case GLP_ERANGE: return "result out of range"; - break; default: GNUNET_break (0); return "unknown error"; - break; } - GNUNET_break (0); - return "unknown error"; } @@ -124,29 +104,20 @@ mlp_status_to_string (int retcode) switch (retcode) { case GLP_UNDEF: return "solution is undefined"; - break; case GLP_FEAS: return "solution is feasible"; - break; case GLP_INFEAS: return "solution is infeasible"; - break; case GLP_NOFEAS: return "no feasible solution exists"; - break; case GLP_OPT: return "solution is optimal"; - break; case GLP_UNBND: return "solution is unbounded"; - break; default: GNUNET_break (0); return "unknown error"; - break; } - GNUNET_break (0); - return "unknown error"; } /** @@ -162,37 +133,26 @@ mlp_ats_to_string (int ats_index) switch (ats_index) { case GNUNET_ATS_ARRAY_TERMINATOR: return "GNUNET_ATS_ARRAY_TERMINATOR"; - break; case GNUNET_ATS_UTILIZATION_UP: return "GNUNET_ATS_UTILIZATION_UP"; - break; case GNUNET_ATS_UTILIZATION_DOWN: return "GNUNET_ATS_UTILIZATION_DOWN"; - break; case GNUNET_ATS_COST_LAN: return "GNUNET_ATS_COST_LAN"; - break; case GNUNET_ATS_COST_WAN: return "GNUNET_ATS_COST_LAN"; - break; case GNUNET_ATS_COST_WLAN: return "GNUNET_ATS_COST_WLAN"; - break; case GNUNET_ATS_NETWORK_TYPE: return "GNUNET_ATS_NETWORK_TYPE"; - break; case GNUNET_ATS_QUALITY_NET_DELAY: return "GNUNET_ATS_QUALITY_NET_DELAY"; - break; case GNUNET_ATS_QUALITY_NET_DISTANCE: return "GNUNET_ATS_QUALITY_NET_DISTANCE"; - break; default: + GNUNET_break (0); return "unknown"; - break; } - GNUNET_break (0); - return "unknown error"; } /** @@ -278,7 +238,7 @@ mlp_delete_problem (struct GAS_MLP_Handle *mlp) * @return GNUNET_OK to continue */ static int -create_constraint_it (void *cls, const GNUNET_HashCode * key, void *value) +create_constraint_it (void *cls, const struct GNUNET_HashCode * key, void *value) { struct GAS_MLP_Handle *mlp = cls; struct ATS_Address *address = value; @@ -286,8 +246,8 @@ create_constraint_it (void *cls, const GNUNET_HashCode * key, void *value) unsigned int row_index; char *name; - GNUNET_assert (address->mlp_information != NULL); - mlpi = (struct MLP_information *) address->mlp_information; + GNUNET_assert (address->solver_information != NULL); + mlpi = (struct MLP_information *) address->solver_information; /* c 1) bandwidth capping * b_t + (-M) * n_t <= 0 @@ -379,6 +339,7 @@ create_constraint_it (void *cls, const GNUNET_HashCode * key, void *value) return GNUNET_OK; } +#if 0 /** * Find the required ATS information for an address * @@ -387,7 +348,6 @@ create_constraint_it (void *cls, const GNUNET_HashCode * key, void *value) * * @return the index on success, otherwise GNUNET_SYSERR */ - static int mlp_lookup_ats (struct ATS_Address *addr, int ats_index) { @@ -407,6 +367,7 @@ mlp_lookup_ats (struct ATS_Address *addr, int ats_index) else return GNUNET_SYSERR; } +#endif /** * Adds the problem constraints for all addresses @@ -599,7 +560,7 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON /* For all addresses of this peer */ while (addr != NULL) { - mlpi = (struct MLP_information *) addr->mlp_information; + mlpi = (struct MLP_information *) addr->solver_information; /* coefficient for c 2) */ ia[mlp->ci] = peer->r_c2; @@ -650,7 +611,7 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON for (tp = mlp->peer_head; tp != NULL; tp = tp->next) for (ta = tp->head; ta != NULL; ta = ta->next) { - mlpi = ta->mlp_information; + mlpi = ta->solver_information; value = mlpi->q_averaged[c]; mlpi->r_q[c] = mlp->r_q[c]; @@ -674,7 +635,7 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON * @return GNUNET_OK to continue */ static int -create_columns_it (void *cls, const GNUNET_HashCode * key, void *value) +create_columns_it (void *cls, const struct GNUNET_HashCode * key, void *value) { struct GAS_MLP_Handle *mlp = cls; struct ATS_Address *address = value; @@ -682,8 +643,8 @@ create_columns_it (void *cls, const GNUNET_HashCode * key, void *value) unsigned int col; char *name; - GNUNET_assert (address->mlp_information != NULL); - mlpi = address->mlp_information; + GNUNET_assert (address->solver_information != NULL); + mlpi = address->solver_information; /* Add bandwidth column */ col = glp_add_cols (mlp->prob, 2); @@ -866,7 +827,7 @@ lp_solv: end = GNUNET_TIME_absolute_get (); duration = GNUNET_TIME_absolute_get_difference (start, end); mlp->lp_solved++; - mlp->lp_total_duration =+ duration.rel_value; + mlp->lp_total_duration += duration.rel_value; s_ctx->lp_duration = duration; GNUNET_STATISTICS_update (mlp->stats,"# LP problem solved", 1, GNUNET_NO); @@ -943,7 +904,7 @@ mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContex end = GNUNET_TIME_absolute_get (); duration = GNUNET_TIME_absolute_get_difference (start, end); mlp->mlp_solved++; - mlp->mlp_total_duration =+ duration.rel_value; + mlp->mlp_total_duration += duration.rel_value; s_ctx->mlp_duration = duration; GNUNET_STATISTICS_update (mlp->stats,"# MLP problem solved", 1, GNUNET_NO); @@ -972,7 +933,7 @@ mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContex return GNUNET_OK; } -int GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContext *ctx); +int GAS_mlp_solve_problem (void *solver, struct GAS_MLP_SolutionContext *ctx); static void @@ -996,13 +957,14 @@ mlp_scheduler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** * Solves the MLP problem * - * @param mlp the MLP Handle + * @param solver the MLP Handle * @param ctx solution context * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure */ int -GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContext *ctx) +GAS_mlp_solve_problem (void *solver, struct GAS_MLP_SolutionContext *ctx) { + struct GAS_MLP_Handle *mlp = solver; int res; /* Check if solving is already running */ if (GNUNET_YES == mlp->semaphore) @@ -1080,7 +1042,7 @@ GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContex double b = 0.0; double n = 0.0; - mlpi = a->mlp_information; + mlpi = a->solver_information; b = glp_mip_col_val(mlp->prob, mlpi->c_b); mlpi->b = b; @@ -1111,15 +1073,23 @@ GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContex * * @param cfg the GNUNET_CONFIGURATION_Handle handle * @param stats the GNUNET_STATISTICS handle - * @param max_duration maximum numbers of iterations for the LP/MLP Solver - * @param max_iterations maximum time limit for the LP/MLP Solver - * @return struct GAS_MLP_Handle * on success, NULL on fail + * @param network array of GNUNET_ATS_NetworkType with length dest_length + * @param out_dest array of outbound quotas + * @param in_dest array of outbound quota + * @param dest_length array length for quota arrays + * @param bw_changed_cb callback for changed bandwidth amounts + * @param bw_changed_cb_cls cls for callback + * @return struct GAS_MLP_Handle on success, NULL on fail */ -struct GAS_MLP_Handle * +void * GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_STATISTICS_Handle *stats, - struct GNUNET_TIME_Relative max_duration, - unsigned int max_iterations) + int *network, + unsigned long long *out_dest, + unsigned long long *in_dest, + int dest_length, + GAS_bandwidth_changed_cb bw_changed_cb, + void *bw_changed_cb_cls) { struct GAS_MLP_Handle * mlp = GNUNET_malloc (sizeof (struct GAS_MLP_Handle)); @@ -1134,6 +1104,9 @@ GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg, char * quota_out_str; char * quota_in_str; + struct GNUNET_TIME_Relative max_duration; + long long unsigned int max_iterations; + /* Init GLPK environment */ int res = glp_init_env(); switch (res) { @@ -1167,6 +1140,18 @@ GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg, mlp->BIG_M = (double) BIG_M_VALUE; + /* Get timeout for iterations */ + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time(cfg, "ats", "MAX_DURATION", &max_duration)) + { + max_duration = MLP_MAX_EXEC_DURATION; + } + + /* Get maximum number of iterations */ + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_size(cfg, "ats", "MAX_ITERATIONS", &max_iterations)) + { + max_iterations = MLP_MAX_ITERATIONS; + } + /* Get diversity coefficient from configuration */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (cfg, "ats", "COEFFICIENT_D", @@ -1388,29 +1373,33 @@ update_quality (struct GAS_MLP_Handle *mlp, struct ATS_Address * address) GNUNET_i2s (&address->peer)); GNUNET_assert (NULL != address); - GNUNET_assert (NULL != address->mlp_information); - GNUNET_assert (NULL != address->ats); + GNUNET_assert (NULL != address->solver_information); +// GNUNET_assert (NULL != address->ats); - struct MLP_information *mlpi = address->mlp_information; - struct GNUNET_ATS_Information *ats = address->ats; + struct MLP_information *mlpi = address->solver_information; + //struct GNUNET_ATS_Information *ats = address->ats; GNUNET_assert (mlpi != NULL); int c; for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++) { - int index = mlp_lookup_ats(address, mlp->q[c]); + + /* FIXME int index = mlp_lookup_ats(address, mlp->q[c]); */ + int index = GNUNET_SYSERR; if (index == GNUNET_SYSERR) continue; - + /* FIXME GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating address for peer `%s' value `%s': %f\n", GNUNET_i2s (&address->peer), mlp_ats_to_string(mlp->q[c]), (double) ats[index].value); - int i = mlpi->q_avg_i[c]; + int i = mlpi->q_avg_i[c];*/ double * qp = mlpi->q[c]; + /* FIXME qp[i] = (double) ats[index].value; + */ int t; for (t = 0; t < MLP_AVERAGING_QUEUE_LENGTH; t++) @@ -1538,6 +1527,20 @@ update_quality (struct GAS_MLP_Handle *mlp, struct ATS_Address * address) } } + +/** + * Add a single address to the solve + * + * @param solver the solver Handle + * @param addresses the address hashmap containing all addresses + * @param address the address to add + */ +void +GAS_mlp_address_add (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address) +{ + +} + /** * Updates a single address in the MLP problem * @@ -1547,14 +1550,24 @@ update_quality (struct GAS_MLP_Handle *mlp, struct ATS_Address * address) * Otherwise the addresses' values can be updated and the existing base can * be reused * - * @param mlp the MLP Handle - * @param addresses the address hashmap - * the address has to be already removed from the hashmap - * @param address the address to update + * @param solver the solver Handle + * @param addresses the address hashmap containing all addresses + * @param address the update address + * @param session the new session (if changed otherwise current) + * @param in_use the new address in use state (if changed otherwise current) + * @param atsi the latest ATS information + * @param atsi_count the atsi count */ void -GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address) +GAS_mlp_address_update (void *solver, + struct GNUNET_CONTAINER_MultiHashMap *addresses, + struct ATS_Address *address, + uint32_t session, + int in_use, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count) { + struct GAS_MLP_Handle *mlp = solver; int new; struct MLP_information *mlpi; struct GAS_MLP_SolutionContext ctx; @@ -1562,7 +1575,7 @@ GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult GNUNET_STATISTICS_update (mlp->stats, "# MLP address updates", 1, GNUNET_NO); /* We add a new address */ - if (address->mlp_information == NULL) + if (address->solver_information == NULL) new = GNUNET_YES; else new = GNUNET_NO; @@ -1583,7 +1596,7 @@ GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult mlpi->q_averaged[c] = 0.0; } - address->mlp_information = mlpi; + address->solver_information = mlpi; mlp->addr_in_problem ++; GNUNET_STATISTICS_update (mlp->stats, "# addresses in MLP", 1, GNUNET_NO); @@ -1650,22 +1663,27 @@ GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult * * The MLP problem has to be recreated and the problem has to be resolved * - * @param mlp the MLP Handle + * @param solver the MLP Handle * @param addresses the address hashmap * the address has to be already removed from the hashmap * @param address the address to delete + * @param session_only delete only session not whole address */ void -GAS_mlp_address_delete (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address) +GAS_mlp_address_delete (void *solver, + struct GNUNET_CONTAINER_MultiHashMap * addresses, + struct ATS_Address *address, + int session_only) { + struct GAS_MLP_Handle *mlp = solver; GNUNET_STATISTICS_update (mlp->stats,"# LP address deletions", 1, GNUNET_NO); struct GAS_MLP_SolutionContext ctx; /* Free resources */ - if (address->mlp_information != NULL) + if (address->solver_information != NULL) { - GNUNET_free (address->mlp_information); - address->mlp_information = NULL; + GNUNET_free (address->solver_information); + address->solver_information = NULL; mlp->addr_in_problem --; GNUNET_STATISTICS_update (mlp->stats, "# addresses in MLP", -1, GNUNET_NO); @@ -1706,22 +1724,22 @@ GAS_mlp_address_delete (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult } static int -mlp_get_preferred_address_it (void *cls, const GNUNET_HashCode * key, void *value) +mlp_get_preferred_address_it (void *cls, const struct GNUNET_HashCode * key, void *value) { - struct ATS_PreferedAddress *aa = (struct ATS_PreferedAddress *) cls; + struct ATS_Address *aa = (struct ATS_Address *) cls; struct ATS_Address *addr = value; - struct MLP_information *mlpi = addr->mlp_information; + struct MLP_information *mlpi = addr->solver_information; if (mlpi == NULL) return GNUNET_YES; if (mlpi->n == GNUNET_YES) { - aa->address = addr; + aa = addr; if (mlpi->b > (double) UINT32_MAX) - aa->bandwidth_out = UINT32_MAX; + aa->assigned_bw_out.value__ = htonl (UINT32_MAX); else - aa->bandwidth_out = (uint32_t) mlpi->b; - aa->bandwidth_in = 0; + aa->assigned_bw_out.value__ = htonl((uint32_t) mlpi->b); + aa->assigned_bw_in.value__ = htonl(0); return GNUNET_NO; } return GNUNET_YES; @@ -1731,20 +1749,17 @@ mlp_get_preferred_address_it (void *cls, const GNUNET_HashCode * key, void *valu /** * Get the preferred address for a specific peer * - * @param mlp the MLP Handle + * @param solver the MLP Handle * @param addresses address hashmap * @param peer the peer * @return suggested address */ -struct ATS_PreferedAddress * -GAS_mlp_get_preferred_address (struct GAS_MLP_Handle *mlp, +const struct ATS_Address * +GAS_mlp_get_preferred_address (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, const struct GNUNET_PeerIdentity *peer) { - struct ATS_PreferedAddress * aa = GNUNET_malloc (sizeof (struct ATS_PreferedAddress)); - aa->address = NULL; - aa->bandwidth_in = 0; - aa->bandwidth_out = 0; + struct ATS_Address * aa = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting preferred address for `%s'\n", GNUNET_i2s (peer)); GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey, mlp_get_preferred_address_it, aa); return aa; @@ -1754,31 +1769,37 @@ GAS_mlp_get_preferred_address (struct GAS_MLP_Handle *mlp, /** * Changes the preferences for a peer in the MLP problem * - * @param mlp the MLP Handle + * @param solver the MLP Handle + * @param client client * @param peer the peer * @param kind the kind to change the preference * @param score the score */ void -GAS_mlp_address_change_preference (struct GAS_MLP_Handle *mlp, +GAS_mlp_address_change_preference (void *solver, + void *client, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, float score) { + struct GAS_MLP_Handle *mlp = solver; GNUNET_STATISTICS_update (mlp->stats,"# LP address preference changes", 1, GNUNET_NO); - struct ATS_Peer *p = mlp_find_peer (mlp, peer); - p = p; + //struct ATS_Peer *p = mlp_find_peer (mlp, peer); + //FIXME to finish implementation /* Here we have to do the matching */ + } /** * Shutdown the MLP problem solving component - * @param mlp the MLP handle + * + * @param solver the solver handle */ void -GAS_mlp_done (struct GAS_MLP_Handle *mlp) +GAS_mlp_done (void *solver) { + struct GAS_MLP_Handle *mlp = solver; struct ATS_Peer * peer; struct ATS_Address *addr; @@ -1799,8 +1820,8 @@ GAS_mlp_done (struct GAS_MLP_Handle *mlp) for (addr = peer->head; NULL != addr; addr = peer->head) { GNUNET_CONTAINER_DLL_remove(peer->head, peer->tail, addr); - GNUNET_free (addr->mlp_information); - addr->mlp_information = NULL; + GNUNET_free (addr->solver_information); + addr->solver_information = NULL; } GNUNET_free (peer); peer = mlp->peer_head; diff --git a/src/ats/gnunet-service-ats_addresses_mlp.h b/src/ats/gnunet-service-ats_addresses_mlp.h index d37eea7..a49f585 100644 --- a/src/ats/gnunet-service-ats_addresses_mlp.h +++ b/src/ats/gnunet-service-ats_addresses_mlp.h @@ -20,7 +20,7 @@ /** * @file ats/gnunet-service-ats_addresses_mlp.h - * @brief ats mlp problem solver + * @brief ats MLP problem solver * @author Matthias Wachs * @author Christian Grothoff */ @@ -34,8 +34,6 @@ #ifndef GNUNET_SERVICE_ATS_ADDRESSES_MLP_H #define GNUNET_SERVICE_ATS_ADDRESSES_MLP_H -#define DEBUG_MLP GNUNET_EXTRA_LOGGING - #define BIG_M_VALUE (UINT32_MAX) /10 #define BIG_M_STRING "unlimited" @@ -66,13 +64,6 @@ struct ATS_Peer struct ATS_Address *tail; }; -struct ATS_PreferedAddress -{ - uint32_t bandwidth_out; - uint32_t bandwidth_in; - struct ATS_Address *address; -}; - struct GAS_MLP_SolutionContext { int lp_result; @@ -105,12 +96,20 @@ struct GAS_MLP_Handle /** * GLPK LP control parameter */ +#if HAVE_LIBGLPK glp_smcp control_param_lp; +#else + void *control_param_lp; +#endif /** * GLPK LP control parameter */ +#if HAVE_LIBGLPK glp_iocp control_param_mlp; +#else + void *control_param_mlp; +#endif /** * Solves the task in an regular interval @@ -317,26 +316,34 @@ struct MLP_information * * @param cfg configuration handle * @param stats the GNUNET_STATISTICS handle - * @param max_duration maximum numbers of iterations for the LP/MLP Solver - * @param max_iterations maximum time limit for the LP/MLP Solver - * @return struct GAS_MLP_Handle * on success, NULL on fail + * @param network array of GNUNET_ATS_NetworkType with length dest_length + * @param out_dest array of outbound quotas + * @param in_dest array of outbound quota + * @param dest_length array length for quota arrays + * @param bw_changed_cb callback for changed bandwidth amounts + * @param bw_changed_cb_cls cls for callback + * @return struct GAS_MLP_Handle on success, NULL on fail */ -struct GAS_MLP_Handle * +void * GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_STATISTICS_Handle *stats, - struct GNUNET_TIME_Relative max_duration, - unsigned int max_iterations); + int *network, + unsigned long long *out_dest, + unsigned long long *in_dest, + int dest_length, + GAS_bandwidth_changed_cb bw_changed_cb, + void *bw_changed_cb_cls); + /** - * Solves the MLP problem on demand + * Add a single address to the solve * - * @param mlp the MLP Handle - * @param ctx solution context - * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure + * @param solver the solver Handle + * @param addresses the address hashmap containing all addresses + * @param address the address to add */ -int -GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContext *ctx); - +void +GAS_mlp_address_add (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address); /** * Updates a single address in the MLP problem @@ -347,13 +354,22 @@ GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContex * Otherwise the addresses' values can be updated and the existing base can * be reused * - * @param mlp the MLP Handle - * @param addresses the address hashmap - * the address has to be already added from the hashmap - * @param address the address to update + * @param solver the solver Handle + * @param addresses the address hashmap containing all addresses + * @param address the update address + * @param session the new session (if changed otherwise current) + * @param in_use the new address in use state (if changed otherwise current) + * @param atsi the latest ATS information + * @param atsi_count the atsi count */ void -GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address); +GAS_mlp_address_update (void *solver, + struct GNUNET_CONTAINER_MultiHashMap *addresses, + struct ATS_Address *address, + uint32_t session, + int in_use, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count); /** @@ -361,25 +377,31 @@ GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult * * The MLP problem has to be recreated and the problem has to be resolved * - * @param mlp the MLP Handle + * @param solver the MLP Handle * @param addresses the address hashmap * the address has to be already removed from the hashmap * @param address the address to delete + * @param session_only delete only session not whole address */ void -GAS_mlp_address_delete (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address); +GAS_mlp_address_delete (void *solver, + struct GNUNET_CONTAINER_MultiHashMap *addresses, + struct ATS_Address *address, + int session_only); /** * Changes the preferences for a peer in the MLP problem * - * @param mlp the MLP Handle + * @param solver the MLP Handle + * @param client client * @param peer the peer * @param kind the kind to change the preference * @param score the score */ void -GAS_mlp_address_change_preference (struct GAS_MLP_Handle *mlp, +GAS_mlp_address_change_preference (void *solver, + void *client, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, float score); @@ -388,21 +410,23 @@ GAS_mlp_address_change_preference (struct GAS_MLP_Handle *mlp, /** * Get the preferred address for a specific peer * - * @param mlp the MLP Handle + * @param solver the MLP Handle * @param addresses address hashmap * @param peer the peer * @return suggested address */ -struct ATS_PreferedAddress * -GAS_mlp_get_preferred_address (struct GAS_MLP_Handle *mlp, +const struct ATS_Address * +GAS_mlp_get_preferred_address (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, const struct GNUNET_PeerIdentity *peer); /** * Shutdown the MLP problem solving component + * + * @param solver the solver handle */ void -GAS_mlp_done (); +GAS_mlp_done (void *solver); #endif /* end of gnunet-service-ats_addresses_mlp.h */ diff --git a/src/ats/gnunet-service-ats_addresses_simplistic.c b/src/ats/gnunet-service-ats_addresses_simplistic.c new file mode 100644 index 0000000..74a4b43 --- /dev/null +++ b/src/ats/gnunet-service-ats_addresses_simplistic.c @@ -0,0 +1,1377 @@ +/* + This file is part of GNUnet. + (C) 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/gnunet-service-ats_addresses_simplistic.h + * @brief ats simplistic ressource assignment + * @author Matthias Wachs + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet-service-ats_addresses.h" +#include "gnunet_statistics_service.h" + +#define LOG(kind,...) GNUNET_log_from (kind, "ats-simplistic",__VA_ARGS__) + +/** + * ATS simplistic solver + * + * Assigns in and outbound bandwidth equally for all addresses in specific + * network type (WAN, LAN) based on configured in and outbound quota for this + * network. + * + * For each peer only a single is selected and marked as "active" in the address + * struct. + * + * E.g.: + * + * You have the networks WAN and LAN and quotas + * WAN_TOTAL_IN, WAN_TOTAL_OUT + * LAN_TOTAL_IN, LAN_TOTAL_OUT + * + * If you have x addresses in the network segment LAN, the quotas are + * QUOTA_PER_ADDRESS = LAN_TOTAL_OUT / x + * + * Quotas are automatically recalculated and reported back when addresses are + * - requested + * + */ + +#define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) +#define PREF_AGING_FACTOR 0.95 + +#define DEFAULT_PREFERENCE 1.0 +#define MIN_UPDATE_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +/** + * A handle for the simplistic solver + */ +struct GAS_SIMPLISTIC_Handle +{ + /** + * Statistics handle + */ + + struct GNUNET_STATISTICS_Handle *stats; + + /** + * Total number of addresses for solver + */ + unsigned int total_addresses; + + /** + * Number of active addresses for solver + */ + unsigned int active_addresses; + + /** + * Networks array + */ + struct Network *network_entries; + + /** + * Number of networks + */ + unsigned int networks; + + /** + * Callback + */ + GAS_bandwidth_changed_cb bw_changed; + + /** + * Callback cls + */ + void *bw_changed_cls; + + struct GNUNET_CONTAINER_MultiHashMap *prefs; + + struct PreferenceClient *pc_head; + struct PreferenceClient *pc_tail; +}; + +struct Network +{ + /** + * ATS network type + */ + unsigned int type; + + /** + * Network description + */ + char *desc; + + /** + * Total inbound quota + * + */ + unsigned long long total_quota_in; + + /** + * Total outbound quota + * + */ + unsigned long long total_quota_out; + + /** + * Number of active addresses for this network + */ + unsigned int active_addresses; + + /** + * Number of total addresses for this network + */ + unsigned int total_addresses; + + /** + * String for statistics total addresses + */ + char *stat_total; + + /** + * String for statistics active addresses + */ + char *stat_active; + + struct AddressWrapper *head; + struct AddressWrapper *tail; +}; + +struct AddressWrapper +{ + struct AddressWrapper *next; + struct AddressWrapper *prev; + + struct ATS_Address *addr; +}; + + +struct PreferenceClient +{ + struct PreferenceClient *prev; + struct PreferenceClient *next; + void *client; + + double f_total[GNUNET_ATS_PreferenceCount]; + + struct PreferencePeer *p_head; + struct PreferencePeer *p_tail; +}; + + +struct PreferencePeer +{ + struct PreferencePeer *next; + struct PreferencePeer *prev; + struct PreferenceClient *client; + struct GAS_SIMPLISTIC_Handle *s; + struct GNUNET_PeerIdentity id; + + double f[GNUNET_ATS_PreferenceCount]; + double f_rel[GNUNET_ATS_PreferenceCount]; + double f_rel_total; + + GNUNET_SCHEDULER_TaskIdentifier aging_task; +}; + +/** + * Get the prefered address for a specific peer + * + * @param solver the solver handle + * @param addresses the address hashmap containing all addresses + * @param peer the identity of the peer + */ +const struct ATS_Address * +GAS_simplistic_get_preferred_address (void *solver, + struct GNUNET_CONTAINER_MultiHashMap * addresses, + const struct GNUNET_PeerIdentity *peer); + +/** + * Init the simplistic problem solving component + * + * Quotas: + * network[i] contains the network type as type GNUNET_ATS_NetworkType[i] + * out_quota[i] contains outbound quota for network type i + * in_quota[i] contains inbound quota for network type i + * + * Example + * network = {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN} + * network[2] == GNUNET_ATS_NET_LAN + * out_quota[2] == 65353 + * in_quota[2] == 65353 + * + * @param cfg configuration handle + * @param stats the GNUNET_STATISTICS handle + * @param network array of GNUNET_ATS_NetworkType with length dest_length + * @param out_quota array of outbound quotas + * @param in_quota array of outbound quota + * @param dest_length array length for quota arrays + * @param bw_changed_cb callback for changed bandwidth amounts + * @param bw_changed_cb_cls cls for callback + * @return handle for the solver on success, NULL on fail + */ +void * +GAS_simplistic_init (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_STATISTICS_Handle *stats, + int *network, + unsigned long long *out_quota, + unsigned long long *in_quota, + int dest_length, + GAS_bandwidth_changed_cb bw_changed_cb, + void *bw_changed_cb_cls) +{ + int c; + struct GAS_SIMPLISTIC_Handle *s = GNUNET_malloc (sizeof (struct GAS_SIMPLISTIC_Handle)); + struct Network * cur; + char * net_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; + + + s->stats = (struct GNUNET_STATISTICS_Handle *) stats; + s->bw_changed = bw_changed_cb; + s->bw_changed_cls = bw_changed_cb_cls; + s->networks = dest_length; + s->network_entries = GNUNET_malloc (dest_length * sizeof (struct Network)); + s->active_addresses = 0; + s->total_addresses = 0; + s->prefs = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); + + for (c = 0; c < dest_length; c++) + { + cur = &s->network_entries[c]; + cur->total_addresses = 0; + cur->active_addresses = 0; + cur->type = network[c]; + cur->total_quota_in = in_quota[c]; + cur->total_quota_out = out_quota[c]; + cur->desc = net_str[c]; + GNUNET_asprintf (&cur->stat_total, "# ATS addresses %s total", cur->desc); + GNUNET_asprintf (&cur->stat_active, "# ATS active addresses %s total", cur->desc); + } + return s; +} + +static int +free_pref (void *cls, + const struct GNUNET_HashCode * key, + void *value) +{ + float *v = value; + GNUNET_free (v); + return GNUNET_OK; +} + +/** + * Shutdown the simplistic problem solving component + * + * @param solver the respective handle to shutdown + */ +void +GAS_simplistic_done (void *solver) +{ + struct GAS_SIMPLISTIC_Handle *s = solver; + struct PreferenceClient *pc; + struct PreferenceClient *next_pc; + struct PreferencePeer *p; + struct PreferencePeer *next_p; + struct AddressWrapper *cur; + struct AddressWrapper *next; + int c; + GNUNET_assert (s != NULL); + + for (c = 0; c < s->networks; c++) + { + if (s->network_entries[c].total_addresses > 0) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Had %u addresses for network `%s' not deleted during shutdown\n", + s->network_entries[c].total_addresses, + s->network_entries[c].desc); + GNUNET_break (0); + } + + if (s->network_entries[c].active_addresses > 0) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Had %u active addresses for network `%s' not deleted during shutdown\n", + s->network_entries[c].active_addresses, + s->network_entries[c].desc); + GNUNET_break (0); + } + + next = s->network_entries[c].head; + while (NULL != (cur = next)) + { + next = cur->next; + GNUNET_CONTAINER_DLL_remove (s->network_entries[c].head, + s->network_entries[c].tail, + cur); + GNUNET_free (cur); + } + GNUNET_free (s->network_entries[c].stat_total); + GNUNET_free (s->network_entries[c].stat_active); + } + if (s->total_addresses > 0) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Had %u addresses not deleted during shutdown\n", + s->total_addresses); + GNUNET_break (0); + } + if (s->active_addresses > 0) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Had %u active addresses not deleted during shutdown\n", + s->active_addresses); + GNUNET_break (0); + } + GNUNET_free (s->network_entries); + + next_pc = s->pc_head; + while (NULL != (pc = next_pc)) + { + next_pc = pc->next; + GNUNET_CONTAINER_DLL_remove (s->pc_head, s->pc_tail, pc); + next_p = pc->p_head; + while (NULL != (p = next_p)) + { + next_p = p->next; + if (GNUNET_SCHEDULER_NO_TASK != p->aging_task) + { + GNUNET_SCHEDULER_cancel(p->aging_task); + p->aging_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_CONTAINER_DLL_remove (pc->p_head, pc->p_tail, p); + GNUNET_free (p); + } + GNUNET_free (pc); + } + + GNUNET_CONTAINER_multihashmap_iterate (s->prefs, &free_pref, NULL); + GNUNET_CONTAINER_multihashmap_destroy (s->prefs); + GNUNET_free (s); +} + + +/** + * Test if bandwidth is available in this network + * + * @param s the solver handle + * @param net the network type to update + * @return GNUNET_YES or GNUNET_NO + */ + +static int +bw_available_in_network (struct Network *net) +{ + unsigned int na = net->active_addresses + 1; + uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); + if (((net->total_quota_in / na) > min_bw) && + ((net->total_quota_out / na) > min_bw)) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Enough bandwidth available for %u active addresses in network `%s'\n", + na, + net->desc); + + return GNUNET_YES; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Not enough bandwidth available for %u active addresses in network `%s'\n", + na, + net->desc); + return GNUNET_NO; +} + + +/** + * Update the quotas for a network type + * + * @param s the solver handle + * @param net the network type to update + * @param address_except address excluded from notifcation, since we suggest + * this address + */ +static void +update_quota_per_network (struct GAS_SIMPLISTIC_Handle *s, + struct Network *net, + struct ATS_Address *address_except) +{ + unsigned long long remaining_quota_in = 0; + unsigned long long quota_out_used = 0; + + unsigned long long remaining_quota_out = 0; + unsigned long long quota_in_used = 0; + uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); + double total_prefs; /* Important: has to be double not float due to precision */ + double cur_pref; /* Important: has to be double not float due to precision */ + double *t = NULL; /* Important: has to be double not float due to precision */ + + unsigned long long assigned_quota_in = 0; + unsigned long long assigned_quota_out = 0; + struct AddressWrapper *cur; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Recalculate quota for network type `%s' for %u addresses (in/out): %llu/%llu \n", + net->desc, net->active_addresses, net->total_quota_in, net->total_quota_in); + + if (net->active_addresses == 0) + return; /* no addresses to update */ + + /* Idea TODO + * + * Assign every peer in network minimum Bandwidth + * Distribute bandwidth left according to preference + */ + + if ((net->active_addresses * min_bw) > net->total_quota_in) + { + GNUNET_break (0); + return; + } + if ((net->active_addresses * min_bw) > net->total_quota_out) + { + GNUNET_break (0); + return; + } + + remaining_quota_in = net->total_quota_in - (net->active_addresses * min_bw); + remaining_quota_out = net->total_quota_out - (net->active_addresses * min_bw); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Remaining bandwidth : (in/out): %llu/%llu \n", + remaining_quota_in, remaining_quota_out); + total_prefs = 0.0; + for (cur = net->head; NULL != cur; cur = cur->next) + { + if (GNUNET_YES == cur->addr->active) + { + t = GNUNET_CONTAINER_multihashmap_get (s->prefs, &cur->addr->peer.hashPubKey); + if (NULL == t) + total_prefs += DEFAULT_PREFERENCE; + else + { + total_prefs += (*t); + } + } + } + for (cur = net->head; NULL != cur; cur = cur->next) + { + if (GNUNET_YES == cur->addr->active) + { + cur_pref = 0.0; + t = GNUNET_CONTAINER_multihashmap_get (s->prefs, &cur->addr->peer.hashPubKey); + if (NULL == t) + cur_pref = DEFAULT_PREFERENCE; + else + cur_pref = (*t); + assigned_quota_in = min_bw + ((cur_pref / total_prefs) * remaining_quota_in); + assigned_quota_out = min_bw + ((cur_pref / total_prefs) * remaining_quota_out); + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "New quota for peer `%s' with preference (cur/total) %.3f/%.3f (in/out): %llu / %llu\n", + GNUNET_i2s (&cur->addr->peer), + cur_pref, total_prefs, + assigned_quota_in, assigned_quota_out); + } + else + { + assigned_quota_in = 0; + assigned_quota_out = 0; + } + + quota_in_used += assigned_quota_in; + quota_out_used += assigned_quota_out; + /* Prevent overflow due to rounding errors */ + if (assigned_quota_in > UINT32_MAX) + assigned_quota_in = UINT32_MAX; + if (assigned_quota_out > UINT32_MAX) + assigned_quota_out = UINT32_MAX; + + /* Compare to current bandwidth assigned */ + if ((assigned_quota_in != ntohl(cur->addr->assigned_bw_in.value__)) || + (assigned_quota_out != ntohl(cur->addr->assigned_bw_out.value__))) + { + cur->addr->assigned_bw_in.value__ = htonl (assigned_quota_in); + cur->addr->assigned_bw_out.value__ = htonl (assigned_quota_out); + /* Notify on change */ + if ((GNUNET_YES == cur->addr->active) && (cur->addr != address_except)) + s->bw_changed (s->bw_changed_cls, cur->addr); + } + + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Total bandwidth assigned is (in/out): %llu /%llu\n", + quota_in_used, + quota_out_used); + if (quota_out_used > net->total_quota_out + 1) /* +1 is required due to rounding errors */ + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Total outbound bandwidth assigned is larger than allowed (used/allowed) for %u active addresses: %llu / %llu\n", + net->active_addresses, + quota_out_used, + net->total_quota_out); + } + if (quota_in_used > net->total_quota_in + 1) /* +1 is required due to rounding errors */ + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Total inbound bandwidth assigned is larger than allowed (used/allowed) for %u active addresses: %llu / %llu\n", + net->active_addresses, + quota_in_used, + net->total_quota_in); + } +} + +static void +update_all_networks (struct GAS_SIMPLISTIC_Handle *s) +{ + int i; + for (i = 0; i < s->networks; i++) + update_quota_per_network (s, &s->network_entries[i], NULL); + +} + +static void +addresse_increment (struct GAS_SIMPLISTIC_Handle *s, + struct Network *net, + int total, + int active) +{ + if (GNUNET_YES == total) + { + s->total_addresses ++; + net->total_addresses ++; + GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", 1, GNUNET_NO); + GNUNET_STATISTICS_update (s->stats, net->stat_total, 1, GNUNET_NO); + } + if (GNUNET_YES == active) + { + net->active_addresses ++; + s->active_addresses ++; + GNUNET_STATISTICS_update (s->stats, "# ATS active addresses total", 1, GNUNET_NO); + GNUNET_STATISTICS_update (s->stats, net->stat_active, 1, GNUNET_NO); + } + +} + +static int +addresse_decrement (struct GAS_SIMPLISTIC_Handle *s, + struct Network *net, + int total, + int active) +{ + int res = GNUNET_OK; + if (GNUNET_YES == total) + { + if (s->total_addresses < 1) + { + GNUNET_break (0); + res = GNUNET_SYSERR; + } + else + { + s->total_addresses --; + GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", -1, GNUNET_NO); + } + if (net->total_addresses < 1) + { + GNUNET_break (0); + res = GNUNET_SYSERR; + } + else + { + net->total_addresses --; + GNUNET_STATISTICS_update (s->stats, net->stat_total, -1, GNUNET_NO); + } + } + + if (GNUNET_YES == active) + { + if (net->active_addresses < 1) + { + GNUNET_break (0); + res = GNUNET_SYSERR; + } + else + { + net->active_addresses --; + GNUNET_STATISTICS_update (s->stats, net->stat_active, -1, GNUNET_NO); + } + if (s->active_addresses < 1) + { + GNUNET_break (0); + res = GNUNET_SYSERR; + } + else + { + s->active_addresses --; + GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", -1, GNUNET_NO); + } + } + return res; +} + + +/** + * Add a single address to the solve + * + * @param solver the solver Handle + * @param addresses the address hashmap containing all addresses + * @param address the address to add + */ +void +GAS_simplistic_address_add (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address) +{ + struct GAS_SIMPLISTIC_Handle *s = solver; + struct Network *net = NULL; + struct AddressWrapper *aw = NULL; + + GNUNET_assert (NULL != s); + int c; + for (c = 0; c < s->networks; c++) + { + net = &s->network_entries[c]; + if (address->atsp_network_type == net->type) + break; + } + if (NULL == net) + { + GNUNET_break (0); + return; + } + + aw = GNUNET_malloc (sizeof (struct AddressWrapper)); + aw->addr = address; + GNUNET_CONTAINER_DLL_insert (net->head, net->tail, aw); + addresse_increment (s, net, GNUNET_YES, GNUNET_NO); + aw->addr->solver_information = net; + + + 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); +} + +/** + * Remove an address from the solver + * + * @param solver the solver handle + * @param addresses the address hashmap containing all addresses + * @param address the address to remove + * @param session_only delete only session not whole address + */ +void +GAS_simplistic_address_delete (void *solver, + struct GNUNET_CONTAINER_MultiHashMap * addresses, + struct ATS_Address *address, int session_only) +{ + struct GAS_SIMPLISTIC_Handle *s = solver; + struct Network *net; + struct AddressWrapper *aw; + + /* Remove an adress completely, we have to: + * - Remove from specific network + * - Decrease number of total addresses + * - If active: + * - decrease number of active addreses + * - update quotas + */ + + net = (struct Network *) address->solver_information; + + if (GNUNET_NO == session_only) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, "Deleting %s address %p for peer `%s' from network `%s' (total: %u/ active: %u)\n", + (GNUNET_NO == address->active) ? "inactive" : "active", + address, GNUNET_i2s (&address->peer), + net->desc, net->total_addresses, net->active_addresses); + + /* Remove address */ + addresse_decrement (s, net, GNUNET_YES, GNUNET_NO); + for (aw = net->head; NULL != aw; aw = aw->next) + { + if (aw->addr == address) + break; + } + if (NULL == aw ) + { + GNUNET_break (0); + return; + } + GNUNET_CONTAINER_DLL_remove (net->head, net->tail, aw); + GNUNET_free (aw); + } + else + { + /* Remove session only: remove if active and update */ + LOG (GNUNET_ERROR_TYPE_DEBUG, "Deleting %s session %p for peer `%s' from network `%s' (total: %u/ active: %u)\n", + (GNUNET_NO == address->active) ? "inactive" : "active", + address, GNUNET_i2s (&address->peer), + net->desc, net->total_addresses, net->active_addresses); + } + + if (GNUNET_YES == address->active) + { + /* Address was active, remove from network and update quotas*/ + address->active = GNUNET_NO; + if (GNUNET_SYSERR == addresse_decrement (s, net, GNUNET_NO, GNUNET_YES)) + GNUNET_break (0); + 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; +} + +/** + * Updates a single address in the solve + * + * @param solver the solver Handle + * @param addresses the address hashmap containing all addresses + * @param address the update address + * @param session the new session (if changed otherwise current) + * @param in_use the new address in use state (if changed otherwise current) + * @param atsi the latest ATS information + * @param atsi_count the atsi count + */ +void +GAS_simplistic_address_update (void *solver, + struct GNUNET_CONTAINER_MultiHashMap *addresses, + struct ATS_Address *address, + uint32_t session, + int in_use, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count) +{ + struct ATS_Address *new; + 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); + value = ntohl (atsi[i].value); + switch (type) + { + case GNUNET_ATS_UTILIZATION_UP: + //if (address->atsp_utilization_out.value__ != atsi[i].value) + + break; + case GNUNET_ATS_UTILIZATION_DOWN: + //if (address->atsp_utilization_in.value__ != atsi[i].value) + + break; + case GNUNET_ATS_QUALITY_NET_DELAY: + //if (address->atsp_latency.rel_value != value) + + break; + case GNUNET_ATS_QUALITY_NET_DISTANCE: + //if (address->atsp_distance != value) + + break; + case GNUNET_ATS_COST_WAN: + //if (address->atsp_cost_wan != value) + + break; + case GNUNET_ATS_COST_LAN: + //if (address->atsp_cost_lan != value) + + break; + case GNUNET_ATS_COST_WLAN: + //if (address->atsp_cost_wlan != value) + + break; + case GNUNET_ATS_NETWORK_TYPE: + if (address->atsp_network_type != value) + { + + 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)); + + save_active = address->active; + /* remove from old network */ + GAS_simplistic_address_delete (solver, addresses, address, GNUNET_NO); + + /* 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; + } + + /* Add to new network and update*/ + GAS_simplistic_address_add (solver, addresses, address); + if (GNUNET_YES == save_active) + { + /* check if bandwidth available in new network */ + if (GNUNET_YES == (bw_available_in_network (new_net))) + { + /* Suggest updated address */ + address->active = GNUNET_YES; + addresse_increment (s, new_net, GNUNET_NO, GNUNET_YES); + update_quota_per_network (solver, new_net, NULL); + } + else + { + LOG (GNUNET_ERROR_TYPE_DEBUG, "Not enough bandwidth in new network, suggesting alternative address ..\n"); + + /* Set old address to zero bw */ + address->assigned_bw_in = GNUNET_BANDWIDTH_value_init (0); + address->assigned_bw_out = GNUNET_BANDWIDTH_value_init (0); + s->bw_changed (s->bw_changed_cls, address); + + /* Find new address to suggest since no bandwidth in network*/ + new = (struct ATS_Address *) GAS_simplistic_get_preferred_address (s, addresses, &address->peer); + if (NULL != new) + { + /* Have an alternative address to suggest */ + s->bw_changed (s->bw_changed_cls, new); + } + + } + } + } + break; + case GNUNET_ATS_ARRAY_TERMINATOR: + break; + default: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Received unsupported ATS type %u\n", type); + GNUNET_break (0); + break; + + } + + } + if (address->session_id != session) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Session changed from %u to %u\n", address->session_id, session); + address->session_id = session; + } + if (address->used != in_use) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Usage changed from %u to %u\n", address->used, in_use); + address->used = in_use; + } + +} + + + +/** + * Find a "good" address to use for a peer. If we already have an existing + * address, we stick to it. Otherwise, we pick by lowest distance and then + * by lowest latency. + * + * @param cls the 'struct ATS_Address**' where we store the result + * @param key unused + * @param value another 'struct ATS_Address*' to consider using + * @return GNUNET_OK (continue to iterate) + */ +static int +find_address_it (void *cls, const struct GNUNET_HashCode * key, void *value) +{ + struct ATS_Address **previous_p = cls; + struct ATS_Address *current = (struct ATS_Address *) value; + struct ATS_Address *previous = *previous_p; + struct GNUNET_TIME_Absolute now; + struct Network *net = (struct Network *) current->solver_information; + + now = GNUNET_TIME_absolute_get(); + + if (current->blocked_until.abs_value == GNUNET_TIME_absolute_max (now, current->blocked_until).abs_value) + { + /* This address is blocked for suggestion */ + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Address %p blocked for suggestion for %llu ms \n", + current, + GNUNET_TIME_absolute_get_difference(now, current->blocked_until).rel_value); + return GNUNET_OK; + } + + if (GNUNET_NO == bw_available_in_network (net)) + return GNUNET_OK; /* There's no bandwidth available in this network */ + + if (NULL != previous) + { + if ((0 == strcmp (previous->plugin, "tcp")) && + (0 == strcmp (current->plugin, "tcp"))) + { + if ((0 != previous->addr_len) && + (0 == current->addr_len)) + { + /* saved address was an outbound address, but we have an inbound address */ + *previous_p = current; + return GNUNET_OK; + } + if (0 == previous->addr_len) + { + /* saved address was an inbound address, so do not overwrite */ + return GNUNET_OK; + } + } + } + + if (NULL == previous) + { + *previous_p = current; + return GNUNET_OK; + } + if ((ntohl (previous->assigned_bw_in.value__) == 0) && + (ntohl (current->assigned_bw_in.value__) > 0)) + { + /* stick to existing connection */ + *previous_p = current; + return GNUNET_OK; + } + if (previous->atsp_distance > current->atsp_distance) + { + /* user shorter distance */ + *previous_p = current; + return GNUNET_OK; + } + if (previous->atsp_latency.rel_value > current->atsp_latency.rel_value) + { + /* user lower latency */ + *previous_p = current; + return GNUNET_OK; + } + /* don't care */ + return GNUNET_OK; +} + +static int +find_active_address_it (void *cls, const struct GNUNET_HashCode * key, void *value) +{ + struct ATS_Address * dest = (struct ATS_Address *) (*(struct ATS_Address **)cls); + struct ATS_Address * aa = (struct ATS_Address *) value; + + if (GNUNET_YES == aa->active) + { + if (dest != NULL) + { + /* should never happen */ + LOG (GNUNET_ERROR_TYPE_ERROR, "Multiple active addresses for peer `%s'\n", GNUNET_i2s (&aa->peer)); + GNUNET_break (0); + return GNUNET_NO; + } + dest = aa; + } + return GNUNET_OK; +} + +static struct ATS_Address * +find_active_address (void *solver, + struct GNUNET_CONTAINER_MultiHashMap * addresses, + const struct GNUNET_PeerIdentity *peer) +{ + struct ATS_Address * dest = NULL; + + GNUNET_CONTAINER_multihashmap_get_multiple(addresses, + &peer->hashPubKey, + &find_active_address_it, &dest); + return dest; +} + +/** + * Get the prefered address for a specific peer + * + * @param solver the solver handle + * @param addresses the address hashmap containing all addresses + * @param peer the identity of the peer + */ +const struct ATS_Address * +GAS_simplistic_get_preferred_address (void *solver, + struct GNUNET_CONTAINER_MultiHashMap * addresses, + const struct GNUNET_PeerIdentity *peer) +{ + struct GAS_SIMPLISTIC_Handle *s = solver; + struct Network *net_prev; + struct Network *net_cur; + struct ATS_Address *cur; + struct ATS_Address *prev; + + GNUNET_assert (s != NULL); + cur = NULL; + /* Get address with: stick to current address, lower distance, lower latency */ + GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey, + &find_address_it, &cur); + if (NULL == cur) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer)); + return NULL; + } + + LOG (GNUNET_ERROR_TYPE_DEBUG, "Suggesting %s address %p for peer `%s'\n", + (GNUNET_NO == cur->active) ? "inactive" : "active", + cur, GNUNET_i2s (peer)); + net_cur = (struct Network *) cur->solver_information; + if (GNUNET_YES == cur->active) + { + /* This address was selected previously, so no need to update quotas */ + return cur; + } + + /* This address was not active, so we have to: + * + * - mark previous active address as not active + * - update quota for previous address network + * - update quota for this address network + */ + + prev = find_active_address (s, addresses, peer); + if (NULL != prev) + { + net_prev = (struct Network *) prev->solver_information; + prev->active = GNUNET_NO; /* No active any longer */ + prev->assigned_bw_in = GNUNET_BANDWIDTH_value_init (0); /* no bw assigned */ + prev->assigned_bw_out = GNUNET_BANDWIDTH_value_init (0); /* no bw assigned */ + s->bw_changed (s->bw_changed_cls, prev); /* notify about bw change, REQUIRED? */ + if (GNUNET_SYSERR == addresse_decrement (s, net_prev, GNUNET_NO, GNUNET_YES)) + GNUNET_break (0); + update_quota_per_network (s, net_prev, NULL); + } + + if (GNUNET_NO == (bw_available_in_network (cur->solver_information))) + { + GNUNET_break (0); /* This should never happen*/ + return NULL; + } + + cur->active = GNUNET_YES; + addresse_increment(s, net_cur, GNUNET_NO, GNUNET_YES); + update_quota_per_network (s, net_cur, cur); + + return cur; +} + +static void +recalculate_preferences (struct PreferencePeer *p) +{ + struct GAS_SIMPLISTIC_Handle *s = p->s; + struct PreferencePeer *p_cur; + struct PreferenceClient *c_cur = p->client; + double p_rel_global; + double *dest; + int kind; + int rkind; + int clients; + + /** + * Idea: + * + * We have: + * Set of clients c + * Set of peers p_i in P + * Set of preference kinds k + * A preference value f_k_p_i with an unknown range + * + * We get: + * A client specific relative preference f_p_i_rel [1..2] for all peers + * + * For every client c + * { + * For every preference kind k: + * { + * We remember for the preference f_p_i for each peer p_i. + * We have a default preference value f_p_i = 0 + * We have a sum of all preferences f_t = sum (f_p_i) + * So we can calculate a relative preference value fr_p_i: + * + * f_k_p_i_rel = (f_t + f_p_i) / f_t + * f_k_p_i_rel = [1..2], default 1.0 + * } + * f_p_i_rel = sum (f_k_p_i_rel) / #k + * } + * + **/ + + /* For this client: for all preferences, except TERMINATOR */ + for (kind = GNUNET_ATS_PREFERENCE_END + 1 ; kind < GNUNET_ATS_PreferenceCount; kind ++) + { + /* Recalcalculate total preference for this quality kind over all peers*/ + c_cur->f_total[kind] = 0; + for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next) + c_cur->f_total[kind] += p_cur->f[kind]; + + LOG (GNUNET_ERROR_TYPE_DEBUG, "Client %p has total preference for %s of %.3f\n", + c_cur->client, + GNUNET_ATS_print_preference_type (kind), + c_cur->f_total[kind]); + + /* Recalcalculate relative preference for all peers */ + for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next) + { + /* Calculate relative preference for specific kind */ + if (0.0 == c_cur->f_total[kind]) + { + /* No one has preference, so set default preference */ + p_cur->f_rel[kind] = DEFAULT_PREFERENCE; + } + else + { + p_cur->f_rel[kind] = (c_cur->f_total[kind] + p_cur->f[kind]) / c_cur->f_total[kind]; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, "Client %p: peer `%s' has relative preference for %s of %.3f\n", + c_cur->client, + GNUNET_i2s (&p_cur->id), + GNUNET_ATS_print_preference_type (kind), + p_cur->f_rel[kind]); + + /* Calculate peer relative preference */ + /* Start with kind = 1 to exclude terminator */ + p_cur->f_rel_total = 0; + for (rkind = GNUNET_ATS_PREFERENCE_END + 1; rkind < GNUNET_ATS_PreferenceCount; rkind ++) + { + p_cur->f_rel_total += p_cur->f_rel[rkind]; + } + p_cur->f_rel_total /= (GNUNET_ATS_PreferenceCount - 1.0); /* -1 due to terminator */ + LOG (GNUNET_ERROR_TYPE_DEBUG, "Client %p: peer `%s' has total relative preference of %.3f\n", + c_cur->client, + GNUNET_i2s (&p_cur->id), + p_cur->f_rel_total); + } + } + + /* Calculcate global total relative peer preference over all clients */ + p_rel_global = 0.0; + clients = 0; + for (c_cur = s->pc_head; NULL != c_cur; c_cur = c_cur->next) + { + for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next) + if (0 == memcmp (&p_cur->id, &p->id, sizeof (p_cur->id))) + break; + if (NULL != p_cur) + { + clients++; + p_rel_global += p_cur->f_rel_total; + } + } + p_rel_global /= clients; + LOG (GNUNET_ERROR_TYPE_DEBUG, "Global preference value for peer `%s': %.3f\n", + GNUNET_i2s (&p->id), p_rel_global); + + /* Update global map */ + if (NULL != (dest = GNUNET_CONTAINER_multihashmap_get(s->prefs, &p->id.hashPubKey))) + (*dest) = p_rel_global; + else + { + dest = GNUNET_malloc (sizeof (double)); + (*dest) = p_rel_global; + GNUNET_CONTAINER_multihashmap_put(s->prefs, + &p->id.hashPubKey, + dest, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + } +} + +static void +update_preference (struct PreferencePeer *p, + enum GNUNET_ATS_PreferenceKind kind, + float score_f) +{ + double score = score_f; + + /* Update preference value according to type */ + switch (kind) { + case GNUNET_ATS_PREFERENCE_BANDWIDTH: + case GNUNET_ATS_PREFERENCE_LATENCY: + p->f[kind] = (p->f[kind] + score) / 2; + break; + case GNUNET_ATS_PREFERENCE_END: + break; + default: + break; + } + recalculate_preferences(p); + update_all_networks (p->s); +} + + +static void +preference_aging (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + int i; + double *t = NULL; + double backup; + struct PreferencePeer *p = cls; + GNUNET_assert (NULL != p); + + + p->aging_task = GNUNET_SCHEDULER_NO_TASK; + + LOG (GNUNET_ERROR_TYPE_DEBUG, "Aging preferences for peer `%s'\n", + GNUNET_i2s (&p->id)); + + /* Issue for aging : + * + * Not for every peer preference values are set by default, so reducing the + * absolute preference value does not help for aging because it does not have + * influence on the relative values. + * + * So we have to reduce the relative value to have an immediate impact on + * quota calculation. In addition we cannot call recalculate_preferences here + * but instead reduce the absolute value to have an aging impact on future + * calls to change_preference where recalculate_preferences is called + * + */ + /* Aging absolute values: */ + for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) + { + if (p->f[i] > 1.0) + { + backup = p->f[i]; + p->f[i] *= PREF_AGING_FACTOR; + LOG (GNUNET_ERROR_TYPE_DEBUG, "Aged preference for peer `%s' from %.3f to %.3f\n", + GNUNET_i2s (&p->id), backup, p->f[i]); + } + } + /* Updating relative value */ + t = GNUNET_CONTAINER_multihashmap_get (p->s->prefs, &p->id.hashPubKey); + if (NULL == t) + { + GNUNET_break (0); + } + else + { + if ((*t) > 1.0) + (*t) = (*t) * PREF_AGING_FACTOR; + else + (*t) = 1.0; + update_all_networks (p->s); + } + p->aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL, + &preference_aging, p); +} + + +/** + * Changes the preferences for a peer in the problem + * + * @param solver the solver handle + * @param client the client with this preference + * @param peer the peer to change the preference for + * @param kind the kind to change the preference + * @param score the score + */ +void +GAS_simplistic_address_change_preference (void *solver, + void *client, + const struct GNUNET_PeerIdentity *peer, + enum GNUNET_ATS_PreferenceKind kind, + float score_f) +{ + static struct GNUNET_TIME_Absolute next_update; + struct GAS_SIMPLISTIC_Handle *s = solver; + struct PreferenceClient *c_cur; + struct PreferencePeer *p_cur; + int i; + + GNUNET_assert (NULL != solver); + GNUNET_assert (NULL != client); + GNUNET_assert (NULL != peer); + + LOG (GNUNET_ERROR_TYPE_DEBUG, "Client %p changes preference for peer `%s' %s %f\n", + client, + GNUNET_i2s (peer), + GNUNET_ATS_print_preference_type (kind), + score_f); + + if (kind >= GNUNET_ATS_PreferenceCount) + { + GNUNET_break (0); + return; + } + + /* Find preference client */ + for (c_cur = s->pc_head; NULL != c_cur; c_cur = c_cur->next) + { + if (client == c_cur->client) + break; + } + /* Not found: create new preference client */ + if (NULL == c_cur) + { + c_cur = GNUNET_malloc (sizeof (struct PreferenceClient)); + c_cur->client = client; + GNUNET_CONTAINER_DLL_insert (s->pc_head, s->pc_tail, c_cur); + } + + /* Find entry for peer */ + for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next) + if (0 == memcmp (&p_cur->id, peer, sizeof (p_cur->id))) + break; + + /* Not found: create new peer entry */ + if (NULL == p_cur) + { + p_cur = GNUNET_malloc (sizeof (struct PreferencePeer)); + p_cur->s = s; + p_cur->client = c_cur; + p_cur->id = (*peer); + for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) + { + /* Default value per peer absolut preference for a quality: + * No value set, so absolute preference 0 */ + p_cur->f[i] = 0.0; + /* Default value per peer relative preference for a quality: 1.0 */ + p_cur->f_rel[i] = DEFAULT_PREFERENCE; + } + p_cur->aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL, &preference_aging, p_cur); + GNUNET_CONTAINER_DLL_insert (c_cur->p_head, c_cur->p_tail, p_cur); + } + + update_preference (p_cur, kind, score_f); + + /* FIXME: We should update quotas if UPDATE_INTERVAL is reached */ + if (GNUNET_TIME_absolute_get().abs_value > next_update.abs_value) + { + /* update quotas*/ + next_update = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), + MIN_UPDATE_INTERVAL); + } +} + +/* end of gnunet-service-ats_addresses_simplistic.c */ diff --git a/src/ats/gnunet-service-ats_addresses_simplistic.h b/src/ats/gnunet-service-ats_addresses_simplistic.h new file mode 100644 index 0000000..eab221c --- /dev/null +++ b/src/ats/gnunet-service-ats_addresses_simplistic.h @@ -0,0 +1,151 @@ +/* + This file is part of GNUnet. + (C) 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/gnunet-service-ats_addresses_simplistic.h + * @brief ats simplistic ressource assignment + * @author Matthias Wachs + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_statistics_service.h" +#include "gnunet-service-ats_addresses.h" + +#define BIG_M_STRING "unlimited" + +/** + * Init the simplistic problem solving component + * + * Quotas: + * network[i] contains the network type as type GNUNET_ATS_NetworkType[i] + * out_quota[i] contains outbound quota for network type i + * in_quota[i] contains inbound quota for network type i + * + * Example + * network = {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN} + * network[2] == GNUNET_ATS_NET_LAN + * out_quota[2] == 65353 + * in_quota[2] == 65353 + * + * @param cfg configuration handle + * @param stats the GNUNET_STATISTICS handle + * @param network array of GNUNET_ATS_NetworkType with length dest_length + * @param out_quota array of outbound quotas + * @param in_quota array of outbound quota + * @param dest_length array length for quota arrays + * @param bw_changed_cb callback for changed bandwidth amounts + * @param bw_changed_cb_cls cls for callback + * @return handle for the solver on success, NULL on fail + */ +void * +GAS_simplistic_init (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_STATISTICS_Handle *stats, + int *network, + unsigned long long *out_quota, + unsigned long long *in_quota, + int dest_length, + GAS_bandwidth_changed_cb bw_changed_cb, + void *bw_changed_cb_cls); + +/** + * Shutdown the simplistic problem solving component + * + * @param solver the respective handle to shutdown + */ +void +GAS_simplistic_done (void * solver); + +/** + * Add a single address to the solve + * + * @param solver the solver Handle + * @param addresses the address hashmap containing all addresses + * @param address the address to add + */ +void +GAS_simplistic_address_add (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address); + + +/** + * Updates a single address in the solve + * + * @param solver the solver Handle + * @param addresses the address hashmap containing all addresses + * @param address the update address + * @param session the new session (if changed otherwise current) + * @param in_use the new address in use state (if changed otherwise current) + * @param atsi the latest ATS information + * @param atsi_count the atsi count + */ +void +GAS_simplistic_address_update (void *solver, + struct GNUNET_CONTAINER_MultiHashMap *addresses, + struct ATS_Address *address, + uint32_t session, + int in_use, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count); + + +/** + * Remove an address from the solver + * + * @param solver the solver handle + * @param addresses the address hashmap containing all addresses + * @param address the address to remove + * @param session_only delete only session not whole address + */ +void +GAS_simplistic_address_delete (void *solver, + struct GNUNET_CONTAINER_MultiHashMap * addresses, + struct ATS_Address *address, int session_only); + + +/** + * Get the prefered address for a specific peer + * + * @param solver the solver handle + * @param addresses the address hashmap containing all addresses + * @param peer the identity of the peer + */ +const struct ATS_Address * +GAS_simplistic_get_preferred_address (void *solver, + struct GNUNET_CONTAINER_MultiHashMap * addresses, + const struct GNUNET_PeerIdentity *peer); + + +/** + * Changes the preferences for a peer in the problem + * + * @param solver the solver handle + * @param client the client with this preference + * @param peer the peer to change the preference for + * @param kind the kind to change the preference + * @param score the score + */ +void +GAS_simplistic_address_change_preference (void *solver, + void *client, + const struct GNUNET_PeerIdentity *peer, + enum GNUNET_ATS_PreferenceKind kind, + float score); + + +/* end of gnunet-service-ats_addresses_simplistic.h */ diff --git a/src/ats/gnunet-service-ats_performance.c b/src/ats/gnunet-service-ats_performance.c index 7ab8e9a..35f0223 100644 --- a/src/ats/gnunet-service-ats_performance.c +++ b/src/ats/gnunet-service-ats_performance.c @@ -61,6 +61,28 @@ struct PerformanceClient /** + * We keep clients that are interested in performance in a linked list. + */ +struct AddressIteration +{ + /** + * Actual handle to the client. + */ + struct PerformanceClient *pc; + + int all; + + uint32_t id; + + unsigned int msg_type; +}; + +/** + * Address handle + */ +static struct GAS_Addresses_Handle *GSA_addresses; + +/** * Head of linked list of all clients to this service. */ static struct PerformanceClient *pc_head; @@ -93,29 +115,6 @@ find_client (struct GNUNET_SERVER_Client *client) return NULL; } - -/** - * Register a new performance client. - * - * @param client handle of the new client - * @param flag flag specifying the type of the client - */ -void -GAS_performance_add_client (struct GNUNET_SERVER_Client *client, - enum StartFlag flag) -{ - struct PerformanceClient *pc; - - GNUNET_break (NULL == find_client (client)); - pc = GNUNET_malloc (sizeof (struct PerformanceClient)); - pc->client = client; - pc->flag = flag; - GNUNET_SERVER_notification_context_add (nc, client); - GNUNET_SERVER_client_keep (client); - GNUNET_CONTAINER_DLL_insert (pc_head, pc_tail, pc); -} - - /** * Unregister a client (which may have been a performance client, * but this is not assured). @@ -126,7 +125,6 @@ void GAS_performance_remove_client (struct GNUNET_SERVER_Client *client) { struct PerformanceClient *pc; - pc = find_client (client); if (NULL == pc) return; @@ -135,31 +133,34 @@ GAS_performance_remove_client (struct GNUNET_SERVER_Client *client) GNUNET_free (pc); } - /** * Transmit the given performance information to all performance * clients. * + * @param pc performance client to send to * @param peer peer for which this is an address suggestion * @param plugin_name 0-termintated string specifying the transport plugin * @param plugin_addr binary address for the plugin to use * @param plugin_addr_len number of bytes in plugin_addr + * @param active is this address active * @param atsi performance data for the address * @param atsi_count number of performance records in 'ats' * @param bandwidth_out assigned outbound bandwidth * @param bandwidth_in assigned inbound bandwidth */ void -GAS_performance_notify_clients (const struct GNUNET_PeerIdentity *peer, - const char *plugin_name, - const void *plugin_addr, size_t plugin_addr_len, - const struct GNUNET_ATS_Information *atsi, - uint32_t atsi_count, - struct GNUNET_BANDWIDTH_Value32NBO - bandwidth_out, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) +GAS_performance_notify_client (struct PerformanceClient *pc, + const struct GNUNET_PeerIdentity *peer, + const char *plugin_name, + const void *plugin_addr, size_t plugin_addr_len, + const int active, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count, + struct GNUNET_BANDWIDTH_Value32NBO + bandwidth_out, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) { - struct PerformanceClient *pc; + struct PeerInformationMessage *msg; size_t plugin_name_length = strlen (plugin_name) + 1; size_t msize = @@ -170,6 +171,10 @@ GAS_performance_notify_clients (const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Information *atsp; char *addrp; + GNUNET_assert (NULL != pc); + if (NULL == find_client (pc->client)) + return; /* Client disconnected */ + GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); GNUNET_assert (atsi_count < GNUNET_SERVER_MAX_MESSAGE_SIZE / @@ -177,9 +182,11 @@ GAS_performance_notify_clients (const struct GNUNET_PeerIdentity *peer, msg = (struct PeerInformationMessage *) buf; msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_PEER_INFORMATION); + msg->id = htonl (0); msg->ats_count = htonl (atsi_count); msg->peer = *peer; msg->address_length = htons (plugin_addr_len); + msg->address_active = ntohl (active); msg->plugin_name_length = htons (plugin_name_length); msg->bandwidth_out = bandwidth_out; msg->bandwidth_in = bandwidth_in; @@ -188,18 +195,314 @@ GAS_performance_notify_clients (const struct GNUNET_PeerIdentity *peer, addrp = (char *) &atsp[atsi_count]; memcpy (addrp, plugin_addr, plugin_addr_len); strcpy (&addrp[plugin_addr_len], plugin_name); + GNUNET_SERVER_notification_context_unicast (nc, pc->client, &msg->header, + GNUNET_YES); +} + + +/** + * Transmit the given performance information to all performance + * clients. + * + * @param peer peer for which this is an address suggestion + * @param plugin_name 0-termintated string specifying the transport plugin + * @param plugin_addr binary address for the plugin to use + * @param plugin_addr_len number of bytes in plugin_addr + * @param active is this address active + * @param atsi performance data for the address + * @param atsi_count number of performance records in 'ats' + * @param bandwidth_out assigned outbound bandwidth + * @param bandwidth_in assigned inbound bandwidth + */ +void +GAS_performance_notify_all_clients (const struct GNUNET_PeerIdentity *peer, + const char *plugin_name, + const void *plugin_addr, size_t plugin_addr_len, + const int active, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count, + struct GNUNET_BANDWIDTH_Value32NBO + bandwidth_out, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) +{ + struct PerformanceClient *pc; + for (pc = pc_head; pc != NULL; pc = pc->next) if (pc->flag == START_FLAG_PERFORMANCE_WITH_PIC) { - GNUNET_SERVER_notification_context_unicast (nc, pc->client, &msg->header, - GNUNET_YES); - GNUNET_STATISTICS_update (GSA_stats, - "# performance updates given to clients", 1, - GNUNET_NO); + GAS_performance_notify_client (pc, + peer, + plugin_name, plugin_addr, plugin_addr_len, + active, + atsi, atsi_count, + bandwidth_out, bandwidth_in); } + GNUNET_STATISTICS_update (GSA_stats, + "# performance updates given to clients", 1, + GNUNET_NO); } +static void +peerinfo_it (void *cls, + const struct GNUNET_PeerIdentity *id, + const char *plugin_name, + const void *plugin_addr, size_t plugin_addr_len, + const int active, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count, + struct GNUNET_BANDWIDTH_Value32NBO + bandwidth_out, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) +{ + struct PerformanceClient *pc = cls; + GNUNET_assert (NULL != pc); + if (NULL == id) + return; + + if (GNUNET_NO == active) + return; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Callback for peer `%s' plugin `%s' BW out %llu, BW in %llu \n", + GNUNET_i2s (id), + plugin_name, + ntohl (bandwidth_out.value__), + ntohl (bandwidth_in.value__)); + GAS_performance_notify_client(pc, + id, + plugin_name, plugin_addr, plugin_addr_len, + active, + atsi, atsi_count, + bandwidth_out, bandwidth_in); +} + + +/** + * Iterator for GAS_performance_add_client + * + * @param cls the client requesting information + * @param id result + */ +static void +peer_it (void *cls, + const struct GNUNET_PeerIdentity *id) +{ + struct PerformanceClient *pc = cls; + if (NULL != id) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer `%s'\n", GNUNET_i2s (id)); + GAS_addresses_get_peer_info (GSA_addresses, id, &peerinfo_it, pc); + } +} + +/** + * Register a new performance client. + * + * @param client handle of the new client + * @param flag flag specifying the type of the client + */ +void +GAS_performance_add_client (struct GNUNET_SERVER_Client *client, + enum StartFlag flag) +{ + struct PerformanceClient *pc; + GNUNET_break (NULL == find_client (client)); + + pc = GNUNET_malloc (sizeof (struct PerformanceClient)); + pc->client = client; + pc->flag = flag; + GNUNET_SERVER_notification_context_add (nc, client); + GNUNET_SERVER_client_keep (client); + GNUNET_CONTAINER_DLL_insert (pc_head, pc_tail, pc); + + /* Send information about clients */ + GAS_addresses_iterate_peers (GSA_addresses, &peer_it, pc); +} + +static void transmit_req_addr (struct AddressIteration *ai, + const struct GNUNET_PeerIdentity *id, + const char *plugin_name, + const void *plugin_addr, size_t plugin_addr_len, + const int active, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count, + struct GNUNET_BANDWIDTH_Value32NBO + bandwidth_out, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) + +{ + + struct GNUNET_ATS_Information *atsp; + struct PeerInformationMessage *msg; + char *addrp; + size_t plugin_name_length; + size_t msize; + + if (NULL != plugin_name) + plugin_name_length = strlen (plugin_name) + 1; + else + plugin_name_length = 0; + msize = sizeof (struct PeerInformationMessage) + + atsi_count * sizeof (struct GNUNET_ATS_Information) + + plugin_addr_len + plugin_name_length; + char buf[msize] GNUNET_ALIGN; + + GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); + GNUNET_assert (atsi_count < + GNUNET_SERVER_MAX_MESSAGE_SIZE / + sizeof (struct GNUNET_ATS_Information)); + msg = (struct PeerInformationMessage *) buf; + msg->header.size = htons (msize); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE); + msg->ats_count = htonl (atsi_count); + msg->id = htonl (ai->id); + if (NULL != id) + msg->peer = *id; + else + memset (&msg->peer, '\0', sizeof (struct GNUNET_PeerIdentity)); + msg->address_length = htons (plugin_addr_len); + msg->address_active = ntohl (active); + msg->plugin_name_length = htons (plugin_name_length); + msg->bandwidth_out = bandwidth_out; + msg->bandwidth_in = bandwidth_in; + atsp = (struct GNUNET_ATS_Information *) &msg[1]; + memcpy (atsp, atsi, sizeof (struct GNUNET_ATS_Information) * atsi_count); + addrp = (char *) &atsp[atsi_count]; + if (NULL != plugin_addr) + memcpy (addrp, plugin_addr, plugin_addr_len); + if (NULL != plugin_name) + strcpy (&addrp[plugin_addr_len], plugin_name); + GNUNET_SERVER_notification_context_unicast (nc, ai->pc->client, &msg->header, + GNUNET_NO); +} + +static void +req_addr_peerinfo_it (void *cls, + const struct GNUNET_PeerIdentity *id, + const char *plugin_name, + const void *plugin_addr, size_t plugin_addr_len, + const int active, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count, + struct GNUNET_BANDWIDTH_Value32NBO + bandwidth_out, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) +{ + struct AddressIteration *ai = cls; + + GNUNET_assert (NULL != ai); + GNUNET_assert (NULL != ai->pc); + if (NULL == find_client (ai->pc->client)) + return; /* Client disconnected */ + + if ((NULL == id) && (NULL == plugin_name) && (NULL == plugin_addr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Address iteration done\n"); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Callback for %s peer `%s' plugin `%s' BW out %u, BW in %u \n", + (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE", + GNUNET_i2s (id), + plugin_name, + (unsigned int) ntohl (bandwidth_out.value__), + (unsigned int) ntohl (bandwidth_in.value__)); + + /* Transmit result */ + if ((GNUNET_YES == ai->all) || (GNUNET_YES == active)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending result for %s peer `%s' plugin `%s' BW out %u, BW in %u \n", + (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE", + GNUNET_i2s (id), + plugin_name, + (unsigned int) ntohl (bandwidth_out.value__), + (unsigned int) ntohl (bandwidth_in.value__)); + transmit_req_addr (cls, + id, + plugin_name, + plugin_addr, plugin_addr_len, + active, + atsi, + atsi_count, + bandwidth_out, bandwidth_in); + } +} + + +/** + * Iterator for GAS_handle_request_address_list + * + * @param cls the client requesting information + * @param id result + */ +static void +req_addr_peer_it (void *cls, + const struct GNUNET_PeerIdentity *id) +{ + struct AddressIteration *ai = cls; + if (NULL != id) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer `%s'\n", GNUNET_i2s (id)); + GAS_addresses_get_peer_info (GSA_addresses, id, &req_addr_peerinfo_it, ai); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer iteration done\n"); + } +} + +/** + * Handle 'address list request' messages from clients. + * + * @param cls unused, NULL + * @param client client that sent the request + * @param message the request message + */ +void +GAS_handle_request_address_list (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + struct PerformanceClient *pc; + struct AddressIteration ai; + struct AddressListRequestMessage * alrm = (struct AddressListRequestMessage *) message; + struct GNUNET_PeerIdentity allzeros; + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_zero; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", + "ADDRESSLIST_REQUEST"); + + if (NULL == (pc = find_client(client))) + { + GNUNET_break (0); + return; + } + + ai.all = ntohl (alrm->all); + ai.id = ntohl (alrm->id); + ai.pc = pc; + + memset (&allzeros, '\0', sizeof (struct GNUNET_PeerIdentity)); + bandwidth_zero.value__ = htonl (0); + if (0 == memcmp (&alrm->peer, &allzeros, sizeof (struct GNUNET_PeerIdentity))) + { + /* Return addresses for all peers */ + GAS_addresses_iterate_peers (GSA_addresses, &req_addr_peer_it, &ai); + transmit_req_addr (&ai, NULL, NULL, NULL, 0, GNUNET_NO, NULL, 0, bandwidth_zero, bandwidth_zero); + } + else + { + /* Return addresses for a specific peer */ + GAS_addresses_get_peer_info (GSA_addresses, &alrm->peer, &req_addr_peerinfo_it, &ai); + transmit_req_addr (&ai, NULL, NULL, NULL, 0, GNUNET_NO, NULL, 0, bandwidth_zero, bandwidth_zero); + } + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + + + /** * Handle 'reservation request' messages from clients. * @@ -251,7 +554,8 @@ GAS_handle_reservation_request (void *cls, struct GNUNET_SERVER_Client *client, * @param message the request message */ void -GAS_handle_preference_change (void *cls, struct GNUNET_SERVER_Client *client, +GAS_handle_preference_change (void *cls, + struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ChangePreferenceMessage *msg; @@ -283,7 +587,9 @@ GAS_handle_preference_change (void *cls, struct GNUNET_SERVER_Client *client, 1, GNUNET_NO); pi = (const struct PreferenceInformation *) &msg[1]; for (i = 0; i < nump; i++) - GAS_addresses_change_preference (&msg->peer, + GAS_addresses_change_preference (GSA_addresses, + client, + &msg->peer, (enum GNUNET_ATS_PreferenceKind) ntohl (pi[i].preference_kind), pi[i].preference_value); @@ -295,10 +601,13 @@ GAS_handle_preference_change (void *cls, struct GNUNET_SERVER_Client *client, * Initialize performance subsystem. * * @param server handle to our server + * @param addresses the address handle to use */ void -GAS_performance_init (struct GNUNET_SERVER_Handle *server) +GAS_performance_init (struct GNUNET_SERVER_Handle *server, + struct GAS_Addresses_Handle *addresses) { + GSA_addresses = addresses; nc = GNUNET_SERVER_notification_context_create (server, 128); } diff --git a/src/ats/gnunet-service-ats_performance.h b/src/ats/gnunet-service-ats_performance.h index 75d555a..6d527ae 100644 --- a/src/ats/gnunet-service-ats_performance.h +++ b/src/ats/gnunet-service-ats_performance.h @@ -60,15 +60,17 @@ GAS_performance_remove_client (struct GNUNET_SERVER_Client *client); * @param plugin_name 0-termintated string specifying the transport plugin * @param plugin_addr binary address for the plugin to use * @param plugin_addr_len number of bytes in plugin_addr + * @param active is this address active * @param atsi performance data for the address * @param atsi_count number of performance records in 'ats' * @param bandwidth_out assigned outbound bandwidth * @param bandwidth_in assigned inbound bandwidth */ void -GAS_performance_notify_clients (const struct GNUNET_PeerIdentity *peer, +GAS_performance_notify_all_clients (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, + const int active, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count, struct GNUNET_BANDWIDTH_Value32NBO @@ -78,6 +80,18 @@ GAS_performance_notify_clients (const struct GNUNET_PeerIdentity *peer, /** + * Handle 'address list request' messages from clients. + * + * @param cls unused, NULL + * @param client client that sent the request + * @param message the request message + */ +void +GAS_handle_request_address_list (void *cls, + struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message); + +/** * Handle 'reservation request' messages from clients. * * @param cls unused, NULL @@ -85,7 +99,8 @@ GAS_performance_notify_clients (const struct GNUNET_PeerIdentity *peer, * @param message the request message */ void -GAS_handle_reservation_request (void *cls, struct GNUNET_SERVER_Client *client, +GAS_handle_reservation_request (void *cls, + struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); @@ -97,7 +112,8 @@ GAS_handle_reservation_request (void *cls, struct GNUNET_SERVER_Client *client, * @param message the request message */ void -GAS_handle_preference_change (void *cls, struct GNUNET_SERVER_Client *client, +GAS_handle_preference_change (void *cls, + struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); @@ -105,9 +121,11 @@ GAS_handle_preference_change (void *cls, struct GNUNET_SERVER_Client *client, * Initialize performance subsystem. * * @param server handle to our server + * @param addresses the address handle to use */ void -GAS_performance_init (struct GNUNET_SERVER_Handle *server); +GAS_performance_init (struct GNUNET_SERVER_Handle *server, + struct GAS_Addresses_Handle *GSA_addresses); /** diff --git a/src/ats/gnunet-service-ats_reservations.c b/src/ats/gnunet-service-ats_reservations.c index d1212dd..3354c4e 100644 --- a/src/ats/gnunet-service-ats_reservations.c +++ b/src/ats/gnunet-service-ats_reservations.c @@ -122,7 +122,7 @@ GAS_reservations_set_bandwidth (const struct GNUNET_PeerIdentity *peer, void GAS_reservations_init () { - trackers = GNUNET_CONTAINER_multihashmap_create (128); + trackers = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO); } @@ -135,7 +135,7 @@ GAS_reservations_init () * @return GNUNET_OK (continue to iterate) */ static int -free_tracker (void *cls, const GNUNET_HashCode * key, void *value) +free_tracker (void *cls, const struct GNUNET_HashCode * key, void *value) { struct GNUNET_BANDWIDTH_Tracker *tracker = value; diff --git a/src/ats/gnunet-service-ats_scheduling.c b/src/ats/gnunet-service-ats_scheduling.c index 0b66ac5..4a20f90 100644 --- a/src/ats/gnunet-service-ats_scheduling.c +++ b/src/ats/gnunet-service-ats_scheduling.c @@ -43,6 +43,11 @@ static struct GNUNET_SERVER_Client *my_client; /** + * Handle to address subsystem + */ +static struct GAS_Addresses_Handle *address_handle; + +/** * Register a new scheduling client. * * @param client handle of the new client @@ -74,7 +79,7 @@ GAS_scheduling_remove_client (struct GNUNET_SERVER_Client *client) { if (my_client != client) return; - GAS_addresses_destroy_all (); + GAS_addresses_destroy_all (address_handle); my_client = NULL; } @@ -166,10 +171,8 @@ GAS_handle_request_address (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "REQUEST_ADDRESS"); - GNUNET_STATISTICS_update (GSA_stats, "# address requests received", 1, - GNUNET_NO); GNUNET_break (0 == ntohl (msg->reserved)); - GAS_addresses_request_address (&msg->peer); + GAS_addresses_request_address (address_handle, &msg->peer); GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -193,7 +196,7 @@ GAS_handle_request_address_cancel (void *cls, "REQUEST_ADDRESS_CANCEL"); GNUNET_break (0 == ntohl (msg->reserved)); - /* TODO */ + GAS_addresses_request_address_cancel (address_handle, &msg->peer); GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -215,10 +218,66 @@ GAS_handle_reset_backoff (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "RESET_BACKOFF"); - GNUNET_STATISTICS_update (GSA_stats, "# backoff reset requests received", 1, - GNUNET_NO); GNUNET_break (0 == ntohl (msg->reserved)); - GAS_addresses_handle_backoff_reset (&msg->peer); + GAS_addresses_handle_backoff_reset (address_handle, &msg->peer); + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +/** + * Handle 'address add' messages from clients. + * + * @param cls unused, NULL + * @param client client that sent the request + * @param message the request message + */ +void +GAS_handle_address_add (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + const struct AddressUpdateMessage *m; + const struct GNUNET_ATS_Information *atsi; + const char *address; + const char *plugin_name; + uint16_t address_length; + uint16_t plugin_name_length; + uint32_t ats_count; + uint16_t size; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", + "ADDRESS_ADD"); + size = ntohs (message->size); + if (size < sizeof (struct AddressUpdateMessage)) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + m = (const struct AddressUpdateMessage *) message; + ats_count = ntohl (m->ats_count); + address_length = ntohs (m->address_length); + plugin_name_length = ntohs (m->plugin_name_length); + atsi = (const struct GNUNET_ATS_Information *) &m[1]; + address = (const char *) &atsi[ats_count]; + if (plugin_name_length != 0) + plugin_name = &address[address_length]; + else + plugin_name = ""; + + if ((address_length + plugin_name_length + + ats_count * sizeof (struct GNUNET_ATS_Information) + + sizeof (struct AddressUpdateMessage) != ntohs (message->size)) || + (ats_count > + GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)) || + ((plugin_name_length > 0) && (plugin_name[plugin_name_length - 1] != '\0'))) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + GNUNET_STATISTICS_update (GSA_stats, "# address updates received", 1, + GNUNET_NO); + GAS_addresses_add (address_handle, &m->peer, plugin_name, address, address_length, + ntohl (m->session_id), atsi, ats_count); GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -276,7 +335,7 @@ GAS_handle_address_update (void *cls, struct GNUNET_SERVER_Client *client, } GNUNET_STATISTICS_update (GSA_stats, "# address updates received", 1, GNUNET_NO); - GAS_addresses_update (&m->peer, plugin_name, address, address_length, + GAS_addresses_update (address_handle, &m->peer, plugin_name, address, address_length, ntohl (m->session_id), atsi, ats_count); GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -332,12 +391,13 @@ GAS_handle_address_in_use (void *cls, struct GNUNET_SERVER_Client *client, } in_use = ntohs (m->in_use); - res = GAS_addresses_in_use (&m->peer, - plugin_name, - address, - address_length, - ntohl (m->session_id), - in_use); + res = GAS_addresses_in_use (address_handle, + &m->peer, + plugin_name, + address, + address_length, + ntohl (m->session_id), + in_use); if (res == GNUNET_OK) GNUNET_SERVER_receive_done (client, GNUNET_OK); @@ -402,7 +462,8 @@ GAS_handle_address_destroyed (void *cls, struct GNUNET_SERVER_Client *client, return; } GNUNET_STATISTICS_update (GSA_stats, "# addresses destroyed", 1, GNUNET_NO); - GAS_addresses_destroy (&m->peer, plugin_name, address, address_length, + GAS_addresses_destroy (address_handle, &m->peer, plugin_name, + address, address_length, ntohl (m->session_id)); if (0 != ntohl (m->session_id)) { @@ -421,10 +482,12 @@ GAS_handle_address_destroyed (void *cls, struct GNUNET_SERVER_Client *client, * Initialize scheduling subsystem. * * @param server handle to our server + * @param ah the address handle to use */ void -GAS_scheduling_init (struct GNUNET_SERVER_Handle *server) +GAS_scheduling_init (struct GNUNET_SERVER_Handle *server, struct GAS_Addresses_Handle *ah) { + address_handle = ah; nc = GNUNET_SERVER_notification_context_create (server, 128); } diff --git a/src/ats/gnunet-service-ats_scheduling.h b/src/ats/gnunet-service-ats_scheduling.h index 08a7f1b..d7b5e9c 100644 --- a/src/ats/gnunet-service-ats_scheduling.h +++ b/src/ats/gnunet-service-ats_scheduling.h @@ -115,6 +115,18 @@ GAS_handle_request_address_cancel (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); + +/** + * Handle 'address add' messages from clients. + * + * @param cls unused, NULL + * @param client client that sent the request + * @param message the request message + */ +void +GAS_handle_address_add (void *cls, struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message); + /** * Handle 'address update' messages from clients. * @@ -147,7 +159,8 @@ GAS_handle_address_in_use (void *cls, struct GNUNET_SERVER_Client *client, * @param message the request message */ void -GAS_handle_address_destroyed (void *cls, struct GNUNET_SERVER_Client *client, +GAS_handle_address_destroyed (void *cls, + struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); @@ -155,9 +168,10 @@ GAS_handle_address_destroyed (void *cls, struct GNUNET_SERVER_Client *client, * Initialize scheduling subsystem. * * @param server handle to our server + * @param ah the address handle to use */ void -GAS_scheduling_init (struct GNUNET_SERVER_Handle *server); +GAS_scheduling_init (struct GNUNET_SERVER_Handle *server, struct GAS_Addresses_Handle *ah); /** diff --git a/src/ats/perf_ats_mlp.c b/src/ats/perf_ats_mlp.c deleted file mode 100644 index b9ee5e4..0000000 --- a/src/ats/perf_ats_mlp.c +++ /dev/null @@ -1,372 +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/perf_ats_mlp - * @brief performance test for the MLP solver - * @author Christian Grothoff - * @author Matthias Wachs - - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_statistics_service.h" -#include "gnunet-service-ats_addresses_mlp.h" - -#define MLP_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3) -#define MLP_MAX_ITERATIONS INT_MAX - -#define DEF_PEERS 10 -#define DEF_ADDRESSES_PER_PEER 5 -#define DEF_ATS_VALUES 2 -#define DEF_ATS_MAX_DELAY 30 -#define DEF_ATS_MAX_DISTANCE 3 - -static unsigned int peers; -static unsigned int addresses; -static unsigned int numeric; -static unsigned int update_percentage; - -static int start; -static int end; - -struct ATS_Peer *p; -struct ATS_Address *a; - -static int ret; - -static struct GNUNET_CONTAINER_MultiHashMap * amap; - -static struct GAS_MLP_Handle *mlp; - - - - -GNUNET_SCHEDULER_TaskIdentifier shutdown_task; - -struct PeerContext -{ - struct GNUNET_PeerIdentity id; - - struct Address *addr; -}; - -struct Address -{ - char *plugin; - size_t plugin_len; - - void *addr; - size_t addr_len; - - struct GNUNET_ATS_Information *ats; - int ats_count; - - void *session; -}; - -void -do_shutdown (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - unsigned int ca; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); - - if (NULL != mlp) - { - GAS_mlp_done (mlp); - mlp = NULL; - } - - if (NULL != a) - { - for (ca=0; ca < (peers * addresses); ca++) - { - GNUNET_free (a[ca].plugin); - GNUNET_free (a[ca].ats); - } - } - - if (NULL != amap) - GNUNET_CONTAINER_multihashmap_destroy(amap); - GNUNET_free_non_null (a); - GNUNET_free_non_null (p); - -} - -static void -update_addresses (struct ATS_Address * a, unsigned int addrs, unsigned int percentage) -{ - if (percentage == 0) - return; - - unsigned int ua = (addrs) * ((float) percentage / 100); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updating %u of %u addresses per peer\n", ua, addrs); - - unsigned int updated[addrs]; - unsigned int u_types[DEF_ATS_VALUES]; - unsigned int updates = 0; - unsigned int u_type = 0; - unsigned int u_val = 0; - unsigned int cur = 0; - - u_types[0] = 0; - u_types[1] = 0; - - for (cur = 0; cur < addrs; cur ++) - { - updated[cur] = 0; - } - cur = 0; - - while (updates < ua) - { - cur = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, addrs); - if (0 == updated[cur]) - { - u_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_VALUES); - switch (u_type) { - case 0: - do - { - u_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DELAY); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating DELAY from %u to %u\n",a[cur].ats[u_type].value, u_val); - } - while (a[cur].ats[u_type].value == u_val); - break; - case 1: - do - { - u_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DISTANCE); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating DISTANCE from %u to %u\n",a[cur].ats[u_type].value, u_val); - } - while (a[cur].ats[u_type].value == u_val); - break; - default: - GNUNET_break (0); - break; - } - u_types[u_type]++; - - a[cur].ats[u_type].value = u_val; - updated[cur] = 1; - GAS_mlp_address_update(mlp, amap, &a[cur]); - updates++; - } - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updated %u delay and %u distance values\n", u_types[0], u_types[1]); - -} - - -static void -check (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - unsigned int c = 0; - unsigned int c2 = 0; - unsigned int ca = 0; - int update = GNUNET_NO; - int range = GNUNET_NO; - int res; - -#if !HAVE_LIBGLPK - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed!"); - ret = 1; - return; -#endif - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up %u peers with %u addresses per peer\n", peers, addresses); - - mlp = GAS_mlp_init (cfg, NULL, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS); - if (NULL == mlp) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to init MLP\n"); - ret = 1; - if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) - GNUNET_SCHEDULER_cancel(shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } - - if (peers == 0) - peers = DEF_PEERS; - if (addresses == 0) - addresses = DEF_ADDRESSES_PER_PEER; - - p = GNUNET_malloc (peers * sizeof (struct ATS_Peer)); - a = GNUNET_malloc (peers * addresses * sizeof (struct ATS_Address)); - - amap = GNUNET_CONTAINER_multihashmap_create(addresses * peers); - - mlp->auto_solve = GNUNET_NO; - if (start == 0) - start = 0; - if (end == 0) - end = -1; - if ((start != -1) && (end != -1)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Solving problem starting from %u to %u\n", start , end); - range = GNUNET_YES; - } - else - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Solving problem for %u peers\n", peers); - - if ((update_percentage >= 0) && (update_percentage <= 100)) - { - update = GNUNET_YES; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Benchmarking with existing presolution and %u%% updated addresses\n", update_percentage); - } - else if ((update_percentage > 100) && (update_percentage != UINT_MAX)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Invalid percentage: %u\n", update_percentage); - ret = 1; - return; - } - - for (c=0; c < peers; c++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up peer %u\n", c); - GNUNET_CRYPTO_hash_create_random(GNUNET_CRYPTO_QUALITY_NONCE, &p[c].id.hashPubKey); - - for (c2=0; c2 < addresses; c2++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up address %u for peer %u\n", c2, c); - /* Setting required information */ - a[ca].mlp_information = NULL; - a[ca].prev = NULL; - a[ca].next = NULL; - - /* Setting address */ - a[ca].peer = p[c].id; - a[ca].plugin = GNUNET_strdup("test"); - a[ca].atsp_network_type = GNUNET_ATS_NET_LOOPBACK; - - a[ca].ats = GNUNET_malloc (DEF_ATS_VALUES * sizeof (struct GNUNET_ATS_Information)); - a[ca].ats[0].type = GNUNET_ATS_QUALITY_NET_DELAY; - a[ca].ats[0].value = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DELAY); - a[ca].ats[1].type = GNUNET_ATS_QUALITY_NET_DISTANCE; - a[ca].ats[1].value = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DISTANCE); - a[ca].ats_count = 2; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up address %u\n", ca); - GNUNET_CONTAINER_multihashmap_put (amap, &a[ca].peer.hashPubKey, &a[ca], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - GAS_mlp_address_update(mlp, amap, &a[ca]); - ca++; - } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Problem contains %u peers and %u adresses\n", mlp->c_p, mlp->addr_in_problem); - - if (((GNUNET_YES == range) && (((start >= 0) && ((c+1) >= start)) && (c <= end))) || ((c+1) == peers)) - { - GNUNET_assert ((c+1) == mlp->c_p); - GNUNET_assert ((c+1) * addresses == mlp->addr_in_problem); - - /* Solving the problem */ - struct GAS_MLP_SolutionContext ctx; - - res = GAS_mlp_solve_problem(mlp, &ctx); - - if (GNUNET_NO == update) - { - if (GNUNET_OK == res) - { - GNUNET_assert (GNUNET_OK == ctx.lp_result); - GNUNET_assert (GNUNET_OK == ctx.mlp_result); - if (GNUNET_YES == numeric) - printf ("%u;%u;%llu;%llu\n",mlp->c_p, mlp->addr_in_problem, (unsigned long long) ctx.lp_duration.rel_value, (unsigned long long) ctx.mlp_duration.rel_value); - else - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Problem solved for %u peers with %u address successfully (LP: %llu ms / MLP: %llu ms)\n", - mlp->c_p, mlp->addr_in_problem, ctx.lp_duration.rel_value, ctx.mlp_duration.rel_value); - } - else - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Solving problem with %u peers and %u addresses failed\n", c, c2); - } - else - { - struct GAS_MLP_SolutionContext uctx; - /* Update addresses */ - update_addresses (a, (c+1) * c2, update_percentage); - - /* Solve again */ - res = GAS_mlp_solve_problem(mlp, &uctx); - - if (GNUNET_OK == res) - { - GNUNET_assert (GNUNET_OK == uctx.lp_result); - GNUNET_assert (GNUNET_OK == uctx.mlp_result); - if (GNUNET_YES == numeric) - printf ("%u;%u;%llu;%llu;%llu;%llu\n",mlp->c_p, mlp->addr_in_problem, - (unsigned long long) ctx.lp_duration.rel_value, (unsigned long long) ctx.mlp_duration.rel_value, - (unsigned long long) uctx.lp_duration.rel_value, (unsigned long long) uctx.mlp_duration.rel_value); - else - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updated problem solved for %u peers with %u address successfully (Initial: LP/MLP: %llu/%llu ms, Update: %llu/%llu ms)\n", - mlp->c_p, mlp->addr_in_problem, - (unsigned long long) ctx.lp_duration.rel_value, (unsigned long long) ctx.mlp_duration.rel_value, - (unsigned long long) uctx.lp_duration.rel_value, (unsigned long long) uctx.mlp_duration.rel_value); - } - else - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Solving updated problem with %u peers and %u addresses failed\n", c, c2); - } - } - } - - if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) - GNUNET_SCHEDULER_cancel(shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - -} - - -int -main (int argc, char *argv[]) -{ - /* Init invalid */ - update_percentage = UINT_MAX; - static struct GNUNET_GETOPT_CommandLineOption options[] = { - {'a', "addresses", NULL, - gettext_noop ("addresses per peer"), 1, - &GNUNET_GETOPT_set_uint, &addresses}, - {'p', "peers", NULL, - gettext_noop ("peers"), 1, - &GNUNET_GETOPT_set_uint, &peers}, - {'n', "numeric", NULL, - gettext_noop ("numeric output only"), 0, - &GNUNET_GETOPT_set_one, &numeric}, - {'e', "end", NULL, - gettext_noop ("end solving problem"), 1, - &GNUNET_GETOPT_set_uint, &end}, - {'s', "start", NULL, - gettext_noop ("start solving problem"), 1, - &GNUNET_GETOPT_set_uint, &start}, - {'u', "update", NULL, - gettext_noop ("benchmark with existing solution (address updates)"), 1, - &GNUNET_GETOPT_set_uint, &update_percentage}, - GNUNET_GETOPT_OPTION_END - }; - - - GNUNET_PROGRAM_run (argc, argv, - "perf_ats_mlp", "nohelp", options, - &check, NULL); - - - return ret; -} - -/* end of file perf_ats_mlp.c */ diff --git a/src/ats/test_ats_api.conf b/src/ats/test_ats_api.conf index efd7fc9..9e00a15 100644 --- a/src/ats/test_ats_api.conf +++ b/src/ats/test_ats_api.conf @@ -7,13 +7,11 @@ DEFAULTSERVICES = ats UNIXPATH = /tmp/test-ats-scheduling-arm.sock [ats] -#DEBUG = YES -#PREFIX = valgrind --leak-check=full +#PREFIX = valgrind --leak-check=full --track-origins=yes --num-callers=25 AUTOSTART = YES PORT = 12002 HOSTNAME = localhost HOME = $SERVICEHOME -CONFIG = $DEFAULTCONFIG BINARY = gnunet-service-ats ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; @@ -22,8 +20,11 @@ UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # Enable MLP mode (default: NO) -MLP = NO +MODE = SIMPLISTIC # Network specific inbound/outbound quotas +# UNSPECIFIED +UNSPECIFIED_QUOTA_IN = 64 KiB +UNSPECIFIED_QUOTA_OUT = 64 KiB # LOOPBACK LOOPBACK_QUOTA_IN = unlimited LOOPBACK_QUOTA_OUT = unlimited @@ -34,8 +35,8 @@ LAN_QUOTA_OUT = unlimited WAN_QUOTA_IN = 64 KiB WAN_QUOTA_OUT = 64 KiB # WLAN -WLAN_QUOTA_IN = 1 MiB -WLAN_QUOTA_OUT = 1 MiB +WLAN_QUOTA_IN = 512 +WLAN_QUOTA_OUT = 512 # ATS extended options DUMP_MLP = NO diff --git a/src/ats/test_ats_api_common.c b/src/ats/test_ats_api_common.c new file mode 100644 index 0000000..f1002f8 --- /dev/null +++ b/src/ats/test_ats_api_common.c @@ -0,0 +1,139 @@ +/* + 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_common.c + * @brief shared functions for ats test + * @author Christian Grothoff + * @author Matthias Wachs + */ + +#include "test_ats_api_common.h" + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) + +#define PEERID0 "2AK99KD8RM9UA9LC3QKA0IQ5UBFC0FBB50EBGCFQT8448DGGACNAC4CJQDD1CPFS494O41U88DJD1FLIG8VA5CQR9IN4L96GP104MVO" +#define PEERID1 "5ED7I0AR3MSTAL7FQN04S22E0EQ3CR9RLASCDLVMM1BNFPUPTCT46DLKNJ4DACASJ6U0DR5J8S3R2UJL49682JS7MOVRAB8P8A4PJH0" + +void +create_test_address (struct Test_Address *dest, char * plugin, void *session, void *addr, size_t addrlen) +{ + + dest->plugin = GNUNET_strdup (plugin); + dest->session = session; + if (addrlen > 0) + { + dest->addr = GNUNET_malloc (addrlen); + memcpy (dest->addr, addr, addrlen); + } + else + dest->addr = NULL; + dest->addr_len = addrlen; +} + +void +free_test_address (struct Test_Address *dest) +{ + GNUNET_free (dest->plugin); + if (NULL != dest->addr) + GNUNET_free (dest->addr); +} + +int +compare_addresses (const struct GNUNET_HELLO_Address *address1, void *session1, + const struct GNUNET_HELLO_Address *address2, void *session2) +{ + if (0 != memcmp (&address1->peer, &address2->peer, sizeof (struct GNUNET_PeerIdentity))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggestion with invalid peer id'\n"); + return GNUNET_SYSERR; + } + if (0 != strcmp (address1->transport_name, address2->transport_name)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggestion with invalid plugin'\n"); + return GNUNET_SYSERR; + } + if (address1->address_length != address2->address_length) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggestion with invalid address length'\n"); + return GNUNET_SYSERR; + + } + else if (0 != memcmp (address1->address, address2->address, address2->address_length)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggestion with invalid address'\n"); + return GNUNET_SYSERR; + } + if (session1 != session2) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggestion with invalid session1 %p vs session2 %p'\n", + session1, session2); + return GNUNET_SYSERR; + + } + return GNUNET_OK; +} + + +int +compare_ats (const struct GNUNET_ATS_Information *ats_is, uint32_t ats_count_is, + const struct GNUNET_ATS_Information *ats_should, uint32_t ats_count_should) +{ + unsigned int c_o; + unsigned int c_i; + char *prop[] = GNUNET_ATS_PropertyStrings; + uint32_t type1; + uint32_t type2; + uint32_t val1; + uint32_t val2; + int res = GNUNET_OK; + + for (c_o = 0; c_o < ats_count_is; c_o++) + { + for (c_i = 0; c_i < ats_count_should; c_i++) + { + type1 = ntohl(ats_is[c_o].type); + type2 = ntohl(ats_should[c_i].type); + if (type1 == type2) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS type `%s'\n", + prop[type1]); + val1 = ntohl(ats_is[c_o].value); + val2 = ntohl(ats_should[c_i].value); + if (val1 != val2) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ATS value `%s' not equal: %u != %u\n", + prop[type1], + val1, val2); + res = GNUNET_SYSERR; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS value `%s' equal: %u == %u\n", + prop[type1], + val1, val2); + } + } + } + } + return res; +} + + +/* end of file test_ats_api_common.c */ diff --git a/src/ats/test_ats_api_common.h b/src/ats/test_ats_api_common.h new file mode 100644 index 0000000..04dd11b --- /dev/null +++ b/src/ats/test_ats_api_common.h @@ -0,0 +1,75 @@ +/* + 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_common.h + * @brief shared definitions for ats testcases + * @author Christian Grothoff + * @author Matthias Wachs + */ + +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_ats_service.h" + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) + +#define PEERID0 "2AK99KD8RM9UA9LC3QKA0IQ5UBFC0FBB50EBGCFQT8448DGGACNAC4CJQDD1CPFS494O41U88DJD1FLIG8VA5CQR9IN4L96GP104MVO" +#define PEERID1 "5ED7I0AR3MSTAL7FQN04S22E0EQ3CR9RLASCDLVMM1BNFPUPTCT46DLKNJ4DACASJ6U0DR5J8S3R2UJL49682JS7MOVRAB8P8A4PJH0" + +struct Test_Address +{ + char *plugin; + size_t plugin_len; + + void *addr; + size_t addr_len; + + struct GNUNET_ATS_Information *ats; + int ats_count; + + void *session; +}; + +struct PeerContext +{ + struct GNUNET_PeerIdentity id; + + struct Test_Address *addr; + + unsigned long long bw_out_assigned; + + unsigned long long bw_in_assigned; +}; + +void +free_test_address (struct Test_Address *dest); + +void +create_test_address (struct Test_Address *dest, char * plugin, void *session, void *addr, size_t addrlen); + +int +compare_addresses (const struct GNUNET_HELLO_Address *address1, void *session1, + const struct GNUNET_HELLO_Address *address2, void *session2); + +int +compare_ats (const struct GNUNET_ATS_Information *ats_is, uint32_t ats_count_is, + const struct GNUNET_ATS_Information *ats_should, uint32_t ats_count_should); + +/* end of file test_ats_api_common.h */ diff --git a/src/ats/test_ats_api_performance.c b/src/ats/test_ats_api_performance.c new file mode 100644 index 0000000..64737d8 --- /dev/null +++ b/src/ats/test_ats_api_performance.c @@ -0,0 +1,596 @@ +/* + 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_performance.c + * @brief test adding addresses in automatic transport selection performance API + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +struct GNUNET_CONFIGURATION_Handle *cfg; + +static struct GNUNET_ATS_SchedulingHandle *atsh; +static struct GNUNET_ATS_PerformanceHandle *ph; +struct GNUNET_ATS_AddressListHandle* phal; + +static int ret; + +struct Address +{ + char *plugin; + size_t plugin_len; + + void *addr; + size_t addr_len; + + struct GNUNET_ATS_Information *ats; + int ats_count; + + void *session; +}; + +struct PeerContext +{ + struct GNUNET_PeerIdentity id; + + struct Address *addr; +}; + + + +static struct PeerContext p[2]; + +static struct Address p0_addresses[2]; +static struct Address p1_addresses[2]; + +struct GNUNET_HELLO_Address p0_ha[2]; +struct GNUNET_HELLO_Address p1_ha[2]; +struct GNUNET_HELLO_Address *s_ha[2]; + +static unsigned int stage = 0; + +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout in stage %u\n", stage); + + if (NULL != atsh) + GNUNET_ATS_scheduling_done (atsh); + if (phal != NULL) + GNUNET_ATS_performance_list_addresses_cancel (phal); + phal = NULL; + if (ph != NULL) + GNUNET_ATS_performance_done (ph); + ph = NULL; + + GNUNET_free_non_null (p0_addresses[0].addr); + GNUNET_free_non_null (p0_addresses[1].addr); + GNUNET_free_non_null (p1_addresses[0].addr); + GNUNET_free_non_null (p1_addresses[1].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; + } + if (NULL != atsh) + GNUNET_ATS_scheduling_done (atsh); + if (phal != NULL) + GNUNET_ATS_performance_list_addresses_cancel (phal); + phal = NULL; + if (ph != NULL) + GNUNET_ATS_performance_done (ph); + ph = NULL; + + GNUNET_free_non_null (p0_addresses[0].addr); + GNUNET_free_non_null (p0_addresses[1].addr); + GNUNET_free_non_null (p1_addresses[0].addr); + GNUNET_free_non_null (p1_addresses[1].addr); + + ret = 0; +} + +static void +test_performance_api (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + +void all_active_addresses_peer_cb (void *cls, + const struct + GNUNET_HELLO_Address * + address, + struct + GNUNET_BANDWIDTH_Value32NBO + bandwidth_out, + struct + GNUNET_BANDWIDTH_Value32NBO + bandwidth_in, + const struct + GNUNET_ATS_Information * + ats, uint32_t ats_count) +{ + static int cb = 0; + int fail = GNUNET_NO; + + if (address != NULL) + { + if (0 == memcmp (&address->peer, &p[0].id, + sizeof (struct GNUNET_PeerIdentity))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Did not expected callback for peer 0 address `%s', got address `%s'!\n", + s_ha[0]->address, address->address); + GNUNET_ATS_performance_list_addresses_cancel (phal); + fail = GNUNET_YES; + } + + if (0 == memcmp (&address->peer, &p[1].id, + sizeof (struct GNUNET_PeerIdentity))) + { + if (0 == strcmp(address->address, s_ha[1]->address)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Callback for peer 1 suggested address %s\n", + s_ha[1]->address); + cb ++; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Expected callback for peer 1 address `%s', got address `%s'!\n", + s_ha[1]->address, address->address); + GNUNET_ATS_performance_list_addresses_cancel (phal); + fail = GNUNET_YES; + } + } + } + if ((address == NULL) || (GNUNET_YES == fail)) + { + phal = NULL; + if ((1 == cb) && (GNUNET_NO == fail)) + { + /* Received all addresses + terminator cb, next stage */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %i: SUCCESS\n", stage); + GNUNET_SCHEDULER_add_now (&test_performance_api, NULL); + return; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %i: FAIL\n", stage); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 5; + return; + } + } +} + +void all_active_addresses_cb (void *cls, + const struct + GNUNET_HELLO_Address * + address, + struct + GNUNET_BANDWIDTH_Value32NBO + bandwidth_out, + struct + GNUNET_BANDWIDTH_Value32NBO + bandwidth_in, + const struct + GNUNET_ATS_Information * + ats, uint32_t ats_count) +{ + static int cb = 0; + int fail = GNUNET_NO; + + if (address != NULL) + { + if (0 == memcmp (&address->peer, &p[0].id, + sizeof (struct GNUNET_PeerIdentity))) + { + if (0 == strcmp(address->address, s_ha[0]->address)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Callback for peer 0 suggested address %s\n", + s_ha[0]->address); + cb ++; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Expected callback for peer 0 address `%s', got address `%s'!\n", + s_ha[0]->address, address->address); + GNUNET_ATS_performance_list_addresses_cancel (phal); + fail = GNUNET_YES; + } + } + + if (0 == memcmp (&address->peer, &p[1].id, + sizeof (struct GNUNET_PeerIdentity))) + { + if (0 == strcmp(address->address, s_ha[1]->address)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Callback for peer 1 suggested address %s\n", + s_ha[1]->address); + cb ++; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Expected callback for peer 1 address `%s', got address `%s'!\n", + s_ha[1]->address, address->address); + GNUNET_ATS_performance_list_addresses_cancel (phal); + fail = GNUNET_YES; + } + } + } + if ((address == NULL) || (GNUNET_YES == fail)) + { + phal = NULL; + if ((2 == cb) && (GNUNET_NO == fail)) + { + /* Received all addresses + terminator cb, next stage */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %i: SUCCESS\n", stage); + GNUNET_SCHEDULER_add_now (&test_performance_api, NULL); + return; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %i: FAIL\n", stage); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 5; + return; + } + } +} + + + +void all_addresses_peer_cb (void *cls, + const struct + GNUNET_HELLO_Address * + address, + struct + GNUNET_BANDWIDTH_Value32NBO + bandwidth_out, + struct + GNUNET_BANDWIDTH_Value32NBO + bandwidth_in, + const struct + GNUNET_ATS_Information * + ats, uint32_t ats_count) +{ + static int cb = 0; + int fail = GNUNET_NO; + + if (address != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Callback for peer `%s' address `%s'\n", + GNUNET_i2s (&address->peer), address->address); + + if (0 != memcmp (&address->peer, &p[1].id, + sizeof (struct GNUNET_PeerIdentity))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Stage %i: Received address for wrong peer\n", stage); + GNUNET_ATS_performance_list_addresses_cancel (phal); + fail = GNUNET_YES; + ret = 4; + } + cb ++; + } + + if ((NULL == address) || (fail)) + { + phal = NULL; + if ((2 == cb) && (GNUNET_NO == fail)) + { + /* Received all addresses + terminator cb, next stage */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %i: SUCCESS\n", stage); + GNUNET_SCHEDULER_add_now (&test_performance_api, NULL); + return; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %i: FAIL\n", stage); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 5; + return; + } + } +} + +void all_addresses_cb (void *cls, + const struct + GNUNET_HELLO_Address * + address, + struct + GNUNET_BANDWIDTH_Value32NBO + bandwidth_out, + struct + GNUNET_BANDWIDTH_Value32NBO + bandwidth_in, + const struct + GNUNET_ATS_Information * + ats, uint32_t ats_count) +{ + static int cb = 0; + + if (address != NULL) + { + if (0 == memcmp (&address->peer, &p[0].id, + sizeof (struct GNUNET_PeerIdentity))) + { + if (0 == strcmp(address->address, p0_addresses[0].addr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 0 address 0\n"); + cb |= 1; + } + if (0 == strcmp(address->address, p0_addresses[1].addr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 0 address 1\n"); + cb |= 2; + } + } + if (0 == memcmp (&address->peer, &p[1].id, + sizeof (struct GNUNET_PeerIdentity))) + { + if (0 == strcmp(address->address, p1_addresses[0].addr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 1 address 0\n"); + cb |= 4; + } + if (0 == strcmp(address->address, p1_addresses[1].addr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 1 address 1\n"); + cb |= 8; + } + } + } + else + { + phal = NULL; + if (((1 << 4) - 1) == cb) + { + /* Received all addresses + terminator cb, next stage */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %i: SUCCESS\n", stage); + GNUNET_SCHEDULER_add_now (&test_performance_api, NULL); + return; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %i: FAIL\n", stage); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 3; + return; + } + } +} + +static void +test_performance_api (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (NULL == ph) + ph = GNUNET_ATS_performance_init (cfg, NULL, NULL); + if (NULL == ph) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to initialize performance handle\n"); + ret = 2; + } + stage++; + switch (stage) { + case 1: /* Get all peers, all addresses */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Run stage 1: \n"); + phal = GNUNET_ATS_performance_list_addresses (ph, + NULL, + GNUNET_YES, + &all_addresses_cb, NULL); + GNUNET_assert (NULL != phal); + break; + case 2: /* Get specific peer, all addresses */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Run stage 2: \n"); + phal = GNUNET_ATS_performance_list_addresses (ph, + &p[1].id, + GNUNET_YES, + &all_addresses_peer_cb, NULL); + GNUNET_assert (NULL != phal); + break; + case 3: /* Get all peers, active addresses */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Run stage 3: \n"); + phal = GNUNET_ATS_performance_list_addresses (ph, + NULL, + GNUNET_NO, + &all_active_addresses_cb, NULL); + GNUNET_assert (NULL != phal); + break; + case 4: /* Get specific peers, active addresses */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Run stage 4: \n"); + phal = GNUNET_ATS_performance_list_addresses (ph, + &p[1].id, + GNUNET_NO, + &all_active_addresses_peer_cb, NULL); + GNUNET_assert (NULL != phal); + break; + default: + /* done */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All tests successful, shutdown... \n"); + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } +} + + +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 *ats, + uint32_t ats_count) +{ + static int suggest_p0 = GNUNET_NO; + static int suggest_p1 = GNUNET_NO; + static int running = GNUNET_NO; + + if ((GNUNET_NO == suggest_p0) && (0 == memcmp (&address->peer, &p[0].id, + sizeof (struct GNUNET_PeerIdentity)))) + { + suggest_p0 = GNUNET_YES;; + + if (s_ha[0] != NULL) + GNUNET_free (s_ha[0]); + s_ha[0] = GNUNET_HELLO_address_copy (address); + GNUNET_ATS_suggest_address_cancel (atsh, &p[0].id); + } + if ((GNUNET_NO == suggest_p1) && (0 == memcmp (&address->peer, &p[1].id, + sizeof (struct GNUNET_PeerIdentity)))) + { + suggest_p1 = GNUNET_YES; + + if (s_ha[1] != NULL) + GNUNET_free (s_ha[1]); + s_ha[1] = GNUNET_HELLO_address_copy (address); + GNUNET_ATS_suggest_address_cancel (atsh, &p[1].id); + } + + + if ((GNUNET_NO == running) && (GNUNET_YES == suggest_p0) && (GNUNET_YES == suggest_p1)) + { + running = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have address suggestion for both peers\n"); + GNUNET_SCHEDULER_add_now (&test_performance_api, NULL); + } + +} + + +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *mycfg, + struct GNUNET_TESTING_Peer *peer) +{ + ret = 1; + cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + + /* set up peer 0 */ + GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, + &p[0].id.hashPubKey); + + p0_addresses[0].plugin = "test"; + p0_addresses[0].session = NULL; + p0_addresses[0].addr = GNUNET_strdup ("test_p0_a0"); + p0_addresses[0].addr_len = strlen (p0_addresses[0].addr) + 1; + + p0_ha[0].address = p0_addresses[0].addr; + p0_ha[0].address_length = p0_addresses[0].addr_len; + p0_ha[0].peer = p[0].id; + p0_ha[0].transport_name = p0_addresses[0].plugin; + + p0_addresses[1].plugin = "test"; + p0_addresses[1].session = NULL; + p0_addresses[1].addr = GNUNET_strdup ("test_p0_a1"); + p0_addresses[1].addr_len = strlen(p0_addresses[1].addr) + 1; + + p0_ha[1].address = p0_addresses[1].addr; + p0_ha[1].address_length = p0_addresses[1].addr_len; + p0_ha[1].peer = p[0].id; + p0_ha[1].transport_name = p0_addresses[1].plugin; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer 0: `%s'\n", + GNUNET_i2s (&p[0].id)); + + GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, + &p[1].id.hashPubKey); + + p1_addresses[0].plugin = "test"; + p1_addresses[0].session = NULL; + p1_addresses[0].addr = GNUNET_strdup ("test_p1_a0"); + p1_addresses[0].addr_len = strlen(p1_addresses[0].addr) + 1; + + p1_ha[0].address = p1_addresses[0].addr; + p1_ha[0].address_length = p1_addresses[0].addr_len; + p1_ha[0].peer = p[1].id; + p1_ha[0].transport_name = p1_addresses[0].plugin; + + p1_addresses[1].plugin = "test"; + p1_addresses[1].session = NULL; + p1_addresses[1].addr = GNUNET_strdup ("test_p1_a1"); + p1_addresses[1].addr_len = strlen(p1_addresses[1].addr) + 1; + + p1_ha[1].address = p1_addresses[1].addr; + p1_ha[1].address_length = p1_addresses[1].addr_len; + p1_ha[1].peer = p[1].id; + p1_ha[1].transport_name = p1_addresses[1].plugin; + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer 1: `%s'\n", + GNUNET_i2s (&p[1].id)); + + + /* Add addresses */ + atsh = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); + if (atsh == NULL) + { + ret = GNUNET_SYSERR; + end (); + return; + } + + GNUNET_ATS_address_add (atsh, &p0_ha[0], NULL, NULL, 0); + GNUNET_ATS_address_add (atsh, &p0_ha[1], NULL, NULL, 0); + + GNUNET_ATS_address_add (atsh, &p1_ha[0], NULL, NULL, 0); + GNUNET_ATS_address_add (atsh, &p1_ha[1], NULL, NULL, 0); + + + GNUNET_ATS_suggest_address (atsh, &p[0].id); + GNUNET_ATS_suggest_address (atsh, &p[1].id); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_api_performance", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + +/* end of file test_ats_api_performance.c */ diff --git a/src/ats/test_ats_api_reset_backoff.c b/src/ats/test_ats_api_reset_backoff.c deleted file mode 100644 index 38c18e1..0000000 --- a/src/ats/test_ats_api_reset_backoff.c +++ /dev/null @@ -1,308 +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_reset_backoff.c - * @brief test case for block reset api - * @author Christian Grothoff - * @author Matthias Wachs - */ -#include "platform.h" -#include "gnunet_ats_service.h" -#include "ats.h" - -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) -#define ATS_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 90) - -static GNUNET_SCHEDULER_TaskIdentifier die_task; - -static GNUNET_SCHEDULER_TaskIdentifier suggest_timeout_task; - -static struct GNUNET_ATS_SchedulingHandle *ats; - -struct GNUNET_OS_Process *arm_proc; - -static int ret; - -struct Address -{ - char *plugin; - size_t plugin_len; - - void *addr; - size_t addr_len; - - struct GNUNET_ATS_Information *ats; - int ats_count; - - void *session; -}; - -struct PeerContext -{ - struct GNUNET_PeerIdentity id; - - struct Address *addr; -}; - -struct GNUNET_HELLO_Address hello_addr; -struct Address address; -struct PeerContext peer; -struct GNUNET_ATS_Information atsi[2]; - -static void -stop_arm () -{ - if (0 != GNUNET_OS_process_kill (arm_proc, SIGTERM)) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); - GNUNET_OS_process_wait (arm_proc); - GNUNET_OS_process_destroy (arm_proc); - arm_proc = NULL; -} - - -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - die_task = GNUNET_SCHEDULER_NO_TASK; - - if (suggest_timeout_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (suggest_timeout_task); - suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK; - } - - if (ats != NULL) - { - GNUNET_ATS_scheduling_done (ats); - ats = NULL; - } - - ret = GNUNET_SYSERR; - - stop_arm (); -} - - -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; - } - - if (suggest_timeout_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (suggest_timeout_task); - suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK; - } - - GNUNET_ATS_scheduling_done (ats); - - ret = 0; - - stop_arm (); -} - - -static void -suggest_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting address for peer timed out\n"); - - if (die_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - } - - die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); -} - -static void -address_suggest_cb (void *cls, const struct GNUNET_HELLO_Address *a, - 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 suggestions; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS suggests address `%s'\n", - GNUNET_i2s (&a->peer)); - - if (0 != memcmp (&a->peer, &peer.id, - sizeof (struct GNUNET_PeerIdentity))) - { - GNUNET_break (0); - if (die_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_SCHEDULER_add_now (&end_badly, NULL); - return; - } - - if (0 != strcmp (a->transport_name, address.plugin)) - { - GNUNET_break (0); - if (die_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_SCHEDULER_add_now (&end_badly, NULL); - return; - } - - if (a->address_length != address.addr_len) - { - GNUNET_break (0); - if (die_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_SCHEDULER_add_now (&end_badly, NULL); - return; - } - - if (0 != memcmp (a->address, address.addr, - a->address_length)) - { - GNUNET_break (0); - if (die_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_SCHEDULER_add_now (&end_badly, NULL); - return; - } - - if (session != address.session) - { - GNUNET_break (0); - if (die_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (die_task); - die_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_SCHEDULER_add_now (&end_badly, NULL); - return; - } - - suggestions ++; - - if (2 == suggestions) - { - GNUNET_SCHEDULER_add_now(&end, NULL); - return; - } - - if (suggest_timeout_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (suggest_timeout_task); - suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK; - } - suggest_timeout_task = GNUNET_SCHEDULER_add_delayed(ATS_TIMEOUT, &suggest_timeout, NULL); -} - -void -start_arm (const char *cfgname) -{ - arm_proc = - GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", - "gnunet-service-arm", - "-c", cfgname, NULL); -} - -static void -check (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - ret = GNUNET_SYSERR; - - die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); - start_arm (cfgfile); - - ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); - - if (ats == NULL) - { - ret = GNUNET_SYSERR; - end (); - return; - } - - /* set up peer */ - GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, - &peer.id.hashPubKey); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s (&peer.id)); - - address.plugin = "test"; - address.session = NULL; - address.addr = GNUNET_strdup ("test"); - address.addr_len = 4; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding address\n"); - - hello_addr.peer = peer.id; - hello_addr.transport_name = address.plugin; - hello_addr.address = address.addr; - hello_addr.address_length = address.addr_len; - GNUNET_ATS_address_update (ats, &hello_addr, address.session, NULL, 0); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting address for peer `%s'\n", - GNUNET_i2s (&peer.id)); - /* Increase block timout far beyond ATS_TIMEOUT */ - GNUNET_ATS_suggest_address (ats, &peer.id); - - GNUNET_ATS_reset_backoff(ats, &peer.id); - GNUNET_ATS_suggest_address (ats, &peer.id); -} - -int -main (int argc, char *argv[]) -{ - static char *const argv2[] = { "test_ats_api_scheduling", - "-c", - "test_ats_api.conf", - "-L", "WARNING", - NULL - }; - - static struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, - "test_ats_api_scheduling", "nohelp", options, &check, - NULL); - - - return ret; -} -/* end of file test_ats_api_reset_backoff.c */ diff --git a/src/ats/test_ats_api_scheduling.c b/src/ats/test_ats_api_scheduling.c deleted file mode 100644 index c9d2206..0000000 --- a/src/ats/test_ats_api_scheduling.c +++ /dev/null @@ -1,253 +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.c - * @brief test automatic transport selection scheduling 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 "ats.h" - -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) - -static GNUNET_SCHEDULER_TaskIdentifier die_task; - -static struct GNUNET_ATS_SchedulingHandle *ats; - -struct GNUNET_OS_Process *arm_proc; - - - -static int ret; - -struct Address -{ - char *plugin; - size_t plugin_len; - - void *addr; - size_t addr_len; - - struct GNUNET_ATS_Information *ats; - int ats_count; - - void *session; -}; - -struct PeerContext -{ - struct GNUNET_PeerIdentity id; - - struct Address *addr; -}; - -struct Address addr[2]; -struct PeerContext p[2]; -struct GNUNET_ATS_Information atsi[2]; - -static void -stop_arm () -{ - if (0 != GNUNET_OS_process_kill (arm_proc, SIGTERM)) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); - GNUNET_OS_process_wait (arm_proc); - GNUNET_OS_process_destroy (arm_proc); - arm_proc = NULL; -} - - -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - die_task = GNUNET_SCHEDULER_NO_TASK; - if (ats != NULL) - GNUNET_ATS_scheduling_done (ats); - - ret = GNUNET_SYSERR; - - stop_arm (); -} - - -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 (ats); - - ret = 0; - - stop_arm (); -} - - -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 *ats, - uint32_t ats_count) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS suggests address `%s'\n", - GNUNET_i2s (&address->peer)); - - GNUNET_assert (0 == - memcmp (&address->peer, &p[0].id, - sizeof (struct GNUNET_PeerIdentity))); - GNUNET_assert (0 == strcmp (address->transport_name, addr[0].plugin)); - GNUNET_assert (address->address_length == addr[0].addr_len); - GNUNET_assert (0 == - memcmp (address->address, addr[0].plugin, - address->address_length)); - GNUNET_assert (addr[0].session == session); - - - /* TODO ats merge - * GNUNET_assert (ats_count == 2); - * GNUNET_assert (atsi[0].type == htons (1)); - * GNUNET_assert (atsi[0].type == htons (2)); - * GNUNET_assert (atsi[1].type == htons (2)); - * GNUNET_assert (atsi[1].type == htons (2)); - */ - - ret = 0; - - GNUNET_SCHEDULER_add_now (&end, NULL); -} - -void -start_arm (const char *cfgname) -{ - arm_proc = - GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", - "gnunet-service-arm", - "-c", cfgname, NULL); -} - -static void -check (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_HELLO_Address address0; - - ret = GNUNET_SYSERR; - - die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); - start_arm (cfgfile); - - ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); - - if (ats == NULL) - { - ret = GNUNET_SYSERR; - end (); - return; - } - - /* set up peer */ - GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, - &p[0].id.hashPubKey); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", - GNUNET_i2s (&p[0].id)); - - GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, - &p[1].id.hashPubKey); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", - GNUNET_i2s (&p[1].id)); - - addr[0].plugin = "test"; - addr[0].session = NULL; - addr[0].addr = GNUNET_strdup ("test"); - addr[0].addr_len = 4; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing address creation\n"); - - address0.peer = p[0].id; - address0.transport_name = addr[0].plugin; - address0.address = addr[0].addr; - address0.address_length = addr[0].addr_len; - GNUNET_ATS_address_update (ats, &address0, addr[0].session, NULL, 0); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing ATS info creation\n"); - - atsi[0].type = htonl (GNUNET_ATS_UTILIZATION_UP); - atsi[0].value = htonl (1024); - - GNUNET_ATS_address_update (ats, &address0, addr[0].session, atsi, 1); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing ATS info update\n"); - - atsi[0].type = htonl (GNUNET_ATS_UTILIZATION_UP); - atsi[0].value = htonl (2048); - - atsi[1].type = htonl (GNUNET_ATS_UTILIZATION_DOWN); - atsi[1].value = htonl (1024); - - GNUNET_ATS_address_update (ats, &address0, addr[0].session, atsi, 2); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing manual address deletion \n"); - address0.peer = p[1].id; // FIXME: why? typo in old code? - GNUNET_ATS_address_update (ats, &address0, addr[0].session, NULL, 0); - GNUNET_ATS_address_destroyed (ats, &address0, addr[0].session); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting peer `%s'\n", - GNUNET_i2s (&p[0].id)); - GNUNET_ATS_suggest_address (ats, &p[0].id); -} - -int -main (int argc, char *argv[]) -{ - static char *const argv2[] = { "test_ats_api_scheduling", - "-c", - "test_ats_api.conf", - "-L", "WARNING", - NULL - }; - - static struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, - "test_ats_api_scheduling", "nohelp", options, &check, - NULL); - - - return ret; -} - -/* end of file test_ats_api_scheduling.c */ diff --git a/src/ats/test_ats_api_scheduling_add_address.c b/src/ats/test_ats_api_scheduling_add_address.c new file mode 100644 index 0000000..f7ee195 --- /dev/null +++ b/src/ats/test_ats_api_scheduling_add_address.c @@ -0,0 +1,199 @@ +/* + 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_add_address.c + * @brief test adding addresses in automatic transport selection scheduling API + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +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 address + */ +struct GNUNET_HELLO_Address test_hello_address; + +/** + * Session + */ +static void *test_session; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[2]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + + +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; + } + if (NULL != sched_ats) + GNUNET_ATS_scheduling_done (sched_ats); + sched_ats = NULL; + free_test_address (&test_addr); +} + +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; + if (0 == stage) + { + if (GNUNET_OK == compare_addresses (address, session, &test_hello_address, test_session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Callback with correct address `%s'\n", + GNUNET_i2s (&address->peer)); + ret = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Callback with invalid address `%s'\n", + 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 0: Callback with incorrect ats info \n"); + ret = 1; + } + stage ++; + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + } +} + +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); + + /* 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_count = 2; + + /* Adding address without session */ + test_session = NULL; + create_test_address (&test_addr, "test", test_session, "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); + + GNUNET_ATS_suggest_address (sched_ats, &p.id); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_api_scheduling_add_address", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + +/* end of file test_ats_api_scheduling_add_address.c */ diff --git a/src/ats/test_ats_api_scheduling_add_session.c b/src/ats/test_ats_api_scheduling_add_session.c new file mode 100644 index 0000000..9394484 --- /dev/null +++ b/src/ats/test_ats_api_scheduling_add_session.c @@ -0,0 +1,237 @@ +/* + 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_add_session.c + * @brief test adding a session to an existing addresses + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +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 address + */ +struct GNUNET_HELLO_Address test_hello_address; + +/** + * Session + */ +static void *test_session; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[2]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + + +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; + } + if (NULL != sched_ats) + GNUNET_ATS_scheduling_done (sched_ats); + sched_ats = NULL; + free_test_address (&test_addr); +} + +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; + if (0 == stage) + { + if (GNUNET_OK == compare_addresses (address, session, &test_hello_address, test_session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Callback with correct address `%s'\n", + GNUNET_i2s (&address->peer)); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Callback with invalid address `%s'\n", + 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 0: Callback with incorrect ats info \n"); + ret = 1; + } + stage ++; + + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + + /* Adding address with session */ + test_session = &test_hello_address; + create_test_address (&test_addr, "test", test_session, "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); + + GNUNET_ATS_suggest_address (sched_ats, &p.id); + return; + } + if (1 == stage) + { + if (GNUNET_OK == compare_addresses (address, session, &test_hello_address, test_session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 1: Callback with correct address `%s'\n", + GNUNET_i2s (&address->peer)); + ret = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 1: Callback with invalid address `%s'\n", + 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 1: Callback with incorrect ats info \n"); + ret = 1; + } + stage ++; + + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + +} + +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); + + /* 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_count = 2; + + /* Adding address without session */ + test_session = NULL; + create_test_address (&test_addr, "test", test_session, "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); + + GNUNET_ATS_suggest_address (sched_ats, &p.id); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_api_scheduling_add_address", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + +/* end of file test_ats_api_scheduling_add_session.c */ diff --git a/src/ats/test_ats_api_scheduling_block_and_reset.c b/src/ats/test_ats_api_scheduling_block_and_reset.c new file mode 100644 index 0000000..b799a5d --- /dev/null +++ b/src/ats/test_ats_api_scheduling_block_and_reset.c @@ -0,0 +1,364 @@ +/* + 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_reset_backoff.c + * @brief test case for blocking suggests and blocking reset API + * measure duration of initial suggest, measure blocking duration, + * reset block, measure suggest, compare time + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +#define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10) + +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +static GNUNET_SCHEDULER_TaskIdentifier wait_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 address + */ +struct GNUNET_HELLO_Address test_hello_address; + +/** + * Session + */ +static void *test_session; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[2]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + + +struct GNUNET_TIME_Absolute initial_start; + +struct GNUNET_TIME_Relative initial_duration; + +/** + * Blocking start + */ +struct GNUNET_TIME_Absolute block_start; + +struct GNUNET_TIME_Relative block_duration; + +struct GNUNET_TIME_Absolute reset_block_start; + +struct GNUNET_TIME_Relative reset_block_duration; + +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + if (wait_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (wait_task); + wait_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; + } + if (wait_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (wait_task); + wait_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_ATS_scheduling_done (sched_ats); + sched_ats = NULL; + free_test_address (&test_addr); +} + +static void +request_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + wait_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_ATS_suggest_address (sched_ats, &p.id); + wait_task = GNUNET_SCHEDULER_add_delayed (WAIT, &request_task, NULL); +} + +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; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %u\n", stage); + if (3 == stage) + { + /* Suggestion after resetting block interval */ + reset_block_duration = GNUNET_TIME_absolute_get_difference(reset_block_start, GNUNET_TIME_absolute_get()); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Address suggestion after resetting blocking took about %llu ms!\n", + (long long unsigned int) reset_block_duration.rel_value); + if ((block_duration.rel_value <= (initial_duration.rel_value * 3)) || + (initial_duration.rel_value <= (block_duration.rel_value * 3))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Address suggestion after resetting blocking (%llu ms) took about the same as initial suggestion (%llu ms)\n", + (long long unsigned int) reset_block_duration.rel_value, + (long long unsigned int) initial_duration.rel_value); + ret = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Address suggestion after resetting blocking (%llu ms) has too big difference to initial suggestion (%llu ms)\n", + (long long unsigned int) reset_block_duration.rel_value, + (long long unsigned int) initial_duration.rel_value); + ret = 1; + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + if (((initial_duration.rel_value * 3) <= block_duration.rel_value ) && + ((reset_block_duration.rel_value * 3) <= block_duration.rel_value)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Address suggestion after resetting blocking (%llu ms) and initial suggestion (%llu ms) much faster than with blocking (%llu ms)\n", + (long long unsigned int) reset_block_duration.rel_value, + (long long unsigned int) initial_duration.rel_value, + (long long unsigned int) block_duration.rel_value); + ret = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Address suggestion after resetting blocking (%llu ms) and initial suggestion (%llu ms) not faster than with blocking (%llu ms)\n", + (long long unsigned int) reset_block_duration.rel_value, + (long long unsigned int) initial_duration.rel_value, + (long long unsigned int) block_duration.rel_value); + ret = 1; + } + + + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + + } + if (2 == stage) + { + /* Suggestion after block*/ + block_duration = GNUNET_TIME_absolute_get_difference(block_start, GNUNET_TIME_absolute_get()); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Address suggestion was blocked for about %llu ms!\n", + (long long unsigned int) block_duration.rel_value); + + 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_DEBUG, "Stage %u: Callback with invalid address `%s'\n", stage, + GNUNET_i2s (&address->peer)); + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + 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"); + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 1; + } + stage ++; + + /* Reset block interval */ + GNUNET_ATS_reset_backoff (sched_ats, &address->peer); + reset_block_start = GNUNET_TIME_absolute_get(); + GNUNET_ATS_suggest_address (sched_ats, &p.id); + } + if (1 == stage) + { + /* Initial suggestion */ + 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_DEBUG, "Stage %u: Callback with invalid address `%s'\n", stage, + GNUNET_i2s (&address->peer)); + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + 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"); + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 1; + } + stage ++; + initial_duration = GNUNET_TIME_absolute_get_difference(initial_start, GNUNET_TIME_absolute_get()); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %u: Initial suggestion took about %llu ms\n", stage, + (long long unsigned int) block_duration.rel_value); + + block_start = GNUNET_TIME_absolute_get(); + wait_task = GNUNET_SCHEDULER_add_delayed (WAIT, &request_task, NULL); + } + if (0 == stage) + { + /* Startup suggestion */ + 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_DEBUG, "Stage %u: Callback with invalid address `%s'\n", stage, + GNUNET_i2s (&address->peer)); + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + 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"); + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 1; + } + stage ++; + + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + + initial_start = GNUNET_TIME_absolute_get(); + GNUNET_ATS_suggest_address (sched_ats, &p.id); + } +} + + +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); + + /* 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_count = 2; + + /* Adding address without session */ + test_session = &test_addr; + create_test_address (&test_addr, "test", test_session, "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); + + initial_start = GNUNET_TIME_absolute_get(); + GNUNET_ATS_suggest_address (sched_ats, &p.id); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_api_scheduling_add_address", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} +/* end of file test_ats_api_scheduling_reset_backoff.c */ diff --git a/src/ats/test_ats_api_scheduling_check_min_bw_alt.c b/src/ats/test_ats_api_scheduling_check_min_bw_alt.c new file mode 100644 index 0000000..bf23ad2 --- /dev/null +++ b/src/ats/test_ats_api_scheduling_check_min_bw_alt.c @@ -0,0 +1,417 @@ +/* + 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_mlp.c + * @brief test for the MLP solver + * @author Christian Grothoff + * @author Matthias Wachs + + */ +/** + * @file ats/test_ats_api_scheduling_check_min_bw_alt.c + * @brief alternative suggestion on network change if no bw is available + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +#define DEBUG_ATS_INFO GNUNET_NO + +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[2]; + +/** + * Test peer + */ +static struct PeerContext p[2]; + + +/** + * HELLO address + */ +struct GNUNET_HELLO_Address test_hello_address[2]; + +/** + * Session + */ +static void *test_session[2]; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[2][2]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + +/** + * Configured WAN out quota + */ +unsigned long long wan_quota_out; + +/** + * Configured WAN in quota + */ +unsigned long long wan_quota_in; + + +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[0]); + free_test_address (&test_addr[1]); + 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[0]); + free_test_address (&test_addr[1]); +} + + +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; + unsigned int bw_in = ntohl(bandwidth_in.value__); + unsigned int bw_out = ntohl(bandwidth_out.value__); + + if (0 == stage) + { + /* Initial suggestion for 1st address */ + if (GNUNET_OK == compare_addresses (address, session, &test_hello_address[0], test_session[0])) + { + 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_DEBUG, "Stage %u: Callback with invalid address `%s'\n", + stage, GNUNET_i2s (&address->peer)); + ret = 1; + } + + if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info[0], test_ats_count)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n"); + ret = 1; + } + + if (bw_in > wan_quota_in) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Suggested WAN inbound quota %u bigger than allowed quota %llu \n", + stage, bw_in, wan_quota_in); + ret = 1; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Suggested WAN inbound quota %u, allowed quota %llu \n", + stage, bw_in, wan_quota_in); + + if (bw_out > wan_quota_out) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Suggested WAN outbound quota %u bigger than allowed quota %llu \n", + stage, bw_out, wan_quota_out); + ret = 1; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Suggested WAN outbound quota %u, allowed quota %llu \n", + stage, bw_out, wan_quota_out); + + if (1 == ret) + { + GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id); + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + p[0].bw_out_assigned = bw_out; + p[0].bw_in_assigned = bw_in; + stage ++; + + /* Add a 2nd address to give ATS an suggestion alternative */ + /* Prepare ATS Information */ + test_ats_info[1][0].type = htonl (GNUNET_ATS_NETWORK_TYPE); + test_ats_info[1][0].value = htonl(GNUNET_ATS_NET_LAN); + test_ats_info[1][1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); + test_ats_info[1][1].value = htonl(1); + test_ats_count = 2; + + /* Adding address with session */ + test_session[1] = &test_addr[1]; + create_test_address (&test_addr[1], "test1", test_session[1], "test1", strlen ("test1") + 1); + test_hello_address[1].peer = p[0].id; + test_hello_address[1].transport_name = test_addr[1].plugin; + test_hello_address[1].address = test_addr[1].addr; + test_hello_address[1].address_length = test_addr[1].addr_len; + GNUNET_ATS_address_add (sched_ats, &test_hello_address[1], test_session[1], + test_ats_info[1], test_ats_count); + + + /* Changing 1st address to network with now bw available (WLAN) */ + test_ats_info[0][0].type = htonl (GNUNET_ATS_NETWORK_TYPE); + test_ats_info[0][0].value = htonl(GNUNET_ATS_NET_WLAN); + test_ats_info[0][1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); + test_ats_info[0][1].value = htonl(1); + test_ats_count = 2; + + GNUNET_ATS_address_update (sched_ats, &test_hello_address[0], test_session[0], + test_ats_info[0], test_ats_count); + return; + } + if (1 == stage) + { + /* Bandwidth update to (in/out) 0/0 for 1st address */ + if (GNUNET_OK == compare_addresses (address, session, &test_hello_address[0], test_session[0])) + { + 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_DEBUG, "Stage %u: Callback with invalid address `%s'\n", + stage, GNUNET_i2s (&address->peer)); + ret = 1; + } + + if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info[0], test_ats_count)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n"); + ret = 1; + } + + if ((bw_in != 0) || (bw_out != 0)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: ATS did not set bandwidth to 0 but instead to %u/%u \n", + stage, bw_in, wan_quota_in); + ret = 1; + } + + if (1 == ret) + { + GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id); + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + p[0].bw_out_assigned = bw_out; + p[0].bw_in_assigned = bw_in; + stage ++; + return; + } + if (2 == stage) + { + /* Expecting suggestion of alternative 2nd address*/ + if (GNUNET_OK == compare_addresses (address, session, &test_hello_address[1], test_session[1])) + { + 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_DEBUG, "Stage %u: Callback with invalid address `%s'\n", + stage, GNUNET_i2s (&address->peer)); + ret = 1; + } + + if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info[1], test_ats_count)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n", + stage); + ret = 1; + } + + if ((bw_in == 0) || (bw_out == 0)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: ATS did not set bandwidth correctly \n", + stage); + ret = 1; + } + + if (1 == ret) + { + GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id); + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 0; + return; + } +} + +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TESTING_Peer *peer) +{ + char *quota_str; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_OUT", "a_str)) + { + fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n"); + ret = 1; + return; + } + if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_out)) + { + fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n"); + ret = 1; + GNUNET_free (quota_str); + return; + } + GNUNET_free (quota_str); + quota_str = NULL; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_IN", "a_str)) + { + fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n"); + ret = 1; + return; + } + if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_in)) + { + fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n"); + GNUNET_free (quota_str); + ret = 1; + return; + } + GNUNET_free (quota_str); + quota_str = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN inbound quota: %llu\n", wan_quota_in); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN outbound quota: %llu\n", wan_quota_out); + + + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + /* 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 0 */ + if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID0, &p[0].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[0].id))); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", + GNUNET_i2s(&p[0].id)); + + /* Set up peer 1*/ + if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID1, &p[1].id.hashPubKey)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); + ret = GNUNET_SYSERR; + end (); + return; + } + + GNUNET_assert (0 == strcmp (PEERID1, GNUNET_i2s_full (&p[1].id))); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", + GNUNET_i2s(&p[1].id)); + + /* Prepare ATS Information */ + test_ats_info[0][0].type = htonl (GNUNET_ATS_NETWORK_TYPE); + test_ats_info[0][0].value = htonl(GNUNET_ATS_NET_WAN); + test_ats_info[0][1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); + test_ats_info[0][1].value = htonl(1); + test_ats_count = 2; + + /* Adding address with session */ + test_session[0] = &test_addr[0]; + create_test_address (&test_addr[0], "test0", test_session[0], "test0", strlen ("test0") + 1); + test_hello_address[0].peer = p[0].id; + test_hello_address[0].transport_name = test_addr[0].plugin; + test_hello_address[0].address = test_addr[0].addr; + test_hello_address[0].address_length = test_addr[0].addr_len; + GNUNET_ATS_address_add (sched_ats, &test_hello_address[0], test_session[0], + test_ats_info[0], test_ats_count); + + GNUNET_ATS_suggest_address (sched_ats, &p[0].id); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_api_scheduling_check_min_bw_alt", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + + +/* end of file test_ats_api_scheduling_check_min_bw_alt.c */ diff --git a/src/ats/test_ats_api_scheduling_destroy_address.c b/src/ats/test_ats_api_scheduling_destroy_address.c new file mode 100644 index 0000000..93b90da --- /dev/null +++ b/src/ats/test_ats_api_scheduling_destroy_address.c @@ -0,0 +1,218 @@ +/* + 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_destroy_address.c + * @brief test destroying addresses in automatic transport selection scheduling API + * @author Christian Grothoff + * @author Matthias Wachs + * + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +static GNUNET_SCHEDULER_TaskIdentifier wait_task; + +#define WAIT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) + + +/** + * 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 address + */ +struct GNUNET_HELLO_Address test_hello_address; + +/** + * Session + */ +static void *test_session; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[2]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + + +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + if (GNUNET_SCHEDULER_NO_TASK != wait_task) + { + GNUNET_SCHEDULER_cancel (wait_task); + wait_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"); + wait_task = GNUNET_SCHEDULER_NO_TASK; + if (die_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + free_test_address (&test_addr); + GNUNET_ATS_scheduling_done (sched_ats); + sched_ats = NULL; +} + +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; + + if (0 ==stage) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Received suggestion for peer `%s'\n", + GNUNET_i2s(&address->peer)); + + 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, "Callback with correct address `%s'\n", + GNUNET_i2s (&address->peer)); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback with invalid address `%s'\n", + GNUNET_i2s (&address->peer)); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 1; + return; + } + stage ++; + ret = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying address for `%s'\n", + GNUNET_i2s (&address->peer)); + /* Destroying address */ + GNUNET_ATS_address_destroyed (sched_ats, &test_hello_address, test_addr.session); + /* Request address */ + GNUNET_ATS_suggest_address (sched_ats, &p.id); + /* Wait for timeout */ + wait_task = GNUNET_SCHEDULER_add_delayed (WAIT_TIMEOUT, &end, NULL); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage 1: Unexpected address suggestion\n"); + ret = 1; + +} + + +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); + + /* 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_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_count = 2; + + /* Adding address without session */ + test_session = NULL; + create_test_address (&test_addr, "test", test_session, "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, 2); + + /* 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_add_address", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + +/* end of file test_ats_api_scheduling_destroy_address.c */ diff --git a/src/ats/test_ats_api_scheduling_destroy_inbound_connection.c b/src/ats/test_ats_api_scheduling_destroy_inbound_connection.c new file mode 100644 index 0000000..fe98859 --- /dev/null +++ b/src/ats/test_ats_api_scheduling_destroy_inbound_connection.c @@ -0,0 +1,223 @@ +/* + 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_destroy_inbound_connection.c + * @brief test destroying sessions for inbound connections: first add an address with a session, + * request the address and compare, delete the session, request and + * compare again, delete whole address, request and wait for timeout, + * shutdown + * @author Christian Grothoff + * @author Matthias Wachs + * + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +static GNUNET_SCHEDULER_TaskIdentifier wait_task; + +#define WAIT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) + + +/** + * 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 address + */ +struct GNUNET_HELLO_Address test_hello_address; + +/** + * Session + */ +static void *test_session; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[2]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + + +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + if (wait_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (wait_task); + wait_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"); + wait_task = GNUNET_SCHEDULER_NO_TASK; + if (die_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + free_test_address (&test_addr); + GNUNET_ATS_scheduling_done (sched_ats); + sched_ats = NULL; +} + + +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; + + if (0 == stage) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Received suggestion for peer `%s'\n", + GNUNET_i2s(&address->peer)); + + 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 0: Callback with correct address `%s'\n", + GNUNET_i2s (&address->peer)); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Callback with invalid address `%s'\n", + GNUNET_i2s (&address->peer)); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 1; + return; + } + stage ++; + ret = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying address for `%s'\n", + GNUNET_i2s (&address->peer)); + /* Destroying session for address */ + test_session = NULL; + GNUNET_ATS_address_destroyed (sched_ats, &test_hello_address, test_addr.session); + /* Request address */ + GNUNET_ATS_suggest_address (sched_ats, &p.id); + + /* Wait for timeout */ + wait_task = GNUNET_SCHEDULER_add_delayed (WAIT_TIMEOUT, &end, NULL); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Unexpected address suggestion\n", stage); + ret = 1; +} + + +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); + + /* 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_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_count = 2; + + /* Adding address with session */ + create_test_address (&test_addr, "test", &test_addr, NULL, 0); + test_session = &test_addr; + 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_addr.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_add_address", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + +/* end of file test_ats_api_scheduling_destroy_inbound_connection.c */ diff --git a/src/ats/test_ats_api_scheduling_destroy_session.c b/src/ats/test_ats_api_scheduling_destroy_session.c new file mode 100644 index 0000000..9467bdc --- /dev/null +++ b/src/ats/test_ats_api_scheduling_destroy_session.c @@ -0,0 +1,235 @@ +/* + 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_destroy_session.c + * @brief test destroying sessions: first add an address with a session, + * request the address and compare, delete the session, request and + * compare again, delete whole address, request and wait for timeout, + * shutdown + * @author Christian Grothoff + * @author Matthias Wachs + * + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +static GNUNET_SCHEDULER_TaskIdentifier wait_task; + +#define WAIT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) + + +/** + * 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 address + */ +struct GNUNET_HELLO_Address test_hello_address; + +/** + * Session + */ +static void *test_session; + + +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + if (wait_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (wait_task); + wait_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"); + wait_task = GNUNET_SCHEDULER_NO_TASK; + if (die_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + free_test_address (&test_addr); + GNUNET_ATS_scheduling_done (sched_ats); + sched_ats = NULL; +} + + +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; + + if (0 == stage) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Received suggestion for peer `%s'\n", + GNUNET_i2s(&address->peer)); + + 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 0: Callback with correct address `%s'\n", + GNUNET_i2s (&address->peer)); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Callback with invalid address `%s'\n", + GNUNET_i2s (&address->peer)); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 1; + return; + } + stage ++; + ret = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying address for `%s'\n", + GNUNET_i2s (&address->peer)); + /* Destroying session for address */ + test_session = NULL; + GNUNET_ATS_address_destroyed (sched_ats, &test_hello_address, test_addr.session); + /* Request address */ + GNUNET_ATS_suggest_address (sched_ats, &p.id); + return; + } + else if (1 == stage) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 1: Received suggestion for peer `%s'\n", + GNUNET_i2s(&address->peer)); + + + 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 1: Callback with correct address `%s'\n", + GNUNET_i2s (&address->peer)); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 1: Callback with invalid address `%s'\n", + GNUNET_i2s (&address->peer)); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 1; + return; + } + stage ++; + ret = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying address for `%s'\n", + GNUNET_i2s (&address->peer)); + /* Destroying complete address */ + GNUNET_ATS_address_destroyed (sched_ats, &test_hello_address, session); + /* Request address */ + GNUNET_ATS_suggest_address (sched_ats, &p.id); + wait_task = GNUNET_SCHEDULER_add_delayed (WAIT_TIMEOUT, &end, NULL); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage 1: Unexpected address suggestion\n"); + ret = 1; + +} + + +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); + + /* 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_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", + GNUNET_i2s_full(&p.id)); + + /* Adding address with session */ + create_test_address (&test_addr, "test", &test_addr, "test", strlen ("test") + 1); + test_session = &test_addr; + 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_addr.session, NULL, 0); + + /* 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_add_address", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + +/* end of file test_ats_api_scheduling_destroy_session.c */ diff --git a/src/ats/test_ats_api_scheduling_init.c b/src/ats/test_ats_api_scheduling_init.c new file mode 100644 index 0000000..bd96a4d --- /dev/null +++ b/src/ats/test_ats_api_scheduling_init.c @@ -0,0 +1,141 @@ +/* + 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_init.c + * @brief test automatic transport selection scheduling API init/shutdown + * @author Christian Grothoff + * @author Matthias Wachs + * + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) +#define DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) + +static GNUNET_SCHEDULER_TaskIdentifier die_task; +static GNUNET_SCHEDULER_TaskIdentifier wait_task; + +static struct GNUNET_ATS_SchedulingHandle *ats; + +static int ret; + +static void +end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + if (GNUNET_SCHEDULER_NO_TASK != wait_task) + { + GNUNET_SCHEDULER_cancel (wait_task); + wait_task = GNUNET_SCHEDULER_NO_TASK; + } + if (ats != NULL) + { + GNUNET_ATS_scheduling_done (ats); + ats = NULL; + } + ret = 1; +} + +static void +end_badly_now () +{ + if (die_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); +} + +static void +delay (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + static int v_delay = 5; + static int v_cur = 0; + + if (v_cur < v_delay) + { + wait_task = GNUNET_SCHEDULER_NO_TASK; + wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &delay, NULL); + fprintf (stderr,"."); + v_cur ++; + return; + } + + fprintf (stderr,"\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown ATS\n"); + GNUNET_ATS_scheduling_done (ats); + ats = NULL; + if (die_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (die_task); + die_task = GNUNET_SCHEDULER_NO_TASK; + } + ret = 0; +} + +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 *ats, + uint32_t ats_count) +{ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received address without asking for it!\n"); + end_badly_now (); +} + + +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TESTING_Peer *peer) +{ + ret = 1; + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initializing ATS\n"); + ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); + if (ats == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to initialize ATS\n"); + end_badly_now (); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for %llu sec\n", (long long unsigned int) DELAY.rel_value); + wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &delay, NULL); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_api_scheduling_init", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + +/* end of file test_ats_api_scheduling_init.c */ diff --git a/src/ats/test_ats_api_scheduling_min_bw.c b/src/ats/test_ats_api_scheduling_min_bw.c new file mode 100644 index 0000000..5a59c23 --- /dev/null +++ b/src/ats/test_ats_api_scheduling_min_bw.c @@ -0,0 +1,185 @@ +/* + 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_min_bw.c + * @brief add in address for a network where quota is below min bw: no suggest expected + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +#define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) + +static GNUNET_SCHEDULER_TaskIdentifier die_task; +static GNUNET_SCHEDULER_TaskIdentifier wait_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 address + */ +struct GNUNET_HELLO_Address test_hello_address; + +/** + * Session + */ +static void *test_session; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[2]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + + +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 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + 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; + } + if (NULL != sched_ats) + GNUNET_ATS_scheduling_done (sched_ats); + sched_ats = NULL; + free_test_address (&test_addr); +} + +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) +{ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion!\n"); + GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id); + GNUNET_SCHEDULER_add_now (&end, NULL); + ret = 1; +} + +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); + + /* 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; + GNUNET_SCHEDULER_add_now (&end , NULL); + 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; + GNUNET_SCHEDULER_add_now (&end , NULL); + 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_WLAN); /* WLAN quota is below min bw */ + test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); + test_ats_info[1].value = htonl(1); + test_ats_count = 2; + + /* Adding address without session */ + test_session = NULL; + create_test_address (&test_addr, "test", test_session, "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); + + GNUNET_ATS_suggest_address (sched_ats, &p.id); + + ret = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for wait period for no suggest...\n"); + wait_task = GNUNET_SCHEDULER_add_delayed (WAIT, &end, NULL); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_api_scheduling_add_address", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + +/* end of file test_ats_api_scheduling_min_bw.c */ diff --git a/src/ats/test_ats_api_scheduling_update_address.c b/src/ats/test_ats_api_scheduling_update_address.c new file mode 100644 index 0000000..2f52d64 --- /dev/null +++ b/src/ats/test_ats_api_scheduling_update_address.c @@ -0,0 +1,247 @@ +/* + 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 an address: add address, get and compare it, update it + * get it again and compre + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +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; + + +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 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; + 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 0: Callback for correct address `%s'\n", + GNUNET_i2s (&address->peer)); + ret = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage 0: Callback with incorrect address `%s'\n", + 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 0: Callback with incorrect ats info \n"); + ret = 1; + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + /* Update address */ + /* 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(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 1: Callback with correct address `%s'\n", + GNUNET_i2s (&address->peer)); + ret = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage 1: Callback with incorrect address `%s'\n", + 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 1: Callback with incorrect ats info \n"); + ret = 1; + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + GNUNET_SCHEDULER_add_now (&end, NULL); + } +} + +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); + + /* 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_mlp.c b/src/ats/test_ats_mlp.c deleted file mode 100644 index c467210..0000000 --- a/src/ats/test_ats_mlp.c +++ /dev/null @@ -1,195 +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_mlp.c - * @brief test for the MLP solver - * @author Christian Grothoff - * @author Matthias Wachs - - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_statistics_service.h" -#include "gnunet_ats_service.h" -#include "gnunet-service-ats_addresses_mlp.h" - -#define MLP_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3) -#define MLP_MAX_ITERATIONS INT_MAX - - -static int ret; - -struct GNUNET_STATISTICS_Handle * stats; - -struct GNUNET_CONTAINER_MultiHashMap * addresses; - -struct GAS_MLP_Handle *mlp; - - -static void -create_address (struct ATS_Address *addr, char * plugin, int ats_count, struct GNUNET_ATS_Information *ats) -{ - addr->mlp_information = NULL; - addr->next = NULL; - addr->prev = NULL; - addr->plugin = GNUNET_strdup (plugin); - addr->ats_count = ats_count; - addr->ats = ats; -} - -static void -set_ats (struct GNUNET_ATS_Information *ats, uint32_t type, uint32_t value) -{ - ats->type = type; - ats->value = value; -} - -static void -check (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ -#if !HAVE_LIBGLPK - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed!"); - ret = 1; - return; -#endif - struct ATS_Address addr[10]; - struct ATS_PreferedAddress *res[10]; - struct GAS_MLP_SolutionContext ctx; - - stats = GNUNET_STATISTICS_create("ats", cfg); - - addresses = GNUNET_CONTAINER_multihashmap_create (10); - - mlp = GAS_mlp_init (cfg, NULL, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS); - mlp->auto_solve = GNUNET_NO; - - struct GNUNET_PeerIdentity p[10]; - - /* Creating peer 1 */ - GNUNET_CRYPTO_hash_create_random(GNUNET_CRYPTO_QUALITY_WEAK, &p[0].hashPubKey); - /* Creating peer 2 */ - GNUNET_CRYPTO_hash_create_random(GNUNET_CRYPTO_QUALITY_WEAK, &p[1].hashPubKey); - - /* Creating peer 1 address 1 */ - addr[0].peer.hashPubKey = p[0].hashPubKey; - struct GNUNET_ATS_Information a1_ats[3]; - set_ats (&a1_ats[0], GNUNET_ATS_QUALITY_NET_DISTANCE, 1); - set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 1); - set_ats (&a1_ats[2], GNUNET_ATS_ARRAY_TERMINATOR, 0); - create_address (&addr[0], "dummy", 3, &a1_ats[0]); - addr[0].atsp_network_type = GNUNET_ATS_NET_WAN; - - /* Creating peer 1 address 2 */ - addr[1].peer.hashPubKey = p[0].hashPubKey; - struct GNUNET_ATS_Information a2_ats[3]; - set_ats (&a2_ats[1], GNUNET_ATS_QUALITY_NET_DISTANCE, 1); - set_ats (&a2_ats[0], GNUNET_ATS_QUALITY_NET_DELAY, 1); - set_ats (&a2_ats[2], GNUNET_ATS_ARRAY_TERMINATOR, 0); - create_address (&addr[1], "dummy2", 3, &a2_ats[0]); - addr[1].atsp_network_type = GNUNET_ATS_NET_LAN; - - /* Creating peer 2 address 1 */ - addr[2].peer.hashPubKey = p[1].hashPubKey; - struct GNUNET_ATS_Information a3_ats[3]; - set_ats (&a3_ats[1], GNUNET_ATS_QUALITY_NET_DISTANCE, 1); - set_ats (&a3_ats[0], GNUNET_ATS_QUALITY_NET_DELAY, 1); - set_ats (&a3_ats[2], GNUNET_ATS_ARRAY_TERMINATOR, 0); - create_address (&addr[2], "dummy3", 3, &a3_ats[0]); - addr[2].atsp_network_type = GNUNET_ATS_NET_LAN; - - GNUNET_CONTAINER_multihashmap_put(addresses, &addr[0].peer.hashPubKey, &addr[0], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - - /* Add peer 1 address 1 */ - GAS_mlp_address_update (mlp, addresses, &addr[0]); - - GNUNET_assert (mlp != NULL); - GNUNET_assert (mlp->addr_in_problem == 1); - - /* Update an peer 1 address 1 */ - set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 1); - GAS_mlp_address_update (mlp, addresses, &addr[0]); - GNUNET_assert (mlp->addr_in_problem == 1); - - /* Add peer 1 address 2 */ - GNUNET_CONTAINER_multihashmap_put(addresses, &addr[0].peer.hashPubKey, &addr[1], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - GAS_mlp_address_update (mlp, addresses, &addr[1]); - GNUNET_assert (mlp->addr_in_problem == 2); - - /* Add peer 2 address 1 */ - GNUNET_CONTAINER_multihashmap_put(addresses, &addr[2].peer.hashPubKey, &addr[2], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - GAS_mlp_address_update (mlp, addresses, &addr[2]); - GNUNET_assert (mlp->addr_in_problem == 3); - - GNUNET_assert (GNUNET_OK == GAS_mlp_solve_problem(mlp, &ctx)); - GNUNET_assert (GNUNET_OK == ctx.lp_result); - GNUNET_assert (GNUNET_OK == ctx.mlp_result); - - res[0] = GAS_mlp_get_preferred_address(mlp, addresses, &p[0]); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Preferred address `%s' outbound bandwidth: %u Bps\n",res[0]->address->plugin, res[0]->bandwidth_out); - res[1] = GAS_mlp_get_preferred_address(mlp, addresses, &p[1]); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Preferred address `%s' outbound bandwidth: %u Bps\n",res[1]->address->plugin, res[1]->bandwidth_out); - - /* Delete an address */ - GNUNET_CONTAINER_multihashmap_remove (addresses, &addr[0].peer.hashPubKey, &addr[0]); - GAS_mlp_address_delete (mlp, addresses, &addr[0]); - GNUNET_CONTAINER_multihashmap_remove (addresses, &addr[1].peer.hashPubKey, &addr[1]); - GAS_mlp_address_delete (mlp, addresses, &addr[1]); - GNUNET_CONTAINER_multihashmap_remove (addresses, &addr[2].peer.hashPubKey, &addr[2]); - GAS_mlp_address_delete (mlp, addresses, &addr[2]); - - GNUNET_assert (mlp->addr_in_problem == 0); - - GAS_mlp_done (mlp); - - GNUNET_free (addr[0].plugin); - GNUNET_free (addr[1].plugin); - GNUNET_CONTAINER_multihashmap_destroy (addresses); - GNUNET_STATISTICS_destroy(stats, GNUNET_NO); - - ret = 0; - return; -} - - -int -main (int argc, char *argv[]) -{ - - static char *const argv2[] = { "test_ats_mlp", - "-c", - "test_ats_api.conf", - "-L", "WARNING", - NULL - }; - - static struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, - "test_ats_mlp", "nohelp", options, - &check, NULL); - - - return ret; -} - -/* end of file test_ats_api_bandwidth_consumption.c */ diff --git a/src/ats/test_ats_mlp_averaging.c b/src/ats/test_ats_mlp_averaging.c deleted file mode 100644 index 97e9aa7..0000000 --- a/src/ats/test_ats_mlp_averaging.c +++ /dev/null @@ -1,178 +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_mlp.c - * @brief test for the MLP solver - * @author Christian Grothoff - * @author Matthias Wachs - - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_statistics_service.h" -#include "gnunet_ats_service.h" -#include "gnunet-service-ats_addresses_mlp.h" - -#define MLP_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3) -#define MLP_MAX_ITERATIONS INT_MAX - - -static int ret; - -struct GNUNET_STATISTICS_Handle * stats; - -struct GNUNET_CONTAINER_MultiHashMap * addresses; - -struct GAS_MLP_Handle *mlp; - - -static void -create_address (struct ATS_Address *addr, char * plugin, int ats_count, struct GNUNET_ATS_Information *ats) -{ - addr->mlp_information = NULL; - addr->next = NULL; - addr->prev = NULL; - addr->plugin = GNUNET_strdup (plugin); - addr->ats_count = ats_count; - addr->ats = ats; -} - -static void -set_ats (struct GNUNET_ATS_Information *ats, uint32_t type, uint32_t value) -{ - ats->type = type; - ats->value = value; -} - -static void -check (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ -#if !HAVE_LIBGLPK - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed!"); - ret = 1; - return; -#endif - struct ATS_Address addr[10]; - struct ATS_PreferedAddress *res[10]; - struct MLP_information *mlpi; - struct GAS_MLP_SolutionContext ctx; - - stats = GNUNET_STATISTICS_create("ats", cfg); - - addresses = GNUNET_CONTAINER_multihashmap_create (10); - - mlp = GAS_mlp_init (cfg, NULL, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS); - mlp->auto_solve = GNUNET_NO; - - struct GNUNET_PeerIdentity p[10]; - - /* Creating peer 1 */ - GNUNET_CRYPTO_hash_create_random(GNUNET_CRYPTO_QUALITY_WEAK, &p[0].hashPubKey); - - /* Creating peer 1 address 1 */ - addr[0].peer.hashPubKey = p[0].hashPubKey; - struct GNUNET_ATS_Information a1_ats[3]; - set_ats (&a1_ats[0], GNUNET_ATS_QUALITY_NET_DISTANCE, 1); - set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 0); - set_ats (&a1_ats[2], GNUNET_ATS_ARRAY_TERMINATOR, 0); - create_address (&addr[0], "dummy", 3, &a1_ats[0]); - addr[0].atsp_network_type = GNUNET_ATS_NET_LAN; - - GNUNET_CONTAINER_multihashmap_put(addresses, &addr[0].peer.hashPubKey, &addr[0], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - - /* Add peer 1 address 1 */ - GAS_mlp_address_update (mlp, addresses, &addr[0]); - mlpi = addr[0].mlp_information; - - GNUNET_assert (mlp != NULL); - GNUNET_assert (mlp->addr_in_problem == 1); - - /* Update an peer 1 address 1 */ - set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 20); - GAS_mlp_address_update (mlp, addresses, &addr[0]); - GNUNET_assert (mlp->addr_in_problem == 1); - - - /* Update an peer 1 address 1 */ - set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 10); - GAS_mlp_address_update (mlp, addresses, &addr[0]); - GNUNET_assert (mlp->addr_in_problem == 1); - - /* Update an peer 1 address 1 */ - set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 10); - GAS_mlp_address_update (mlp, addresses, &addr[0]); - GNUNET_assert (mlp->addr_in_problem == 1); - - /* Update an peer 1 address 1 */ - set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 30); - GAS_mlp_address_update (mlp, addresses, &addr[0]); - GNUNET_assert (mlp->addr_in_problem == 1); - - - GNUNET_assert (GNUNET_OK == GAS_mlp_solve_problem(mlp, &ctx)); - GNUNET_assert (GNUNET_OK == ctx.lp_result); - GNUNET_assert (GNUNET_OK == ctx.mlp_result); - - res[0] = GAS_mlp_get_preferred_address(mlp, addresses, &p[0]); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Preferred address `%s' outbound bandwidth: %u Bps\n",res[0]->address->plugin, res[0]->bandwidth_out); - GNUNET_free (res[0]); - - /* Delete an address */ - GNUNET_CONTAINER_multihashmap_remove (addresses, &addr[0].peer.hashPubKey, &addr[0]); - GAS_mlp_address_delete (mlp, addresses, &addr[0]); - - GNUNET_assert (mlp->addr_in_problem == 0); - - GAS_mlp_done (mlp); - - GNUNET_free (addr[0].plugin); - GNUNET_CONTAINER_multihashmap_destroy (addresses); - GNUNET_STATISTICS_destroy(stats, GNUNET_NO); - - ret = 0; - return; -} - - -int -main (int argc, char *argv[]) -{ - - static char *const argv2[] = { "test_ats_mlp", - "-c", - "test_ats_api.conf", - "-L", "WARNING", - NULL - }; - - static struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, - "test_ats_mlp", "nohelp", options, - &check, NULL); - - - return ret; -} - -/* end of file test_ats_api_bandwidth_consumption.c */ diff --git a/src/ats/test_ats_simplistic.c b/src/ats/test_ats_simplistic.c new file mode 100644 index 0000000..b11ae4e --- /dev/null +++ b/src/ats/test_ats_simplistic.c @@ -0,0 +1,380 @@ +/* + 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_mlp.c + * @brief test for the MLP solver + * @author Christian Grothoff + * @author Matthias Wachs + + */ +/** + * @file ats/test_ats_api_scheduling_add_address.c + * @brief test for ats simplistic solver + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +#define DEBUG_ATS_INFO GNUNET_NO + +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[2]; + +/** + * Test peer + */ +static struct PeerContext p[2]; + + +/** + * HELLO address + */ +struct GNUNET_HELLO_Address test_hello_address[2]; + +/** + * Session + */ +static void *test_session[2]; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[2]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + +/** + * Configured WAN out quota + */ +unsigned long long wan_quota_out; + +/** + * Configured WAN in quota + */ +unsigned long long wan_quota_in; + + +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[0]); + 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[0]); +} + + +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; + unsigned int bw_in = ntohl(bandwidth_in.value__); + unsigned int bw_out = ntohl(bandwidth_out.value__); + if (0 == stage) + { + if (GNUNET_OK == compare_addresses (address, session, &test_hello_address[0], test_session[0])) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Callback with correct address `%s'\n", + GNUNET_i2s (&address->peer)); + ret = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 0: Callback with invalid address `%s'\n", + 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 0: Callback with incorrect ats info \n"); + ret = 1; + } + + if (bw_in > wan_quota_in) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN inbound quota %u bigger than allowed quota %llu \n", + bw_in, wan_quota_in); + ret = 1; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN inbound quota %u, allowed quota %llu \n", + bw_in, wan_quota_in); + + if (bw_out > wan_quota_out) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN outbound quota %u bigger than allowed quota %llu \n", + bw_out, wan_quota_out); + ret = 1; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN outbound quota %u, allowed quota %llu \n", + bw_out, wan_quota_out); + + if (1 == ret) + { + GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id); + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + p[0].bw_out_assigned = bw_out; + p[0].bw_in_assigned = bw_in; + stage ++; + + /* Add a 2nd address */ + /* 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_count = 2; + + /* Adding address with session */ + test_session[1] = &test_addr[1]; + create_test_address (&test_addr[1], "test1", test_session[1], "test1", strlen ("test1") + 1); + test_hello_address[1].peer = p[1].id; + test_hello_address[1].transport_name = test_addr[1].plugin; + test_hello_address[1].address = test_addr[1].addr; + test_hello_address[1].address_length = test_addr[1].addr_len; + GNUNET_ATS_address_add (sched_ats, &test_hello_address[1], test_session[1], test_ats_info, test_ats_count); + } + if (1 == stage) + { + /* Expecting callback for address[0] with updated quota and no callback for address[1]*/ + if (GNUNET_OK == compare_addresses (address, session, &test_hello_address[0], test_session[0])) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 1: Callback with correct address `%s'\n", + GNUNET_i2s (&address->peer)); + ret = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage 1: Callback with invalid address `%s'\n", + 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 1: Callback with incorrect ats info \n"); + ret = 1; + } + + if (bw_in > wan_quota_in) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN inbound quota %u bigger than allowed quota %llu \n", + bw_in, wan_quota_in); + ret = 1; + } + else if (p[0].bw_in_assigned > bw_in) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN inbound quota %u bigger than last quota %llu \n", + bw_in, p[0].bw_in_assigned); + ret = 1; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN inbound quota %u, allowed quota %llu \n", + bw_in, wan_quota_in); + + if (bw_out > wan_quota_out) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN outbound quota %u bigger than allowed quota %llu \n", + bw_out, wan_quota_out); + ret = 1; + } + else if (p[0].bw_out_assigned > bw_out) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN inbound quota %u bigger than last quota %llu \n", + bw_out, p[0].bw_out_assigned); + ret = 1; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN outbound quota %u, allowed quota %llu \n", + bw_out, wan_quota_out); + + if (1 == ret) + { + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + stage ++; + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + +} + +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TESTING_Peer *peer) +{ + char *quota_str; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_OUT", "a_str)) + { + fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n"); + ret = 1; + return; + } + if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_out)) + { + fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n"); + ret = 1; + GNUNET_free (quota_str); + return; + } + GNUNET_free (quota_str); + quota_str = NULL; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_IN", "a_str)) + { + fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n"); + ret = 1; + return; + } + if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_in)) + { + fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n"); + GNUNET_free (quota_str); + ret = 1; + return; + } + GNUNET_free (quota_str); + quota_str = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN inbound quota: %llu\n", wan_quota_in); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN outbound quota: %llu\n", wan_quota_out); + + + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + /* 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 0 */ + if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID0, &p[0].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[0].id))); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", + GNUNET_i2s(&p[0].id)); + + /* Set up peer 1*/ + if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID1, &p[1].id.hashPubKey)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); + ret = GNUNET_SYSERR; + end (); + return; + } + + GNUNET_assert (0 == strcmp (PEERID1, GNUNET_i2s_full (&p[1].id))); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", + GNUNET_i2s(&p[1].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_count = 2; + + /* Adding address with session */ + test_session[0] = &test_addr[0]; + create_test_address (&test_addr[0], "test0", test_session[0], "test0", strlen ("test0") + 1); + test_hello_address[0].peer = p[0].id; + test_hello_address[0].transport_name = test_addr[0].plugin; + test_hello_address[0].address = test_addr[0].addr; + test_hello_address[0].address_length = test_addr[0].addr_len; + GNUNET_ATS_address_add (sched_ats, &test_hello_address[0], test_session[0], test_ats_info, test_ats_count); + + GNUNET_ATS_suggest_address (sched_ats, &p[0].id); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_simplististic", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + + +/* end of file test_ats_api_bandwidth_consumption.c */ diff --git a/src/ats/test_ats_simplistic_change_preference.c b/src/ats/test_ats_simplistic_change_preference.c new file mode 100644 index 0000000..793d0cb --- /dev/null +++ b/src/ats/test_ats_simplistic_change_preference.c @@ -0,0 +1,418 @@ +/* + 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_mlp.c + * @brief test for the MLP solver + * @author Christian Grothoff + * @author Matthias Wachs + + */ +/** + * @file ats/test_ats_simplistic_change_preference.c + * @brief test for changing preferences in ats simplistic solver + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +#define DEBUG_ATS_INFO GNUNET_NO + +#define SLEEP GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) + +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +/** + * Scheduling handle + */ +static struct GNUNET_ATS_SchedulingHandle *sched_ats; + +/** + * Scheduling handle + */ +static struct GNUNET_ATS_PerformanceHandle *perf_ats; + + +/** + * Return value + */ +static int ret; + +/** + * Test address + */ +static struct Test_Address test_addr[2]; + +/** + * Test peer + */ +static struct PeerContext p[2]; + + +/** + * HELLO address + */ +struct GNUNET_HELLO_Address test_hello_address[2]; + +/** + * Session + */ +static void *test_session[2]; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[2]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + +/** + * Configured WAN out quota + */ +unsigned long long wan_quota_out; + +/** + * Configured WAN in quota + */ +unsigned long long wan_quota_in; + + +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); + if (perf_ats != NULL) + GNUNET_ATS_performance_done (perf_ats); + free_test_address (&test_addr[0]); + 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_performance_done (perf_ats); + perf_ats = NULL; + GNUNET_ATS_scheduling_done (sched_ats); + sched_ats = NULL; + free_test_address (&test_addr[0]); +} + + +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; + unsigned int bw_in = ntohl(bandwidth_in.value__); + unsigned int bw_out = ntohl(bandwidth_out.value__); + if (0 == stage) + { + if (GNUNET_OK == compare_addresses (address, session, &test_hello_address[0], test_session[0])) + { + 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_DEBUG, "Stage %u: Callback with invalid 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", + stage); + ret = 1; + } + + if (bw_in > wan_quota_in) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN inbound quota %u bigger than allowed quota %llu \n", + bw_in, wan_quota_in); + ret = 1; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN inbound quota %u, allowed quota %llu \n", + bw_in, wan_quota_in); + + if (bw_out > wan_quota_out) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN outbound quota %u bigger than allowed quota %llu \n", + bw_out, wan_quota_out); + ret = 1; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN outbound quota %u, allowed quota %llu \n", + bw_out, wan_quota_out); + + if (1 == ret) + { + GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id); + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + stage ++; + + GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id); + GNUNET_ATS_suggest_address (sched_ats, &p[1].id); + return; + } + if (1 == stage) + { + if (GNUNET_OK == compare_addresses (address, session, &test_hello_address[1], test_session[1])) + { + 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_DEBUG, "Stage %u: Callback with invalid 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", + stage); + ret = 1; + } + + if (bw_in > wan_quota_in) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN inbound quota %u bigger than allowed quota %llu \n", + bw_in, wan_quota_in); + ret = 1; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN inbound quota %u, allowed quota %llu \n", + bw_in, wan_quota_in); + + if (bw_out > wan_quota_out) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN outbound quota %u bigger than allowed quota %llu \n", + bw_out, wan_quota_out); + ret = 1; + } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN outbound quota %u, allowed quota %llu \n", + bw_out, wan_quota_out); + + if (1 == ret) + { + GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id); + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + stage ++; + GNUNET_ATS_suggest_address_cancel (sched_ats, &p[1].id); + GNUNET_SCHEDULER_add_now (&end, NULL); + + return; + } +} + +static void +sleep_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_ATS_suggest_address (sched_ats, &p[0].id); +} + +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TESTING_Peer *peer) +{ + char *quota_str; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_OUT", "a_str)) + { + fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n"); + ret = 1; + return; + } + if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_out)) + { + fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n"); + ret = 1; + GNUNET_free (quota_str); + return; + } + GNUNET_free (quota_str); + quota_str = NULL; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_IN", "a_str)) + { + fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n"); + ret = 1; + return; + } + if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_in)) + { + fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n"); + GNUNET_free (quota_str); + ret = 1; + return; + } + GNUNET_free (quota_str); + quota_str = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN inbound quota: %llu\n", wan_quota_in); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN outbound quota: %llu\n", wan_quota_out); + + + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + /* 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; + } + + perf_ats = GNUNET_ATS_performance_init (cfg, NULL, NULL); + if (perf_ats == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS performance!\n"); + ret = 1; + end (); + return; + } + + /* Set up peer 0 */ + if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID0, &p[0].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[0].id))); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", + GNUNET_i2s(&p[0].id)); + + + /* Set up peer 0 */ + if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID1, &p[1].id.hashPubKey)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); + ret = GNUNET_SYSERR; + end (); + return; + } + + GNUNET_assert (0 == strcmp (PEERID1, GNUNET_i2s_full (&p[1].id))); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", + GNUNET_i2s(&p[1].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_count = 2; + + /* Adding address with session */ + test_session[0] = &test_addr[0]; + create_test_address (&test_addr[0], "test0", test_session[0], "test0", strlen ("test0") + 1); + test_hello_address[0].peer = p[0].id; + test_hello_address[0].transport_name = test_addr[0].plugin; + test_hello_address[0].address = test_addr[0].addr; + test_hello_address[0].address_length = test_addr[0].addr_len; + GNUNET_ATS_address_add (sched_ats, &test_hello_address[0], test_session[0], test_ats_info, test_ats_count); + + + /* Adding address with session */ + test_session[1] = &test_addr[1]; + create_test_address (&test_addr[1], "test1", test_session[1], "test1", strlen ("test1") + 1); + test_hello_address[1].peer = p[1].id; + test_hello_address[1].transport_name = test_addr[0].plugin; + test_hello_address[1].address = test_addr[0].addr; + test_hello_address[1].address_length = test_addr[0].addr_len; + GNUNET_ATS_address_add (sched_ats, &test_hello_address[1], test_session[1], test_ats_info, test_ats_count); + + + /* Change bandwidth preference */ + GNUNET_ATS_change_preference (perf_ats, + &p[0].id, + GNUNET_ATS_PREFERENCE_BANDWIDTH,(double) 1000, GNUNET_ATS_PREFERENCE_END); + GNUNET_ATS_change_preference (perf_ats, + &p[1].id, + GNUNET_ATS_PREFERENCE_BANDWIDTH,(double) 1000, GNUNET_ATS_PREFERENCE_END); + + + /* Change latency preference */ + + GNUNET_ATS_change_preference (perf_ats, + &p[0].id, + GNUNET_ATS_PREFERENCE_LATENCY,(double) 10, GNUNET_ATS_PREFERENCE_END); + GNUNET_ATS_change_preference (perf_ats, + &p[1].id, + GNUNET_ATS_PREFERENCE_LATENCY,(double) 100, GNUNET_ATS_PREFERENCE_END); + GNUNET_SCHEDULER_add_delayed (SLEEP, &sleep_task, NULL); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_simplistic_change_preference", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + + +/* end of file test_ats_simplistic_change_preference.c */ diff --git a/src/ats/test_ats_simplistic_pref_aging.c b/src/ats/test_ats_simplistic_pref_aging.c new file mode 100644 index 0000000..8591ef1 --- /dev/null +++ b/src/ats/test_ats_simplistic_pref_aging.c @@ -0,0 +1,448 @@ +/* + 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_mlp.c + * @brief test for the MLP solver + * @author Christian Grothoff + * @author Matthias Wachs + + */ +/** + * @file ats/test_ats_api_scheduling_add_address.c + * @brief test for ats simplistic solver preference aging: + * Add 2 addresses and set high preference for one. Expect higher bw for this + * address, wait. Preferences should age and so bw assigned should decrease. + * @author Christian Grothoff + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_ats_service.h" +#include "gnunet_testing_lib.h" +#include "ats.h" +#include "test_ats_api_common.h" + +#define DEBUG_ATS_INFO GNUNET_NO + +static GNUNET_SCHEDULER_TaskIdentifier die_task; + +/** + * Scheduling handle + */ +static struct GNUNET_ATS_SchedulingHandle *sched_ats; + +/** + * Performance handle + */ +static struct GNUNET_ATS_PerformanceHandle *perf_ats; + +/** + * Return value + */ +static int ret; + +/** + * Test address + */ +static struct Test_Address test_addr[2]; + +/** + * Test peer + */ +static struct PeerContext p[2]; + + +/** + * HELLO address + */ +struct GNUNET_HELLO_Address test_hello_address[2]; + +/** + * Session + */ +static void *test_session[2]; + +/** + * Test ats info + */ +struct GNUNET_ATS_Information test_ats_info[2]; + +/** + * Test ats count + */ +uint32_t test_ats_count; + +/** + * Configured WAN out quota + */ +unsigned long long wan_quota_out; + +/** + * Configured WAN in quota + */ +unsigned long long wan_quota_in; + + +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); + sched_ats = NULL; + } + if (perf_ats != NULL) + { + GNUNET_ATS_performance_done (perf_ats); + perf_ats = NULL; + } + free_test_address (&test_addr[0]); + 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_suggest_address_cancel (sched_ats, &p[0].id); + GNUNET_ATS_suggest_address_cancel (sched_ats, &p[1].id); + + if (NULL != sched_ats) + GNUNET_ATS_scheduling_done (sched_ats); + if (NULL != perf_ats) + GNUNET_ATS_performance_done (perf_ats); + sched_ats = NULL; + perf_ats = NULL; + free_test_address (&test_addr[0]); + free_test_address (&test_addr[1]); +} + + +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; + static int sug_p0 = GNUNET_NO; + static int sug_p1 = GNUNET_NO; + + static uint32_t p0_last_bandwidth_out; + static uint32_t p0_last_bandwidth_in; + + static uint32_t p1_last_bandwidth_out; + static uint32_t p1_last_bandwidth_in; + + uint32_t cur_bandwidth_out = ntohl (bandwidth_out.value__); + uint32_t cur_bandwidth_in = ntohl (bandwidth_in.value__); + + if (0 == stage) + { + /* Callback for initial suggestion */ + if (0 == memcmp (&address->peer, &p[0].id, sizeof (p[0].id))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %u: Callback for peer 0 `%s': (in/out) %llu/%llu\n", + stage, + GNUNET_i2s (&address->peer), + ntohl (bandwidth_in.value__), + ntohl (bandwidth_out.value__)); + sug_p0 = GNUNET_YES; + p0_last_bandwidth_out = ntohl(bandwidth_out.value__); + p0_last_bandwidth_in = ntohl(bandwidth_in.value__); + } + if (0 == memcmp (&address->peer, &p[1].id, sizeof (p[1].id))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %u: Callback for peer 1 `%s': (in/out) %llu/%llu\n", + stage, + GNUNET_i2s (&address->peer), + ntohl (bandwidth_in.value__), + ntohl (bandwidth_out.value__)); + sug_p1 = GNUNET_YES; + p1_last_bandwidth_out = ntohl(bandwidth_out.value__); + p1_last_bandwidth_in = ntohl(bandwidth_in.value__); + } + if ((GNUNET_YES == sug_p0) && (GNUNET_YES == sug_p1)) + { + /* Changing preference for peer 0 */ + stage ++; + GNUNET_ATS_change_preference (perf_ats, &p[0].id, GNUNET_ATS_PREFERENCE_BANDWIDTH,(double) 1000, GNUNET_ATS_PREFERENCE_END); + sug_p0 = GNUNET_NO; + sug_p1 = GNUNET_NO; + return; + } + + } + if (1 == stage) + { + /* Callback due to preference change */ + if (0 == memcmp (&address->peer, &p[0].id, sizeof (p[0].id))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %u: Callback for peer 0 `%s': (in/out) %llu/%llu\n", + stage, + GNUNET_i2s (&address->peer), + ntohl (bandwidth_in.value__), + ntohl (bandwidth_out.value__)); + sug_p0 = GNUNET_YES; + + /* Peer 0 should get more bandwidth */ + if (cur_bandwidth_out <= p0_last_bandwidth_out) + GNUNET_break (0); + if (cur_bandwidth_in <= p0_last_bandwidth_in) + GNUNET_break (0); + p0_last_bandwidth_out = ntohl(bandwidth_out.value__); + p0_last_bandwidth_in = ntohl(bandwidth_in.value__); + } + if (0 == memcmp (&address->peer, &p[1].id, sizeof (p[1].id))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %u: Callback for peer 1 `%s': (in/out) %llu/%llu\n", + stage, + GNUNET_i2s (&address->peer), + ntohl (bandwidth_in.value__), + ntohl (bandwidth_out.value__)); + sug_p1 = GNUNET_YES; + + /* Peer 1 should get less bandwidth */ + if (cur_bandwidth_out >= p1_last_bandwidth_out) + { + GNUNET_break (0); + goto error; + } + if (cur_bandwidth_in >= p1_last_bandwidth_in) + { + GNUNET_break (0); + goto error; + } + p1_last_bandwidth_out = ntohl(bandwidth_out.value__); + p1_last_bandwidth_in = ntohl(bandwidth_in.value__); + } + if ((GNUNET_YES == sug_p0) && (GNUNET_YES == sug_p1)) + { + stage ++; + sug_p0 = GNUNET_NO; + sug_p1 = GNUNET_NO; + return; + } + } + if (2 == stage) + { + /* Callback due to preference aging */ + if (0 == memcmp (&address->peer, &p[0].id, sizeof (p[0].id))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %u: Callback for peer 0 `%s': (in/out) %llu/%llu\n", + stage, + GNUNET_i2s (&address->peer), + ntohl (bandwidth_in.value__), + ntohl (bandwidth_out.value__)); + sug_p0 = GNUNET_YES; + + /* Peer 0 should get less bandwidth */ + if (cur_bandwidth_out <= p0_last_bandwidth_out) + GNUNET_break (0); + if (cur_bandwidth_in <= p0_last_bandwidth_in) + GNUNET_break (0); + p0_last_bandwidth_out = ntohl(bandwidth_out.value__); + p0_last_bandwidth_in = ntohl(bandwidth_in.value__); + } + if (0 == memcmp (&address->peer, &p[1].id, sizeof (p[1].id))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %u: Callback for peer 1 `%s': (in/out) %llu/%llu\n", + stage, + GNUNET_i2s (&address->peer), + ntohl (bandwidth_in.value__), + ntohl (bandwidth_out.value__)); + sug_p1 = GNUNET_YES; + /* Peer 1 should get more bandwidth */ + if (cur_bandwidth_out <= p1_last_bandwidth_out) + { + GNUNET_break (0); + goto error; + } + if (cur_bandwidth_in <= p1_last_bandwidth_in) + { + GNUNET_break (0); + goto error; + } + p0_last_bandwidth_out = ntohl(bandwidth_out.value__); + p0_last_bandwidth_in = ntohl(bandwidth_in.value__); + } + + if ((GNUNET_YES == sug_p0) && (GNUNET_YES == sug_p1)) + { + /* Done ! */ + stage ++; + ret = 0; + GNUNET_SCHEDULER_add_now (&end,NULL); + return; + } + } + return; + +error: + /* Error ! */ + ret = 1; + GNUNET_SCHEDULER_add_now (&end,NULL); +} + +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TESTING_Peer *peer) +{ + char *quota_str; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_OUT", "a_str)) + { + fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n"); + ret = 1; + return; + } + if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_out)) + { + fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n"); + ret = 1; + GNUNET_free (quota_str); + return; + } + GNUNET_free (quota_str); + quota_str = NULL; + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_IN", "a_str)) + { + fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n"); + ret = 1; + return; + } + if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_in)) + { + fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n"); + GNUNET_free (quota_str); + ret = 1; + return; + } + GNUNET_free (quota_str); + quota_str = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN inbound quota: %llu\n", wan_quota_in); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN outbound quota: %llu\n", wan_quota_out); + + + die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); + + /* 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; + } + + /* Connect to ATS performance */ + perf_ats = GNUNET_ATS_performance_init(cfg, NULL, 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 0 */ + if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID0, &p[0].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[0].id))); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", + GNUNET_i2s(&p[0].id)); + + /* Set up peer 1*/ + if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID1, &p[1].id.hashPubKey)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); + ret = GNUNET_SYSERR; + end (); + return; + } + + GNUNET_assert (0 == strcmp (PEERID1, GNUNET_i2s_full (&p[1].id))); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", + GNUNET_i2s(&p[1].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_count = 2; + + /* Peer 0: Adding address with session */ + test_session[0] = &test_addr[0]; + create_test_address (&test_addr[0], "test0", test_session[0], "test0", strlen ("test0") + 1); + test_hello_address[0].peer = p[0].id; + test_hello_address[0].transport_name = test_addr[0].plugin; + test_hello_address[0].address = test_addr[0].addr; + test_hello_address[0].address_length = test_addr[0].addr_len; + GNUNET_ATS_address_add (sched_ats, &test_hello_address[0], test_session[0], test_ats_info, test_ats_count); + + /* Peer 1: Adding address with session */ + test_session[1] = &test_addr[1]; + create_test_address (&test_addr[1], "test1", test_session[1], "test1", strlen ("test1") + 1); + test_hello_address[1].peer = p[1].id; + test_hello_address[1].transport_name = test_addr[1].plugin; + test_hello_address[1].address = test_addr[1].addr; + test_hello_address[1].address_length = test_addr[1].addr_len; + GNUNET_ATS_address_add (sched_ats, &test_hello_address[1], test_session[1], test_ats_info, test_ats_count); + + GNUNET_ATS_suggest_address (sched_ats, &p[0].id); + GNUNET_ATS_suggest_address (sched_ats, &p[1].id); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test_ats_simplistic_pref_aging", + "test_ats_api.conf", + &run, NULL)) + return 1; + return ret; +} + + +/* end of file test_ats_simplistic_pref_aging.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 0000000..47a4e44 --- /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.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 */ |
