From 622fd12c7101c53c1fa0f9563a831f3196732dc5 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 6 Oct 2019 21:03:33 +0200 Subject: [PATCH] remove dead, obsolete or never-to-become ATS logic (DCE) --- src/ats-tests/Makefile.am | 116 +- ...luation1_dru_3_peers_1addr_1scope_mlp.conf | 24 - ...aluation1_dru_3_peers_1addr_1scope_mlp.exp | 46 - ...luation1_dru_3_peers_1addr_1scope_ril.conf | 24 - ...aluation1_dru_3_peers_1addr_1scope_ril.exp | 46 - src/ats-tests/perf_ats_mlp_bandwidth.conf | 4 - src/ats-tests/perf_ats_mlp_latency.conf | 4 - src/ats-tests/perf_ats_mlp_none.conf | 4 - src/ats-tests/perf_ats_ril_bandwidth.conf | 4 - src/ats-tests/perf_ats_ril_latency.conf | 4 - src/ats-tests/perf_ats_ril_none.conf | 4 - src/ats/Makefile.am | 127 +- src/ats/ats2.h | 294 -- src/ats/ats_api2_application.c | 366 -- src/ats/ats_api2_transport.c | 689 ---- src/ats/gnunet-service-ats-new.c | 804 ----- src/ats/perf_ats_solver_mlp.conf | 0 src/ats/perf_ats_solver_ril.conf | 0 src/ats/plugin_ats2_common.c | 99 - src/ats/plugin_ats2_simple.c | 1087 ------ src/ats/plugin_ats_mlp.c | 2924 ---------------- src/ats/plugin_ats_ril.c | 2997 ----------------- src/ats/test_ats2_lib.c | 259 -- src/ats/test_ats2_lib.conf | 13 - src/ats/test_ats2_lib.h | 523 --- src/ats/test_ats_api_mlp.conf | 45 - src/ats/test_ats_api_ril.conf | 24 - src/ats/test_ats_solver_delayed_mlp.conf | 20 - src/ats/test_ats_solver_delayed_ril.conf | 31 - src/include/Makefile.am | 1 - src/include/gnunet_ats_plugin_new.h | 247 -- 31 files changed, 8 insertions(+), 10822 deletions(-) delete mode 100644 src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_mlp.conf delete mode 100644 src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_mlp.exp delete mode 100644 src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_ril.conf delete mode 100644 src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_ril.exp delete mode 100644 src/ats-tests/perf_ats_mlp_bandwidth.conf delete mode 100644 src/ats-tests/perf_ats_mlp_latency.conf delete mode 100644 src/ats-tests/perf_ats_mlp_none.conf delete mode 100644 src/ats-tests/perf_ats_ril_bandwidth.conf delete mode 100644 src/ats-tests/perf_ats_ril_latency.conf delete mode 100644 src/ats-tests/perf_ats_ril_none.conf delete mode 100644 src/ats/ats2.h delete mode 100644 src/ats/ats_api2_application.c delete mode 100644 src/ats/ats_api2_transport.c delete mode 100644 src/ats/gnunet-service-ats-new.c delete mode 100644 src/ats/perf_ats_solver_mlp.conf delete mode 100644 src/ats/perf_ats_solver_ril.conf delete mode 100644 src/ats/plugin_ats2_common.c delete mode 100644 src/ats/plugin_ats2_simple.c delete mode 100644 src/ats/plugin_ats_mlp.c delete mode 100644 src/ats/plugin_ats_ril.c delete mode 100644 src/ats/test_ats2_lib.c delete mode 100644 src/ats/test_ats2_lib.conf delete mode 100644 src/ats/test_ats2_lib.h delete mode 100644 src/ats/test_ats_api_mlp.conf delete mode 100644 src/ats/test_ats_api_ril.conf delete mode 100644 src/ats/test_ats_solver_delayed_mlp.conf delete mode 100644 src/ats/test_ats_solver_delayed_ril.conf delete mode 100644 src/include/gnunet_ats_plugin_new.h diff --git a/src/ats-tests/Makefile.am b/src/ats-tests/Makefile.am index 1804a43bf..c965fcc9f 100644 --- a/src/ats-tests/Makefile.am +++ b/src/ats-tests/Makefile.am @@ -9,18 +9,6 @@ if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif -if HAVE_EXPERIMENTAL -if HAVE_LIBGLPK - PERF_MLP = \ - perf_ats_mlp_transport_none \ - perf_ats_mlp_transport_bandwidth \ - perf_ats_mlp_transport_latency \ - perf_ats_mlp_core_none \ - perf_ats_mlp_core_bandwidth \ - perf_ats_mlp_core_latency -endif -endif - if HAVE_TESTING TESTING_TESTS = \ perf_ats_proportional_transport_none \ @@ -31,8 +19,6 @@ TESTING_TESTS = \ perf_ats_proportional_core_latency \ $(PERF_MLP) -# RIL-tests commented out as RIL is currently badly broken. -# perf_ats_ril_transport_none perf_ats_ril_core_none perf_ats_ril_transport_bandwidth perf_ats_ril_core_bandwidth perf_ats_ril_transport_latency perf_ats_ril_core_latency endif lib_LTLIBRARIES = \ @@ -56,7 +42,7 @@ libgnunetatstesting_la_SOURCES = \ libgnunetatstesting_la_LIBADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/transport/libgnunettransport.la \ + $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) @@ -168,106 +154,8 @@ perf_ats_proportional_transport_latency_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la -perf_ats_mlp_core_none_SOURCES = \ - perf_ats.c -perf_ats_mlp_core_none_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ - $(top_builddir)/src/testbed/libgnunettestbed.la \ - $(top_builddir)/src/ats/libgnunetats.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/transport/libgnunettransport.la -perf_ats_mlp_core_none_DEPENDENCIES = \ - libgnunetatstesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -perf_ats_mlp_transport_none_SOURCES = \ - perf_ats.c -perf_ats_mlp_transport_none_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ - $(top_builddir)/src/testbed/libgnunettestbed.la \ - $(top_builddir)/src/ats/libgnunetats.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/transport/libgnunettransport.la -perf_ats_mlp_transport_none_DEPENDENCIES = \ - libgnunetatstesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -perf_ats_mlp_core_bandwidth_SOURCES = \ - perf_ats.c -perf_ats_mlp_core_bandwidth_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ - $(top_builddir)/src/testbed/libgnunettestbed.la \ - $(top_builddir)/src/ats/libgnunetats.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/transport/libgnunettransport.la -perf_ats_mlp_core_bandwidth_DEPENDENCIES = \ - libgnunetatstesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -perf_ats_mlp_transport_bandwidth_SOURCES = \ - perf_ats.c -perf_ats_mlp_transport_bandwidth_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ - $(top_builddir)/src/testbed/libgnunettestbed.la \ - $(top_builddir)/src/ats/libgnunetats.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/transport/libgnunettransport.la -perf_ats_mlp_transport_bandwidth_DEPENDENCIES = \ - libgnunetatstesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -perf_ats_mlp_core_latency_SOURCES = \ - perf_ats.c -perf_ats_mlp_core_latency_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ - $(top_builddir)/src/testbed/libgnunettestbed.la \ - $(top_builddir)/src/ats/libgnunetats.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/transport/libgnunettransport.la -perf_ats_mlp_core_latency_DEPENDENCIES = \ - libgnunetatstesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -perf_ats_mlp_transport_latency_SOURCES = \ - perf_ats.c -perf_ats_mlp_transport_latency_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ - $(top_builddir)/src/testbed/libgnunettestbed.la \ - $(top_builddir)/src/ats/libgnunetats.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/transport/libgnunettransport.la -perf_ats_mlp_transport_latencyDEPENDENCIES = \ - $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ - $(top_builddir)/src/util/libgnunetutil.la - -#perf_ats_ril_core_none_SOURCES = \ -# perf_ats.c -#perf_ats_ril_core_none_LDADD = \ -# $(top_builddir)/src/util/libgnunetutil.la \ -# $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ -# $(top_builddir)/src/testbed/libgnunettestbed.la \ -# $(top_builddir)/src/ats/libgnunetats.la \ -# $(top_builddir)/src/core/libgnunetcore.la \ -# $(top_builddir)/src/transport/libgnunettransport.la -#perf_ats_ril_core_none_DEPENDENCIES = \ -# libgnunetatstesting.la \ -# $(top_builddir)/src/util/libgnunetutil.la - - EXTRA_DIST = \ gnunet_ats_sim_default.conf \ perf_ats_proportional_none.conf \ perf_ats_proportional_bandwidth.conf \ - perf_ats_proportional_latency.conf \ - perf_ats_mlp_none.conf \ - perf_ats_mlp_bandwidth.conf \ - perf_ats_mlp_latency.conf \ - perf_ats_ril_none.conf \ - perf_ats_ril_bandwidth.conf \ - perf_ats_ril_latency.conf + perf_ats_proportional_latency.conf diff --git a/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_mlp.conf b/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_mlp.conf deleted file mode 100644 index 91697eda9..000000000 --- a/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_mlp.conf +++ /dev/null @@ -1,24 +0,0 @@ -@INLINE@ template_perf_ats.conf - -[transport] -plugins = unix - -[ats] -MODE = PROPORTIONAL -UNSPECIFIED_QUOTA_IN = 128 KiB -UNSPECIFIED_QUOTA_OUT = 128 KiB -# LOOPBACK -LOOPBACK_QUOTA_IN = 128 KiB -LOOPBACK_QUOTA_OUT = 128 KiB -# LAN -LAN_QUOTA_IN = 128 KiB -LAN_QUOTA_OUT = 128 KiB -# WAN -WAN_QUOTA_IN = 128 KiB -WAN_QUOTA_OUT = 128 KiB -# WLAN -WLAN_QUOTA_IN = 128 KiB -WLAN_QUOTA_OUT = 128 KiB -# BLUETOOTH -BLUETOOTH_QUOTA_IN = 128 KiB -BLUETOOTH_QUOTA_OUT = 128 KiB \ No newline at end of file diff --git a/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_mlp.exp b/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_mlp.exp deleted file mode 100644 index 9b4c998c4..000000000 --- a/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_mlp.exp +++ /dev/null @@ -1,46 +0,0 @@ -[experiment] -name = sc1_eval_dru_mlp -masters = 1 -slaves = 3 -max_duration = 20 s -log_freq = 100 ms -cfg_file = experiments/evaluation1_dru_3_peers_1addr_1scope_mlp.conf - -[episode-0] -# operations = start_send, stop_send, start_preference, stop_preference -duration = 1 s -op-0-operation = start_send -op-0-src = 0 -op-0-dest = 0 -op-0-type = constant -#op-0-period = 10 s -op-0-base-rate= 10000 -#op-0-max-rate = 10000 - -op-1-operation = start_send -op-1-src = 0 -op-1-dest = 1 -op-1-type = constant -#op-1-period = 10 s -op-1-base-rate= 10000 -#op-1-max-rate = 10000 - -op-2-operation = start_send -op-2-src = 0 -op-2-dest = 2 -op-2-type = constant -#op-1-period = 10 s -op-2-base-rate= 10000 -#op-1-max-rate = 10000 - -[episode-1] -duration = 1 s -op-0-operation = start_preference -op-0-src = 0 -op-0-dest = 2 -op-0-type = constant -#op-0-period = 10 s -op-0-pref = bandwidth -op-0-frequency = 1 s -op-0-base-rate= 50 -#op-0-max-rate = 10000 \ No newline at end of file diff --git a/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_ril.conf b/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_ril.conf deleted file mode 100644 index 4b66e5aea..000000000 --- a/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_ril.conf +++ /dev/null @@ -1,24 +0,0 @@ -@INLINE@ template_perf_ats.conf - -[transport] -plugins = unix - -[ats] -MODE = MLP -UNSPECIFIED_QUOTA_IN = 128 KiB -UNSPECIFIED_QUOTA_OUT = 128 KiB -# LOOPBACK -LOOPBACK_QUOTA_IN = 128 KiB -LOOPBACK_QUOTA_OUT = 128 KiB -# LAN -LAN_QUOTA_IN = 128 KiB -LAN_QUOTA_OUT = 128 KiB -# WAN -WAN_QUOTA_IN = 128 KiB -WAN_QUOTA_OUT = 128 KiB -# WLAN -WLAN_QUOTA_IN = 128 KiB -WLAN_QUOTA_OUT = 128 KiB -# BLUETOOTH -BLUETOOTH_QUOTA_IN = 128 KiB -BLUETOOTH_QUOTA_OUT = 128 KiB \ No newline at end of file diff --git a/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_ril.exp b/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_ril.exp deleted file mode 100644 index 280b1605c..000000000 --- a/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_ril.exp +++ /dev/null @@ -1,46 +0,0 @@ -[experiment] -name = sc1_eval_dru_ril -masters = 1 -slaves = 3 -max_duration = 20 s -log_freq = 100 ms -cfg_file = experiments/evaluation1_dru_3_peers_1addr_1scope_ril.conf - -[episode-0] -# operations = start_send, stop_send, start_preference, stop_preference -duration = 10 s -op-0-operation = start_send -op-0-src = 0 -op-0-dest = 0 -op-0-type = constant -#op-0-period = 10 s -op-0-base-rate= 10000 -#op-0-max-rate = 10000 - -op-1-operation = start_send -op-1-src = 0 -op-1-dest = 1 -op-1-type = constant -#op-1-period = 10 s -op-1-base-rate= 10000 -#op-1-max-rate = 10000 - -op-2-operation = start_send -op-2-src = 0 -op-2-dest = 2 -op-2-type = constant -#op-1-period = 10 s -op-2-base-rate= 10000 -#op-1-max-rate = 10000 - -[episode-1] -duration = 10 s -op-0-operation = start_preference -op-0-src = 0 -op-0-dest = 2 -op-0-type = constant -#op-0-period = 10 s -op-0-pref = bandwidth -op-0-frequency = 1 s -op-0-base-rate= 50 -#op-0-max-rate = 10000 \ No newline at end of file diff --git a/src/ats-tests/perf_ats_mlp_bandwidth.conf b/src/ats-tests/perf_ats_mlp_bandwidth.conf deleted file mode 100644 index b803d683d..000000000 --- a/src/ats-tests/perf_ats_mlp_bandwidth.conf +++ /dev/null @@ -1,4 +0,0 @@ -@INLINE@ template_perf_ats.conf - -[ats] -MODE = mlp diff --git a/src/ats-tests/perf_ats_mlp_latency.conf b/src/ats-tests/perf_ats_mlp_latency.conf deleted file mode 100644 index b803d683d..000000000 --- a/src/ats-tests/perf_ats_mlp_latency.conf +++ /dev/null @@ -1,4 +0,0 @@ -@INLINE@ template_perf_ats.conf - -[ats] -MODE = mlp diff --git a/src/ats-tests/perf_ats_mlp_none.conf b/src/ats-tests/perf_ats_mlp_none.conf deleted file mode 100644 index b803d683d..000000000 --- a/src/ats-tests/perf_ats_mlp_none.conf +++ /dev/null @@ -1,4 +0,0 @@ -@INLINE@ template_perf_ats.conf - -[ats] -MODE = mlp diff --git a/src/ats-tests/perf_ats_ril_bandwidth.conf b/src/ats-tests/perf_ats_ril_bandwidth.conf deleted file mode 100644 index 3e7969a84..000000000 --- a/src/ats-tests/perf_ats_ril_bandwidth.conf +++ /dev/null @@ -1,4 +0,0 @@ -@INLINE@ template_perf_ats.conf - -[ats] -MODE = ril diff --git a/src/ats-tests/perf_ats_ril_latency.conf b/src/ats-tests/perf_ats_ril_latency.conf deleted file mode 100644 index 3e7969a84..000000000 --- a/src/ats-tests/perf_ats_ril_latency.conf +++ /dev/null @@ -1,4 +0,0 @@ -@INLINE@ template_perf_ats.conf - -[ats] -MODE = ril diff --git a/src/ats-tests/perf_ats_ril_none.conf b/src/ats-tests/perf_ats_ril_none.conf deleted file mode 100644 index 3e7969a84..000000000 --- a/src/ats-tests/perf_ats_ril_none.conf +++ /dev/null @@ -1,4 +0,0 @@ -@INLINE@ template_perf_ats.conf - -[ats] -MODE = ril diff --git a/src/ats/Makefile.am b/src/ats/Makefile.am index d7e5b68c7..bd8962158 100644 --- a/src/ats/Makefile.am +++ b/src/ats/Makefile.am @@ -15,22 +15,10 @@ if USE_COVERAGE endif lib_LTLIBRARIES = \ - libgnunetats.la \ - libgnunetatsapplication.la \ - libgnunetatstransport.la + libgnunetats.la plugin_LTLIBRARIES = \ - libgnunet_plugin_ats_proportional.la \ - libgnunet_plugin_ats2_simple.la - -if HAVE_EXPERIMENTAL -plugin_LTLIBRARIES += \ - libgnunet_plugin_ats_ril.la -if HAVE_LIBGLPK -plugin_LTLIBRARIES += \ - libgnunet_plugin_ats_mlp.la -endif -endif + libgnunet_plugin_ats_proportional.la libgnunetats_la_SOURCES = \ ats_api_connectivity.c \ @@ -45,74 +33,20 @@ libgnunetats_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 4:0:0 - -libgnunetatsapplication_la_SOURCES = \ - ats_api2_application.c -libgnunetatsapplication_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(LTLIBINTL) -libgnunetatsapplication_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 0:0:0 - -libgnunetatstransport_la_SOURCES = \ - ats_api2_transport.c -libgnunetatstransport_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(LTLIBINTL) -libgnunetatstransport_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 0:0:0 - libgnunet_plugin_ats_proportional_la_SOURCES = \ plugin_ats_proportional.c libgnunet_plugin_ats_proportional_la_LIBADD = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/nt/libgnunetnt.la \ - $(LTLIBINTL) -libgnunet_plugin_ats_proportional_la_LDFLAGS = \ - $(GN_PLUGIN_LDFLAGS) - -libgnunet_plugin_ats2_simple_la_SOURCES = \ - plugin_ats2_simple.c -libgnunet_plugin_ats2_simple_la_LIBADD = \ - $(top_builddir)/src/hello/libgnunethello.la \ - $(top_builddir)/src/peerstore/libgnunetpeerstore.la \ $(top_builddir)/src/nt/libgnunetnt.la \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) -libgnunet_plugin_ats2_simple_la_LDFLAGS = \ +libgnunet_plugin_ats_proportional_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) -libgnunet_plugin_ats_mlp_la_SOURCES = \ - plugin_ats_mlp.c -libgnunet_plugin_ats_mlp_la_LIBADD = \ - libgnunetats.la \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/nt/libgnunetnt.la \ - $(top_builddir)/src/util/libgnunetutil.la -libgnunet_plugin_ats_mlp_la_LDFLAGS = \ - $(GN_PLUGIN_LDFLAGS) \ - -lglpk - -libgnunet_plugin_ats_ril_la_SOURCES = \ - plugin_ats_ril.c -libgnunet_plugin_ats_ril_la_LIBADD = \ - libgnunetats.la \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/nt/libgnunetnt.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(LTLIBINTL) -libgnunet_plugin_ats_ril_la_LDFLAGS = \ - $(GN_PLUGIN_LDFLAGS) - libexec_PROGRAMS = \ - gnunet-service-ats \ - gnunet-service-ats-new + gnunet-service-ats gnunet_service_ats_SOURCES = \ gnunet-service-ats.c gnunet-service-ats.h \ @@ -131,27 +65,10 @@ gnunet_service_ats_LDADD = \ libgnunetats.la \ $(GN_LIBINTL) -gnunet_service_ats_new_SOURCES = \ - gnunet-service-ats-new.c -gnunet_service_ats_new_LDADD = \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) - - if HAVE_TESTING TESTING_TESTS = \ test_ats_api_proportional \ - test_ats_reservation_api_proportional \ - test_ats2_lib -if HAVE_EXPERIMENTAL -TESTING_TESTS += \ - test_ats_api_ril -if HAVE_LIBGLPK -TESTING_TESTS += \ - test_ats_api_mlp -endif -endif + test_ats_reservation_api_proportional endif check_PROGRAMS = \ @@ -180,40 +97,8 @@ test_ats_reservation_api_proportional_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunetats.la -test_ats_api_ril_SOURCES = \ - test_ats_api.c \ - test_ats_lib.c test_ats_lib.h -test_ats_api_ril_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/hello/libgnunethello.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - libgnunetats.la - -test_ats_api_mlp_SOURCES = \ - test_ats_api.c \ - test_ats_lib.c test_ats_lib.h -test_ats_api_mlp_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/hello/libgnunethello.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - libgnunetats.la - -test_ats2_lib_SOURCES = \ - test_ats2_lib.c test_ats2_lib.h -test_ats2_lib_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/hello/libgnunethello.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - libgnunetatsapplication.la \ - libgnunetatstransport.la - - EXTRA_DIST = \ - ats.h ats2.h \ - plugin_ats2_common.c \ + ats.h \ test_delay \ - test_ats2_lib.conf \ test_ats_api.conf \ - test_ats_api_mlp.conf \ - test_ats_api_ril.conf \ test_ats_api_proportional.conf diff --git a/src/ats/ats2.h b/src/ats/ats2.h deleted file mode 100644 index df402dba2..000000000 --- a/src/ats/ats2.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2010-2015 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file ats/ats2.h - * @brief automatic transport selection messages - * @author Christian Grothoff - * @author Matthias Wachs - */ -#ifndef ATS2_H -#define ATS2_H - -#include "gnunet_util_lib.h" -#include "gnunet_ats_transport_service.h" - - -GNUNET_NETWORK_STRUCT_BEGIN - - -/** - * ATS performance characteristics for an address. - */ -struct PropertiesNBO -{ - /** - * Delay. Time between when the time packet is sent and the packet - * arrives. FOREVER if we did not (successfully) measure yet. - */ - struct GNUNET_TIME_RelativeNBO delay; - - /** - * Confirmed successful payload on this connection from this peer to - * the other peer. In NBO. - * - * Unit: [bytes/second] - */ - uint32_t goodput_out; - - /** - * Confirmed useful payload on this connection to this peer from - * the other peer. In NBO. - * - * Unit: [bytes/second] - */ - uint32_t goodput_in; - - /** - * Actual traffic on this connection from this peer to the other peer. - * Includes transport overhead. In NBO. - * - * Unit: [bytes/second] - */ - uint32_t utilization_out; - - /** - * Actual traffic on this connection from the other peer to this peer. - * Includes transport overhead. In NBO. - * - * Unit: [bytes/second] - */ - uint32_t utilization_in; - - /** - * Distance on network layer (required for distance-vector routing) - * in hops. Zero for direct connections (i.e. plain TCP/UDP). In NBO. - */ - uint32_t distance; - - /** - * MTU of the network layer, UINT32_MAX for no MTU (stream). - * - * Unit: [bytes]. In NBO. - */ - uint32_t mtu; - - /** - * Which network scope does the respective address belong to? - * A `enum GNUNET_NetworkType nt` in NBO. - */ - uint32_t nt; - - /** - * What characteristics does this communicator have? - * A `enum GNUNET_TRANSPORT_CommunicatorCharacteristics` in NBO. - */ - uint32_t cc; -}; - - -/** - * Application client to ATS service: we would like to have - * address suggestions for this peer. - */ -struct ExpressPreferenceMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_ATS_SUGGEST or - * #GNUNET_MESSAGE_TYPE_ATS_SUGGEST_CANCEL to stop - * suggestions. - */ - struct GNUNET_MessageHeader header; - - /** - * What type of performance preference does the client have? - * A `enum GNUNET_MQ_PreferenceKind` in NBO. - */ - uint32_t pk GNUNET_PACKED; - - /** - * Peer to get address suggestions for. - */ - struct GNUNET_PeerIdentity peer; - - /** - * How much bandwidth in bytes/second does the application expect? - */ - struct GNUNET_BANDWIDTH_Value32NBO bw; -}; - - -/** - * Transport client to ATS service: here is another session you can use. - */ -struct SessionAddMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD or - * #GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD_INBOUND_ONLY - */ - struct GNUNET_MessageHeader header; - - /** - * Internal number this client will henceforth use to - * refer to this session. - */ - uint32_t session_id GNUNET_PACKED; - - /** - * Identity of the peer that this session is for. - */ - struct GNUNET_PeerIdentity peer; - - /** - * Performance properties of the session. - */ - struct PropertiesNBO properties; - - /* followed by: - * - char * address (including '\0'-termination). - */ -}; - - -/** - * Message used to notify ATS that the performance - * characteristics for an session have changed. - */ -struct SessionUpdateMessage -{ - /** - * Message of type #GNUNET_MESSAGE_TYPE_ATS_SESSION_UPDATE. - */ - struct GNUNET_MessageHeader header; - - /** - * Internal number this client uses to refer to this session. - */ - uint32_t session_id GNUNET_PACKED; - - /** - * Which peer is this about? (Technically redundant, as the - * @e session_id should be sufficient, but enables ATS service - * to find the session faster). - */ - struct GNUNET_PeerIdentity peer; - - /** - * Performance properties of the session. - */ - struct PropertiesNBO properties; -}; - - -/** - * Message sent by ATS client to ATS service when an session - * was destroyed and must thus henceforth no longer be considered - * for scheduling. - */ -struct SessionDelMessage -{ - /** - * Type is #GNUNET_MESSAGE_TYPE_ATS_SESSION_DEL. - */ - struct GNUNET_MessageHeader header; - - /** - * Internal number this client uses to refer to this session. - */ - uint32_t session_id GNUNET_PACKED; - - /** - * Which peer is this about? (Technically redundant, as the - * @e session_id should be sufficient, but enables ATS service - * to find the session faster). - */ - struct GNUNET_PeerIdentity peer; -}; - - -/** - * ATS Service allocates resources to an session - * identified by the given @e session_id for the given @e peer with - * the given @e bandwidth_in and @e bandwidth_out limits from now on. - */ -struct SessionAllocationMessage -{ - /** - * A message of type #GNUNET_MESSAGE_TYPE_ATS_SESSION_ALLOCATION. - */ - struct GNUNET_MessageHeader header; - - /** - * Internal number this client uses to refer to the session this - * suggestion is about. - */ - uint32_t session_id GNUNET_PACKED; - - /** - * Which peer is this about? (Technically redundant, as the - * @e session_id should be sufficient, but may enable client - * to find the session faster and/or check consistency). - */ - struct GNUNET_PeerIdentity peer; - - /** - * How much bandwidth we are allowed for sending. - */ - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out; - - /** - * How much bandwidth we are allowed for receiving. - */ - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in; -}; - - -/** - * ATS Service suggests to the transport service to try the address - * for the given @e peer. - */ -struct AddressSuggestionMessage -{ - /** - * A message of type #GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION. - */ - struct GNUNET_MessageHeader header; - - /** - * Zero. - */ - uint32_t reserved GNUNET_PACKED; - - /** - * Which peer is this about? (Technically redundant, as the - * @e session_id should be sufficient, but may enable client - * to find the session faster and/or check consistency). - */ - struct GNUNET_PeerIdentity peer; - - /* Followed by 0-terminated address */ -}; - - -GNUNET_NETWORK_STRUCT_END - - - -#endif diff --git a/src/ats/ats_api2_application.c b/src/ats/ats_api2_application.c deleted file mode 100644 index 46e57c5bb..000000000 --- a/src/ats/ats_api2_application.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2010-2016 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file ats/ats_api2_application.c - * @brief enable clients to ask ATS about establishing connections to peers - * @author Christian Grothoff - * @author Matthias Wachs - */ -#include "platform.h" -#include "gnunet_ats_application_service.h" -#include "ats2.h" - - -#define LOG(kind, ...) GNUNET_log_from (kind, "ats-application-api", \ - __VA_ARGS__) - - -/** - * Handle for ATS address suggestion requests. - */ -struct GNUNET_ATS_ApplicationSuggestHandle -{ - /** - * ID of the peer for which address suggestion was requested. - */ - struct GNUNET_PeerIdentity id; - - /** - * Connecitivity handle this suggestion handle belongs to. - */ - struct GNUNET_ATS_ApplicationHandle *ch; - - /** - * What preference is being expressed? - */ - enum GNUNET_MQ_PreferenceKind pk; - - /** - * How much bandwidth does the client expect? - */ - struct GNUNET_BANDWIDTH_Value32NBO bw; -}; - - -/** - * Handle to the ATS subsystem for application management. - */ -struct GNUNET_ATS_ApplicationHandle -{ - /** - * Our configuration. - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Map with the identities of all the peers for which we would - * like to have address suggestions. The key is the PID, the - * value is currently the `struct GNUNET_ATS_ApplicationSuggestHandle` - */ - struct GNUNET_CONTAINER_MultiPeerMap *sug_requests; - - /** - * Message queue for sending requests to the ATS service. - */ - struct GNUNET_MQ_Handle *mq; - - /** - * Task to trigger reconnect. - */ - struct GNUNET_SCHEDULER_Task *task; - - /** - * Reconnect backoff delay. - */ - struct GNUNET_TIME_Relative backoff; -}; - - -/** - * Re-establish the connection to the ATS service. - * - * @param ch handle to use to re-connect. - */ -static void -reconnect (struct GNUNET_ATS_ApplicationHandle *ch); - - -/** - * Re-establish the connection to the ATS service. - * - * @param cls handle to use to re-connect. - */ -static void -reconnect_task (void *cls) -{ - struct GNUNET_ATS_ApplicationHandle *ch = cls; - - ch->task = NULL; - reconnect (ch); -} - - -/** - * Disconnect from ATS and then reconnect. - * - * @param ch our handle - */ -static void -force_reconnect (struct GNUNET_ATS_ApplicationHandle *ch) -{ - if (NULL != ch->mq) - { - GNUNET_MQ_destroy (ch->mq); - ch->mq = NULL; - } - ch->backoff = GNUNET_TIME_STD_BACKOFF (ch->backoff); - ch->task = GNUNET_SCHEDULER_add_delayed (ch->backoff, - &reconnect_task, - ch); -} - - -/** - * We encountered an error handling the MQ to the - * ATS service. Reconnect. - * - * @param cls the `struct GNUNET_ATS_ApplicationHandle` - * @param error details about the error - */ -static void -error_handler (void *cls, - enum GNUNET_MQ_Error error) -{ - struct GNUNET_ATS_ApplicationHandle *ch = cls; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "ATS connection died (code %d), reconnecting\n", - (int) error); - force_reconnect (ch); -} - - -/** - * Transmit request for an address suggestion. - * - * @param cls the `struct GNUNET_ATS_ApplicationHandle` - * @param peer peer to ask for an address suggestion for - * @param value the `struct GNUNET_ATS_SuggestHandle` - * @return #GNUNET_OK (continue to iterate), #GNUNET_SYSERR on - * failure (message queue no longer exists) - */ -static int -transmit_suggestion (void *cls, - const struct GNUNET_PeerIdentity *peer, - void *value) -{ - struct GNUNET_ATS_ApplicationHandle *ch = cls; - struct GNUNET_ATS_ApplicationSuggestHandle *sh = value; - struct GNUNET_MQ_Envelope *ev; - struct ExpressPreferenceMessage *m; - - if (NULL == ch->mq) - return GNUNET_SYSERR; - ev = GNUNET_MQ_msg (m, - GNUNET_MESSAGE_TYPE_ATS_SUGGEST); - m->pk = htonl ((uint32_t) sh->pk); - m->bw = sh->bw; - m->peer = *peer; - GNUNET_MQ_send (ch->mq, ev); - return GNUNET_OK; -} - - -/** - * Re-establish the connection to the ATS service. - * - * @param ch handle to use to re-connect. - */ -static void -reconnect (struct GNUNET_ATS_ApplicationHandle *ch) -{ - static const struct GNUNET_MQ_MessageHandler handlers[] = { - { NULL, 0, 0 } - }; - - GNUNET_assert (NULL == ch->mq); - ch->mq = GNUNET_CLIENT_connect (ch->cfg, - "ats", - handlers, - &error_handler, - ch); - if (NULL == ch->mq) - { - force_reconnect (ch); - return; - } - GNUNET_CONTAINER_multipeermap_iterate (ch->sug_requests, - &transmit_suggestion, - ch); -} - - -/** - * Initialize the ATS application suggestion client handle. - * - * @param cfg configuration to use - * @return ats application handle, NULL on error - */ -struct GNUNET_ATS_ApplicationHandle * -GNUNET_ATS_application_init (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_ATS_ApplicationHandle *ch; - - ch = GNUNET_new (struct GNUNET_ATS_ApplicationHandle); - ch->cfg = cfg; - ch->sug_requests = GNUNET_CONTAINER_multipeermap_create (32, - GNUNET_YES); - reconnect (ch); - return ch; -} - - -/** - * Function called to free all `struct GNUNET_ATS_ApplicationSuggestHandle`s - * in the map. - * - * @param cls NULL - * @param key the key - * @param value the value to free - * @return #GNUNET_OK (continue to iterate) - */ -static int -free_sug_handle (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) -{ - struct GNUNET_ATS_ApplicationSuggestHandle *cur = value; - - GNUNET_free (cur); - return GNUNET_OK; -} - - -/** - * Client is done with ATS application management, release resources. - * - * @param ch handle to release - */ -void -GNUNET_ATS_application_done (struct GNUNET_ATS_ApplicationHandle *ch) -{ - if (NULL != ch->mq) - { - GNUNET_MQ_destroy (ch->mq); - ch->mq = NULL; - } - if (NULL != ch->task) - { - GNUNET_SCHEDULER_cancel (ch->task); - ch->task = NULL; - } - GNUNET_CONTAINER_multipeermap_iterate (ch->sug_requests, - &free_sug_handle, - NULL); - GNUNET_CONTAINER_multipeermap_destroy (ch->sug_requests); - GNUNET_free (ch); -} - - -/** - * We would like to receive address suggestions for a peer. ATS will - * respond with a call to the continuation immediately containing an address or - * no address if none is available. ATS can suggest more addresses until we call - * #GNUNET_ATS_application_suggest_cancel(). - * - * @param ch handle - * @param peer identity of the peer we need an address for - * @param pk what kind of application will the application require (can be - * #GNUNET_MQ_PREFERENCE_NONE, we will still try to connect) - * @param bw desired bandwith, can be zero (we will still try to connect) - * @return suggest handle, NULL if a request is already pending - */ -struct GNUNET_ATS_ApplicationSuggestHandle * -GNUNET_ATS_application_suggest (struct GNUNET_ATS_ApplicationHandle *ch, - const struct GNUNET_PeerIdentity *peer, - enum GNUNET_MQ_PreferenceKind pk, - struct GNUNET_BANDWIDTH_Value32NBO bw) -{ - struct GNUNET_ATS_ApplicationSuggestHandle *s; - - s = GNUNET_new (struct GNUNET_ATS_ApplicationSuggestHandle); - s->ch = ch; - s->id = *peer; - s->pk = pk; - s->bw = bw; - (void) GNUNET_CONTAINER_multipeermap_put (ch->sug_requests, - &s->id, - s, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Requesting ATS to suggest address for `%s'\n", - GNUNET_i2s (peer)); - if (NULL == ch->mq) - return s; - GNUNET_assert (GNUNET_OK == - transmit_suggestion (ch, - &s->id, - s)); - return s; -} - - -/** - * We no longer care about being connected to a peer. - * - * @param sh handle to stop - */ -void -GNUNET_ATS_application_suggest_cancel (struct - GNUNET_ATS_ApplicationSuggestHandle *sh) -{ - struct GNUNET_ATS_ApplicationHandle *ch = sh->ch; - struct GNUNET_MQ_Envelope *ev; - struct ExpressPreferenceMessage *m; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Telling ATS we no longer care for an address for `%s'\n", - GNUNET_i2s (&sh->id)); - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multipeermap_remove (ch->sug_requests, - &sh->id, - sh)); - if (NULL == ch->mq) - { - GNUNET_free (sh); - return; - } - ev = GNUNET_MQ_msg (m, - GNUNET_MESSAGE_TYPE_ATS_SUGGEST_CANCEL); - m->pk = htonl ((uint32_t) sh->pk); - m->bw = sh->bw; - m->peer = sh->id; - GNUNET_MQ_send (ch->mq, - ev); - GNUNET_free (sh); -} - - -/* end of ats_api2_application.c */ diff --git a/src/ats/ats_api2_transport.c b/src/ats/ats_api2_transport.c deleted file mode 100644 index da02ca592..000000000 --- a/src/ats/ats_api2_transport.c +++ /dev/null @@ -1,689 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2010-2015, 2018 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file ats/ats_api2_transport.c - * @brief address suggestions and bandwidth allocation - * @author Christian Grothoff - * @author Matthias Wachs - */ -#include "platform.h" -#include "gnunet_ats_transport_service.h" -#include "ats2.h" - -#define LOG(kind, ...) GNUNET_log_from (kind, "ats-transport-api", __VA_ARGS__) - - -/** - * Information we track per session, incoming or outgoing. It also - * doesn't matter if we have a session, any session that ATS is - * allowed to suggest right now should be tracked. - */ -struct GNUNET_ATS_SessionRecord -{ - /** - * Transport handle this session record belongs to. - */ - struct GNUNET_ATS_TransportHandle *ath; - - /** - * Address data. - */ - const char *address; - - /** - * Session handle, NULL if inbound-only (also implies we cannot - * actually control inbound traffic via transport!). So if - * @e session is NULL, the @e properties are informative for - * ATS (connection exists, utilization) but ATS cannot directly - * influence it (and should thus not call the - * #GNUNET_ATS_AllocationCallback for this @e session, which is - * obvious as NULL is not a meaningful session to allocation - * resources to). - */ - struct GNUNET_ATS_Session *session; - - /** - * Identity of the peer reached at @e address. - */ - struct GNUNET_PeerIdentity pid; - - /** - * Performance data about the @e session. - */ - struct GNUNET_ATS_Properties properties; - - /** - * Unique ID to identify this session at this @a pid in IPC - * messages. - */ - uint32_t slot; -}; - - -/** - * Handle to the ATS subsystem for bandwidth/transport transport information. - */ -struct GNUNET_ATS_TransportHandle -{ - /** - * Our configuration. - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Callback to invoke on suggestions. - */ - GNUNET_ATS_SuggestionCallback suggest_cb; - - /** - * Closure for @e suggest_cb. - */ - void *suggest_cb_cls; - - /** - * Callback to invoke on allocations. - */ - GNUNET_ATS_AllocationCallback alloc_cb; - - /** - * Closure for @e alloc_cb. - */ - void *alloc_cb_cls; - - /** - * Message queue for sending requests to the ATS service. - */ - struct GNUNET_MQ_Handle *mq; - - /** - * Task to trigger reconnect. - */ - struct GNUNET_SCHEDULER_Task *task; - - /** - * Hash map mapping PIDs to session records. - */ - struct GNUNET_CONTAINER_MultiPeerMap *records; - - /** - * Reconnect backoff delay. - */ - struct GNUNET_TIME_Relative backoff; -}; - - - -/** - * Convert ATS properties from host to network byte order. - * - * @param nbo[OUT] value written - * @param hbo value read - */ -static void -properties_hton (struct PropertiesNBO *nbo, - const struct GNUNET_ATS_Properties *hbo) -{ - nbo->delay = GNUNET_TIME_relative_hton (hbo->delay); - nbo->goodput_out = htonl (hbo->goodput_out); - nbo->goodput_in = htonl (hbo->goodput_in); - nbo->utilization_out = htonl (hbo->utilization_out); - nbo->utilization_in = htonl (hbo->utilization_in); - nbo->distance = htonl (hbo->distance); - nbo->mtu = htonl (hbo->mtu); - nbo->nt = htonl ((uint32_t) hbo->nt); - nbo->cc = htonl ((uint32_t) hbo->cc); -} - - -/** - * Re-establish the connection to the ATS service. - * - * @param sh handle to use to re-connect. - */ -static void -reconnect (struct GNUNET_ATS_TransportHandle *ath); - - -/** - * Re-establish the connection to the ATS service. - * - * @param cls handle to use to re-connect. - */ -static void -reconnect_task (void *cls) -{ - struct GNUNET_ATS_TransportHandle *ath = cls; - - ath->task = NULL; - reconnect (ath); -} - - -/** - * Disconnect from ATS and then reconnect. - * - * @param ath our handle - */ -static void -force_reconnect (struct GNUNET_ATS_TransportHandle *ath) -{ - if (NULL != ath->mq) - { - GNUNET_MQ_destroy (ath->mq); - ath->mq = NULL; - } - /* FIXME: do we tell transport service about disconnect events? CON: - initially ATS will have a really screwed picture of the world and - the rapid change would be bad. PRO: if we don't, ATS and - transport may disagree about the allocation for a while... - For now: lazy: do nothing. */ - ath->backoff = GNUNET_TIME_STD_BACKOFF (ath->backoff); - ath->task = GNUNET_SCHEDULER_add_delayed (ath->backoff, - &reconnect_task, - ath); -} - - -/** - * Check format of address suggestion message from the service. - * - * @param cls the `struct GNUNET_ATS_TransportHandle` - * @param m message received - */ -static int -check_ats_address_suggestion (void *cls, - const struct AddressSuggestionMessage *m) -{ - (void) cls; - GNUNET_MQ_check_zero_termination (m); - return GNUNET_SYSERR; -} - - -/** - * We received an address suggestion message from the service. - * - * @param cls the `struct GNUNET_ATS_TransportHandle` - * @param m message received - */ -static void -handle_ats_address_suggestion (void *cls, - const struct AddressSuggestionMessage *m) -{ - struct GNUNET_ATS_TransportHandle *ath = cls; - const char *address = (const char *) &m[1]; - - ath->suggest_cb (ath->suggest_cb_cls, - &m->peer, - address); -} - - -/** - * Closure for #match_session_cb. - */ -struct FindContext -{ - /** - * Key to look for. - */ - uint32_t session_id; - - /** - * Where to store the result. - */ - struct GNUNET_ATS_SessionRecord *sr; -}; - - -/** - * Finds matching session record. - * - * @param cls a `struct FindContext` - * @param pid peer identity (unused) - * @param value a `struct GNUNET_ATS_SessionRecord` - * @return #GNUNET_NO if match found, #GNUNET_YES to continue searching - */ -static int -match_session_cb (void *cls, - const struct GNUNET_PeerIdentity *pid, - void *value) -{ - struct FindContext *fc = cls; - struct GNUNET_ATS_SessionRecord *sr = value; - - (void) pid; - if (fc->session_id == sr->slot) - { - fc->sr = sr; - return GNUNET_NO; - } - return GNUNET_YES; -} - - - -/** - * Find session record for peer @a pid and session @a session_id - * - * @param ath transport handle to search - * @param session_id session ID to match - * @param pid peer to search under - * @return NULL if no such record exists - */ -static struct GNUNET_ATS_SessionRecord * -find_session (struct GNUNET_ATS_TransportHandle *ath, - uint32_t session_id, - const struct GNUNET_PeerIdentity *pid) -{ - struct FindContext fc = { - .session_id = session_id, - .sr = NULL - }; - - GNUNET_CONTAINER_multipeermap_get_multiple (ath->records, - pid, - &match_session_cb, - &fc); - return fc.sr; -} - - -/** - * We received a session allocation message from the service. - * - * @param cls the `struct GNUNET_ATS_TransportHandle` - * @param m message received - */ -static void -handle_ats_session_allocation (void *cls, - const struct SessionAllocationMessage *m) -{ - struct GNUNET_ATS_TransportHandle *ath = cls; - struct GNUNET_ATS_SessionRecord *ar; - uint32_t session_id; - - session_id = ntohl (m->session_id); - ar = find_session (ath, - session_id, - &m->peer); - if (NULL == ar) - { - /* this can (rarely) happen if ATS changes an sessiones allocation - just when the transport service deleted it */ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Allocation ignored, session unknown\n"); - return; - } - ath->backoff = GNUNET_TIME_UNIT_ZERO; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "ATS allocates bandwidth for peer `%s' using address %s\n", - GNUNET_i2s (&ar->pid), - ar->address); - ath->alloc_cb (ath->alloc_cb_cls, - ar->session, - m->bandwidth_out, - m->bandwidth_in); -} - - -/** - * We encountered an error handling the MQ to the ATS service. - * Reconnect. - * - * @param cls the `struct GNUNET_ATS_TransportHandle` - * @param error details about the error - */ -static void -error_handler (void *cls, - enum GNUNET_MQ_Error error) -{ - struct GNUNET_ATS_TransportHandle *ath = cls; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "ATS connection died (code %d), reconnecting\n", - (int) error); - force_reconnect (ath); -} - - -/** - * Generate and transmit the `struct SessionAddMessage` for the given - * session record. - * - * @param ar the session to inform the ATS service about - */ -static void -send_add_session_message (const struct GNUNET_ATS_SessionRecord *ar) -{ - struct GNUNET_ATS_TransportHandle *ath = ar->ath; - struct GNUNET_MQ_Envelope *ev; - struct SessionAddMessage *m; - size_t alen; - - if (NULL == ath->mq) - return; /* disconnected, skip for now */ - alen = strlen (ar->address) + 1; - ev = GNUNET_MQ_msg_extra (m, - alen, - (NULL == ar->session) - ? GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD_INBOUND_ONLY - : GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD); - m->peer = ar->pid; - m->session_id = htonl (ar->slot); - properties_hton (&m->properties, - &ar->properties); - GNUNET_memcpy (&m[1], - ar->address, - alen); - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Adding address `%s' for peer `%s'\n", - ar->address, - GNUNET_i2s (&ar->pid)); - GNUNET_MQ_send (ath->mq, - ev); -} - - -/** - * Send ATS information about the session record. - * - * @param cls our `struct GNUNET_ATS_TransportHandle *`, unused - * @param pid unused - * @param value the `struct GNUNET_ATS_SessionRecord *` to add - * @return #GNUNET_OK - */ -static int -send_add_session_cb (void *cls, - const struct GNUNET_PeerIdentity *pid, - void *value) -{ - struct GNUNET_ATS_SessionRecord *ar = value; - - (void) cls; - (void) pid; - send_add_session_message (ar); - return GNUNET_OK; -} - - -/** - * Re-establish the connection to the ATS service. - * - * @param ath handle to use to re-connect. - */ -static void -reconnect (struct GNUNET_ATS_TransportHandle *ath) -{ - struct GNUNET_MQ_MessageHandler handlers[] = { - GNUNET_MQ_hd_var_size (ats_address_suggestion, - GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION, - struct AddressSuggestionMessage, - ath), - GNUNET_MQ_hd_fixed_size (ats_session_allocation, - GNUNET_MESSAGE_TYPE_ATS_SESSION_ALLOCATION, - struct SessionAllocationMessage, - ath), - GNUNET_MQ_handler_end () - }; - struct GNUNET_MQ_Envelope *ev; - struct GNUNET_MessageHeader *init; - - GNUNET_assert (NULL == ath->mq); - ath->mq = GNUNET_CLIENT_connect (ath->cfg, - "ats", - handlers, - &error_handler, - ath); - if (NULL == ath->mq) - { - GNUNET_break (0); - force_reconnect (ath); - return; - } - ev = GNUNET_MQ_msg (init, - GNUNET_MESSAGE_TYPE_ATS_START); - GNUNET_MQ_send (ath->mq, - ev); - if (NULL == ath->mq) - return; - GNUNET_CONTAINER_multipeermap_iterate (ath->records, - &send_add_session_cb, - ath); -} - - -/** - * Initialize the ATS subsystem. - * - * @param cfg configuration to use - * @param alloc_cb notification to call whenever the allocation changed - * @param alloc_cb_cls closure for @a alloc_cb - * @param suggest_cb notification to call whenever the suggestation is made - * @param suggest_cb_cls closure for @a suggest_cb - * @return ats context - */ -struct GNUNET_ATS_TransportHandle * -GNUNET_ATS_transport_init (const struct GNUNET_CONFIGURATION_Handle *cfg, - GNUNET_ATS_AllocationCallback alloc_cb, - void *alloc_cb_cls, - GNUNET_ATS_SuggestionCallback suggest_cb, - void *suggest_cb_cls) -{ - struct GNUNET_ATS_TransportHandle *ath; - - ath = GNUNET_new (struct GNUNET_ATS_TransportHandle); - ath->cfg = cfg; - ath->suggest_cb = suggest_cb; - ath->suggest_cb_cls = suggest_cb_cls; - ath->alloc_cb = alloc_cb; - ath->alloc_cb_cls = alloc_cb_cls; - ath->records = GNUNET_CONTAINER_multipeermap_create (128, - GNUNET_YES); - reconnect (ath); - return ath; -} - - -/** - * Release memory associated with the session record. - * - * @param cls NULL - * @param pid unused - * @param value a `struct GNUNET_ATS_SessionRecord` - * @return #GNUNET_OK - */ -static int -free_record (void *cls, - const struct GNUNET_PeerIdentity *pid, - void *value) -{ - struct GNUNET_ATS_SessionRecord *ar = value; - - (void) cls; - (void) pid; - GNUNET_free (ar); - return GNUNET_OK; -} - - -/** - * Client is done with ATS transport, release resources. - * - * @param ath handle to release - */ -void -GNUNET_ATS_transport_done (struct GNUNET_ATS_TransportHandle *ath) -{ - if (NULL != ath->mq) - { - GNUNET_MQ_destroy (ath->mq); - ath->mq = NULL; - } - if (NULL != ath->task) - { - GNUNET_SCHEDULER_cancel (ath->task); - ath->task = NULL; - } - GNUNET_CONTAINER_multipeermap_iterate (ath->records, - &free_record, - NULL); - GNUNET_CONTAINER_multipeermap_destroy (ath->records); - GNUNET_free (ath); -} - - -/** - * We have a new session ATS should know. Sessiones have to be added - * with this function before they can be: updated, set in use and - * destroyed. - * - * @param ath handle - * @param pid peer we connected to - * @param address the address (human readable version) - * @param session transport-internal handle for the session/queue, NULL if - * the session is inbound-only - * @param prop performance data for the session - * @return handle to the session representation inside ATS, NULL - * on error (i.e. ATS knows this exact session already) - */ -struct GNUNET_ATS_SessionRecord * -GNUNET_ATS_session_add (struct GNUNET_ATS_TransportHandle *ath, - const struct GNUNET_PeerIdentity *pid, - const char *address, - struct GNUNET_ATS_Session *session, - const struct GNUNET_ATS_Properties *prop) -{ - struct GNUNET_ATS_SessionRecord *ar; - uint32_t s; - size_t alen; - - if (NULL == address) - { - /* we need a valid address */ - GNUNET_break (0); - return NULL; - } - alen = strlen (address) + 1; - if ((alen + sizeof(struct SessionAddMessage) >= GNUNET_MAX_MESSAGE_SIZE) || - (alen >= GNUNET_MAX_MESSAGE_SIZE)) - { - /* address too large for us, this should not happen */ - GNUNET_break (0); - return NULL; - } - - /* Spin 's' until we find an unused session ID for this pid */ - for (s = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT32_MAX); - NULL != find_session (ath, - s, - pid); - s++) - ; - - alen = strlen (address) + 1; - ar = GNUNET_malloc (sizeof(struct GNUNET_ATS_SessionRecord) + alen); - ar->ath = ath; - ar->slot = s; - ar->session = session; - ar->address = (const char *) &ar[1]; - ar->pid = *pid; - ar->properties = *prop; - memcpy (&ar[1], - address, - alen); - (void) GNUNET_CONTAINER_multipeermap_put (ath->records, - &ar->pid, - ar, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - send_add_session_message (ar); - return ar; -} - - -/** - * We have updated performance statistics for a given session. Note - * that this function can be called for sessiones that are currently - * in use as well as sessiones that are valid but not actively in use. - * Furthermore, the peer may not even be connected to us right now (in - * which case the call may be ignored or the information may be stored - * for later use). Update bandwidth assignments. - * - * @param ar session record to update information for - * @param prop performance data for the session - */ -void -GNUNET_ATS_session_update (struct GNUNET_ATS_SessionRecord *ar, - const struct GNUNET_ATS_Properties *prop) -{ - struct GNUNET_ATS_TransportHandle *ath = ar->ath; - struct GNUNET_MQ_Envelope *ev; - struct SessionUpdateMessage *m; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Updating address `%s' for peer `%s'\n", - ar->address, - GNUNET_i2s (&ar->pid)); - ar->properties = *prop; - if (NULL == ath->mq) - return; /* disconnected, skip for now */ - ev = GNUNET_MQ_msg (m, - GNUNET_MESSAGE_TYPE_ATS_SESSION_UPDATE); - m->session_id = htonl (ar->slot); - m->peer = ar->pid; - properties_hton (&m->properties, - &ar->properties); - GNUNET_MQ_send (ath->mq, - ev); -} - - -/** - * A session was destroyed, ATS should now schedule and - * allocate under the assumption that this @a ar is no - * longer in use. - * - * @param ar session record to drop - */ -void -GNUNET_ATS_session_del (struct GNUNET_ATS_SessionRecord *ar) -{ - struct GNUNET_ATS_TransportHandle *ath = ar->ath; - struct GNUNET_MQ_Envelope *ev; - struct SessionDelMessage *m; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Deleting address `%s' for peer `%s'\n", - ar->address, - GNUNET_i2s (&ar->pid)); - if (NULL == ath->mq) - return; - ev = GNUNET_MQ_msg (m, - GNUNET_MESSAGE_TYPE_ATS_SESSION_DEL); - m->session_id = htonl (ar->slot); - m->peer = ar->pid; - GNUNET_MQ_send (ath->mq, - ev); -} - - -/* end of ats_api2_transport.c */ diff --git a/src/ats/gnunet-service-ats-new.c b/src/ats/gnunet-service-ats-new.c deleted file mode 100644 index f2ef92436..000000000 --- a/src/ats/gnunet-service-ats-new.c +++ /dev/null @@ -1,804 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2011, 2018 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file ats/gnunet-service-ats-new.c - * @brief ats service - * @author Matthias Wachs - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_statistics_service.h" -#include "gnunet_ats_plugin_new.h" -#include "ats2.h" - - -/** - * What type of client is this client? - */ -enum ClientType -{ - /** - * We don't know yet. - */ - CT_NONE = 0, - - /** - * Transport service. - */ - CT_TRANSPORT, - - /** - * Application. - */ - CT_APPLICATION -}; - - -/** - * Information we track per client. - */ -struct Client; - -/** - * Preferences expressed by a client are kept in a DLL per client. - */ -struct ClientPreference -{ - /** - * DLL pointer. - */ - struct ClientPreference *next; - - /** - * DLL pointer. - */ - struct ClientPreference *prev; - - /** - * Which client expressed the preference? - */ - struct Client *client; - - /** - * Plugin's representation of the preference. - */ - struct GNUNET_ATS_PreferenceHandle *ph; - - /** - * Details about the preference. - */ - struct GNUNET_ATS_Preference pref; -}; - - -/** - * Information about ongoing sessions of the transport client. - */ -struct GNUNET_ATS_Session -{ - /** - * Session data exposed to the plugin. - */ - struct GNUNET_ATS_SessionData data; - - /** - * The transport client that provided the session. - */ - struct Client *client; - - /** - * Session state in the plugin. - */ - struct GNUNET_ATS_SessionHandle *sh; - - /** - * Unique ID for the session when talking with the client. - */ - uint32_t session_id; -}; - - -/** - * Information we track per client. - */ -struct Client -{ - /** - * Type of the client, initially #CT_NONE. - */ - enum ClientType type; - - /** - * Service handle of the client. - */ - struct GNUNET_SERVICE_Client *client; - - /** - * Message queue to talk to the client. - */ - struct GNUNET_MQ_Handle *mq; - - /** - * Details depending on @e type. - */ - union - { - struct - { - /** - * Head of DLL of preferences expressed by this client. - */ - struct ClientPreference *cp_head; - - /** - * Tail of DLL of preferences expressed by this client. - */ - struct ClientPreference *cp_tail; - } application; - - struct - { - /** - * Map from session IDs to `struct GNUNET_ATS_Session` objects. - */ - struct GNUNET_CONTAINER_MultiHashMap32 *sessions; - } transport; - } details; -}; - - -/** - * Handle for statistics. - */ -static struct GNUNET_STATISTICS_Handle *stats; - -/** - * Our solver. - */ -static struct GNUNET_ATS_SolverFunctions *plugin; - -/** - * Solver plugin name as string - */ -static char *plugin_name; - -/** - * The transport client (there can only be one at a time). - */ -static struct Client *transport_client; - - -/** - * Function called by the solver to prompt the transport to - * try out a new address. - * - * @param cls closure, NULL - * @param pid peer this is about - * @param address address the transport should try - */ -static void -suggest_cb (void *cls, - const struct GNUNET_PeerIdentity *pid, - const char *address) -{ - struct GNUNET_MQ_Envelope *env; - size_t slen = strlen (address) + 1; - struct AddressSuggestionMessage *as; - - if (NULL == transport_client) - { - // FIXME: stats! - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Suggesting address `%s' of peer `%s'\n", - address, - GNUNET_i2s (pid)); - env = GNUNET_MQ_msg_extra (as, - slen, - GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION); - as->peer = *pid; - memcpy (&as[1], - address, - slen); - GNUNET_MQ_send (transport_client->mq, - env); -} - - -/** - * Function called by the solver to tell the transpor to - * allocate bandwidth for the specified session. - * - * @param cls closure, NULL - * @param session session this is about - * @param peer peer this is about - * @param bw_in suggested bandwidth for receiving - * @param bw_out suggested bandwidth for transmission - */ -static void -allocate_cb (void *cls, - struct GNUNET_ATS_Session *session, - const struct GNUNET_PeerIdentity *peer, - struct GNUNET_BANDWIDTH_Value32NBO bw_in, - struct GNUNET_BANDWIDTH_Value32NBO bw_out) -{ - struct GNUNET_MQ_Envelope *env; - struct SessionAllocationMessage *sam; - - (void) cls; - if ((NULL == transport_client) || - (session->client != transport_client)) - { - /* transport must have just died and solver is addressing the - losses of sessions (possibly of previous transport), ignore! */ - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Allocating %u/%u bytes for %p of peer `%s'\n", - ntohl (bw_in.value__), - ntohl (bw_out.value__), - session, - GNUNET_i2s (peer)); - env = GNUNET_MQ_msg (sam, - GNUNET_MESSAGE_TYPE_ATS_SESSION_ALLOCATION); - sam->session_id = session->session_id; - sam->peer = *peer; - sam->bandwidth_in = bw_in; - sam->bandwidth_out = bw_out; - GNUNET_MQ_send (transport_client->mq, - env); -} - - -/** - * Convert @a properties to @a prop - * - * @param properties in NBO - * @param prop[out] in HBO - */ -static void -prop_ntoh (const struct PropertiesNBO *properties, - struct GNUNET_ATS_Properties *prop) -{ - prop->delay = GNUNET_TIME_relative_ntoh (properties->delay); - prop->goodput_out = ntohl (properties->goodput_out); - prop->goodput_in = ntohl (properties->goodput_in); - prop->utilization_out = ntohl (properties->utilization_out); - prop->utilization_in = ntohl (properties->utilization_in); - prop->distance = ntohl (properties->distance); - prop->mtu = ntohl (properties->mtu); - prop->nt = (enum GNUNET_NetworkType) ntohl (properties->nt); - prop->cc = (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl ( - properties->cc); -} - - -/** - * We have received a `struct ExpressPreferenceMessage` from an application client. - * - * @param cls handle to the client - * @param msg the start message - */ -static void -handle_suggest (void *cls, - const struct ExpressPreferenceMessage *msg) -{ - struct Client *c = cls; - struct ClientPreference *cp; - - if (CT_NONE == c->type) - c->type = CT_APPLICATION; - if (CT_APPLICATION != c->type) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (c->client); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Client suggested we talk to %s with preference %d at rate %u\n", - GNUNET_i2s (&msg->peer), - (int) ntohl (msg->pk), - (int) ntohl (msg->bw.value__)); - cp = GNUNET_new (struct ClientPreference); - cp->client = c; - cp->pref.peer = msg->peer; - cp->pref.bw = msg->bw; - cp->pref.pk = (enum GNUNET_MQ_PreferenceKind) ntohl (msg->pk); - cp->ph = plugin->preference_add (plugin->cls, - &cp->pref); - GNUNET_CONTAINER_DLL_insert (c->details.application.cp_head, - c->details.application.cp_tail, - cp); - GNUNET_SERVICE_client_continue (c->client); -} - - -/** - * We have received a `struct ExpressPreferenceMessage` from an application client. - * - * @param cls handle to the client - * @param msg the start message - */ -static void -handle_suggest_cancel (void *cls, - const struct ExpressPreferenceMessage *msg) -{ - struct Client *c = cls; - struct ClientPreference *cp; - - if (CT_NONE == c->type) - c->type = CT_APPLICATION; - if (CT_APPLICATION != c->type) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (c->client); - return; - } - for (cp = c->details.application.cp_head; - NULL != cp; - cp = cp->next) - if ((cp->pref.pk == (enum GNUNET_MQ_PreferenceKind) ntohl (msg->pk)) && - (cp->pref.bw.value__ == msg->bw.value__) && - (0 == GNUNET_memcmp (&cp->pref.peer, - &msg->peer))) - break; - if (NULL == cp) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (c->client); - return; - } - plugin->preference_del (plugin->cls, - cp->ph, - &cp->pref); - GNUNET_CONTAINER_DLL_remove (c->details.application.cp_head, - c->details.application.cp_tail, - cp); - GNUNET_free (cp); - GNUNET_SERVICE_client_continue (c->client); -} - - -/** - * Handle 'start' messages from transport clients. - * - * @param cls client that sent the request - * @param message the request message - */ -static void -handle_start (void *cls, - const struct GNUNET_MessageHeader *hdr) -{ - struct Client *c = cls; - - if (CT_NONE != c->type) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (c->client); - return; - } - c->type = CT_TRANSPORT; - c->details.transport.sessions - = GNUNET_CONTAINER_multihashmap32_create (128); - if (NULL != transport_client) - { - GNUNET_SERVICE_client_drop (transport_client->client); - transport_client = NULL; - } - transport_client = c; - GNUNET_SERVICE_client_continue (c->client); -} - - -/** - * Check 'session_add' message is well-formed and comes from a - * transport client. - * - * @param cls client that sent the request - * @param message the request message - * @return #GNUNET_OK if @a message is well-formed - */ -static int -check_session_add (void *cls, - const struct SessionAddMessage *message) -{ - struct Client *c = cls; - - GNUNET_MQ_check_zero_termination (message); - if (CT_TRANSPORT != c->type) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Handle 'session add' messages from transport clients. - * - * @param cls client that sent the request - * @param message the request message - */ -static void -handle_session_add (void *cls, - const struct SessionAddMessage *message) -{ - struct Client *c = cls; - const char *address = (const char *) &message[1]; - struct GNUNET_ATS_Session *session; - int inbound_only = (GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD_INBOUND_ONLY == - ntohs (message->header.type)); - - session = GNUNET_CONTAINER_multihashmap32_get (c->details.transport.sessions, - message->session_id); - if (NULL != session) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (c->client); - return; - } - session = GNUNET_new (struct GNUNET_ATS_Session); - session->data.session = session; - session->client = c; - session->session_id = message->session_id; - session->data.peer = message->peer; - prop_ntoh (&message->properties, - &session->data.prop); - session->data.inbound_only = inbound_only; - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap32_put ( - c->details.transport.sessions, - message->session_id, - session, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - session->sh = plugin->session_add (plugin->cls, - &session->data, - address); - GNUNET_assert (NULL != session->sh); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transport has new session %p to %s\n", - session, - GNUNET_i2s (&message->peer)); - GNUNET_SERVICE_client_continue (c->client); -} - - -/** - * Handle 'session update' messages from transport clients. - * - * @param cls client that sent the request - * @param msg the request message - */ -static void -handle_session_update (void *cls, - const struct SessionUpdateMessage *msg) -{ - struct Client *c = cls; - struct GNUNET_ATS_Session *session; - - if (CT_TRANSPORT != c->type) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (c->client); - return; - } - session = GNUNET_CONTAINER_multihashmap32_get (c->details.transport.sessions, - msg->session_id); - if (NULL == session) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (c->client); - return; - } - prop_ntoh (&msg->properties, - &session->data.prop); - plugin->session_update (plugin->cls, - session->sh, - &session->data); - GNUNET_SERVICE_client_continue (c->client); -} - - -/** - * Handle 'session delete' messages from transport clients. - * - * @param cls client that sent the request - * @param message the request message - */ -static void -handle_session_del (void *cls, - const struct SessionDelMessage *message) -{ - struct Client *c = cls; - struct GNUNET_ATS_Session *session; - - if (CT_TRANSPORT != c->type) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (c->client); - return; - } - session = GNUNET_CONTAINER_multihashmap32_get (c->details.transport.sessions, - message->session_id); - if (NULL == session) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (c->client); - return; - } - GNUNET_assert (NULL != session->sh); - plugin->session_del (plugin->cls, - session->sh, - &session->data); - session->sh = NULL; - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap32_remove ( - c->details.transport.sessions, - session->session_id, - session)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transport lost session %p to %s\n", - session, - GNUNET_i2s (&session->data.peer)); - GNUNET_free (session); - GNUNET_SERVICE_client_continue (c->client); -} - - -/** - * A client connected to us. Setup the local client - * record. - * - * @param cls unused - * @param client handle of the client - * @param mq message queue to talk to @a client - * @return @a client - */ -static void * -client_connect_cb (void *cls, - struct GNUNET_SERVICE_Client *client, - struct GNUNET_MQ_Handle *mq) -{ - struct Client *c = GNUNET_new (struct Client); - - c->client = client; - c->mq = mq; - return c; -} - - -/** - * Function called on each session to release associated state - * on transport disconnect. - * - * @param cls the `struct Client` - * @param key unused (session_id) - * @param value a `struct GNUNET_ATS_Session` - */ -static int -free_session (void *cls, - uint32_t key, - void *value) -{ - struct Client *c = cls; - struct GNUNET_ATS_Session *session = value; - - (void) key; - GNUNET_assert (c == session->client); - GNUNET_assert (NULL != session->sh); - plugin->session_del (plugin->cls, - session->sh, - &session->data); - session->sh = NULL; - GNUNET_free (session); - return GNUNET_OK; -} - - -/** - * A client disconnected from us. Tear down the local client - * record. - * - * @param cls unused - * @param client handle of the client - * @param app_ctx our `struct Client` - */ -static void -client_disconnect_cb (void *cls, - struct GNUNET_SERVICE_Client *client, - void *app_ctx) -{ - struct Client *c = app_ctx; - - (void) cls; - GNUNET_assert (c->client == client); - switch (c->type) - { - case CT_NONE: - break; - - case CT_APPLICATION: - for (struct ClientPreference *cp = c->details.application.cp_head; - NULL != cp; - cp = c->details.application.cp_head) - { - plugin->preference_del (plugin->cls, - cp->ph, - &cp->pref); - GNUNET_CONTAINER_DLL_remove (c->details.application.cp_head, - c->details.application.cp_tail, - cp); - GNUNET_free (cp); - } - break; - - case CT_TRANSPORT: - if (transport_client == c) - transport_client = NULL; - GNUNET_CONTAINER_multihashmap32_iterate (c->details.transport.sessions, - &free_session, - c); - GNUNET_CONTAINER_multihashmap32_destroy (c->details.transport.sessions); - break; - } - GNUNET_free (c); -} - - -/** - * Task run at the end during shutdown. - * - * @param cls unused - */ -static void -final_cleanup (void *cls) -{ - (void) cls; - if (NULL != stats) - { - GNUNET_STATISTICS_destroy (stats, - GNUNET_NO); - stats = NULL; - } - if (NULL != plugin) - { - GNUNET_PLUGIN_unload (plugin_name, - plugin); - plugin = NULL; - } - if (NULL != plugin_name) - { - GNUNET_free (plugin_name); - plugin_name = NULL; - } -} - - -/** - * Task run during shutdown. - * - * @param cls unused - */ -static void -cleanup_task (void *cls) -{ - (void) cls; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "ATS shutdown initiated\n"); - GNUNET_SCHEDULER_add_now (&final_cleanup, - NULL); -} - - -/** - * Process template requests. - * - * @param cls closure - * @param cfg configuration to use - * @param service the initialized service - */ -static void -run (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_SERVICE_Handle *service) -{ - static struct GNUNET_ATS_PluginEnvironment env; - char *solver; - - stats = GNUNET_STATISTICS_create ("ats", - cfg); - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, - "ats", - "SOLVER", - &solver)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "No ATS solver configured, using 'simple' approach\n"); - solver = GNUNET_strdup ("simple"); - } - GNUNET_SCHEDULER_add_shutdown (&cleanup_task, - NULL); - env.cls = NULL; - env.cfg = cfg; - env.stats = stats; - env.suggest_cb = &suggest_cb; - env.allocate_cb = &allocate_cb; - GNUNET_asprintf (&plugin_name, - "libgnunet_plugin_ats2_%s", - solver); - GNUNET_free (solver); - if (NULL == (plugin = GNUNET_PLUGIN_load (plugin_name, - &env))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to initialize solver `%s'!\n"), - plugin_name); - GNUNET_SCHEDULER_shutdown (); - return; - } -} - - -/** - * Define "main" method using service macro. - */ -GNUNET_SERVICE_MAIN - ("ats", - GNUNET_SERVICE_OPTION_NONE, - &run, - &client_connect_cb, - &client_disconnect_cb, - NULL, - GNUNET_MQ_hd_fixed_size (suggest, - GNUNET_MESSAGE_TYPE_ATS_SUGGEST, - struct ExpressPreferenceMessage, - NULL), - GNUNET_MQ_hd_fixed_size (suggest_cancel, - GNUNET_MESSAGE_TYPE_ATS_SUGGEST_CANCEL, - struct ExpressPreferenceMessage, - NULL), - GNUNET_MQ_hd_fixed_size (start, - GNUNET_MESSAGE_TYPE_ATS_START, - struct GNUNET_MessageHeader, - NULL), - GNUNET_MQ_hd_var_size (session_add, - GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD, - struct SessionAddMessage, - NULL), - GNUNET_MQ_hd_var_size (session_add, - GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD_INBOUND_ONLY, - struct SessionAddMessage, - NULL), - GNUNET_MQ_hd_fixed_size (session_update, - GNUNET_MESSAGE_TYPE_ATS_SESSION_UPDATE, - struct SessionUpdateMessage, - NULL), - GNUNET_MQ_hd_fixed_size (session_del, - GNUNET_MESSAGE_TYPE_ATS_SESSION_DEL, - struct SessionDelMessage, - NULL), - GNUNET_MQ_handler_end ()); - - -/* end of gnunet-service-ats.c */ diff --git a/src/ats/perf_ats_solver_mlp.conf b/src/ats/perf_ats_solver_mlp.conf deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/ats/perf_ats_solver_ril.conf b/src/ats/perf_ats_solver_ril.conf deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/ats/plugin_ats2_common.c b/src/ats/plugin_ats2_common.c deleted file mode 100644 index da20a342c..000000000 --- a/src/ats/plugin_ats2_common.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2011-2015, 2018 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file ats/plugin_ats2_common.c - * @brief ATS solver helper functions to be inlined - * @author Matthias Wachs - * @author Christian Grothoff - */ - -/** - * Default bandwidth assigned to a network: 64 KB/s - */ -#define DEFAULT_BANDWIDTH 65536 - - -/** - * Parse @a cfg for @a quota as specified for @a direction of - * network type @a nts. - * - * @param cfg configuration to parse - * @param nts network type string to get quota for - * @param direction direction to get quota for ("IN" or "OUT") - * @param quota[out] set to quota, #DEFAULT_BANDWIDTH if @a cfg does not say anything useful - */ -static void -get_quota (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *nts, - const char *direction, - unsigned long long *quota) -{ - char *quota_str; - char *quota_s; - int res; - - GNUNET_asprintf ("a_s, - "%s_QUOTA_%s", - nts, - direction); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "ATS", - quota_s, - "a_str)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, - "ATS", - quota_s); - GNUNET_free (quota_s); - return; - } - GNUNET_free (quota_s); - res = GNUNET_NO; - if (0 == strcmp (quota_str, - "unlimited")) - { - *quota = ULONG_MAX; - res = GNUNET_YES; - } - if ((GNUNET_NO == res) && - (GNUNET_OK == - GNUNET_STRINGS_fancy_size_to_bytes (quota_str, - quota))) - res = GNUNET_YES; - if ((GNUNET_NO == res) && - (1 == - sscanf (quota_str, - "%llu", - quota))) - res = GNUNET_YES; - if (GNUNET_NO == res) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ ( - "Could not load %s quota for network `%s': `%s', assigning default bandwidth %llu\n"), - direction, - nts, - quota_str, - (unsigned long long) DEFAULT_BANDWIDTH); - *quota = DEFAULT_BANDWIDTH; - } - GNUNET_free (quota_str); -} diff --git a/src/ats/plugin_ats2_simple.c b/src/ats/plugin_ats2_simple.c deleted file mode 100644 index 3062b6019..000000000 --- a/src/ats/plugin_ats2_simple.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2011-2015, 2018 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file ats/plugin_ats2_simple.c - * @brief ATS simple solver - * @author Matthias Wachs - * @author Christian Grothoff - * - * TODO: - * - needs testing - */ -#include "platform.h" -#include "gnunet_ats_plugin_new.h" -#include "gnunet_hello_lib.h" -#include "gnunet_peerstore_service.h" - -#define LOG(kind, ...) GNUNET_log_from (kind, "ats-simple", __VA_ARGS__) - - -/** - * Base frequency at which we suggest addresses to transport. - * Multiplied by the square of the number of active connections - * (and randomized) to calculate the actual frequency at which - * we will suggest addresses to the transport. Furthermore, each - * address is also bounded by an exponential back-off. - */ -#define SUGGEST_FREQ GNUNET_TIME_UNIT_SECONDS - -/** - * What is the minimum bandwidth we always try to allocate for - * any session that is up? (May still be scaled down lower if - * the number of sessions is so high that the total bandwidth - * is insufficient to allow for this value to be granted.) - */ -#define MIN_BANDWIDTH_PER_SESSION 1024 - - -/** - * A handle for the proportional solver - */ -struct SimpleHandle; - - -/** - * Information about preferences and sessions we track - * per peer. - */ -struct Peer; - - -/** - * Entry in list of addresses we could try per peer. - */ -struct Hello -{ - /** - * Kept in a DLL. - */ - struct Hello *next; - - /** - * Kept in a DLL. - */ - struct Hello *prev; - - /** - * Peer this hello belongs to. - */ - struct Peer *peer; - - /** - * The address we could try. - */ - const char *address; - - /** - * Is a session with this address already up? - * If not, set to NULL. - */ - struct GNUNET_ATS_SessionHandle *sh; - - /** - * When does the HELLO expire? - */ - struct GNUNET_TIME_Absolute expiration; - - /** - * When did we try it last? - */ - struct GNUNET_TIME_Absolute last_attempt; - - /** - * Current exponential backoff value. - */ - struct GNUNET_TIME_Relative backoff; - - /** - * Type of the network for this HELLO. - */ - enum GNUNET_NetworkType nt; -}; - - -/** - * Internal representation of a session by the plugin. - * (If desired, plugin may just use NULL.) - */ -struct GNUNET_ATS_SessionHandle -{ - /** - * Kept in DLL per peer. - */ - struct GNUNET_ATS_SessionHandle *next; - - /** - * Kept in DLL per peer. - */ - struct GNUNET_ATS_SessionHandle *prev; - - /** - * The session in the main ATS service. - */ - struct GNUNET_ATS_Session *session; - - /** - * Current performance data for this @e session - */ - const struct GNUNET_ATS_SessionData *data; - - /** - * Hello matching this session, or NULL for none. - */ - struct Hello *hello; - - /** - * Peer this session is for. - */ - struct Peer *peer; - - /** - * Address used by this session (largely for debugging). - */ - const char *address; - - /** - * When did we last update transport about the allocation? - * Used to dampen the frequency of updates. - */ - struct GNUNET_TIME_Absolute last_allocation; - - /** - * Last BW-in allocation given to the transport service. - */ - struct GNUNET_BANDWIDTH_Value32NBO bw_in; - - /** - * Last BW-out allocation given to the transport service. - */ - struct GNUNET_BANDWIDTH_Value32NBO bw_out; - - /** - * New BW-in allocation given to the transport service. - */ - uint64_t target_in; - - /** - * New BW-out allocation given to the transport service. - */ - uint64_t target_out; -}; - - -/** - * Information about preferences and sessions we track - * per peer. - */ -struct Peer -{ - /** - * Kept in DLL per peer. - */ - struct GNUNET_ATS_SessionHandle *sh_head; - - /** - * Kept in DLL per peer. - */ - struct GNUNET_ATS_SessionHandle *sh_tail; - - /** - * Kept in a DLL. - */ - struct Hello *h_head; - - /** - * Kept in a DLL. - */ - struct Hello *h_tail; - - /** - * The handle for the proportional solver - */ - struct SimpleHandle *h; - - /** - * Watch context where we are currently looking for HELLOs for - * this peer. - */ - struct GNUNET_PEERSTORE_WatchContext *wc; - - /** - * Task used to try again to suggest an address for this peer. - */ - struct GNUNET_SCHEDULER_Task *task; - - /** - * Which peer is this for? - */ - struct GNUNET_PeerIdentity pid; - - /** - * When did we last suggest an address to connect to for this peer? - */ - struct GNUNET_TIME_Absolute last_suggestion; - - /** - * Array where we sum up the bandwidth requests received indexed - * by preference kind (see `enum GNUNET_MQ_PreferenceKind`) - */ - uint64_t bw_by_pk[GNUNET_MQ_PREFERENCE_COUNT]; -}; - - -/** - * Representation of a network (to be expanded...) - */ -struct Network -{ - /** - * Total inbound quota - */ - unsigned long long total_quota_in; - - /** - * Total outbound quota - */ - unsigned long long total_quota_out; - - /** - * ATS network type - */ - enum GNUNET_NetworkType type; -}; - - -/** - * A handle for the proportional solver - */ -struct SimpleHandle -{ - /** - * Our execution environment. - */ - struct GNUNET_ATS_PluginEnvironment *env; - - /** - * Information we track for each peer. - */ - struct GNUNET_CONTAINER_MultiPeerMap *peers; - - /** - * Handle to the peerstore service. - */ - struct GNUNET_PEERSTORE_Handle *ps; - - /** - * Array where we sum up the bandwidth requests received indexed - * by preference kind (see `enum GNUNET_MQ_PreferenceKind`) (sums - * over all peers). - */ - uint64_t bw_by_pk[GNUNET_MQ_PREFERENCE_COUNT]; - - /** - * Information we track per network type (quotas). - */ - struct Network networks[GNUNET_NT_COUNT]; -}; - - -/** - * Lookup peer in the peers map. - * - * @param h handle to look up in - * @param pid peer identity to look up by - * @return NULL for not found - */ -struct Peer * -lookup_peer (struct SimpleHandle *h, const struct GNUNET_PeerIdentity *pid) -{ - return GNUNET_CONTAINER_multipeermap_get (h->peers, pid); -} - - -/** - * Check if there is _any_ interesting information left we - * store about the peer in @a p. - * - * @param p peer to test if we can drop the data structure - * @return #GNUNET_YES if no information is left in @a p - */ -static int -peer_test_dead (struct Peer *p) -{ - for (enum GNUNET_MQ_PreferenceKind pk = 0; pk < GNUNET_MQ_PREFERENCE_COUNT; - pk++) - if (0 != p->bw_by_pk[pk]) - return GNUNET_NO; - if (NULL != p->sh_head) - return GNUNET_NO; - return GNUNET_YES; -} - - -/** - * Contact the transport service and suggest to it to - * try connecting to the address of @a hello. Updates - * backoff and timestamp values in the @a hello. - * - * @param hello[in,out] address suggestion to make - */ -static void -suggest_hello (struct Hello *hello) -{ - struct Peer *p = hello->peer; - struct SimpleHandle *h = p->h; - - p->last_suggestion = hello->last_attempt = GNUNET_TIME_absolute_get (); - hello->backoff = - GNUNET_TIME_randomized_backoff (hello->backoff, - GNUNET_TIME_absolute_get_remaining ( - hello->expiration)); - h->env->suggest_cb (h->env->cls, &p->pid, hello->address); -} - - -/** - * Consider suggesting a HELLO (without a session) to transport. - * We look at how many active sessions we have for the peer, and - * if there are many, reduce the frequency of trying new addresses. - * Also, for each address we consider when we last tried it, and - * its exponential backoff if the attempt failed. Note that it - * is possible that this function is called when no suggestion - * is to be made. - * - * In this case, we only calculate the time until we make the next - * suggestion. - * - * @param cls a `struct Peer` - */ -static void -suggest_start_cb (void *cls) -{ - struct Peer *p = cls; - struct GNUNET_TIME_Relative delay = GNUNET_TIME_UNIT_ZERO; - struct Hello *hello = NULL; - struct GNUNET_TIME_Absolute hpt = GNUNET_TIME_UNIT_FOREVER_ABS; - struct GNUNET_TIME_Relative xdelay; - struct GNUNET_TIME_Absolute xnext; - unsigned int num_sessions = 0; - uint32_t sq; - - /* count number of active sessions */ - for (struct GNUNET_ATS_SessionHandle *sh = p->sh_head; NULL != sh; - sh = sh->next) - num_sessions++; - /* calculate square of number of sessions */ - num_sessions++; /* start with 1, even if we have zero sessions */ - if (num_sessions < UINT16_MAX) - sq = num_sessions * (uint32_t) num_sessions; - else - sq = UINT32_MAX; - xdelay = - GNUNET_TIME_randomized_backoff (GNUNET_TIME_relative_multiply (SUGGEST_FREQ, - sq), - GNUNET_TIME_UNIT_FOREVER_REL); - xnext = GNUNET_TIME_relative_to_absolute (xdelay); - - p->task = NULL; - while (0 == delay.rel_value_us) - { - struct Hello *next; - struct GNUNET_TIME_Absolute xmax; - - if (NULL != hello) - { - /* We went through the loop already once and found - a HELLO that is due *now*, so make a suggestion! */ - GNUNET_break (NULL == hello->sh); - suggest_hello (hello); - hello = NULL; - hpt = GNUNET_TIME_UNIT_FOREVER_ABS; - } - for (struct Hello *pos = p->h_head; NULL != pos; pos = next) - { - struct GNUNET_TIME_Absolute pt; - - next = pos->next; - if (NULL != pos->sh) - continue; - if (0 == - GNUNET_TIME_absolute_get_remaining (pos->expiration).rel_value_us) - { - /* expired, remove! */ - GNUNET_CONTAINER_DLL_remove (p->h_head, p->h_tail, pos); - GNUNET_free (pos); - continue; - } - pt = GNUNET_TIME_absolute_add (pos->last_attempt, pos->backoff); - if ((NULL == hello) || (pt.abs_value_us < hpt.abs_value_us)) - { - hello = pos; - hpt = pt; - } - } - if (NULL == hello) - return; /* no HELLOs that could still be tried */ - - /* hpt is now the *earliest* possible time for any HELLO - but we might not want to go for as early as possible for - this peer. So the actual time is the max of the earliest - HELLO and the 'xnext' */ - xmax = GNUNET_TIME_absolute_max (hpt, xnext); - delay = GNUNET_TIME_absolute_get_remaining (xmax); - } - p->task = GNUNET_SCHEDULER_add_delayed (delay, &suggest_start_cb, p); -} - - -/** - * Function called by PEERSTORE for each matching record. - * - * @param cls closure with a `struct Peer` - * @param record peerstore record information - * @param emsg error message, or NULL if no errors - */ -static void -watch_cb (void *cls, - const struct GNUNET_PEERSTORE_Record *record, - const char *emsg) -{ - struct Peer *p = cls; - char *addr; - size_t alen; - enum GNUNET_NetworkType nt; - struct GNUNET_TIME_Absolute expiration; - struct Hello *hello; - - if (0 != GNUNET_memcmp (&p->pid, &record->peer)) - { - GNUNET_break (0); - return; - } - if (0 != strcmp (record->key, GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY)) - { - GNUNET_break (0); - return; - } - addr = GNUNET_HELLO_extract_address (record->value, - record->value_size, - &p->pid, - &nt, - &expiration); - if (NULL == addr) - return; /* invalid hello, bad signature, other problem */ - if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) - { - /* expired, ignore */ - GNUNET_free (addr); - return; - } - /* check if addr is already known */ - for (struct Hello *he = p->h_head; NULL != he; he = he->next) - { - if (0 != strcmp (he->address, addr)) - continue; - if (he->expiration.abs_value_us < expiration.abs_value_us) - { - he->expiration = expiration; - he->nt = nt; - } - GNUNET_free (addr); - return; - } - /* create new HELLO */ - alen = strlen (addr) + 1; - hello = GNUNET_malloc (sizeof(struct Hello) + alen); - hello->address = (const char *) &hello[1]; - hello->expiration = expiration; - hello->nt = nt; - hello->peer = p; - memcpy (&hello[1], addr, alen); - GNUNET_CONTAINER_DLL_insert (p->h_head, p->h_tail, hello); - /* check if sh for this HELLO already exists */ - for (struct GNUNET_ATS_SessionHandle *sh = p->sh_head; NULL != sh; - sh = sh->next) - { - if ((NULL == sh->address) || (0 != strcmp (sh->address, addr))) - continue; - GNUNET_assert (NULL == sh->hello); - sh->hello = hello; - hello->sh = sh; - break; - } - GNUNET_free (addr); - if (NULL == p->task) - p->task = GNUNET_SCHEDULER_add_now (&suggest_start_cb, p); -} - - -/** - * Find or add peer if necessary. - * - * @param h our plugin handle - * @param pid the peer identity to add/look for - * @return a peer handle - */ -static struct Peer * -peer_add (struct SimpleHandle *h, const struct GNUNET_PeerIdentity *pid) -{ - struct Peer *p = lookup_peer (h, pid); - - if (NULL != p) - return p; - p = GNUNET_new (struct Peer); - p->h = h; - p->pid = *pid; - p->wc = GNUNET_PEERSTORE_watch (h->ps, - "transport", - &p->pid, - GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY, - &watch_cb, - p); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_put ( - h->peers, - &p->pid, - p, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - - return p; -} - - -/** - * Free the entry (and associated tasks) of peer @a p. - * Note that @a p must be dead already (see #peer_test_dead()). - * - * @param p the peer to free - */ -static void -peer_free (struct Peer *p) -{ - struct SimpleHandle *h = p->h; - struct Hello *hello; - - GNUNET_assert (NULL == p->sh_head); - while (NULL != (hello = p->h_head)) - { - GNUNET_CONTAINER_DLL_remove (p->h_head, p->h_tail, hello); - GNUNET_assert (NULL == hello->sh); - GNUNET_free (hello); - } - if (NULL != p->task) - { - GNUNET_SCHEDULER_cancel (p->task); - p->task = NULL; - } - if (NULL != p->wc) - { - GNUNET_PEERSTORE_watch_cancel (p->wc); - p->wc = NULL; - } - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (h->peers, &p->pid, p)); - GNUNET_free (p); -} - - -/** - * Check if the new allocation for @a sh is significantly different - * from the last one, and if so, tell transport. - * - * @param sh session handle to consider updating transport for - */ -static void -consider_notify_transport (struct GNUNET_ATS_SessionHandle *sh) -{ - struct Peer *peer = sh->peer; - struct SimpleHandle *h = peer->h; - enum GNUNET_NetworkType nt = sh->data->prop.nt; - struct GNUNET_TIME_Relative delay; - uint64_t sig_in; - uint64_t sig_out; - int64_t delta_in; - int64_t delta_out; - - delay = GNUNET_TIME_absolute_get_duration (sh->last_allocation); - /* A significant change is more than 10% of the quota, - which is given in bytes/second */ - sig_in = h->networks[nt].total_quota_in * (delay.rel_value_us / 1000LL) - / 1000LL / 10; - sig_out = h->networks[nt].total_quota_out * (delay.rel_value_us / 1000LL) - / 1000LL / 10; - delta_in = ((int64_t) ntohl (sh->bw_in.value__)) - ((int64_t) sh->target_in); - delta_out = ((int64_t) ntohl (sh->bw_in.value__)) - ((int64_t) sh->target_in); - /* we want the absolute values */ - if (delta_in < 0) - delta_in = -delta_in; - if (INT64_MIN == delta_in) - delta_in = INT64_MAX; /* Handle corner case: INT_MIN == - INT_MIN */ - if (delta_out < 0) - delta_out = -delta_out; - if (INT64_MIN == delta_out) - delta_out = INT64_MAX; /* Handle corner case: INT_MIN == - INT_MIN */ - if ((sig_in > delta_in) && (sig_out > delta_out)) - return; /* insignificant change */ - /* change is significant, tell transport! */ - if (sh->target_in > UINT32_MAX) - sh->target_in = UINT32_MAX; - sh->bw_in.value__ = htonl ((uint32_t) sh->target_in); - if (sh->target_out > UINT32_MAX) - sh->target_out = UINT32_MAX; - sh->bw_out.value__ = htonl ((uint32_t) sh->target_out); - sh->last_allocation = GNUNET_TIME_absolute_get (); - h->env->allocate_cb (h->env->cls, - sh->session, - &peer->pid, - sh->bw_in, - sh->bw_out); -} - - -/** - * Closure for #update_counters and #update_allocation. - */ -struct Counters -{ - /** - * Plugin's state. - */ - struct SimpleHandle *h; - - /** - * Bandwidth that applications would prefer to allocate in this - * network type. We initially add all requested allocations to the - * respective network type where the given preference is best - * satisfied. Later we may rebalance. - */ - uint64_t bw_out_by_nt[GNUNET_NT_COUNT]; - - /** - * Current bandwidth utilization for this network type. We simply - * add the current goodput up (with some fairness considerations). - */ - uint64_t bw_in_by_nt[GNUNET_NT_COUNT]; - - /** - * By how much do we have to scale (up or down) our expectations - * for outbound bandwidth? - */ - double scale_out[GNUNET_NT_COUNT]; - - /** - * By how much do we have to scale (up or down) our expectations - * for inbound bandwidth? - */ - double scale_in[GNUNET_NT_COUNT]; -}; - - -/** - * Function used to iterate over all peers and collect - * counter data. - * - * @param cls a `struct Counters *` - * @param pid identity of the peer we process, unused - * @param value a `struct Peer *` - * @return #GNUNET_YES (continue to iterate) - */ -static int -update_counters (void *cls, const struct GNUNET_PeerIdentity *pid, void *value) -{ - struct Counters *c = cls; - struct Peer *peer = value; - struct GNUNET_ATS_SessionHandle *best[GNUNET_MQ_PREFERENCE_COUNT]; - - (void) pid; - if (NULL == peer->sh_head) - return GNUNET_YES; /* no available session, cannot allocate bandwidth */ - memset (best, 0, sizeof(best)); - for (struct GNUNET_ATS_SessionHandle *sh = peer->sh_head; NULL != sh; - sh = sh->next) - { - enum GNUNET_NetworkType nt = sh->data->prop.nt; - - sh->target_out = MIN_BANDWIDTH_PER_SESSION; - c->bw_out_by_nt[nt] += MIN_BANDWIDTH_PER_SESSION; - c->bw_in_by_nt[nt] += - GNUNET_MAX (MIN_BANDWIDTH_PER_SESSION, sh->data->prop.goodput_in); - for (enum GNUNET_MQ_PreferenceKind pk = 0; pk < GNUNET_MQ_PREFERENCE_COUNT; - pk++) - { - /* General rule: always prefer smaller distance if possible, - otherwise decide by pk: */ - switch (pk) - { - case GNUNET_MQ_PREFERENCE_NONE: - break; - - case GNUNET_MQ_PREFERENCE_BANDWIDTH: - /* For bandwidth, we compare the sum of transmitted bytes and - confirmed transmitted bytes, so confirmed data counts twice */ - if ((NULL == best[pk]) || - (sh->data->prop.distance < best[pk]->data->prop.distance) || - (sh->data->prop.utilization_out + sh->data->prop.goodput_out > - best[pk]->data->prop.utilization_out - + best[pk]->data->prop.goodput_out)) - best[pk] = sh; - /* If both are equal (i.e. usually this happens if there is a zero), use - latency as a yardstick */ - if ((sh->data->prop.utilization_out + sh->data->prop.goodput_out == - best[pk]->data->prop.utilization_out - + best[pk]->data->prop.goodput_out) && - (sh->data->prop.distance == best[pk]->data->prop.distance) && - (sh->data->prop.delay.rel_value_us < - best[pk]->data->prop.delay.rel_value_us)) - best[pk] = sh; - break; - - case GNUNET_MQ_PREFERENCE_LATENCY: - if ((NULL == best[pk]) || - (sh->data->prop.distance < best[pk]->data->prop.distance) || - ((sh->data->prop.distance == best[pk]->data->prop.distance) && - (sh->data->prop.delay.rel_value_us < - best[pk]->data->prop.delay.rel_value_us))) - best[pk] = sh; - break; - - case GNUNET_MQ_PREFERENCE_RELIABILITY: - /* For reliability, we consider the ratio of goodput to utilization - (but use multiplicative formultations to avoid division by zero) */ - if ((NULL == best[pk]) || (1ULL * sh->data->prop.goodput_out - * best[pk]->data->prop.utilization_out > - 1ULL * sh->data->prop.utilization_out - * best[pk]->data->prop.goodput_out)) - best[pk] = sh; - /* If both are equal (i.e. usually this happens if there is a zero), use - latency as a yardstick */ - if ((1ULL * sh->data->prop.goodput_out - * best[pk]->data->prop.utilization_out == - 1ULL * sh->data->prop.utilization_out - * best[pk]->data->prop.goodput_out) && - (sh->data->prop.distance == best[pk]->data->prop.distance) && - (sh->data->prop.delay.rel_value_us < - best[pk]->data->prop.delay.rel_value_us)) - best[pk] = sh; - break; - } - } - } - /* for first round, assign target bandwidth simply to sum of - requested bandwidth */ - for (enum GNUNET_MQ_PreferenceKind pk = - 1 /* skip GNUNET_MQ_PREFERENCE_NONE */; - pk < GNUNET_MQ_PREFERENCE_COUNT; - pk++) - { - const struct GNUNET_ATS_SessionData *data = best[pk]->data; - enum GNUNET_NetworkType nt; - - GNUNET_assert (NULL != data); - nt = data->prop.nt; - best[pk]->target_out = - GNUNET_MIN (peer->bw_by_pk[pk], MIN_BANDWIDTH_PER_SESSION); - c->bw_out_by_nt[nt] += - (uint64_t) (best[pk]->target_out - MIN_BANDWIDTH_PER_SESSION); - } - return GNUNET_YES; -} - - -/** - * Function used to iterate over all peers and collect - * counter data. - * - * @param cls a `struct Counters *` - * @param pid identity of the peer we process, unused - * @param value a `struct Peer *` - * @return #GNUNET_YES (continue to iterate) - */ -static int -update_allocation (void *cls, - const struct GNUNET_PeerIdentity *pid, - void *value) -{ - struct Counters *c = cls; - struct Peer *peer = value; - - (void) pid; - for (struct GNUNET_ATS_SessionHandle *sh = peer->sh_head; NULL != sh; - sh = sh->next) - { - enum GNUNET_NetworkType nt = sh->data->prop.nt; - - sh->target_out = (uint64_t) (c->scale_out[nt] * sh->target_out); - sh->target_in = (uint64_t) (c->scale_in[nt] * sh->target_in); - consider_notify_transport (sh); - } - return GNUNET_YES; -} - - -/** - * The world changed, recalculate our allocations. - */ -static void -update (struct SimpleHandle *h) -{ - struct Counters cnt = { .h = h }; - - GNUNET_CONTAINER_multipeermap_iterate (h->peers, &update_counters, &cnt); - /* calculate how badly the missmatch between requested - allocations and available bandwidth is per network type */ - for (enum GNUNET_NetworkType nt = 0; nt < GNUNET_NT_COUNT; nt++) - { - cnt.scale_out[nt] = - 1.0 * cnt.bw_out_by_nt[nt] / h->networks[nt].total_quota_out; - cnt.scale_in[nt] = - 1.0 * cnt.bw_in_by_nt[nt] / h->networks[nt].total_quota_in; - } - /* recalculate allocations, considering scaling factor, and - update transport if the change is significant */ - GNUNET_CONTAINER_multipeermap_iterate (h->peers, &update_allocation, &cnt); -} - - -/** - * The plugin should begin to respect a new preference. - * - * @param cls the closure - * @param pref the preference to add - * @return plugin's internal representation, or NULL - */ -static struct GNUNET_ATS_PreferenceHandle * -simple_preference_add (void *cls, const struct GNUNET_ATS_Preference *pref) -{ - struct SimpleHandle *h = cls; - struct Peer *p = peer_add (h, &pref->peer); - - GNUNET_assert (pref->pk < GNUNET_MQ_PREFERENCE_COUNT); - p->bw_by_pk[pref->pk] += ntohl (pref->bw.value__); - h->bw_by_pk[pref->pk] += ntohl (pref->bw.value__); - update (h); - return NULL; -} - - -/** - * The plugin should end respecting a preference. - * - * @param cls the closure - * @param ph whatever @e preference_add returned - * @param pref the preference to delete - * @return plugin's internal representation, or NULL - */ -static void -simple_preference_del (void *cls, - struct GNUNET_ATS_PreferenceHandle *ph, - const struct GNUNET_ATS_Preference *pref) -{ - struct SimpleHandle *h = cls; - struct Peer *p = lookup_peer (h, &pref->peer); - - GNUNET_assert (NULL != p); - GNUNET_assert (pref->pk < GNUNET_MQ_PREFERENCE_COUNT); - p->bw_by_pk[pref->pk] -= ntohl (pref->bw.value__); - h->bw_by_pk[pref->pk] -= ntohl (pref->bw.value__); - if ((0 == p->bw_by_pk[pref->pk]) && (GNUNET_YES == peer_test_dead (p))) - peer_free (p); - update (h); -} - - -/** - * Transport established a new session with performance - * characteristics given in @a data. - * - * @param cls closure - * @param data performance characteristics of @a sh - * @param address address information (for debugging) - * @return handle by which the plugin will identify this session - */ -static struct GNUNET_ATS_SessionHandle * -simple_session_add (void *cls, - const struct GNUNET_ATS_SessionData *data, - const char *address) -{ - struct SimpleHandle *h = cls; - struct Peer *p = peer_add (h, &data->peer); - struct Hello *hello; - size_t alen; - struct GNUNET_ATS_SessionHandle *sh; - - /* setup session handle */ - GNUNET_assert (NULL != data); - if (NULL == address) - alen = 0; - else - alen = strlen (address) + 1; - sh = GNUNET_malloc (sizeof(struct GNUNET_ATS_SessionHandle) + alen); - sh->peer = p; - sh->session = data->session; - sh->data = data; - if (NULL == address) - { - sh->address = NULL; - } - else - { - memcpy (&sh[1], address, alen); - sh->address = (const char *) &sh[1]; - } - GNUNET_CONTAINER_DLL_insert (p->sh_head, p->sh_tail, sh); - if (NULL != address) - { - /* match HELLO */ - hello = p->h_head; - while ((NULL != hello) && (0 != strcmp (address, hello->address))) - hello = hello->next; - if (NULL != hello) - { - hello->sh = sh; - hello->backoff = GNUNET_TIME_UNIT_ZERO; - sh->hello = hello; - } - } - update (h); - return sh; -} - - -/** - * @a data changed for a given @a sh, solver should consider - * the updated performance characteristics. - * - * @param cls closure - * @param sh session this is about - * @param data performance characteristics of @a sh - */ -static void -simple_session_update (void *cls, - struct GNUNET_ATS_SessionHandle *sh, - const struct GNUNET_ATS_SessionData *data) -{ - struct SimpleHandle *h = cls; - - GNUNET_assert (NULL != data); - sh->data = data; /* this statement should not really do anything... */ - update (h); -} - - -/** - * A session went away. Solver should update accordingly. - * - * @param cls closure - * @param sh session this is about - * @param data (last) performance characteristics of @a sh - */ -static void -simple_session_del (void *cls, - struct GNUNET_ATS_SessionHandle *sh, - const struct GNUNET_ATS_SessionData *data) -{ - struct SimpleHandle *h = cls; - struct Peer *p = sh->peer; - struct Hello *hello = sh->hello; - - /* clean up sh */ - GNUNET_CONTAINER_DLL_remove (p->sh_head, p->sh_tail, sh); - if (NULL != hello) - { - GNUNET_assert (sh == hello->sh); - hello->sh = NULL; - /* session went down, if necessary restart suggesting - addresses */ - if (NULL == p->task) - p->task = GNUNET_SCHEDULER_add_now (&suggest_start_cb, p); - } - GNUNET_free (sh); - /* del peer if otherwise dead */ - if ((NULL == p->sh_head) && (GNUNET_YES == peer_test_dead (p))) - peer_free (p); - update (h); -} - - -#include "plugin_ats2_common.c" - - -/** - * Function invoked when the plugin is loaded. - * - * @param[in,out] cls the `struct GNUNET_ATS_PluginEnvironment *` to use; - * modified to return the API functions (ugh). - * @return the `struct SimpleHandle` to pass as a closure - */ -void * -libgnunet_plugin_ats2_simple_init (void *cls) -{ - static struct GNUNET_ATS_SolverFunctions sf; - struct GNUNET_ATS_PluginEnvironment *env = cls; - struct SimpleHandle *s; - - s = GNUNET_new (struct SimpleHandle); - s->env = env; - s->peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES); - s->ps = GNUNET_PEERSTORE_connect (env->cfg); - sf.cls = s; - sf.preference_add = &simple_preference_add; - sf.preference_del = &simple_preference_del; - sf.session_add = &simple_session_add; - sf.session_update = &simple_session_update; - sf.session_del = &simple_session_del; - for (enum GNUNET_NetworkType nt = 0; nt < GNUNET_NT_COUNT; nt++) - { - const char *name = GNUNET_NT_to_string (nt); - - if (NULL == name) - { - GNUNET_break (0); - break; - } - get_quota (env->cfg, name, "IN", &s->networks[nt].total_quota_in); - get_quota (env->cfg, name, "OUT", &s->networks[nt].total_quota_out); - s->networks[nt].type = nt; - } - return &sf; -} - - -/** - * Function used to unload the plugin. - * - * @param cls return value from #libgnunet_plugin_ats_proportional_init() - */ -void * -libgnunet_plugin_ats2_simple_done (void *cls) -{ - struct GNUNET_ATS_SolverFunctions *sf = cls; - struct SimpleHandle *s = sf->cls; - - GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (s->peers)); - GNUNET_CONTAINER_multipeermap_destroy (s->peers); - GNUNET_PEERSTORE_disconnect (s->ps, GNUNET_NO); - GNUNET_free (s); - return NULL; -} - - -/* end of plugin_ats2_simple.c */ diff --git a/src/ats/plugin_ats_mlp.c b/src/ats/plugin_ats_mlp.c deleted file mode 100644 index 6ab823b1e..000000000 --- a/src/ats/plugin_ats_mlp.c +++ /dev/null @@ -1,2924 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2011-2014 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file ats/plugin_ats_mlp.c - * @brief ats mlp problem solver - * @author Matthias Wachs - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_ats_service.h" -#include "gnunet_ats_plugin.h" -#include "gnunet-service-ats_addresses.h" -#include "gnunet_statistics_service.h" -#include -#include - - -#define BIG_M_VALUE (UINT32_MAX) / 10 -#define BIG_M_STRING "unlimited" - -#define MLP_AVERAGING_QUEUE_LENGTH 3 - -#define MLP_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_SECONDS, 10) -#define MLP_MAX_ITERATIONS 4096 - -#define MLP_DEFAULT_D 1.0 -#define MLP_DEFAULT_R 1.0 -#define MLP_DEFAULT_U 1.0 -#define MLP_DEFAULT_QUALITY 1.0 -#define MLP_DEFAULT_MIN_CONNECTIONS 4 -#define MLP_DEFAULT_PEER_PREFERENCE 1.0 - -#define MLP_NaN -1 -#define MLP_UNDEFINED 0 -#define GLP_YES 1.0 -#define GLP_NO 0.0 - -enum MLP_Output_Format -{ - MLP_MPS, - MLP_CPLEX, - MLP_GLPK -}; - - -enum QualityMetrics -{ - RQ_QUALITY_METRIC_DELAY = 0, - RQ_QUALITY_METRIC_DISTANCE = 1, - RQ_QUALITY_METRIC_COUNT = 2 -}; - - -static const char * -print_quality_type (enum QualityMetrics qm) -{ - switch (qm) - { - case RQ_QUALITY_METRIC_DELAY: - return "delay"; - - case RQ_QUALITY_METRIC_DISTANCE: - return "distance"; - - default: - GNUNET_break (0); - return NULL; - } -} - - -struct MLP_Solution -{ - int lp_res; - int lp_presolv; - int mip_res; - int mip_presolv; - - double lp_objective_value; - double mlp_objective_value; - double mlp_gap; - double lp_mlp_gap; - - int p_elements; - int p_cols; - int p_rows; - - int n_peers; - int n_addresses; -}; - -struct ATS_Peer -{ - struct GNUNET_PeerIdentity id; - - /* Was this peer already added to the current problem? */ - int processed; - - /* constraint 2: 1 address per peer*/ - unsigned int r_c2; - - /* constraint 9: relativity */ - unsigned int r_c9; - - /* Legacy preference value */ - double f; -}; - -struct MLP_Problem -{ - /** - * GLPK (MLP) problem object - */ - glp_prob *prob; - - /* Number of addresses in problem */ - unsigned int num_addresses; - /* Number of peers in problem */ - unsigned int num_peers; - /* Number of elements in problem matrix */ - unsigned int num_elements; - - /* Row index constraint 2: */ - unsigned int r_c2; - /* Row index constraint 4: minimum connections */ - unsigned int r_c4; - /* Row index constraint 6: maximize diversity */ - unsigned int r_c6; - /* Row index constraint 8: utilization*/ - unsigned int r_c8; - /* Row index constraint 9: relativity*/ - unsigned int r_c9; - /* Row indices quality metrics */ - int r_q[RQ_QUALITY_METRIC_COUNT]; - /* Row indices ATS network quotas */ - int r_quota[GNUNET_NT_COUNT]; - - /* Column index Diversity (D) column */ - int c_d; - /* Column index Utilization (U) column */ - int c_u; - /* Column index Proportionality (R) column */ - int c_r; - /* Column index quality metrics */ - int c_q[RQ_QUALITY_METRIC_COUNT]; - - /* Problem matrix */ - /* Current index */ - unsigned int ci; - /* Row index array */ - int *ia; - /* Column index array */ - int *ja; - /* Column index value */ - double *ar; -}; - -struct MLP_Variables -{ - /* Big M value for bandwidth capping */ - double BIG_M; - - /* MIP Gap */ - double mip_gap; - - /* LP MIP Gap */ - double lp_mip_gap; - - /* Number of quality metrics @deprecated, use RQ_QUALITY_METRIC_COUNT */ - int m_q; - - /* Number of quality metrics */ - int m_rc; - - /* Quality metric coefficients*/ - double co_Q[RQ_QUALITY_METRIC_COUNT]; - - /* Ressource costs coefficients*/ - double co_RC[RQ_QUALITY_METRIC_COUNT]; - - /* Diversity coefficient */ - double co_D; - - /* Utility coefficient */ - double co_U; - - /* Relativity coefficient */ - double co_R; - - /* Minimum bandwidth assigned to an address */ - unsigned int b_min; - - /* Minimum number of addresses with bandwidth assigned */ - unsigned int n_min; - - /* Quotas */ - /* Array mapping array index to ATS network */ - int quota_index[GNUNET_NT_COUNT]; - /* Outbound quotas */ - unsigned long long quota_out[GNUNET_NT_COUNT]; - /* Inbound quotas */ - - unsigned long long quota_in[GNUNET_NT_COUNT]; - - /* ATS ressource costs - * array with GNUNET_ATS_QualityPropertiesCount elements - * contains mapping to GNUNET_ATS_Property - * */ - int rc[RQ_QUALITY_METRIC_COUNT]; -}; - -/** - * MLP Handle - */ -struct GAS_MLP_Handle -{ - struct GNUNET_ATS_PluginEnvironment *env; - - /** - * Exclude peer from next result propagation - */ - const struct GNUNET_PeerIdentity *exclude_peer; - - /** - * Encapsulation for the MLP problem - */ - struct MLP_Problem p; - - /** - * Encapsulation for the MLP problem variables - */ - struct MLP_Variables pv; - - /** - * Encapsulation for the MLP solution - */ - struct MLP_Solution ps; - - /** - * Bulk lock - */ - int stat_bulk_lock; - - /** - * Number of changes while solver was locked - */ - int stat_bulk_requests; - - /** - * GLPK LP control parameter - */ - glp_smcp control_param_lp; - - /** - * GLPK LP control parameter - */ - glp_iocp control_param_mlp; - - /** - * Peers with pending address requests - */ - struct GNUNET_CONTAINER_MultiPeerMap *requested_peers; - - /** - * Was the problem updated since last solution - */ - int stat_mlp_prob_updated; - - /** - * Has the problem size changed since last solution - */ - int stat_mlp_prob_changed; - - /** - * Solve the problem automatically when updates occur? - * Default: GNUNET_YES - * Can be disabled for test and measurements - */ - int opt_mlp_auto_solve; - - /** - * Write all MILP problems to a MPS file - */ - int opt_dump_problem_all; - - /** - * Write all MILP problem solutions to a file - */ - int opt_dump_solution_all; - - /** - * Write MILP problems to a MPS file when solver fails - */ - int opt_dump_problem_on_fail; - - /** - * Write MILP problem solutions to a file when solver fails - */ - int opt_dump_solution_on_fail; - - /** - * solve feasibility only - */ - int opt_dbg_feasibility_only; - - /** - * solve autoscale the problem - */ - int opt_dbg_autoscale_problem; - - /** - * use the intopt presolver instead of simplex - */ - int opt_dbg_intopt_presolver; - - /** - * Print GLPK output - */ - int opt_dbg_glpk_verbose; - - /** - * solve autoscale the problem - */ - int opt_dbg_optimize_relativity; - - /** - * solve autoscale the problem - */ - int opt_dbg_optimize_diversity; - - /** - * solve autoscale the problem - */ - int opt_dbg_optimize_quality; - - /** - * solve autoscale the problem - */ - int opt_dbg_optimize_utility; - - - /** - * Output format - */ - enum MLP_Output_Format opt_log_format; -}; - -/** - * Address specific MLP information - */ -struct MLP_information -{ - /** - * Bandwidth assigned outbound - */ - uint32_t b_out; - - /** - * Bandwidth assigned inbound - */ - uint32_t b_in; - - /** - * Address selected - */ - int n; - - /** - * bandwidth column index - */ - signed int c_b; - - /** - * address usage column - */ - signed int c_n; - - /* row indexes */ - - /** - * constraint 1: bandwidth capping - */ - unsigned int r_c1; - - /** - * constraint 3: minimum bandwidth - */ - unsigned int r_c3; -}; - - - -/** - * - * NOTE: Do not modify this documentation. This documentation is based on - * gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex - * use build_txt.sh to generate plaintext output - * - * The MLP solver (mlp) tries to finds an optimal bandwidth assignmentby - * optimizing an mixed integer programming problem. The MLP solver uses a - * number of constraints to find the best adddress for a peer and an optimal - * bandwidth assignment. mlp uses the GNU Linear Programming Kit to solve the - * MLP problem. - * - * We defined a constraint system to find an optimal bandwidth assignment. - * This constraint system uses as an input data addresses, bandwidth quotas, - * preferences and quality values. This constraint system is stored in an - * matrix based equotation system. - * - * 5 Using GLPK - * - * A (M)LP problem consists of a target function to optimizes, constraints - * and rows and columns. FIXME GLP uses three arrays to index the matrix: two - * integer arrays storing the row and column indices in the matrix and an - * float array to store the coeeficient. - * - * To solve the problem we first find an initial solution for the LP problem - * using the LP solver and then find an MLP solution based on this solution - * using the MLP solver. - * - * Solving (M)LP problems has the property that finding an initial solution - * for the LP problem is computationally expensive and finding the MLP - * solution is cheaper. This is especially interesting an existing LP - * solution can be reused if only coefficients in the matrix have changed - * (addresses updated). Only when the problem size changes (addresses added - * or deleted) a new LP solution has to be found. - * - * Intended usage - * The mlp solver solves the bandwidth assignment problem only on demand when - * an address suggestion is requested. When an address is requested mlp the - * solves the mlp problem and if the active address or the bandwidth assigned - * changes it calls the callback to addresses. The mlp solver gets notified - * about new addresses (adding sessions), removed addresses (address - * deletions) and address updates. To benefit from the mlp properties - * mentioned in section 5 the solver rembers if since the last solution - * addresses were added or deleted (problem size changed, problem has to be - * rebuild and solved from sratch) or if addresses were updated and the - * existing solution can be reused. - * - * 5.1 Input data - * - * The quotas for each network segment are passed by addresses. MLP can be - * adapted using configuration settings and uses the following parameters: - * * MLP_MAX_DURATION: - * Maximum duration for a MLP solution procees (default: 3 sec.) - * * MLP_MAX_ITERATIONS: - * Maximum number of iterations for a MLP solution process (default: - * 1024) - * * MLP_MIN_CONNECTIONS: - * Minimum number of desired connections (default: 4) - * * MLP_MIN_BANDWIDTH: - * Minimum amount of bandwidth assigned to an address (default: 1024) - * * MLP_COEFFICIENT_D: - * Diversity coefficient (default: 1.0) - * * MLP_COEFFICIENT_R: - * Relativity coefficient (default: 1.0) - * * MLP_COEFFICIENT_U: - * Utilization coefficient (default: 1.0) - * * MLP_COEFFICIENT_D: - * Diversity coefficient (default: 1.0) - * * MLP_COEFFICIENT_QUALITY_DELAY: - * Quality delay coefficient (default: 1.0) - * * MLP_COEFFICIENT_QUALITY_DISTANCE: - * Quality distance coefficient (default: 1.0) - * * MLP_COEFFICIENT_QUALITY_DISTANCE: - * Quality distance coefficient (default: 1.0) - * * MLP_COEFFICIENT_QUALITY_DISTANCE: - * Quality distance coefficient (default: 1.0) - * * MLP_COEFFICIENT_QUALITY_DISTANCE: - * Quality distance coefficient (default: 1.0) - * - * 5.2 Data structures used - * - * mlp has for each known peer a struct ATS_Peer containing information about - * a specific peer. The address field solver_information contains information - * about the mlp properties of this address. - * - * 5.3 Initializing - * - * During initialization mlp initializes the GLPK libray used to solve the - * MLP problem: it initializes the glpk environment and creates an initial LP - * problem. Next it loads the configuration values from the configuration or - * uses the default values configured in -addresses_mlp.h. The quotas used - * are given by addresses but may have to be adjusted. mlp uses a upper limit - * for the bandwidth assigned called BIG M and a minimum amount of bandwidth - * an address gets assigned as well as a minium desired number of - * connections. If the configured quota is bigger than BIG M, it is reduced - * to BIG M. If the configured quota is smaller than MLP_MIN_CONNECTIONS - * *MLP_MIN_BANDWIDTH it is increased to this value. - * - * 5.4 Shutdown - - */ - -#define LOG(kind, ...) GNUNET_log_from (kind, "ats-mlp", __VA_ARGS__) - -/** - * Print debug output for mlp problem creation - */ -#define DEBUG_MLP_PROBLEM_CREATION GNUNET_NO - - -/** - * Intercept GLPK terminal output - * @param info the mlp handle - * @param s the string to print - * @return 0: glpk prints output on terminal, 0 != surpress output - */ -static int -mlp_term_hook (void *info, const char *s) -{ - struct GAS_MLP_Handle *mlp = info; - - if (mlp->opt_dbg_glpk_verbose) - LOG (GNUNET_ERROR_TYPE_ERROR, "%s", s); - return 1; -} - - -/** - * Reset peers for next problem creation - * - * @param cls not used - * @param key the key - * @param value ATS_Peer - * @return #GNUNET_OK - */ -static int -reset_peers (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) -{ - struct ATS_Peer *peer = value; - - peer->processed = GNUNET_NO; - return GNUNET_OK; -} - -/** - * Delete the MLP problem and free the constrain matrix - * - * @param mlp the MLP handle - */ -static void -mlp_delete_problem (struct GAS_MLP_Handle *mlp) -{ - int c; - - if (mlp == NULL) - return; - if (mlp->p.prob != NULL) - { - glp_delete_prob (mlp->p.prob); - mlp->p.prob = NULL; - } - - /* delete row index */ - if (mlp->p.ia != NULL) - { - GNUNET_free (mlp->p.ia); - mlp->p.ia = NULL; - } - - /* delete column index */ - if (mlp->p.ja != NULL) - { - GNUNET_free (mlp->p.ja); - mlp->p.ja = NULL; - } - - /* delete coefficients */ - if (mlp->p.ar != NULL) - { - GNUNET_free (mlp->p.ar); - mlp->p.ar = NULL; - } - mlp->p.ci = 0; - mlp->p.prob = NULL; - - mlp->p.c_d = MLP_UNDEFINED; - mlp->p.c_r = MLP_UNDEFINED; - mlp->p.r_c2 = MLP_UNDEFINED; - mlp->p.r_c4 = MLP_UNDEFINED; - mlp->p.r_c6 = MLP_UNDEFINED; - mlp->p.r_c9 = MLP_UNDEFINED; - for (c = 0; c < RQ_QUALITY_METRIC_COUNT; c++) - mlp->p.r_q[c] = MLP_UNDEFINED; - for (c = 0; c < GNUNET_NT_COUNT; c++) - mlp->p.r_quota[c] = MLP_UNDEFINED; - mlp->p.ci = MLP_UNDEFINED; - - - GNUNET_CONTAINER_multipeermap_iterate (mlp->requested_peers, - &reset_peers, NULL); -} - - -/** - * Translate glpk status error codes to text - * @param retcode return code - * @return string with result - */ -static const char * -mlp_status_to_string (int retcode) -{ - switch (retcode) - { - case GLP_UNDEF: - return "solution is undefined"; - - case GLP_FEAS: - return "solution is feasible"; - - case GLP_INFEAS: - return "solution is infeasible"; - - case GLP_NOFEAS: - return "no feasible solution exists"; - - case GLP_OPT: - return "solution is optimal"; - - case GLP_UNBND: - return "solution is unbounded"; - - default: - GNUNET_break (0); - return "unknown error"; - } -} - - -/** - * Translate glpk solver error codes to text - * @param retcode return code - * @return string with result - */ -static const char * -mlp_solve_to_string (int retcode) -{ - switch (retcode) - { - case 0: - return "ok"; - - case GLP_EBADB: - return "invalid basis"; - - case GLP_ESING: - return "singular matrix"; - - case GLP_ECOND: - return "ill-conditioned matrix"; - - case GLP_EBOUND: - return "invalid bounds"; - - case GLP_EFAIL: - return "solver failed"; - - case GLP_EOBJLL: - return "objective lower limit reached"; - - case GLP_EOBJUL: - return "objective upper limit reached"; - - case GLP_EITLIM: - return "iteration limit exceeded"; - - case GLP_ETMLIM: - return "time limit exceeded"; - - case GLP_ENOPFS: - return "no primal feasible solution"; - - case GLP_ENODFS: - return "no dual feasible solution"; - - case GLP_EROOT: - return "root LP optimum not provided"; - - case GLP_ESTOP: - return "search terminated by application"; - - case GLP_EMIPGAP: - return "relative mip gap tolerance reached"; - - case GLP_ENOFEAS: - return "no dual feasible solution"; - - case GLP_ENOCVG: - return "no convergence"; - - case GLP_EINSTAB: - return "numerical instability"; - - case GLP_EDATA: - return "invalid data"; - - case GLP_ERANGE: - return "result out of range"; - - default: - GNUNET_break (0); - return "unknown error"; - } -} - - -struct CountContext -{ - const struct GNUNET_CONTAINER_MultiPeerMap *map; - int result; -}; - -static int -mlp_create_problem_count_addresses_it (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) -{ - struct CountContext *cctx = cls; - - /* Check if we have to add this peer due to a pending request */ - if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (cctx->map, key)) - cctx->result++; - return GNUNET_OK; -} - - -static int -mlp_create_problem_count_addresses (const struct - GNUNET_CONTAINER_MultiPeerMap * - requested_peers, - const struct - GNUNET_CONTAINER_MultiPeerMap *addresses) -{ - struct CountContext cctx; - - cctx.map = requested_peers; - cctx.result = 0; - GNUNET_CONTAINER_multipeermap_iterate (addresses, - &mlp_create_problem_count_addresses_it, - &cctx); - return cctx.result; -} - - -static int -mlp_create_problem_count_peers_it (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) -{ - struct CountContext *cctx = cls; - - /* Check if we have to addresses for the requested peer */ - if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (cctx->map, key)) - cctx->result++; - return GNUNET_OK; -} - - -static int -mlp_create_problem_count_peers (const struct - GNUNET_CONTAINER_MultiPeerMap *requested_peers, - const struct - GNUNET_CONTAINER_MultiPeerMap *addresses) -{ - struct CountContext cctx; - - cctx.map = addresses; - cctx.result = 0; - GNUNET_CONTAINER_multipeermap_iterate (requested_peers, - &mlp_create_problem_count_peers_it, - &cctx); - return cctx.result; -} - - -/** - * Updates an existing value in the matrix - * - * Extract the row, updates the value and updates the row in the problem - * - * @param p the mlp problem - * @param row the row to create the value in - * @param col the column to create the value in - * @param val the value to set - * @param line calling line for debbuging - * @return GNUNET_YES value changed, GNUNET_NO value did not change, GNUNET_SYSERR - * on error - */ -static int -mlp_create_problem_update_value (struct MLP_Problem *p, - int row, int col, double val, - int line) -{ - int c_cols; - int c_elems; - int c1; - int res; - int found; - double *val_array; - int *ind_array; - - GNUNET_assert (NULL != p->prob); - - /* Get number of columns and prepare data structure */ - c_cols = glp_get_num_cols (p->prob); - if (0 >= c_cols) - return GNUNET_SYSERR; - - val_array = GNUNET_malloc ((c_cols + 1) * sizeof(double)); - GNUNET_assert (NULL != val_array); - ind_array = GNUNET_malloc ((c_cols + 1) * sizeof(int)); - GNUNET_assert (NULL != ind_array); - /* Extract the row */ - - /* Update the value */ - c_elems = glp_get_mat_row (p->prob, row, ind_array, val_array); - found = GNUNET_NO; - for (c1 = 1; c1 < (c_elems + 1); c1++) - { - if (ind_array[c1] == col) - { - found = GNUNET_YES; - break; - } - } - if (GNUNET_NO == found) - { - ind_array[c_elems + 1] = col; - val_array[c_elems + 1] = val; - LOG (GNUNET_ERROR_TYPE_DEBUG, "[P] Setting value in [%s : %s] to `%.2f'\n", - glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col), - val); - glp_set_mat_row (p->prob, row, c_elems + 1, ind_array, val_array); - GNUNET_free (ind_array); - GNUNET_free (val_array); - return GNUNET_YES; - } - else - { - /* Update value */ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "[P] Updating value in [%s : %s] from `%.2f' to `%.2f'\n", - glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col), - val_array[c1], val); - if (val != val_array[c1]) - res = GNUNET_YES; - else - res = GNUNET_NO; - val_array[c1] = val; - /* Update the row in the matrix */ - glp_set_mat_row (p->prob, row, c_elems, ind_array, val_array); - } - - GNUNET_free (ind_array); - GNUNET_free (val_array); - return res; -} - -/** - * Creates a new value in the matrix - * - * Sets the row and column index in the problem array and increments the - * position field - * - * @param p the mlp problem - * @param row the row to create the value in - * @param col the column to create the value in - * @param val the value to set - * @param line calling line for debbuging - */ -static void -mlp_create_problem_set_value (struct MLP_Problem *p, - int row, int col, double val, - int line) -{ - if ((p->ci) >= p->num_elements) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "[P]: line %u: Request for index %u bigger than array size of %u\n", - line, p->ci + 1, p->num_elements); - GNUNET_break (0); - return; - } - if ((0 == row) || (0 == col)) - { - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_ERROR, - "[P]: Invalid call from line %u: row = %u, col = %u\n", - line, row, col); - } - p->ia[p->ci] = row; - p->ja[p->ci] = col; - p->ar[p->ci] = val; -#if DEBUG_MLP_PROBLEM_CREATION - LOG (GNUNET_ERROR_TYPE_DEBUG, - "[P]: line %u: Set value [%u,%u] in index %u == %.2f\n", - line, p->ia[p->ci], p->ja[p->ci], p->ci, p->ar[p->ci]); -#endif - p->ci++; -} - -static int -mlp_create_problem_create_column (struct MLP_Problem *p, char *name, - unsigned int type, unsigned int bound, double - lb, double ub, - double coef) -{ - int col = glp_add_cols (p->prob, 1); - - glp_set_col_name (p->prob, col, name); - glp_set_col_bnds (p->prob, col, bound, lb, ub); - glp_set_col_kind (p->prob, col, type); - glp_set_obj_coef (p->prob, col, coef); -#if DEBUG_MLP_PROBLEM_CREATION - LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added column [%u] `%s': %.2f\n", - col, name, coef); -#endif - return col; -} - -static int -mlp_create_problem_create_constraint (struct MLP_Problem *p, char *name, - unsigned int bound, double lb, double ub) -{ - char *op; - int row = glp_add_rows (p->prob, 1); - - /* set row name */ - glp_set_row_name (p->prob, row, name); - /* set row bounds: <= 0 */ - glp_set_row_bnds (p->prob, row, bound, lb, ub); - switch (bound) - { - case GLP_UP: - GNUNET_asprintf (&op, "-inf <= x <= %.2f", ub); - break; - - case GLP_DB: - GNUNET_asprintf (&op, "%.2f <= x <= %.2f", lb, ub); - break; - - case GLP_FX: - GNUNET_asprintf (&op, "%.2f == x == %.2f", lb, ub); - break; - - case GLP_LO: - GNUNET_asprintf (&op, "%.2f <= x <= inf", lb); - break; - - default: - GNUNET_asprintf (&op, "ERROR"); - break; - } -#if DEBUG_MLP_PROBLEM_CREATION - LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added row [%u] `%s': %s\n", - row, name, op); -#endif - GNUNET_free (op); - return row; -} - -/** - * Create the - * - address columns b and n - * - address dependent constraint rows c1, c3 - * - peer dependent rows c2 and c9 - * - Set address dependent entries in problem matrix as well - */ -static int -mlp_create_problem_add_address_information (void *cls, - const struct - GNUNET_PeerIdentity *key, - void *value) -{ - struct GAS_MLP_Handle *mlp = cls; - struct MLP_Problem *p = &mlp->p; - struct ATS_Address *address = value; - struct ATS_Peer *peer; - struct MLP_information *mlpi; - char *name; - double cur_bigm; - uint32_t addr_net; - uint32_t addr_net_index; - unsigned long long max_quota; - int c; - - /* Check if we have to add this peer due to a pending request */ - if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (mlp->requested_peers, - key)) - return GNUNET_OK; - - mlpi = address->solver_information; - if (NULL == mlpi) - { - fprintf (stderr, "%s %p\n", GNUNET_i2s (&address->peer), address); - GNUNET_break (0); - return GNUNET_OK; - } - - addr_net = address->properties.scope; - for (addr_net_index = 0; addr_net_index < GNUNET_NT_COUNT; addr_net_index++) - { - if (mlp->pv.quota_index[addr_net_index] == addr_net) - break; - } - - if (addr_net_index >= GNUNET_NT_COUNT) - { - GNUNET_break (0); - return GNUNET_OK; - } - - max_quota = 0; - for (c = 0; c < GNUNET_NT_COUNT; c++) - { - if (mlp->pv.quota_out[c] > max_quota) - max_quota = mlp->pv.quota_out[c]; - if (mlp->pv.quota_in[c] > max_quota) - max_quota = mlp->pv.quota_in[c]; - } - if (max_quota > mlp->pv.BIG_M) - cur_bigm = (double) mlp->pv.BIG_M; - else - cur_bigm = max_quota; - - - /* Get peer */ - peer = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, key); - GNUNET_assert (NULL != peer); - if (peer->processed == GNUNET_NO) - { - /* Add peer dependent constraints */ - /* Add c2) One address active per peer */ - GNUNET_asprintf (&name, "c2_%s", GNUNET_i2s (&address->peer)); - peer->r_c2 = mlp_create_problem_create_constraint (p, name, GLP_FX, 1.0, - 1.0); - GNUNET_free (name); - if (GNUNET_NO == mlp->opt_dbg_feasibility_only) - { - if (GNUNET_YES == mlp->opt_dbg_optimize_relativity) - { - /* Add c9) Relativity */ - GNUNET_asprintf (&name, "c9_%s", GNUNET_i2s (&address->peer)); - peer->r_c9 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, - 0.0); - GNUNET_free (name); - /* c9) set coefficient */ - mlp_create_problem_set_value (p, peer->r_c9, p->c_r, -peer->f, - __LINE__); - } - } - peer->processed = GNUNET_YES; - } - - /* Reset addresses' solver information */ - mlpi->c_b = 0; - mlpi->c_n = 0; - mlpi->n = 0; - mlpi->r_c1 = 0; - mlpi->r_c3 = 0; - - /* Add bandwidth column */ - GNUNET_asprintf (&name, "b_%s_%s_%p", GNUNET_i2s (&address->peer), - address->plugin, address); - if (GNUNET_NO == mlp->opt_dbg_feasibility_only) - { - mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, - 0.0, 0.0); - } - else - { - /* Maximize for bandwidth assignment in feasibility testing */ - mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, - 0.0, 1.0); - } - GNUNET_free (name); - - /* Add address active column */ - GNUNET_asprintf (&name, "n_%s_%s_%p", GNUNET_i2s (&address->peer), - address->plugin, address); - mlpi->c_n = mlp_create_problem_create_column (p, name, GLP_IV, GLP_DB, 0.0, - 1.0, 0.0); - GNUNET_free (name); - - /* Add address dependent constraints */ - /* Add c1) bandwidth capping: b_t + (-M) * n_t <= 0 */ - GNUNET_asprintf (&name, "c1_%s_%s_%p", GNUNET_i2s (&address->peer), - address->plugin, address); - mlpi->r_c1 = mlp_create_problem_create_constraint (p, name, GLP_UP, 0.0, 0.0); - GNUNET_free (name); - /* c1) set b = 1 coefficient */ - mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_b, 1, __LINE__); - /* c1) set n = - min (M, quota) coefficient */ - cur_bigm = (double) mlp->pv.quota_out[addr_net_index]; - if (cur_bigm > mlp->pv.BIG_M) - cur_bigm = (double) mlp->pv.BIG_M; - mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_n, -cur_bigm, __LINE__); - - /* Add constraint c 3) minimum bandwidth - * b_t + (-n_t * b_min) >= 0 - * */ - GNUNET_asprintf (&name, "c3_%s_%s_%p", GNUNET_i2s (&address->peer), - address->plugin, address); - mlpi->r_c3 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, 0.0); - GNUNET_free (name); - - /* c3) set b = 1 coefficient */ - mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_b, 1, __LINE__); - /* c3) set n = -b_min coefficient */ - mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_n, - -((double ) mlp->pv.b_min), __LINE__); - - - /* Set coefficient entries in invariant rows */ - - /* Feasbility */ - - /* c 4) minimum connections */ - mlp_create_problem_set_value (p, p->r_c4, mlpi->c_n, 1, __LINE__); - /* c 2) 1 address peer peer */ - mlp_create_problem_set_value (p, peer->r_c2, mlpi->c_n, 1, __LINE__); - /* c 10) obey network specific quotas - * (1)*b_1 + ... + (1)*b_m <= quota_n - */ - mlp_create_problem_set_value (p, p->r_quota[addr_net_index], mlpi->c_b, 1, - __LINE__); - - /* Optimality */ - if (GNUNET_NO == mlp->opt_dbg_feasibility_only) - { - /* c 6) maximize diversity */ - mlp_create_problem_set_value (p, p->r_c6, mlpi->c_n, 1, __LINE__); - /* c 9) relativity */ - if (GNUNET_YES == mlp->opt_dbg_optimize_relativity) - mlp_create_problem_set_value (p, peer->r_c9, mlpi->c_b, 1, __LINE__); - /* c 8) utility */ - if (GNUNET_YES == mlp->opt_dbg_optimize_utility) - mlp_create_problem_set_value (p, p->r_c8, mlpi->c_b, 1, __LINE__); - /* c 7) Optimize quality */ - /* For all quality metrics, set quality of this address */ - if (GNUNET_YES == mlp->opt_dbg_optimize_quality) - { - mlp_create_problem_set_value (p, - p->r_q[RQ_QUALITY_METRIC_DELAY], - mlpi->c_b, - address->norm_delay.norm, - __LINE__); - mlp_create_problem_set_value (p, - p->r_q[RQ_QUALITY_METRIC_DISTANCE], - mlpi->c_b, - address->norm_distance.norm, - __LINE__); - } - } - - return GNUNET_OK; -} - - -/** - * Create the invariant columns c4, c6, c10, c8, c7 - */ -static void -mlp_create_problem_add_invariant_rows (struct GAS_MLP_Handle *mlp, struct - MLP_Problem *p) -{ - int c; - - /* Feasibility */ - - /* Row for c4) minimum connection */ - /* Number of minimum connections is min(|Peers|, n_min) */ - p->r_c4 = mlp_create_problem_create_constraint (p, "c4", GLP_LO, - (mlp->pv.n_min > - p->num_peers) ? - p->num_peers : mlp->pv.n_min, - 0.0); - - /* Rows for c 10) Enforce network quotas */ - for (c = 0; c < GNUNET_NT_COUNT; c++) - { - char *text; - GNUNET_asprintf (&text, "c10_quota_ats_%s", - GNUNET_NT_to_string (mlp->pv.quota_index[c])); - p->r_quota[c] = mlp_create_problem_create_constraint (p, text, GLP_DB, 0.0, - mlp->pv.quota_out[c]); - GNUNET_free (text); - } - - /* Optimality */ - if (GNUNET_NO == mlp->opt_dbg_feasibility_only) - { - char *name; - /* Add row for c6) Maximize for diversity */ - if (GNUNET_YES == mlp->opt_dbg_optimize_diversity) - { - p->r_c6 = mlp_create_problem_create_constraint (p, "c6", GLP_FX, 0.0, - 0.0); - /* Set c6 ) Setting -D */ - mlp_create_problem_set_value (p, p->r_c6, p->c_d, -1, __LINE__); - } - - /* Adding rows for c 8) Maximize utility */ - if (GNUNET_YES == mlp->opt_dbg_optimize_utility) - { - p->r_c8 = mlp_create_problem_create_constraint (p, "c8", GLP_FX, 0.0, - 0.0); - /* -u */ - mlp_create_problem_set_value (p, p->r_c8, p->c_u, -1, __LINE__); - } - - /* For all quality metrics: - * c 7) Maximize quality, austerity */ - if (GNUNET_YES == mlp->opt_dbg_optimize_quality) - { - for (c = 0; c < mlp->pv.m_q; c++) - { - GNUNET_asprintf (&name, - "c7_q%i_%s", c, - print_quality_type (c)); - p->r_q[c] = mlp_create_problem_create_constraint (p, name, GLP_FX, 0.0, - 0.0); - GNUNET_free (name); - mlp_create_problem_set_value (p, - p->r_q[c], - p->c_q[c], -1, __LINE__); - } - } - } -} - - -/** - * Create the invariant columns d, u, r, q0 ... qm - */ -static void -mlp_create_problem_add_invariant_columns (struct GAS_MLP_Handle *mlp, struct - MLP_Problem *p) -{ - if (GNUNET_NO == mlp->opt_dbg_feasibility_only) - { - char *name; - int c; - - /* Diversity d column */ - if (GNUNET_YES == mlp->opt_dbg_optimize_diversity) - p->c_d = mlp_create_problem_create_column (p, "d", GLP_CV, GLP_LO, 0.0, - 0.0, mlp->pv.co_D); - - /* Utilization u column */ - if (GNUNET_YES == mlp->opt_dbg_optimize_utility) - p->c_u = mlp_create_problem_create_column (p, "u", GLP_CV, GLP_LO, 0.0, - 0.0, mlp->pv.co_U); - - /* Relativity r column */ - if (GNUNET_YES == mlp->opt_dbg_optimize_relativity) - p->c_r = mlp_create_problem_create_column (p, "r", GLP_CV, GLP_LO, 0.0, - 0.0, mlp->pv.co_R); - - /* Quality metric columns */ - if (GNUNET_YES == mlp->opt_dbg_optimize_quality) - { - for (c = 0; c < mlp->pv.m_q; c++) - { - GNUNET_asprintf (&name, "q_%u", c); - p->c_q[c] = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, - 0.0, 0.0, - mlp->pv.co_Q[c]); - GNUNET_free (name); - } - } - } -} - - -/** - * Create the MLP problem - * - * @param mlp the MLP handle - * @return #GNUNET_OK or #GNUNET_SYSERR - */ -static int -mlp_create_problem (struct GAS_MLP_Handle *mlp) -{ - struct MLP_Problem *p = &mlp->p; - int res = GNUNET_OK; - - GNUNET_assert (p->prob == NULL); - GNUNET_assert (p->ia == NULL); - GNUNET_assert (p->ja == NULL); - GNUNET_assert (p->ar == NULL); - /* Reset MLP problem struct */ - - /* create the glpk problem */ - p->prob = glp_create_prob (); - GNUNET_assert (NULL != p->prob); - p->num_peers = mlp_create_problem_count_peers (mlp->requested_peers, - mlp->env->addresses); - p->num_addresses = mlp_create_problem_count_addresses (mlp->requested_peers, - mlp->env->addresses); - - /* Create problem matrix: 10 * #addresses + #q * #addresses + #q, + #peer + 2 + 1 */ - p->num_elements = (10 * p->num_addresses + mlp->pv.m_q * p->num_addresses - + mlp->pv.m_q + p->num_peers + 2 + 1); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Rebuilding problem for %u peer(s) and %u addresse(s) and %u quality metrics == %u elements\n", - p->num_peers, - p->num_addresses, - mlp->pv.m_q, - p->num_elements); - - /* Set a problem name */ - glp_set_prob_name (p->prob, "GNUnet ATS bandwidth distribution"); - /* Set optimization direction to maximize */ - glp_set_obj_dir (p->prob, GLP_MAX); - - /* Create problem matrix */ - /* last +1 caused by glpk index starting with one: [1..elements]*/ - p->ci = 1; - /* row index */ - p->ia = GNUNET_malloc (p->num_elements * sizeof(int)); - /* column index */ - p->ja = GNUNET_malloc (p->num_elements * sizeof(int)); - /* coefficient */ - p->ar = GNUNET_malloc (p->num_elements * sizeof(double)); - - if ((NULL == p->ia) || (NULL == p->ja) || (NULL == p->ar)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ( - "Problem size too large, cannot allocate memory!\n")); - return GNUNET_SYSERR; - } - - /* Adding invariant columns */ - mlp_create_problem_add_invariant_columns (mlp, p); - - /* Adding address independent constraint rows */ - mlp_create_problem_add_invariant_rows (mlp, p); - - /* Adding address dependent columns constraint rows */ - GNUNET_CONTAINER_multipeermap_iterate (mlp->env->addresses, - & - mlp_create_problem_add_address_information, - mlp); - - /* Load the matrix */ - LOG (GNUNET_ERROR_TYPE_DEBUG, "Loading matrix\n"); - glp_load_matrix (p->prob, (p->ci) - 1, p->ia, p->ja, p->ar); - if (GNUNET_YES == mlp->opt_dbg_autoscale_problem) - { - glp_scale_prob (p->prob, GLP_SF_AUTO); - } - - return res; -} - - -/** - * Solves the LP problem - * - * @param mlp the MLP Handle - * @return #GNUNET_OK if could be solved, #GNUNET_SYSERR on failure - */ -static int -mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp) -{ - int res = 0; - int res_status = 0; - - res = glp_simplex (mlp->p.prob, &mlp->control_param_lp); - if (0 == res) - LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: %s\n", - mlp_solve_to_string (res)); - else - LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem failed: %s\n", - mlp_solve_to_string (res)); - - /* Analyze problem status */ - res_status = glp_get_status (mlp->p.prob); - switch (res_status) - { - case GLP_OPT: /* solution is optimal */ - LOG (GNUNET_ERROR_TYPE_INFO, - "Solving LP problem: %s, %s\n", - mlp_solve_to_string (res), - mlp_status_to_string (res_status)); - return GNUNET_OK; - - default: - LOG (GNUNET_ERROR_TYPE_ERROR, - "Solving LP problem failed: %s %s\n", - mlp_solve_to_string (res), - mlp_status_to_string (res_status)); - return GNUNET_SYSERR; - } -} - - -/** - * Propagates the results when MLP problem was solved - * - * @param cls the MLP handle - * @param key the peer identity - * @param value the address - * @return #GNUNET_OK to continue - */ -static int -mlp_propagate_results (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) -{ - struct GAS_MLP_Handle *mlp = cls; - struct ATS_Address *address; - struct MLP_information *mlpi; - double mlp_bw_in = MLP_NaN; - double mlp_bw_out = MLP_NaN; - double mlp_use = MLP_NaN; - - /* Check if we have to add this peer due to a pending request */ - if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (mlp->requested_peers, - key)) - { - return GNUNET_OK; - } - address = value; - GNUNET_assert (address->solver_information != NULL); - mlpi = address->solver_information; - - mlp_bw_in = glp_mip_col_val (mlp->p.prob, mlpi->c_b);/* FIXME */ - if (mlp_bw_in > (double) UINT32_MAX) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Overflow in assigned bandwidth, reducing ...\n"); - mlp_bw_in = (double) UINT32_MAX; - } - mlp_bw_out = glp_mip_col_val (mlp->p.prob, mlpi->c_b); - if (mlp_bw_out > (double) UINT32_MAX) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Overflow in assigned bandwidth, reducing ...\n"); - mlp_bw_out = (double) UINT32_MAX; - } - mlp_use = glp_mip_col_val (mlp->p.prob, mlpi->c_n); - - /* - * Debug: solution - * LOG (GNUNET_ERROR_TYPE_INFO, "MLP result address: `%s' `%s' length %u session %u, mlp use %.3f\n", - * GNUNET_i2s(&address->peer), address->plugin, - * address->addr_len, address->session_id); - */ - - if (GLP_YES == mlp_use) - { - /* This address was selected by the solver to be used */ - mlpi->n = GNUNET_YES; - if (GNUNET_NO == address->active) - { - /* Address was not used before, enabling address */ - LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : enabling address\n", - (1 == mlp_use) ? "[x]" : "[ ]", mlp_bw_out); - address->active = GNUNET_YES; - address->assigned_bw_in = mlp_bw_in; - mlpi->b_in = mlp_bw_in; - address->assigned_bw_out = mlp_bw_out; - mlpi->b_out = mlp_bw_out; - if ((NULL == mlp->exclude_peer) || (0 != GNUNET_memcmp (&address->peer, - mlp->exclude_peer))) - mlp->env->bandwidth_changed_cb (mlp->env->cls, address); - return GNUNET_OK; - } - else if (GNUNET_YES == address->active) - { - /* Address was used before, check for bandwidth change */ - if ((mlp_bw_out != address->assigned_bw_out) || - (mlp_bw_in != address->assigned_bw_in)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : bandwidth changed\n", - (1 == mlp_use) ? "[x]" : "[ ]", mlp_bw_out); - address->assigned_bw_in = mlp_bw_in; - mlpi->b_in = mlp_bw_in; - address->assigned_bw_out = mlp_bw_out; - mlpi->b_out = mlp_bw_out; - if ((NULL == mlp->exclude_peer) || (0 != GNUNET_memcmp (&address->peer, - mlp-> - exclude_peer))) - mlp->env->bandwidth_changed_cb (mlp->env->cls, address); - return GNUNET_OK; - } - } - else - GNUNET_break (0); - } - else if (GLP_NO == mlp_use) - { - /* This address was selected by the solver to be not used */ - mlpi->n = GNUNET_NO; - if (GNUNET_NO == address->active) - { - /* Address was not used before, nothing to do */ - LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : no change\n", - (1 == mlp_use) ? "[x]" : "[ ]", mlp_bw_out); - return GNUNET_OK; - } - else if (GNUNET_YES == address->active) - { - /* Address was used before, disabling address */ - LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : disabling address\n", - (1 == mlp_use) ? "[x]" : "[ ]", mlp_bw_out); - address->active = GNUNET_NO; - /* Set bandwidth to 0 */ - address->assigned_bw_in = 0; - mlpi->b_in = 0; - address->assigned_bw_out = 0; - mlpi->b_out = 0; - return GNUNET_OK; - } - else - GNUNET_break (0); - } - else - GNUNET_break (0); - - return GNUNET_OK; -} - - -static void -notify (struct GAS_MLP_Handle *mlp, - enum GAS_Solver_Operation op, - enum GAS_Solver_Status stat, - enum GAS_Solver_Additional_Information add) -{ - mlp->env->info_cb (mlp->env->cls, - op, - stat, - add); -} - - -static void -mlp_branch_and_cut_cb (glp_tree *tree, void *info) -{ - struct GAS_MLP_Handle *mlp = info; - double mlp_obj = 0; - - switch (glp_ios_reason (tree)) - { - case GLP_ISELECT: - /* Do nothing here */ - break; - - case GLP_IPREPRO: - /* Do nothing here */ - break; - - case GLP_IROWGEN: - /* Do nothing here */ - break; - - case GLP_IHEUR: - /* Do nothing here */ - break; - - case GLP_ICUTGEN: - /* Do nothing here */ - break; - - case GLP_IBRANCH: - /* Do nothing here */ - break; - - case GLP_IBINGO: - /* A better solution was found */ - mlp->ps.mlp_gap = glp_ios_mip_gap (tree); - mlp_obj = glp_mip_obj_val (mlp->p.prob); - mlp->ps.lp_mlp_gap = (abs (mlp_obj - mlp->ps.lp_objective_value)) / (abs ( - mlp_obj) - + - DBL_EPSILON); - - LOG (GNUNET_ERROR_TYPE_INFO, - "Found better integer solution, current gaps: %.3f <= %.3f, %.3f <= %.3f\n", - mlp->ps.mlp_gap, mlp->pv.mip_gap, - mlp->ps.lp_mlp_gap, mlp->pv.lp_mip_gap); - - if (mlp->ps.mlp_gap <= mlp->pv.mip_gap) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Current LP/MLP gap of %.3f smaller than tolerated gap of %.3f, terminating search\n", - mlp->ps.lp_mlp_gap, mlp->pv.lp_mip_gap); - glp_ios_terminate (tree); - } - - if (mlp->ps.lp_mlp_gap <= mlp->pv.lp_mip_gap) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Current LP/MLP gap of %.3f smaller than tolerated gap of %.3f, terminating search\n", - mlp->ps.lp_mlp_gap, mlp->pv.lp_mip_gap); - glp_ios_terminate (tree); - } - - break; - - default: - break; - } - // GNUNET_break (0); -} - - -/** - * Solves the MLP problem - * - * @param solver the MLP Handle - * @return #GNUNET_OK if could be solved, #GNUNET_SYSERR on failure - */ -static int -GAS_mlp_solve_problem (void *solver) -{ - struct GAS_MLP_Handle *mlp = solver; - char *filename; - int res_lp = 0; - int mip_res = 0; - int mip_status = 0; - - struct GNUNET_TIME_Absolute start_total; - struct GNUNET_TIME_Absolute start_cur_op; - struct GNUNET_TIME_Relative dur_total; - struct GNUNET_TIME_Relative dur_setup; - struct GNUNET_TIME_Relative dur_lp; - struct GNUNET_TIME_Relative dur_mlp; - - GNUNET_assert (NULL != solver); - dur_lp = GNUNET_TIME_UNIT_ZERO; - - if (GNUNET_YES == mlp->stat_bulk_lock) - { - mlp->stat_bulk_requests++; - return GNUNET_NO; - } - notify (mlp, GAS_OP_SOLVE_START, GAS_STAT_SUCCESS, - (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : - GAS_INFO_UPDATED); - start_total = GNUNET_TIME_absolute_get (); - - if (0 == GNUNET_CONTAINER_multipeermap_size (mlp->requested_peers)) - { - notify (mlp, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_NONE); - return GNUNET_OK; /* No pending requests */ - } - if (0 == GNUNET_CONTAINER_multipeermap_size (mlp->env->addresses)) - { - notify (mlp, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_NONE); - return GNUNET_OK; /* No addresses available */ - } - - if ((GNUNET_NO == mlp->stat_mlp_prob_changed) - && (GNUNET_NO == mlp->stat_mlp_prob_updated)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "No changes to problem\n"); - notify (mlp, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_NONE); - return GNUNET_OK; - } - if (GNUNET_YES == mlp->stat_mlp_prob_changed) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem size changed, rebuilding\n"); - notify (mlp, GAS_OP_SOLVE_SETUP_START, GAS_STAT_SUCCESS, GAS_INFO_FULL); - mlp_delete_problem (mlp); - if (GNUNET_SYSERR == mlp_create_problem (mlp)) - { - notify (mlp, GAS_OP_SOLVE_SETUP_STOP, GAS_STAT_FAIL, GAS_INFO_FULL); - return GNUNET_SYSERR; - } - notify (mlp, GAS_OP_SOLVE_SETUP_STOP, GAS_STAT_SUCCESS, GAS_INFO_FULL); - if (GNUNET_NO == mlp->opt_dbg_intopt_presolver) - { - mlp->control_param_lp.presolve = GLP_YES; /* LP presolver, we need lp solution */ - mlp->control_param_mlp.presolve = GNUNET_NO; /* No presolver, we have LP solution */ - } - else - { - mlp->control_param_lp.presolve = GNUNET_NO; /* LP presolver, we need lp solution */ - mlp->control_param_mlp.presolve = GLP_YES; /* No presolver, we have LP solution */ - dur_lp = GNUNET_TIME_UNIT_ZERO; - } - } - else - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n"); - } - - /* Reset solution info */ - mlp->ps.lp_objective_value = 0.0; - mlp->ps.mlp_gap = 1.0; - mlp->ps.mlp_objective_value = 0.0; - mlp->ps.lp_mlp_gap = 0.0; - - dur_setup = GNUNET_TIME_absolute_get_duration (start_total); - - /* Run LP solver */ - if (GNUNET_NO == mlp->opt_dbg_intopt_presolver) - { - notify (mlp, GAS_OP_SOLVE_MLP_LP_START, GAS_STAT_SUCCESS, - (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : - GAS_INFO_UPDATED); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Running LP solver %s\n", - (GLP_YES == mlp->control_param_lp.presolve) ? "with presolver" : - "without presolver"); - start_cur_op = GNUNET_TIME_absolute_get (); - - /* Solve LP */ - /* Only for debugging: - * Always use LP presolver: - * mlp->control_param_lp.presolve = GLP_YES; */ - res_lp = mlp_solve_lp_problem (mlp); - if (GNUNET_OK == res_lp) - { - mlp->ps.lp_objective_value = glp_get_obj_val (mlp->p.prob); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "LP solution was: %.3f\n", - mlp->ps.lp_objective_value); - } - - dur_lp = GNUNET_TIME_absolute_get_duration (start_cur_op); - notify (mlp, GAS_OP_SOLVE_MLP_LP_STOP, - (GNUNET_OK == res_lp) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL, - (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : - GAS_INFO_UPDATED); - } - - if (GNUNET_YES == mlp->opt_dbg_intopt_presolver) - res_lp = GNUNET_OK; - - /* Run MLP solver */ - if ((GNUNET_OK == res_lp) || (GNUNET_YES == mlp->opt_dbg_intopt_presolver)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Running MLP solver \n"); - notify (mlp, GAS_OP_SOLVE_MLP_MLP_START, GAS_STAT_SUCCESS, - (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : - GAS_INFO_UPDATED); - start_cur_op = GNUNET_TIME_absolute_get (); - - /* Solve MIP */ - - /* Only for debugging, always use LP presolver */ - if (GNUNET_YES == mlp->opt_dbg_intopt_presolver) - mlp->control_param_mlp.presolve = GNUNET_YES; - - mip_res = glp_intopt (mlp->p.prob, &mlp->control_param_mlp); - switch (mip_res) - { - case 0: - /* Successful */ - LOG (GNUNET_ERROR_TYPE_INFO, - "Solving MLP problem: %s\n", - mlp_solve_to_string (mip_res)); - break; - - case GLP_ETMLIM: /* Time limit reached */ - case GLP_EMIPGAP: /* MIP gap tolerance limit reached */ - case GLP_ESTOP: /* Solver was instructed to stop*/ - /* Semi-successful */ - LOG (GNUNET_ERROR_TYPE_INFO, - "Solving MLP problem solution was interupted: %s\n", - mlp_solve_to_string (mip_res)); - break; - - case GLP_EBOUND: - case GLP_EROOT: - case GLP_ENOPFS: - case GLP_ENODFS: - case GLP_EFAIL: - default: - /* Fail */ - LOG (GNUNET_ERROR_TYPE_INFO, - "Solving MLP problem failed: %s\n", - mlp_solve_to_string (mip_res)); - break; - } - - /* Analyze problem status */ - mip_status = glp_mip_status (mlp->p.prob); - switch (mip_status) - { - case GLP_OPT: /* solution is optimal */ - LOG (GNUNET_ERROR_TYPE_WARNING, - "Solution of MLP problem is optimal: %s, %s\n", - mlp_solve_to_string (mip_res), - mlp_status_to_string (mip_status)); - mip_res = GNUNET_OK; - break; - - case GLP_FEAS: /* solution is feasible but not proven optimal */ - - if ((mlp->ps.mlp_gap <= mlp->pv.mip_gap) || - (mlp->ps.lp_mlp_gap <= mlp->pv.lp_mip_gap)) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Solution of MLP problem is feasible and solution within gap constraints: %s, %s\n", - mlp_solve_to_string (mip_res), - mlp_status_to_string (mip_status)); - mip_res = GNUNET_OK; - } - else - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Solution of MLP problem is feasible but solution not within gap constraints: %s, %s\n", - mlp_solve_to_string (mip_res), - mlp_status_to_string (mip_status)); - mip_res = GNUNET_SYSERR; - } - break; - - case GLP_UNDEF: /* Solution undefined */ - case GLP_NOFEAS: /* No feasible solution */ - default: - LOG (GNUNET_ERROR_TYPE_ERROR, - "Solving MLP problem failed: %s %s\n", - mlp_solve_to_string (mip_res), - mlp_status_to_string (mip_status)); - mip_res = GNUNET_SYSERR; - break; - } - - dur_mlp = GNUNET_TIME_absolute_get_duration (start_cur_op); - dur_total = GNUNET_TIME_absolute_get_duration (start_total); - - notify (mlp, GAS_OP_SOLVE_MLP_MLP_STOP, - (GNUNET_OK == mip_res) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL, - (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : - GAS_INFO_UPDATED); - } - else - { - /* Do not execute mip solver since lp solution is invalid */ - dur_mlp = GNUNET_TIME_UNIT_ZERO; - dur_total = GNUNET_TIME_absolute_get_duration (start_total); - - notify (mlp, GAS_OP_SOLVE_MLP_MLP_STOP, GAS_STAT_FAIL, - (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : - GAS_INFO_UPDATED); - mip_res = GNUNET_SYSERR; - } - - /* Notify about end */ - notify (mlp, GAS_OP_SOLVE_STOP, - ((GNUNET_OK == mip_res) && (GNUNET_OK == mip_res)) ? - GAS_STAT_SUCCESS : GAS_STAT_FAIL, - (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : - GAS_INFO_UPDATED); - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Execution time for %s solve: (total/setup/lp/mlp) : %llu %llu %llu %llu\n", - (GNUNET_YES == mlp->stat_mlp_prob_changed) ? "full" : "updated", - (unsigned long long) dur_total.rel_value_us, - (unsigned long long) dur_setup.rel_value_us, - (unsigned long long) dur_lp.rel_value_us, - (unsigned long long) dur_mlp.rel_value_us); - - /* Save stats */ - mlp->ps.lp_res = res_lp; - mlp->ps.mip_res = mip_res; - mlp->ps.lp_presolv = mlp->control_param_lp.presolve; - mlp->ps.mip_presolv = mlp->control_param_mlp.presolve; - mlp->ps.p_cols = glp_get_num_cols (mlp->p.prob); - mlp->ps.p_rows = glp_get_num_rows (mlp->p.prob); - mlp->ps.p_elements = mlp->p.num_elements; - - /* Propagate result*/ - notify (mlp, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START, - (GNUNET_OK == res_lp) && (GNUNET_OK == mip_res) ? GAS_STAT_SUCCESS : - GAS_STAT_FAIL, - GAS_INFO_NONE); - if ((GNUNET_OK == res_lp) && (GNUNET_OK == mip_res)) - { - GNUNET_CONTAINER_multipeermap_iterate (mlp->env->addresses, - &mlp_propagate_results, mlp); - } - notify (mlp, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP, - (GNUNET_OK == res_lp) && (GNUNET_OK == mip_res) ? GAS_STAT_SUCCESS : - GAS_STAT_FAIL, - GAS_INFO_NONE); - - struct GNUNET_TIME_Absolute time = GNUNET_TIME_absolute_get (); - if ((GNUNET_YES == mlp->opt_dump_problem_all) || - (mlp->opt_dump_problem_on_fail && ((GNUNET_OK != res_lp) || (GNUNET_OK != - mip_res)))) - { - /* Write problem to disk */ - switch (mlp->opt_log_format) - { - case MLP_CPLEX: - GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.cplex", - mlp->p.num_peers, - mlp->p.num_addresses, time.abs_value_us); - glp_write_lp (mlp->p.prob, NULL, filename); - break; - - case MLP_GLPK: - GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.glpk", - mlp->p.num_peers, - mlp->p.num_addresses, time.abs_value_us); - glp_write_prob (mlp->p.prob, 0, filename); - break; - - case MLP_MPS: - GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.mps", mlp->p.num_peers, - mlp->p.num_addresses, time.abs_value_us); - glp_write_mps (mlp->p.prob, GLP_MPS_FILE, NULL, filename); - break; - - default: - break; - } - LOG (GNUNET_ERROR_TYPE_ERROR, "Dumped problem to file: `%s' \n", filename); - GNUNET_free (filename); - } - if ((mlp->opt_dump_solution_all) || - (mlp->opt_dump_solution_on_fail && ((GNUNET_OK != res_lp) || (GNUNET_OK != - mip_res)))) - { - /* Write solution to disk */ - GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.sol", mlp->p.num_peers, - mlp->p.num_addresses, time.abs_value_us); - glp_print_mip (mlp->p.prob, filename); - LOG (GNUNET_ERROR_TYPE_ERROR, "Dumped solution to file: `%s' \n", filename); - GNUNET_free (filename); - } - - /* Reset change and update marker */ - mlp->control_param_lp.presolve = GLP_NO; - mlp->stat_mlp_prob_updated = GNUNET_NO; - mlp->stat_mlp_prob_changed = GNUNET_NO; - - if ((GNUNET_OK == res_lp) && (GNUNET_OK == mip_res)) - return GNUNET_OK; - else - return GNUNET_SYSERR; -} - -/** - * Add a single address to the solve - * - * @param solver the solver Handle - * @param address the address to add - * @param network network type of this address - */ -static void -GAS_mlp_address_add (void *solver, - struct ATS_Address *address, - uint32_t network) -{ - struct GAS_MLP_Handle *mlp = solver; - - if (GNUNET_NT_COUNT <= network) - { - GNUNET_break (0); - return; - } - - if (NULL == address->solver_information) - { - address->solver_information = GNUNET_new (struct MLP_information); - } - else - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Adding address for peer `%s' multiple times\n"), - GNUNET_i2s (&address->peer)); - - /* Is this peer included in the problem? */ - if (NULL == - GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, - &address->peer)) - { - /* FIXME: should this be an error? */ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Adding address for peer `%s' without address request\n", - GNUNET_i2s (&address->peer)); - return; - } - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Adding address for peer `%s' with address request \n", - GNUNET_i2s (&address->peer)); - /* Problem size changed: new address for peer with pending request */ - mlp->stat_mlp_prob_changed = GNUNET_YES; - if (GNUNET_YES == mlp->opt_mlp_auto_solve) - GAS_mlp_solve_problem (solver); -} - - -/** - * Transport properties for this address have changed - * - * @param solver solver handle - * @param address the address - */ -static void -GAS_mlp_address_property_changed (void *solver, - struct ATS_Address *address) -{ - struct MLP_information *mlpi = address->solver_information; - struct GAS_MLP_Handle *mlp = solver; - - if (NULL == mlp->p.prob) - return; /* There is no MLP problem to update yet */ - - if (NULL == mlpi) - { - LOG (GNUNET_ERROR_TYPE_INFO, - _ ("Updating address property for peer `%s' %p not added before\n"), - GNUNET_i2s (&address->peer), - address); - GNUNET_break (0); - return; - } - if (NULL == - GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, - &address->peer)) - { - /* Peer is not requested, so no need to update problem */ - return; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Updating properties for peer `%s'\n", - GNUNET_i2s (&address->peer)); - - if (GNUNET_YES == mlp->opt_dbg_feasibility_only) - return; - - /* Update c7) [r_q[index]][c_b] = f_q * q_averaged[type_index] */ - if ((GNUNET_YES == - mlp_create_problem_update_value (&mlp->p, - mlp->p.r_q[RQ_QUALITY_METRIC_DELAY], - mlpi->c_b, - address->norm_delay.norm, - __LINE__)) || - (GNUNET_YES == - mlp_create_problem_update_value (&mlp->p, - mlp->p.r_q[RQ_QUALITY_METRIC_DISTANCE], - mlpi->c_b, - address->norm_distance.norm, - __LINE__))) - { - mlp->stat_mlp_prob_updated = GNUNET_YES; - if (GNUNET_YES == mlp->opt_mlp_auto_solve) - GAS_mlp_solve_problem (solver); - } -} - - -/** - * Find the active address in the set of addresses of a peer - * @param cls destination - * @param key peer id - * @param value address - * @return #GNUNET_OK - */ -static int -mlp_get_preferred_address_it (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) -{ - static int counter = 0; - struct ATS_Address **aa = cls; - struct ATS_Address *addr = value; - struct MLP_information *mlpi = addr->solver_information; - - if (mlpi == NULL) - return GNUNET_YES; - - /* - * Debug output - * GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - * "MLP [%u] Peer `%s' %s length %u session %u active %s mlp active %s\n", - * counter, GNUNET_i2s (&addr->peer), addr->plugin, addr->addr_len, addr->session_id, - * (GNUNET_YES == addr->active) ? "active" : "inactive", - * (GNUNET_YES == mlpi->n) ? "active" : "inactive"); - */ - - if (GNUNET_YES == mlpi->n) - { - (*aa) = addr; - (*aa)->assigned_bw_in = mlpi->b_in; - (*aa)->assigned_bw_out = mlpi->b_out; - return GNUNET_NO; - } - counter++; - return GNUNET_YES; -} - - -static double -get_peer_pref_value (struct GAS_MLP_Handle *mlp, - const struct GNUNET_PeerIdentity *peer) -{ - double res; - const double *preferences; - int c; - - preferences = mlp->env->get_preferences (mlp->env->cls, peer); - res = 0.0; - for (c = 0; c < GNUNET_ATS_PREFERENCE_END; c++) - { - /* fprintf (stderr, "VALUE[%u] %s %.3f \n", - * c, GNUNET_i2s (&cur->addr->peer), t[c]); */ - res += preferences[c]; - } - - res /= GNUNET_ATS_PREFERENCE_END; - res += 1.0; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Peer preference for peer `%s' == %.2f\n", - GNUNET_i2s (peer), res); - - return res; -} - - -/** - * Get the preferred address for a specific peer - * - * @param solver the MLP Handle - * @param peer the peer - */ -static void -GAS_mlp_get_preferred_address (void *solver, - const struct GNUNET_PeerIdentity *peer) -{ - struct GAS_MLP_Handle *mlp = solver; - struct ATS_Peer *p; - struct ATS_Address *res; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Getting preferred address for `%s'\n", - GNUNET_i2s (peer)); - - /* Is this peer included in the problem? */ - if (NULL == - GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, - peer)) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Adding peer `%s' to list of requested_peers with requests\n", - GNUNET_i2s (peer)); - - p = GNUNET_new (struct ATS_Peer); - p->id = (*peer); - p->f = get_peer_pref_value (mlp, peer); - GNUNET_CONTAINER_multipeermap_put (mlp->requested_peers, - peer, p, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); - - /* Added new peer, we have to rebuild problem before solving */ - mlp->stat_mlp_prob_changed = GNUNET_YES; - - if ((GNUNET_YES == mlp->opt_mlp_auto_solve) && - (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains ( - mlp->env->addresses, - peer))) - { - mlp->exclude_peer = peer; - GAS_mlp_solve_problem (mlp); - mlp->exclude_peer = NULL; - } - } - /* Get prefered address */ - res = NULL; - GNUNET_CONTAINER_multipeermap_get_multiple (mlp->env->addresses, peer, - &mlp_get_preferred_address_it, - &res); - if (NULL != res) - mlp->env->bandwidth_changed_cb (mlp->env->cls, - res); -} - - -/** - * Deletes a single address in the MLP problem - * - * The MLP problem has to be recreated and the problem has to be resolved - * - * @param solver the MLP Handle - * @param address the address to delete - */ -static void -GAS_mlp_address_delete (void *solver, - struct ATS_Address *address) -{ - struct GAS_MLP_Handle *mlp = solver; - struct MLP_information *mlpi; - struct ATS_Address *res; - int was_active; - - mlpi = address->solver_information; - if (NULL != mlpi) - { - /* Remove full address */ - GNUNET_free (mlpi); - address->solver_information = NULL; - } - was_active = address->active; - address->active = GNUNET_NO; - address->assigned_bw_in = 0; - address->assigned_bw_out = 0; - - /* Is this peer included in the problem? */ - if (NULL == - GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, - &address->peer)) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Deleting address for peer `%s' without address request \n", - GNUNET_i2s (&address->peer)); - return; - } - LOG (GNUNET_ERROR_TYPE_INFO, - "Deleting address for peer `%s' with address request \n", - GNUNET_i2s (&address->peer)); - - /* Problem size changed: new address for peer with pending request */ - mlp->stat_mlp_prob_changed = GNUNET_YES; - if (GNUNET_YES == mlp->opt_mlp_auto_solve) - { - GAS_mlp_solve_problem (solver); - } - if (GNUNET_YES == was_active) - { - GAS_mlp_get_preferred_address (solver, &address->peer); - res = NULL; - GNUNET_CONTAINER_multipeermap_get_multiple (mlp->env->addresses, - &address->peer, - &mlp_get_preferred_address_it, - &res); - if (NULL == res) - { - /* No alternative address, disconnecting peer */ - mlp->env->bandwidth_changed_cb (mlp->env->cls, address); - } - } -} - - -/** - * Start a bulk operation - * - * @param solver the solver - */ -static void -GAS_mlp_bulk_start (void *solver) -{ - struct GAS_MLP_Handle *s = solver; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Locking solver for bulk operation ...\n"); - GNUNET_assert (NULL != solver); - s->stat_bulk_lock++; -} - - -static void -GAS_mlp_bulk_stop (void *solver) -{ - struct GAS_MLP_Handle *s = solver; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Unlocking solver from bulk operation ...\n"); - GNUNET_assert (NULL != solver); - - if (s->stat_bulk_lock < 1) - { - GNUNET_break (0); - return; - } - s->stat_bulk_lock--; - - if (0 < s->stat_bulk_requests) - { - GAS_mlp_solve_problem (solver); - s->stat_bulk_requests = 0; - } -} - - - -/** - * Stop notifying about address and bandwidth changes for this peer - * - * @param solver the MLP handle - * @param peer the peer - */ -static void -GAS_mlp_stop_get_preferred_address (void *solver, - const struct GNUNET_PeerIdentity *peer) -{ - struct GAS_MLP_Handle *mlp = solver; - struct ATS_Peer *p = NULL; - - GNUNET_assert (NULL != solver); - GNUNET_assert (NULL != peer); - if (NULL != (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, - peer))) - { - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (mlp->requested_peers, - peer, p)); - GNUNET_free (p); - - mlp->stat_mlp_prob_changed = GNUNET_YES; - if (GNUNET_YES == mlp->opt_mlp_auto_solve) - { - GAS_mlp_solve_problem (solver); - } - } -} - - -/** - * Changes the preferences for a peer in the MLP problem - * - * @param solver the MLP Handle - * @param peer the peer - * @param kind the kind to change the preference - * @param pref_rel the relative score - */ -static void -GAS_mlp_address_change_preference (void *solver, - const struct GNUNET_PeerIdentity *peer, - enum GNUNET_ATS_PreferenceKind kind, - double pref_rel) -{ - struct GAS_MLP_Handle *mlp = solver; - struct ATS_Peer *p; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Changing preference for address for peer `%s' to %.2f\n", - GNUNET_i2s (peer), - pref_rel); - - GNUNET_STATISTICS_update (mlp->env->stats, - "# LP address preference changes", 1, GNUNET_NO); - /* Update the constraints with changed preferences */ - - - - /* Update relativity constraint c9 */ - if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, - peer))) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Updating preference for unknown peer `%s'\n", - GNUNET_i2s (peer)); - return; - } - - if (GNUNET_NO == mlp->opt_dbg_feasibility_only) - { - p->f = get_peer_pref_value (mlp, peer); - mlp_create_problem_update_value (&mlp->p, - p->r_c9, - mlp->p.c_r, - -p->f, - __LINE__); - - /* Problem size changed: new address for peer with pending request */ - mlp->stat_mlp_prob_updated = GNUNET_YES; - if (GNUNET_YES == mlp->opt_mlp_auto_solve) - GAS_mlp_solve_problem (solver); - } -} - - -/** - * Get application feedback for a peer - * - * @param solver the solver handle - * @param application the application - * @param peer the peer to change the preference for - * @param scope the time interval for this feedback: [now - scope .. now] - * @param kind the kind to change the preference - * @param score the score - */ -static void -GAS_mlp_address_preference_feedback (void *solver, - struct GNUNET_SERVICE_Client *application, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_TIME_Relative scope, - enum GNUNET_ATS_PreferenceKind kind, - double score) -{ - struct GAS_PROPORTIONAL_Handle *s = solver; - - GNUNET_assert (NULL != solver); - GNUNET_assert (NULL != peer); - GNUNET_assert (NULL != s); -} - - -static int -mlp_free_peers (void *cls, - const struct GNUNET_PeerIdentity *key, void *value) -{ - struct GNUNET_CONTAINER_MultiPeerMap *map = cls; - struct ATS_Peer *p = value; - - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (map, key, value)); - GNUNET_free (p); - - return GNUNET_OK; -} - - -/** - * Shutdown the MLP problem solving component - * - * @param cls the solver handle - * @return NULL - */ -void * -libgnunet_plugin_ats_mlp_done (void *cls) -{ - struct GNUNET_ATS_SolverFunctions *sf = cls; - struct GAS_MLP_Handle *mlp = sf->cls; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Shutting down mlp solver\n"); - mlp_delete_problem (mlp); - GNUNET_CONTAINER_multipeermap_iterate (mlp->requested_peers, - &mlp_free_peers, - mlp->requested_peers); - GNUNET_CONTAINER_multipeermap_destroy (mlp->requested_peers); - mlp->requested_peers = NULL; - - /* Clean up GLPK environment */ - glp_free_env (); - GNUNET_free (mlp); - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Shutdown down of mlp solver complete\n"); - return NULL; -} - - -void * -libgnunet_plugin_ats_mlp_init (void *cls) -{ - static struct GNUNET_ATS_SolverFunctions sf; - struct GNUNET_ATS_PluginEnvironment *env = cls; - struct GAS_MLP_Handle *mlp = GNUNET_new (struct GAS_MLP_Handle); - float f_tmp; - unsigned long long tmp; - unsigned int b_min; - unsigned int n_min; - int c; - char *outputformat; - - struct GNUNET_TIME_Relative max_duration; - long long unsigned int max_iterations; - - /* Init GLPK environment */ - int res = glp_init_env (); - - switch (res) - { - case 0: - LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n", - "initialization successful"); - break; - - case 1: - LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n", - "environment is already initialized"); - break; - - case 2: - LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n", - "initialization failed (insufficient memory)"); - GNUNET_free (mlp); - return NULL; - break; - - case 3: - LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n", - "initialization failed (unsupported programming model)"); - GNUNET_free (mlp); - return NULL; - break; - - default: - break; - } - - mlp->opt_dump_problem_all = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, - "ats", - "MLP_DUMP_PROBLEM_ALL"); - if (GNUNET_SYSERR == mlp->opt_dump_problem_all) - mlp->opt_dump_problem_all = GNUNET_NO; - - mlp->opt_dump_solution_all = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, - "ats", - "MLP_DUMP_SOLUTION_ALL"); - if (GNUNET_SYSERR == mlp->opt_dump_solution_all) - mlp->opt_dump_solution_all = GNUNET_NO; - - mlp->opt_dump_problem_on_fail = GNUNET_CONFIGURATION_get_value_yesno ( - env->cfg, - "ats", - "MLP_DUMP_PROBLEM_ON_FAIL"); - if (GNUNET_SYSERR == mlp->opt_dump_problem_on_fail) - mlp->opt_dump_problem_on_fail = GNUNET_NO; - - mlp->opt_dump_solution_on_fail = GNUNET_CONFIGURATION_get_value_yesno ( - env->cfg, - "ats", - "MLP_DUMP_SOLUTION_ON_FAIL"); - if (GNUNET_SYSERR == mlp->opt_dump_solution_on_fail) - mlp->opt_dump_solution_on_fail = GNUNET_NO; - - mlp->opt_dbg_glpk_verbose = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, - "ats", - "MLP_DBG_GLPK_VERBOSE"); - if (GNUNET_SYSERR == mlp->opt_dbg_glpk_verbose) - mlp->opt_dbg_glpk_verbose = GNUNET_NO; - - mlp->opt_dbg_feasibility_only = GNUNET_CONFIGURATION_get_value_yesno ( - env->cfg, - "ats", - "MLP_DBG_FEASIBILITY_ONLY"); - if (GNUNET_SYSERR == mlp->opt_dbg_feasibility_only) - mlp->opt_dbg_feasibility_only = GNUNET_NO; - if (GNUNET_YES == mlp->opt_dbg_feasibility_only) - LOG (GNUNET_ERROR_TYPE_WARNING, - "MLP solver is configured to check feasibility only!\n"); - - mlp->opt_dbg_autoscale_problem = GNUNET_CONFIGURATION_get_value_yesno ( - env->cfg, - "ats", - "MLP_DBG_AUTOSCALE_PROBLEM"); - if (GNUNET_SYSERR == mlp->opt_dbg_autoscale_problem) - mlp->opt_dbg_autoscale_problem = GNUNET_NO; - if (GNUNET_YES == mlp->opt_dbg_autoscale_problem) - LOG (GNUNET_ERROR_TYPE_WARNING, - "MLP solver is configured automatically scale the problem!\n"); - - mlp->opt_dbg_intopt_presolver = GNUNET_CONFIGURATION_get_value_yesno ( - env->cfg, - "ats", - "MLP_DBG_INTOPT_PRESOLVE"); - if (GNUNET_SYSERR == mlp->opt_dbg_intopt_presolver) - mlp->opt_dbg_intopt_presolver = GNUNET_NO; - if (GNUNET_YES == mlp->opt_dbg_intopt_presolver) - LOG (GNUNET_ERROR_TYPE_WARNING, - "MLP solver is configured use the mlp presolver\n"); - - mlp->opt_dbg_optimize_diversity = GNUNET_CONFIGURATION_get_value_yesno ( - env->cfg, - "ats", - "MLP_DBG_OPTIMIZE_DIVERSITY"); - if (GNUNET_SYSERR == mlp->opt_dbg_optimize_diversity) - mlp->opt_dbg_optimize_diversity = GNUNET_YES; - if (GNUNET_NO == mlp->opt_dbg_optimize_diversity) - LOG (GNUNET_ERROR_TYPE_WARNING, - "MLP solver is not optimizing for diversity\n"); - - mlp->opt_dbg_optimize_relativity = GNUNET_CONFIGURATION_get_value_yesno ( - env->cfg, - "ats", - "MLP_DBG_OPTIMIZE_RELATIVITY"); - if (GNUNET_SYSERR == mlp->opt_dbg_optimize_relativity) - mlp->opt_dbg_optimize_relativity = GNUNET_YES; - if (GNUNET_NO == mlp->opt_dbg_optimize_relativity) - LOG (GNUNET_ERROR_TYPE_WARNING, - "MLP solver is not optimizing for relativity\n"); - - mlp->opt_dbg_optimize_quality = GNUNET_CONFIGURATION_get_value_yesno ( - env->cfg, - "ats", - "MLP_DBG_OPTIMIZE_QUALITY"); - if (GNUNET_SYSERR == mlp->opt_dbg_optimize_quality) - mlp->opt_dbg_optimize_quality = GNUNET_YES; - if (GNUNET_NO == mlp->opt_dbg_optimize_quality) - LOG (GNUNET_ERROR_TYPE_WARNING, - "MLP solver is not optimizing for quality\n"); - - mlp->opt_dbg_optimize_utility = GNUNET_CONFIGURATION_get_value_yesno ( - env->cfg, - "ats", - "MLP_DBG_OPTIMIZE_UTILITY"); - if (GNUNET_SYSERR == mlp->opt_dbg_optimize_utility) - mlp->opt_dbg_optimize_utility = GNUNET_YES; - if (GNUNET_NO == mlp->opt_dbg_optimize_utility) - LOG (GNUNET_ERROR_TYPE_WARNING, - "MLP solver is not optimizing for utility\n"); - - if ((GNUNET_NO == mlp->opt_dbg_optimize_utility) && - (GNUNET_NO == mlp->opt_dbg_optimize_quality) && - (GNUNET_NO == mlp->opt_dbg_optimize_relativity) && - (GNUNET_NO == mlp->opt_dbg_optimize_utility) && - (GNUNET_NO == mlp->opt_dbg_feasibility_only)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ( - "MLP solver is not optimizing for anything, changing to feasibility check\n")); - mlp->opt_dbg_feasibility_only = GNUNET_YES; - } - - if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (env->cfg, - "ats", - "MLP_LOG_FORMAT", - &outputformat)) - mlp->opt_log_format = MLP_CPLEX; - else - { - GNUNET_STRINGS_utf8_toupper (outputformat, outputformat); - if (0 == strcmp (outputformat, "MPS")) - { - mlp->opt_log_format = MLP_MPS; - } - else if (0 == strcmp (outputformat, "CPLEX")) - { - mlp->opt_log_format = MLP_CPLEX; - } - else if (0 == strcmp (outputformat, "GLPK")) - { - mlp->opt_log_format = MLP_GLPK; - } - else - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Invalid log format `%s' in configuration, using CPLEX!\n", - outputformat); - mlp->opt_log_format = MLP_CPLEX; - } - GNUNET_free (outputformat); - } - - mlp->pv.BIG_M = (double) BIG_M_VALUE; - - mlp->pv.mip_gap = (double) 0.0; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "MLP_MAX_MIP_GAP", - &f_tmp)) - { - if ((f_tmp < 0.0) || (f_tmp > 1.0)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "MIP gap", f_tmp); - } - else - { - mlp->pv.mip_gap = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n", - "MIP gap", f_tmp); - } - } - - mlp->pv.lp_mip_gap = (double) 0.0; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "MLP_MAX_LP_MIP_GAP", - &f_tmp)) - { - if ((f_tmp < 0.0) || (f_tmp > 1.0)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "LP/MIP", f_tmp); - } - else - { - mlp->pv.lp_mip_gap = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n", - "LP/MIP", f_tmp); - } - } - - /* Get timeout for iterations */ - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (env->cfg, "ats", - "MLP_MAX_DURATION", - &max_duration)) - { - max_duration = MLP_MAX_EXEC_DURATION; - } - - /* Get maximum number of iterations */ - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", - "MLP_MAX_ITERATIONS", - &max_iterations)) - { - max_iterations = MLP_MAX_ITERATIONS; - } - - /* Get diversity coefficient from configuration */ - mlp->pv.co_D = MLP_DEFAULT_D; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "MLP_COEFFICIENT_D", - &f_tmp)) - { - if ((f_tmp < 0.0)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "MLP_COEFFICIENT_D", f_tmp); - } - else - { - mlp->pv.co_D = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n", - "MLP_COEFFICIENT_D", f_tmp); - } - } - - /* Get relativity coefficient from configuration */ - mlp->pv.co_R = MLP_DEFAULT_R; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "MLP_COEFFICIENT_R", - &f_tmp)) - { - if ((f_tmp < 0.0)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "MLP_COEFFICIENT_R", f_tmp); - } - else - { - mlp->pv.co_R = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n", - "MLP_COEFFICIENT_R", f_tmp); - } - } - - - /* Get utilization coefficient from configuration */ - mlp->pv.co_U = MLP_DEFAULT_U; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "MLP_COEFFICIENT_U", - &f_tmp)) - { - if ((f_tmp < 0.0)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "MLP_COEFFICIENT_U", f_tmp); - } - else - { - mlp->pv.co_U = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n", - "MLP_COEFFICIENT_U", f_tmp); - } - } - - /* Get quality metric coefficients from configuration */ - for (c = 0; c < RQ_QUALITY_METRIC_COUNT; c++) - { - /* initialize quality coefficients with default value 1.0 */ - mlp->pv.co_Q[c] = MLP_DEFAULT_QUALITY; - } - - - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", - "MLP_COEFFICIENT_QUALITY_DELAY", - &tmp)) - mlp->pv.co_Q[RQ_QUALITY_METRIC_DELAY] = (double) tmp / 100; - else - mlp->pv.co_Q[RQ_QUALITY_METRIC_DELAY] = MLP_DEFAULT_QUALITY; - - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", - "MLP_COEFFICIENT_QUALITY_DISTANCE", - &tmp)) - mlp->pv.co_Q[RQ_QUALITY_METRIC_DISTANCE] = (double) tmp / 100; - else - mlp->pv.co_Q[RQ_QUALITY_METRIC_DISTANCE] = MLP_DEFAULT_QUALITY; - - /* Get minimum bandwidth per used address from configuration */ - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", - "MLP_MIN_BANDWIDTH", - &tmp)) - b_min = tmp; - else - { - b_min = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); - } - - /* Get minimum number of connections from configuration */ - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", - "MLP_MIN_CONNECTIONS", - &tmp)) - n_min = tmp; - else - n_min = MLP_DEFAULT_MIN_CONNECTIONS; - - /* Init network quotas */ - for (c = 0; c < GNUNET_NT_COUNT; c++) - { - mlp->pv.quota_index[c] = c; - mlp->pv.quota_out[c] = env->out_quota[c]; - mlp->pv.quota_in[c] = env->in_quota[c]; - - LOG (GNUNET_ERROR_TYPE_INFO, - "Quota for network `%s' (in/out) %llu/%llu\n", - GNUNET_NT_to_string (c), - mlp->pv.quota_out[c], - mlp->pv.quota_in[c]); - /* Check if defined quota could make problem unsolvable */ - if ((n_min * b_min) > mlp->pv.quota_out[c]) - { - LOG (GNUNET_ERROR_TYPE_INFO, - _ ( - "Adjusting inconsistent outbound quota configuration for network `%s', is %llu must be at least %llu\n"), - GNUNET_NT_to_string (mlp->pv.quota_index[c]), - mlp->pv.quota_out[c], - (n_min * b_min)); - mlp->pv.quota_out[c] = (n_min * b_min); - } - if ((n_min * b_min) > mlp->pv.quota_in[c]) - { - LOG (GNUNET_ERROR_TYPE_INFO, - _ ( - "Adjusting inconsistent inbound quota configuration for network `%s', is %llu must be at least %llu\n"), - GNUNET_NT_to_string (mlp->pv.quota_index[c]), - mlp->pv.quota_in[c], - (n_min * b_min)); - mlp->pv.quota_in[c] = (n_min * b_min); - } - /* Check if bandwidth is too big to make problem solvable */ - if (mlp->pv.BIG_M < mlp->pv.quota_out[c]) - { - LOG (GNUNET_ERROR_TYPE_INFO, - _ ( - "Adjusting outbound quota configuration for network `%s'from %llu to %.0f\n"), - GNUNET_NT_to_string (mlp->pv.quota_index[c]), - mlp->pv.quota_out[c], - mlp->pv.BIG_M); - mlp->pv.quota_out[c] = mlp->pv.BIG_M; - } - if (mlp->pv.BIG_M < mlp->pv.quota_in[c]) - { - LOG (GNUNET_ERROR_TYPE_INFO, - _ ( - "Adjusting inbound quota configuration for network `%s' from %llu to %.0f\n"), - GNUNET_NT_to_string (mlp->pv.quota_index[c]), - mlp->pv.quota_in[c], - mlp->pv.BIG_M); - mlp->pv.quota_in[c] = mlp->pv.BIG_M; - } - } - mlp->env = env; - sf.cls = mlp; - sf.s_add = &GAS_mlp_address_add; - sf.s_address_update_property = &GAS_mlp_address_property_changed; - sf.s_get = &GAS_mlp_get_preferred_address; - sf.s_get_stop = &GAS_mlp_stop_get_preferred_address; - sf.s_pref = &GAS_mlp_address_change_preference; - sf.s_feedback = &GAS_mlp_address_preference_feedback; - sf.s_del = &GAS_mlp_address_delete; - sf.s_bulk_start = &GAS_mlp_bulk_start; - sf.s_bulk_stop = &GAS_mlp_bulk_stop; - - /* Setting MLP Input variables */ - mlp->pv.b_min = b_min; - mlp->pv.n_min = n_min; - mlp->pv.m_q = RQ_QUALITY_METRIC_COUNT; - mlp->stat_mlp_prob_changed = GNUNET_NO; - mlp->stat_mlp_prob_updated = GNUNET_NO; - mlp->opt_mlp_auto_solve = GNUNET_YES; - mlp->requested_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); - mlp->stat_bulk_requests = 0; - mlp->stat_bulk_lock = 0; - - /* Setup GLPK */ - /* Redirect GLPK output to GNUnet logging */ - glp_term_hook (&mlp_term_hook, (void *) mlp); - - /* Init LP solving parameters */ - glp_init_smcp (&mlp->control_param_lp); - mlp->control_param_lp.msg_lev = GLP_MSG_OFF; - if (GNUNET_YES == mlp->opt_dbg_glpk_verbose) - mlp->control_param_lp.msg_lev = GLP_MSG_ALL; - - mlp->control_param_lp.it_lim = max_iterations; - mlp->control_param_lp.tm_lim = max_duration.rel_value_us / 1000LL; - - /* Init MLP solving parameters */ - glp_init_iocp (&mlp->control_param_mlp); - /* Setting callback function */ - mlp->control_param_mlp.cb_func = &mlp_branch_and_cut_cb; - mlp->control_param_mlp.cb_info = mlp; - mlp->control_param_mlp.msg_lev = GLP_MSG_OFF; - mlp->control_param_mlp.mip_gap = mlp->pv.mip_gap; - if (GNUNET_YES == mlp->opt_dbg_glpk_verbose) - mlp->control_param_mlp.msg_lev = GLP_MSG_ALL; - mlp->control_param_mlp.tm_lim = max_duration.rel_value_us / 1000LL; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "solver ready\n"); - - return &sf; -} - -/* end of plugin_ats_mlp.c */ diff --git a/src/ats/plugin_ats_ril.c b/src/ats/plugin_ats_ril.c deleted file mode 100644 index 7be3cb0a1..000000000 --- a/src/ats/plugin_ats_ril.c +++ /dev/null @@ -1,2997 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2011-2014 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @file ats/plugin_ats_ril.c - * @brief ATS reinforcement learning solver - * @author Fabian Oehlmann - * @author Matthias Wachs - */ -#include "platform.h" -#include -#include -#include "gnunet_ats_plugin.h" -#include "gnunet-service-ats_addresses.h" - - - -#define LOG(kind, ...) GNUNET_log_from (kind, "ats-ril", __VA_ARGS__) - -#define RIL_MIN_BW (5 * ntohl ( \ - GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT. \ - value__)) -#define RIL_MAX_BW GNUNET_ATS_MaxBandwidth - -#define RIL_ACTION_INVALID -1 -#define RIL_INTERVAL_EXPONENT 10 -#define RIL_UTILITY_DELAY_MAX 1000 - -#define RIL_DEFAULT_STEP_TIME_MIN GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_MILLISECONDS, 200) -#define RIL_DEFAULT_STEP_TIME_MAX GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_MILLISECONDS, 2000) -#define RIL_DEFAULT_ALGORITHM RIL_ALGO_SARSA -#define RIL_DEFAULT_SELECT RIL_SELECT_SOFTMAX -#define RIL_DEFAULT_WELFARE RIL_WELFARE_NASH -#define RIL_DEFAULT_DISCOUNT_BETA 0.6 -#define RIL_DEFAULT_DISCOUNT_GAMMA 0.5 -#define RIL_DEFAULT_GRADIENT_STEP_SIZE 0.01 -#define RIL_DEFAULT_TRACE_DECAY 0.5 -#define RIL_DEFAULT_EXPLORE_RATIO 1 -#define RIL_DEFAULT_EXPLORE_DECAY 0.95 -#define RIL_DEFAULT_RBF_DIVISOR 50 -#define RIL_DEFAULT_TEMPERATURE 0.1 -#define RIL_DEFAULT_TEMPERATURE_DECAY 1 - -#define RIL_INC_DEC_STEP_SIZE 1 -#define RIL_NOP_DECAY 0.5 - -/** - * ATS reinforcement learning solver - * - * General description - */ - -/** - * The actions, how an agent can manipulate the current assignment. I.e. how the bandwidth can be - * changed for the currently chosen address. Not depicted in the enum are the actions of switching - * to a particular address. The action of switching to address with index i is depicted by the - * number (RIL_ACTION_TYPE_NUM + i). - */ -enum RIL_Action_Type -{ - RIL_ACTION_NOTHING = 0, - RIL_ACTION_BW_IN_DBL = -2, // TODO? Potentially add more actions - RIL_ACTION_BW_IN_HLV = -3, - RIL_ACTION_BW_IN_INC = 1, - RIL_ACTION_BW_IN_DEC = 2, - RIL_ACTION_BW_OUT_DBL = -4, - RIL_ACTION_BW_OUT_HLV = -5, - RIL_ACTION_BW_OUT_INC = 3, - RIL_ACTION_BW_OUT_DEC = 4, - RIL_ACTION_TYPE_NUM = 5 -}; - -enum RIL_Algorithm -{ - RIL_ALGO_SARSA = 0, - RIL_ALGO_Q = 1 -}; - -enum RIL_Select -{ - RIL_SELECT_SOFTMAX = 0, - RIL_SELECT_EGREEDY = 1 -}; - -enum RIL_Welfare -{ - RIL_WELFARE_NASH, - RIL_WELFARE_EGALITARIAN -}; - -enum RIL_E_Modification -{ - RIL_E_DECAY, - RIL_E_ZERO, - RIL_E_ACCUMULATE, - RIL_E_REPLACE -}; - -/** - * Global learning parameters - */ -struct RIL_Learning_Parameters -{ - /** - * The TD-algorithm to use - */ - enum RIL_Algorithm algorithm; - - /** - * Gradient-descent step-size - */ - double alpha; - - /** - * Learning discount variable in the TD-update for semi-MDPs - */ - double beta; - - /** - * Learning discount factor in the TD-update for MDPs - */ - double gamma; - - /** - * Trace-decay factor for eligibility traces - */ - double lambda; - - /** - * Whether to accumulate or replace eligibility traces - */ - enum RIL_E_Modification eligibility_trace_mode; - - /** - * Initial softmax action-selection temperature - */ - double temperature_init; - - /** - * Softmax action-selection temperature - */ - double temperature; - - /** - * Decay factor of the temperature value - */ - double temperature_decay; - - /** - * Which measure of social welfare should be used - */ - enum RIL_Welfare social_welfare; - - /** - * State space divisor - */ - unsigned long long rbf_divisor; - - /** - * Action selection strategy; - */ - enum RIL_Select select; - - /** - * Initial exploration ratio value - */ - double epsilon_init; - - /** - * Ratio, with what probability an agent should explore in the e-greed policy - */ - double epsilon; - - /** - * Decay factor of the explore ratio - */ - double epsilon_decay; - - /** - * Minimal interval time between steps in milliseconds - */ - struct GNUNET_TIME_Relative step_time_min; - - /** - * Maximum interval time between steps in milliseconds - */ - struct GNUNET_TIME_Relative step_time_max; -}; - -/** - * Wrapper for addresses to store them in agent's linked list - */ -struct RIL_Address_Wrapped -{ - /** - * Next in DLL - */ - struct RIL_Address_Wrapped *next; - - /** - * Previous in DLL - */ - struct RIL_Address_Wrapped *prev; - - /** - * The address - */ - struct ATS_Address *address_naked; -}; - - -struct RIL_Peer_Agent -{ - /** - * Next agent in solver's linked list - */ - struct RIL_Peer_Agent *next; - - /** - * Previous agent in solver's linked list - */ - struct RIL_Peer_Agent *prev; - - /** - * Environment handle - */ - struct GAS_RIL_Handle *envi; - - /** - * Peer ID - */ - struct GNUNET_PeerIdentity peer; - - /** - * Whether the agent is active or not - */ - int is_active; - - /** - * Number of performed time-steps - */ - unsigned long long step_count; - - /** - * Experience matrix W - */ - double **W; - - /** - * Number of rows of W / Number of state-vector features - */ - unsigned int m; - - /** - * Number of columns of W / Number of actions - */ - unsigned int n; - - /** - * Last perceived state feature vector - */ - double *s_old; - - /** - * Last chosen action - */ - int a_old; - - /** - * Eligibility traces - */ - double **E; - - /** - * Whether to reset the eligibility traces to 0 after a Q-exploration step - */ - int eligibility_reset; - - /** - * Address in use - */ - struct ATS_Address *address_inuse; - - /** - * Head of addresses DLL - */ - struct RIL_Address_Wrapped *addresses_head; - - /** - * Tail of addresses DLL - */ - struct RIL_Address_Wrapped *addresses_tail; - - /** - * Inbound bandwidth assigned by the agent - */ - uint32_t bw_in; - - /** - * Outbound bandwidth assigned by the agent - */ - uint32_t bw_out; - - /** - * Flag whether a suggestion has to be issued - */ - int suggestion_issue; - - /** - * The address which has to be issued - */ - struct ATS_Address *suggestion_address; - - /** - * The agent's last objective value - */ - double objective_old; - - /** - * NOP bonus - */ - double nop_bonus; -}; - -struct RIL_Scope -{ - /** - * ATS network type - */ - enum GNUNET_NetworkType type; - - /** - * Total available inbound bandwidth - */ - uint32_t bw_in_available; - - /** - * Bandwidth inbound assigned in network after last step - */ - uint32_t bw_in_assigned; - - /** - * Bandwidth inbound actually utilized in the network - */ - uint32_t bw_in_utilized; - - /** - * Total available outbound bandwidth - */ - uint32_t bw_out_available; - - /** - * Bandwidth outbound assigned in network after last step - */ - unsigned long long bw_out_assigned; - - /** - * Bandwidth outbound actually utilized in the network - */ - unsigned long long bw_out_utilized; - - /** - * Number of active agents in scope - */ - unsigned int active_agent_count; - - /** - * The social welfare achieved in the scope - */ - double social_welfare; -}; - -/** - * A handle for the reinforcement learning solver - */ -struct GAS_RIL_Handle -{ - /** - * The solver-plugin environment of the solver-plugin API - */ - struct GNUNET_ATS_PluginEnvironment *env; - - /** - * Number of performed steps - */ - unsigned long long step_count; - - /** - * Timestamp for the last time-step - */ - struct GNUNET_TIME_Absolute step_time_last; - - /** - * Task identifier of the next time-step to be executed - */ - struct GNUNET_SCHEDULER_Task *step_next_task_id; - - /** - * Variable discount factor, dependent on time between steps - */ - double global_discount_variable; - - /** - * Integrated variable discount factor, dependent on time between steps - */ - double global_discount_integrated; - - /** - * Lock for bulk operations - */ - int bulk_lock; - - /** - * Number of changes during a lock - */ - int bulk_changes; - - /** - * Learning parameters - */ - struct RIL_Learning_Parameters parameters; - - /** - * Array of networks with global assignment state - */ - struct RIL_Scope *network_entries; - - /** - * Networks count - */ - unsigned int networks_count; - - /** - * List of active peer-agents - */ - struct RIL_Peer_Agent *agents_head; - struct RIL_Peer_Agent *agents_tail; - - /** - * Shutdown - */ - int done; - - /** - * Simulate steps, i.e. schedule steps immediately - */ - unsigned long long simulate; -}; - -/* - * "Private" functions - * --------------------------- - */ - -/** - * Estimate the current action-value for state s and action a - * - * @param agent agent performing the estimation - * @param state s - * @param action a - * @return estimation value - */ -static double -agent_q (struct RIL_Peer_Agent *agent, - const double *state, - int action) -{ - unsigned int i; - double result = 0.0; - - for (i = 0; i < agent->m; i++) - result += state[i] * agent->W[action][i]; - - /* prevent crashes if learning diverges */ - if (isnan (result)) - return isnan (result) * UINT32_MAX; - if (isinf (result)) - return isinf (result) * UINT32_MAX; - return result; -} - - -/** - * Get the index of the address in the agent's list. - * - * @param agent agent handle - * @param address address handle - * @return the index, starting with zero - */ -static int -agent_address_get_index (struct RIL_Peer_Agent *agent, struct - ATS_Address *address) -{ - int i; - struct RIL_Address_Wrapped *cur; - - i = -1; - for (cur = agent->addresses_head; NULL != cur; cur = cur->next) - { - i++; - if (cur->address_naked == address) - return i; - } - return i; -} - - -/** - * Gets the wrapped address from the agent's list - * - * @param agent agent handle - * @param address address handle - * @return wrapped address - */ -static struct RIL_Address_Wrapped * -agent_address_get_wrapped (struct RIL_Peer_Agent *agent, struct - ATS_Address *address) -{ - struct RIL_Address_Wrapped *cur; - - for (cur = agent->addresses_head; NULL != cur; cur = cur->next) - if (cur->address_naked == address) - return cur; - return NULL; -} - - -static int -agent_action_is_possible (struct RIL_Peer_Agent *agent, int action) -{ - int address_index; - - switch (action) - { - case RIL_ACTION_NOTHING: - return GNUNET_YES; - break; - - case RIL_ACTION_BW_IN_INC: - case RIL_ACTION_BW_IN_DBL: - if (agent->bw_in >= RIL_MAX_BW) - return GNUNET_NO; - else - return GNUNET_YES; - break; - - case RIL_ACTION_BW_IN_DEC: - case RIL_ACTION_BW_IN_HLV: - if (agent->bw_in <= 0) - return GNUNET_NO; - else - return GNUNET_YES; - break; - - case RIL_ACTION_BW_OUT_INC: - case RIL_ACTION_BW_OUT_DBL: - if (agent->bw_out >= RIL_MAX_BW) - return GNUNET_NO; - else - return GNUNET_YES; - break; - - case RIL_ACTION_BW_OUT_DEC: - case RIL_ACTION_BW_OUT_HLV: - if (agent->bw_out <= 0) - return GNUNET_NO; - else - return GNUNET_YES; - break; - - default: - if ((action >= RIL_ACTION_TYPE_NUM) && (action < agent->n)) // switch address action - { - address_index = action - RIL_ACTION_TYPE_NUM; - - GNUNET_assert (address_index >= 0); - GNUNET_assert ( - address_index <= agent_address_get_index (agent, - agent->addresses_tail-> - address_naked)); - - if ((agent_address_get_index (agent, agent->address_inuse) == - address_index) || - agent->address_inuse->active) - return GNUNET_NO; - else - return GNUNET_YES; - break; - } - // error - action does not exist - GNUNET_assert (GNUNET_NO); - } -} - - -/** - * Gets the action, with the maximal estimated Q-value (i.e. the one currently estimated to bring the - * most reward in the future) - * - * @param agent agent performing the calculation - * @param state the state from which to take the action - * @return the action promising most future reward - */ -static int -agent_get_action_max (struct RIL_Peer_Agent *agent, double *state) -{ - int i; - int max_i = RIL_ACTION_INVALID; - double cur_q; - double max_q = -DBL_MAX; - - for (i = 0; i < agent->n; i++) - { - if (agent_action_is_possible (agent, i)) - { - cur_q = agent_q (agent, state, i); - if (cur_q > max_q) - { - max_q = cur_q; - max_i = i; - } - } - } - - GNUNET_assert (RIL_ACTION_INVALID != max_i); - - return max_i; -} - -/** - * Chooses a random action from the set of possible ones - * - * @param agent the agent performing the action - * @return the action index - */ -static int -agent_get_action_random (struct RIL_Peer_Agent *agent) -{ - int i; - int is_possible[agent->n]; - int sum = 0; - int r; - - for (i = 0; i < agent->n; i++) - { - if (agent_action_is_possible (agent, i)) - { - is_possible[i] = GNUNET_YES; - sum++; - } - else - { - is_possible[i] = GNUNET_NO; - } - } - - r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, sum); - - sum = -1; - for (i = 0; i < agent->n; i++) - { - if (is_possible[i]) - { - sum++; - if (sum == r) - return i; - } - } - - GNUNET_assert (GNUNET_NO); - return RIL_ACTION_INVALID; -} - - -/** - * Updates the weights (i.e. coefficients) of the weight vector in matrix W for action a - * - * @param agent the agent performing the update - * @param reward the reward received for the last action - * @param s_next the new state, the last step got the agent into - * @param a_prime the new - */ -static void -agent_update (struct RIL_Peer_Agent *agent, double reward, double *s_next, int - a_prime) -{ - int i; - int k; - double delta; - double **theta = agent->W; - - delta = agent->envi->global_discount_integrated * reward; // reward - delta += agent->envi->global_discount_variable * agent_q (agent, s_next, - a_prime); // discounted future value - delta -= agent_q (agent, agent->s_old, agent->a_old); // one step - -// LOG(GNUNET_ERROR_TYPE_INFO, "update() Step# %llu Q(s,a): %f a: %f r: %f y: %f Q(s+1,a+1) = %f delta: %f\n", -// agent->step_count, -// agent_q (agent, agent->s_old, agent->a_old), -// agent->envi->parameters.alpha, -// reward, -// agent->envi->global_discount_variable, -// agent_q (agent, s_next, a_prime), -// delta); - - for (k = 0; k < agent->n; k++) - { - for (i = 0; i < agent->m; i++) - { - // LOG(GNUNET_ERROR_TYPE_INFO, "alpha = %f delta = %f e[%d] = %f\n", - // agent->envi->parameters.alpha, - // delta, - // i, - // agent->e[i]); - theta[k][i] += agent->envi->parameters.alpha * delta * agent->E[k][i]; - } - } -} - - -/** - * Changes the eligibility trace vector e in various manners: - * #RIL_E_ACCUMULATE - adds @a feature to each component as in accumulating eligibility traces - * #RIL_E_REPLACE - resets each component to @a feature as in replacing traces - * #RIL_E_DECAY - multiplies e with discount factor and lambda as in the update rule - * #RIL_E_ZERO - sets e to 0 as in Watkin's Q-learning algorithm when exploring and when initializing - * - * @param agent the agent handle - * @param mod the kind of modification - * @param feature the feature vector - * @param action the action to take - */ -static void -agent_modify_eligibility (struct RIL_Peer_Agent *agent, - enum RIL_E_Modification mod, - double *feature, - int action) -{ - int i; - int k; - - for (i = 0; i < agent->m; i++) - { - switch (mod) - { - case RIL_E_ACCUMULATE: - agent->E[action][i] += feature[i]; - break; - - case RIL_E_REPLACE: - agent->E[action][i] = agent->E[action][i] > feature[i] ? - agent->E[action][i] : feature[i]; - break; - - case RIL_E_DECAY: - for (k = 0; k < agent->n; k++) - { - agent->E[k][i] *= agent->envi->global_discount_variable - * agent->envi->parameters.lambda; - } - break; - - case RIL_E_ZERO: - for (k = 0; k < agent->n; k++) - { - agent->E[k][i] = 0; - } - break; - } - } -} - -/** - * Informs the environment about the status of the solver - * - * @param solver - * @param op - * @param stat - */ -static void -ril_inform (struct GAS_RIL_Handle *solver, - enum GAS_Solver_Operation op, - enum GAS_Solver_Status stat) -{ - solver->env->info_cb (solver->env->cls, - op, - stat, - GAS_INFO_NONE); -} - -/** - * Calculates the maximum bandwidth an agent can assign in a network scope - * - * @param net - */ -static unsigned long long -ril_get_max_bw (struct RIL_Scope *net) -{ - return GNUNET_MIN (2 * GNUNET_MAX (net->bw_in_available, - net->bw_out_available), - GNUNET_ATS_MaxBandwidth); -} - -/** - * Changes the active assignment suggestion of the handler and invokes the bw_changed callback to - * notify ATS of its new decision - * - * @param solver solver handle - * @param agent agent handle - * @param new_address the address which is to be used - * @param new_bw_in the new amount of inbound bandwidth set for this address - * @param new_bw_out the new amount of outbound bandwidth set for this address - * @param silent disables invocation of the bw_changed callback, if #GNUNET_YES - */ -static void -envi_set_active_suggestion (struct GAS_RIL_Handle *solver, - struct RIL_Peer_Agent *agent, - struct ATS_Address *new_address, - unsigned long long new_bw_in, - unsigned long long new_bw_out, - int silent) -{ - int notify = GNUNET_NO; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - " set_active_suggestion() for peer '%s'\n", - GNUNET_i2s (&agent->peer)); - - // address change - if (agent->address_inuse != new_address) - { - if (NULL != agent->address_inuse) - { - agent->address_inuse->active = GNUNET_NO; - agent->address_inuse->assigned_bw_in = 0; - agent->address_inuse->assigned_bw_out = 0; - } - if (NULL != new_address) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, " set address active: %s\n", - agent->is_active ? "yes" : "no"); - new_address->active = agent->is_active; - new_address->assigned_bw_in = agent->bw_in; - new_address->assigned_bw_out = agent->bw_out; - } - notify |= GNUNET_YES; - } - - if (new_address) - { - // activity change - if (new_address->active != agent->is_active) - { - new_address->active = agent->is_active; - notify |= GNUNET_YES; - } - - // bw change - if (agent->bw_in != new_bw_in) - { - agent->bw_in = new_bw_in; - new_address->assigned_bw_in = new_bw_in; - notify |= GNUNET_YES; - } - if (agent->bw_out != new_bw_out) - { - agent->bw_out = new_bw_out; - new_address->assigned_bw_out = new_bw_out; - notify |= GNUNET_YES; - } - } - - if (notify && agent->is_active && (GNUNET_NO == silent)) - { - if (new_address) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - " envi_set_active_suggestion() notify\n"); - agent->suggestion_issue = GNUNET_YES; - agent->suggestion_address = new_address; - } - else if (agent->address_inuse) - { - /* disconnect case, no new address */ - GNUNET_assert (0 == agent->address_inuse->assigned_bw_in); - GNUNET_assert (0 == agent->address_inuse->assigned_bw_out); - agent->bw_in = 0; - agent->bw_out = 0; - - agent->suggestion_issue = GNUNET_YES; - agent->suggestion_address = agent->address_inuse; - } - } - agent->address_inuse = new_address; -} - - -/** - * Allocates a state vector and fills it with the features present - * @param solver the solver handle - * @param agent the agent handle - * @return pointer to the state vector - */ -static double * -envi_get_state (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent) -{ - double *state; - double y[2]; - double x[2]; - double d[2]; - double sigma; - double f; - int m; - int i; - int k; - unsigned long long max_bw; - - state = GNUNET_malloc (sizeof(double) * agent->m); - - max_bw = ril_get_max_bw ((struct - RIL_Scope *) agent->address_inuse-> - solver_information); - - y[0] = (double) agent->bw_out; - y[1] = (double) agent->bw_in; - - m = agent_address_get_index (agent, agent->address_inuse) - * (solver->parameters.rbf_divisor + 1) * (solver->parameters.rbf_divisor - + 1); - for (i = 0; i <= solver->parameters.rbf_divisor; i++) - { - for (k = 0; k <= solver->parameters.rbf_divisor; k++) - { - x[0] = (double) i * (double) max_bw - / (double) solver->parameters.rbf_divisor; - x[1] = (double) k * (double) max_bw - / (double) solver->parameters.rbf_divisor; - d[0] = x[0] - y[0]; - d[1] = x[1] - y[1]; - sigma = (((double) max_bw / ((double) solver->parameters.rbf_divisor - + 1)) * 0.5); - f = exp (-((d[0] * d[0] + d[1] * d[1]) / (2 * sigma * sigma))); - state[m++] = f; - } - } - - return state; -} - - -/** - * Returns the utility value of the connection an agent manages - * - * @param agent the agent in question - * @return the utility value - */ -static double -agent_get_utility (struct RIL_Peer_Agent *agent) -{ - const double *preferences; - double delay_atsi; - double delay_norm; - double pref_match; - - preferences = agent->envi->env->get_preferences (agent->envi->env->cls, - &agent->peer); - - delay_atsi = agent->address_inuse->norm_delay.norm; - delay_norm = RIL_UTILITY_DELAY_MAX * exp (-delay_atsi * 0.00001); - - pref_match = preferences[GNUNET_ATS_PREFERENCE_LATENCY] * delay_norm; - pref_match += preferences[GNUNET_ATS_PREFERENCE_BANDWIDTH] - * sqrt ((double) (agent->bw_in / RIL_MIN_BW) - * (double) (agent->bw_out / RIL_MIN_BW)); - return pref_match; -} - -/** - * Calculates the social welfare within a network scope according to what social - * welfare measure is set in the configuration. - * - * @param solver the solver handle - * @param scope the network scope in question - * @return the social welfare value - */ -static double -ril_network_get_social_welfare (struct GAS_RIL_Handle *solver, struct - RIL_Scope *scope) -{ - struct RIL_Peer_Agent *cur; - double result; - - switch (solver->parameters.social_welfare) - { - case RIL_WELFARE_EGALITARIAN: - result = DBL_MAX; - for (cur = solver->agents_head; NULL != cur; cur = cur->next) - { - if (cur->is_active && cur->address_inuse && - (cur->address_inuse->solver_information == scope)) - { - result = GNUNET_MIN (result, agent_get_utility (cur)); - } - } - return result; - - case RIL_WELFARE_NASH: - result = 0; - for (cur = solver->agents_head; NULL != cur; cur = cur->next) - { - if (cur->is_active && cur->address_inuse && - (cur->address_inuse->solver_information == scope)) - { - result *= pow (agent_get_utility (cur), 1.0 - / (double) scope->active_agent_count); - } - } - return result; - } - GNUNET_assert (GNUNET_NO); - return 1; -} - -static double -envi_get_penalty (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent) -{ - struct RIL_Scope *net; - unsigned long long over_max; - unsigned long long over_in = 0; - unsigned long long over_out = 0; - - net = agent->address_inuse->solver_information; - - if (net->bw_in_utilized > net->bw_in_available) - { - over_in = net->bw_in_utilized - net->bw_in_available; - if (RIL_ACTION_BW_IN_INC == agent->a_old) - { - /* increase quadratically */ - over_in *= over_in; - } - } - if (net->bw_out_utilized > net->bw_out_available) - { - over_out = net->bw_out_utilized - net->bw_out_available; - if (RIL_ACTION_BW_OUT_INC == agent->a_old) - { - /* increase quadratically */ - over_out *= over_out; - } - } - over_max = (over_in + over_out) / (RIL_MIN_BW * RIL_MIN_BW); - - return -1.0 * (double) over_max; -} - -/** - * Gets the reward for the last performed step, which is calculated in equal - * parts from the local (the peer specific) and the global (for all peers - * identical) reward. - * - * @param solver the solver handle - * @param agent the agent handle - * @return the reward - */ -static double -envi_get_reward (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent) -{ - struct RIL_Scope *net; - double objective; - double delta; - double steady; - double penalty; - double reward; - - net = agent->address_inuse->solver_information; - - penalty = envi_get_penalty (solver, agent); - objective = (agent_get_utility (agent) + net->social_welfare) / 2; - delta = objective - agent->objective_old; - agent->objective_old = objective; - - if ((delta != 0)&&(penalty == 0)) - { - agent->nop_bonus = delta * RIL_NOP_DECAY; - } - else - { - agent->nop_bonus *= RIL_NOP_DECAY; - } - - steady = (RIL_ACTION_NOTHING == agent->a_old) ? agent->nop_bonus : 0; - - reward = delta + steady; - return reward + penalty; -} - -/** - * Doubles the bandwidth for the active address - * - * @param solver solver handle - * @param agent agent handle - * @param direction_in if GNUNET_YES, change inbound bandwidth, otherwise the outbound bandwidth - */ -static void -envi_action_bw_double (struct GAS_RIL_Handle *solver, - struct RIL_Peer_Agent *agent, - int direction_in) -{ - unsigned long long new_bw; - unsigned long long max_bw; - - max_bw = ril_get_max_bw ((struct - RIL_Scope *) agent->address_inuse-> - solver_information); - - if (direction_in) - { - new_bw = agent->bw_in * 2; - if ((new_bw < agent->bw_in) ||(new_bw > max_bw) ) - new_bw = max_bw; - envi_set_active_suggestion (solver, agent, agent->address_inuse, new_bw, - agent->bw_out, GNUNET_NO); - } - else - { - new_bw = agent->bw_out * 2; - if ((new_bw < agent->bw_out) ||(new_bw > max_bw) ) - new_bw = max_bw; - envi_set_active_suggestion (solver, agent, agent->address_inuse, - agent->bw_in, - new_bw, GNUNET_NO); - } -} - -/** - * Cuts the bandwidth for the active address in half. The least amount of bandwidth suggested, is - * the minimum bandwidth for a peer, in order to not invoke a disconnect. - * - * @param solver solver handle - * @param agent agent handle - * @param direction_in if GNUNET_YES, change inbound bandwidth, otherwise change the outbound - * bandwidth - */ -static void -envi_action_bw_halven (struct GAS_RIL_Handle *solver, - struct RIL_Peer_Agent *agent, - int direction_in) -{ - unsigned long long new_bw; - - if (direction_in) - { - new_bw = agent->bw_in / 2; - if ((new_bw <= 0) ||(new_bw > agent->bw_in) ) - new_bw = 0; - envi_set_active_suggestion (solver, agent, agent->address_inuse, new_bw, - agent->bw_out, - GNUNET_NO); - } - else - { - new_bw = agent->bw_out / 2; - if ((new_bw <= 0) ||(new_bw > agent->bw_out) ) - new_bw = 0; - envi_set_active_suggestion (solver, agent, agent->address_inuse, - agent->bw_in, new_bw, - GNUNET_NO); - } -} - -/** - * Increases the bandwidth by 5 times the minimum bandwidth for the active address. - * - * @param solver solver handle - * @param agent agent handle - * @param direction_in if GNUNET_YES, change inbound bandwidth, otherwise change the outbound - * bandwidth - */ -static void -envi_action_bw_inc (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, - int direction_in) -{ - unsigned long long new_bw; - unsigned long long max_bw; - - max_bw = ril_get_max_bw ((struct - RIL_Scope *) agent->address_inuse-> - solver_information); - - if (direction_in) - { - new_bw = agent->bw_in + (RIL_INC_DEC_STEP_SIZE * RIL_MIN_BW); - if ((new_bw < agent->bw_in) ||(new_bw > max_bw) ) - new_bw = max_bw; - envi_set_active_suggestion (solver, agent, agent->address_inuse, new_bw, - agent->bw_out, GNUNET_NO); - } - else - { - new_bw = agent->bw_out + (RIL_INC_DEC_STEP_SIZE * RIL_MIN_BW); - if ((new_bw < agent->bw_out) ||(new_bw > max_bw) ) - new_bw = max_bw; - envi_set_active_suggestion (solver, agent, agent->address_inuse, - agent->bw_in, - new_bw, GNUNET_NO); - } -} - -/** - * Decreases the bandwidth by 5 times the minimum bandwidth for the active address. The least amount - * of bandwidth suggested, is the minimum bandwidth for a peer, in order to not invoke a disconnect. - * - * @param solver solver handle - * @param agent agent handle - * @param direction_in if GNUNET_YES, change inbound bandwidth, otherwise change the outbound - * bandwidth - */ -static void -envi_action_bw_dec (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, - int direction_in) -{ - unsigned long long new_bw; - - if (direction_in) - { - new_bw = agent->bw_in - (RIL_INC_DEC_STEP_SIZE * RIL_MIN_BW); - if ((new_bw <= 0) ||(new_bw > agent->bw_in) ) - new_bw = 0; - envi_set_active_suggestion (solver, agent, agent->address_inuse, new_bw, - agent->bw_out, - GNUNET_NO); - } - else - { - new_bw = agent->bw_out - (RIL_INC_DEC_STEP_SIZE * RIL_MIN_BW); - if ((new_bw <= 0) ||(new_bw > agent->bw_out) ) - new_bw = 0; - envi_set_active_suggestion (solver, agent, agent->address_inuse, - agent->bw_in, new_bw, - GNUNET_NO); - } -} - -/** - * Switches to the address given by its index - * - * @param solver solver handle - * @param agent agent handle - * @param address_index index of the address as it is saved in the agent's list, starting with zero - */ -static void -envi_action_address_switch (struct GAS_RIL_Handle *solver, - struct RIL_Peer_Agent *agent, - unsigned int address_index) -{ - struct RIL_Address_Wrapped *cur; - int i = 0; - - // cur = agent_address_get_wrapped(agent, agent->address_inuse); - - for (cur = agent->addresses_head; NULL != cur; cur = cur->next) - { - if (i == address_index) - { - envi_set_active_suggestion (solver, agent, cur->address_naked, - agent->bw_in, agent->bw_out, - GNUNET_NO); - return; - } - - i++; - } - - // no address with address_index exists, in this case this action should not be callable - GNUNET_assert (GNUNET_NO); -} - -/** - * Puts the action into effect by calling the according function - * - * @param solver the solver handle - * @param agent the action handle - * @param action the action to perform by the solver - */ -static void -envi_do_action (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, int - action) -{ - int address_index; - - switch (action) - { - case RIL_ACTION_NOTHING: - break; - - case RIL_ACTION_BW_IN_DBL: - envi_action_bw_double (solver, agent, GNUNET_YES); - break; - - case RIL_ACTION_BW_IN_HLV: - envi_action_bw_halven (solver, agent, GNUNET_YES); - break; - - case RIL_ACTION_BW_IN_INC: - envi_action_bw_inc (solver, agent, GNUNET_YES); - break; - - case RIL_ACTION_BW_IN_DEC: - envi_action_bw_dec (solver, agent, GNUNET_YES); - break; - - case RIL_ACTION_BW_OUT_DBL: - envi_action_bw_double (solver, agent, GNUNET_NO); - break; - - case RIL_ACTION_BW_OUT_HLV: - envi_action_bw_halven (solver, agent, GNUNET_NO); - break; - - case RIL_ACTION_BW_OUT_INC: - envi_action_bw_inc (solver, agent, GNUNET_NO); - break; - - case RIL_ACTION_BW_OUT_DEC: - envi_action_bw_dec (solver, agent, GNUNET_NO); - break; - - default: - if ((action >= RIL_ACTION_TYPE_NUM) && (action < agent->n)) // switch address action - { - address_index = action - RIL_ACTION_TYPE_NUM; - - GNUNET_assert (address_index >= 0); - GNUNET_assert ( - address_index <= agent_address_get_index (agent, - agent->addresses_tail-> - address_naked)); - - envi_action_address_switch (solver, agent, address_index); - break; - } - // error - action does not exist - GNUNET_assert (GNUNET_NO); - } -} - -/** - * Selects the next action using the e-greedy strategy. I.e. with a probability - * of (1-e) the action with the maximum expected return will be chosen - * (=> exploitation) and with probability (e) a random action will be chosen. - * In case the Q-learning rule is set, the function also resets the eligibility - * traces in the exploration case (after Watkin's Q-learning). - * - * @param agent the agent selecting an action - * @param state the current state-feature vector - * @return the action index - */ -static int -agent_select_egreedy (struct RIL_Peer_Agent *agent, double *state) -{ - int action; - double r = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT32_MAX) - / (double) UINT32_MAX; - - if (r < agent->envi->parameters.epsilon) // explore - { - action = agent_get_action_random (agent); - if (RIL_ALGO_Q == agent->envi->parameters.algorithm) - { - agent->eligibility_reset = GNUNET_YES; - } - agent->envi->parameters.epsilon *= agent->envi->parameters.epsilon_decay; - return action; - } - else // exploit - { - action = agent_get_action_max (agent, state); - return action; - } -} - -/** - * Selects the next action with a probability corresponding to its value. The - * probability is calculated using a Boltzmann distribution with a temperature - * value. The higher the temperature, the more are the action selection - * probabilities the same. With a temperature of 0, the selection is greedy, - * i.e. always the action with the highest value is chosen. - * @param agent - * @param state - * @return - */ -static int -agent_select_softmax (struct RIL_Peer_Agent *agent, double *state) -{ - int i; - int a_max; - double eqt[agent->n]; - double p[agent->n]; - double sum = 0; - double r; - - a_max = agent_get_action_max (agent, state); - - for (i = 0; i < agent->n; i++) - { - if (agent_action_is_possible (agent, i)) - { - eqt[i] = exp (agent_q (agent, state, i) - / agent->envi->parameters.temperature); - if (isinf (eqt[i])) - eqt[i] = isinf (eqt[i]) * UINT32_MAX; - sum += eqt[i]; - } - } - for (i = 0; i < agent->n; i++) - { - if (agent_action_is_possible (agent, i)) - { - p[i] = eqt[i] / sum; - } - else - { - p[i] = 0; - } - } - r = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT32_MAX) / (double) UINT32_MAX; - sum = 0; - for (i = 0; i < agent->n; i++) - { - if (sum + p[i] > r) - { - if (i != a_max) - { - if (RIL_ALGO_Q == agent->envi->parameters.algorithm) - agent->eligibility_reset = GNUNET_YES; - agent->envi->parameters.temperature *= - agent->envi->parameters.temperature_decay; - } - return i; - } - sum += p[i]; - } - GNUNET_assert (GNUNET_NO); - return RIL_ACTION_INVALID; -} - -/** - * Select the next action of an agent either according to the e-greedy strategy - * or the softmax strategy. - * - * @param agent the agent in question - * @param state the current state-feature vector - * @return the action index - */ -static int -agent_select_action (struct RIL_Peer_Agent *agent, double *state) -{ - if (agent->envi->parameters.select == RIL_SELECT_EGREEDY) - { - return agent_select_egreedy (agent, state); - } - else - { - return agent_select_softmax (agent, state); - } -} - -/** - * Performs one step of the Markov Decision Process. Other than in the literature the step starts - * after having done the last action a_old. It observes the new state s_next and the reward - * received. Then the coefficient update is done according to the SARSA or Q-learning method. The - * next action is put into effect. - * - * @param agent the agent performing the step - */ -static void -agent_step (struct RIL_Peer_Agent *agent) -{ - int a_next = RIL_ACTION_INVALID; - int a_max; - double *s_next; - double reward; - - LOG (GNUNET_ERROR_TYPE_DEBUG, " agent_step() Peer '%s', algorithm %s\n", - GNUNET_i2s (&agent->peer), - agent->envi->parameters.algorithm ? "Q" : "SARSA"); - - s_next = envi_get_state (agent->envi, agent); - reward = envi_get_reward (agent->envi, agent); - - if (agent->eligibility_reset) - { - agent_modify_eligibility (agent, RIL_E_ZERO, NULL, -1); - agent->eligibility_reset = GNUNET_NO; - } - else - { - agent_modify_eligibility (agent, RIL_E_DECAY, NULL, -1); - } - if (RIL_ACTION_INVALID != agent->a_old) - { - agent_modify_eligibility (agent, - agent->envi->parameters.eligibility_trace_mode, - agent->s_old, agent->a_old); - } - - switch (agent->envi->parameters.algorithm) - { - case RIL_ALGO_SARSA: - a_next = agent_select_action (agent, s_next); - if (RIL_ACTION_INVALID != agent->a_old) - { - // updates weights with selected action (on-policy), if not first step - agent_update (agent, reward, s_next, a_next); - } - break; - - case RIL_ALGO_Q: - a_max = agent_get_action_max (agent, s_next); - if (RIL_ACTION_INVALID != agent->a_old) - { - // updates weights with best action, disregarding actually selected action (off-policy), if not first step - agent_update (agent, reward, s_next, a_max); - } - a_next = agent_select_action (agent, s_next); - break; - } - - GNUNET_assert (RIL_ACTION_INVALID != a_next); - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "step() Step# %llu R: %f IN %llu OUT %llu A: %d\n", - agent->step_count, - reward, - agent->bw_in / 1024, - agent->bw_out / 1024, - a_next); - - envi_do_action (agent->envi, agent, a_next); - - GNUNET_free (agent->s_old); - agent->s_old = s_next; - agent->a_old = a_next; - - agent->step_count += 1; -} - -/** - * Prototype of the ril_step() procedure - * - * @param solver the solver handle - */ -static void -ril_step (struct GAS_RIL_Handle *solver); - - -/** - * Task for the scheduler, which performs one step and lets the solver know that - * no further step is scheduled. - * - * @param cls the solver handle - */ -static void -ril_step_scheduler_task (void *cls) -{ - struct GAS_RIL_Handle *solver = cls; - - solver->step_next_task_id = NULL; - ril_step (solver); -} - -/** - * Determines how much of the available bandwidth is assigned. If more is - * assigned than available it returns 1. The function is used to determine the - * step size of the adaptive stepping. - * - * @param solver the solver handle - * @return the ratio - */ -static double -ril_get_used_resource_ratio (struct GAS_RIL_Handle *solver) -{ - int i; - struct RIL_Scope net; - unsigned long long sum_assigned = 0; - unsigned long long sum_available = 0; - double ratio; - - for (i = 0; i < solver->networks_count; i++) - { - net = solver->network_entries[i]; - if (net.bw_in_assigned > 0) // only consider scopes where an address is actually active - { - sum_assigned += net.bw_in_utilized; - sum_assigned += net.bw_out_utilized; - sum_available += net.bw_in_available; - sum_available += net.bw_out_available; - } - } - if (sum_available > 0) - { - ratio = ((double) sum_assigned) / ((double) sum_available); - } - else - { - ratio = 0; - } - - return ratio > 1 ? 1 : ratio; // overutilization is possible, cap at 1 -} - -/** - * Lookup network struct by type - * - * @param s the solver handle - * @param type the network type - * @return the network struct - */ -static struct RIL_Scope * -ril_get_network (struct GAS_RIL_Handle *s, uint32_t type) -{ - int i; - - for (i = 0; i < s->networks_count; i++) - { - if (s->network_entries[i].type == type) - { - return &s->network_entries[i]; - } - } - return NULL; -} - -/** - * Determines whether more connections are allocated in a network scope, than - * they would theoretically fit. This is used as a heuristic to determine, - * whether a new connection can be allocated or not. - * - * @param solver the solver handle - * @param network the network scope in question - * @return GNUNET_YES if there are theoretically enough resources left - */ -static int -ril_network_is_not_full (struct GAS_RIL_Handle *solver, enum GNUNET_NetworkType - network) -{ - struct RIL_Scope *net; - struct RIL_Peer_Agent *agent; - unsigned long long address_count = 0; - - for (agent = solver->agents_head; NULL != agent; agent = agent->next) - { - if (agent->address_inuse && agent->is_active) - { - net = agent->address_inuse->solver_information; - if (net->type == network) - { - address_count++; - } - } - } - - net = ril_get_network (solver, network); - return (net->bw_in_available > RIL_MIN_BW * address_count) && - (net->bw_out_available > RIL_MIN_BW * address_count); -} - -/** - * Unblocks an agent for which a connection request is there, that could not - * be satisfied. Iterates over the addresses of the agent, if one of its - * addresses can now be allocated in its scope the agent is unblocked, - * otherwise it remains unchanged. - * - * @param solver the solver handle - * @param agent the agent in question - * @param silent - */ -static void -ril_try_unblock_agent (struct GAS_RIL_Handle *solver, struct - RIL_Peer_Agent *agent, int silent) -{ - struct RIL_Address_Wrapped *addr_wrap; - struct RIL_Scope *net; - unsigned long long start_in; - unsigned long long start_out; - - for (addr_wrap = agent->addresses_head; NULL != addr_wrap; addr_wrap = - addr_wrap->next) - { - net = addr_wrap->address_naked->solver_information; - if (ril_network_is_not_full (solver, net->type)) - { - if (NULL == agent->address_inuse) - { - start_in = net->bw_in_available < net->bw_in_utilized ? - (net->bw_in_available - net->bw_in_utilized) / 2 : - RIL_MIN_BW; - start_out = net->bw_out_available < net->bw_out_utilized ? - (net->bw_out_available - net->bw_out_utilized) / 2 : - RIL_MIN_BW; - envi_set_active_suggestion (solver, agent, addr_wrap->address_naked, - start_in, start_out, silent); - } - return; - } - } - agent->address_inuse = NULL; -} - -/** - * Determines how much the reward needs to be discounted depending on the amount - * of time, which has passed since the last time-step. - * - * @param solver the solver handle - */ -static void -ril_calculate_discount (struct GAS_RIL_Handle *solver) -{ - struct GNUNET_TIME_Absolute time_now; - struct GNUNET_TIME_Relative time_delta; - double tau; - - // MDP case only for debugging purposes - if (solver->simulate) - { - solver->global_discount_variable = solver->parameters.gamma; - solver->global_discount_integrated = 1; - return; - } - - // semi-MDP case - - // calculate tau, i.e. how many real valued time units have passed, one time unit is one minimum time step - time_now = GNUNET_TIME_absolute_get (); - time_delta = GNUNET_TIME_absolute_get_difference (solver->step_time_last, - time_now); - solver->step_time_last = time_now; - tau = (double) time_delta.rel_value_us - / (double) solver->parameters.step_time_min.rel_value_us; - - // calculate reward discounts (once per step for all agents) - solver->global_discount_variable = pow (M_E, ((-1.0) - * ((double) solver->parameters. - beta) * tau)); - solver->global_discount_integrated = (1.0 - solver->global_discount_variable) - / (double) solver->parameters.beta; -} - -/** - * Count the number of active agents/connections in a network scope - * - * @param solver the solver handle - * @param scope the network scope in question - * @return the number of allocated connections - */ -static int -ril_network_count_active_agents (struct GAS_RIL_Handle *solver, struct - RIL_Scope *scope) -{ - int c = 0; - struct RIL_Peer_Agent *cur_agent; - - for (cur_agent = solver->agents_head; NULL != cur_agent; cur_agent = - cur_agent->next) - { - if (cur_agent->is_active && cur_agent->address_inuse && - (cur_agent->address_inuse->solver_information == scope)) - { - c++; - } - } - return c; -} - -/** - * Calculates how much bandwidth is assigned in sum in a network scope, either - * in the inbound or in the outbound direction. - * - * @param solver the solver handle - * @param type the type of the network scope in question - * @param direction_in GNUNET_YES if the inbound direction should be summed up, - * otherwise the outbound direction will be summed up - * @return the sum of the assigned bandwidths - */ -static unsigned long long -ril_network_get_assigned (struct GAS_RIL_Handle *solver, enum GNUNET_NetworkType - type, int direction_in) -{ - struct RIL_Peer_Agent *cur; - struct RIL_Scope *net; - unsigned long long sum = 0; - - for (cur = solver->agents_head; NULL != cur; cur = cur->next) - { - if (cur->is_active && cur->address_inuse) - { - net = cur->address_inuse->solver_information; - if (net->type == type) - { - if (direction_in) - sum += cur->bw_in; - else - sum += cur->bw_out; - } - } - } - - return sum; -} - -/** - * Calculates how much bandwidth is actually utilized in sum in a network scope, - * either in the inbound or in the outbound direction. - * - * @param solver the solver handle - * @param type the type of the network scope in question - * @param direction_in GNUNET_YES if the inbound direction should be summed up, - * otherwise the outbound direction will be summed up - * @return the sum of the utilized bandwidths (in bytes/second) - */ -static unsigned long long -ril_network_get_utilized (struct GAS_RIL_Handle *solver, enum GNUNET_NetworkType - type, int direction_in) -{ - struct RIL_Peer_Agent *cur; - struct RIL_Scope *net; - unsigned long long sum = 0; - - for (cur = solver->agents_head; NULL != cur; cur = cur->next) - { - if (cur->is_active && cur->address_inuse) - { - net = cur->address_inuse->solver_information; - if (net->type == type) - { - if (direction_in) - sum += cur->address_inuse->norm_utilization_in.norm; - else - sum += cur->address_inuse->norm_utilization_out.norm; - } - } - } - - return sum; -} - -/** - * Retrieves the state of the network scope, so that its attributes are up-to- - * date. - * - * @param solver the solver handle - */ -static void -ril_networks_update_state (struct GAS_RIL_Handle *solver) -{ - int c; - struct RIL_Scope *net; - - for (c = 0; c < solver->networks_count; c++) - { - net = &solver->network_entries[c]; - net->bw_in_assigned = ril_network_get_assigned (solver, net->type, - GNUNET_YES); - net->bw_in_utilized = ril_network_get_utilized (solver, net->type, - GNUNET_YES); - net->bw_out_assigned = ril_network_get_assigned (solver, net->type, - GNUNET_NO); - net->bw_out_utilized = ril_network_get_utilized (solver, net->type, - GNUNET_NO); - net->active_agent_count = ril_network_count_active_agents (solver, net); - net->social_welfare = ril_network_get_social_welfare (solver, net); - } -} - -/** - * Schedules the next global step in an adaptive way. The more resources are - * left, the earlier the next step is scheduled. This serves the reactivity of - * the solver to changed inputs. - * - * @param solver the solver handle - */ -static void -ril_step_schedule_next (struct GAS_RIL_Handle *solver) -{ - double used_ratio; - double factor; - double y; - double offset; - struct GNUNET_TIME_Relative time_next; - - used_ratio = ril_get_used_resource_ratio (solver); - - GNUNET_assert ( - solver->parameters.step_time_min.rel_value_us - <= solver->parameters.step_time_max.rel_value_us); - - factor = (double) GNUNET_TIME_relative_subtract ( - solver->parameters.step_time_max, - solver->parameters. - step_time_min).rel_value_us; - offset = (double) solver->parameters.step_time_min.rel_value_us; - y = factor * pow (used_ratio, RIL_INTERVAL_EXPONENT) + offset; - - GNUNET_assert (y <= (double) solver->parameters.step_time_max.rel_value_us); - GNUNET_assert (y >= (double) solver->parameters.step_time_min.rel_value_us); - - time_next = GNUNET_TIME_relative_saturating_multiply ( - GNUNET_TIME_UNIT_MICROSECONDS, (unsigned long long) y); - -// LOG (GNUNET_ERROR_TYPE_INFO, "ratio: %f, factor: %f, offset: %f, y: %f\n", -// used_ratio, -// factor, -// offset, -// y); - - if (solver->simulate) - { - time_next = GNUNET_TIME_UNIT_ZERO; - } - - if ((NULL == solver->step_next_task_id) && (GNUNET_NO == solver->done)) - { - solver->step_next_task_id = GNUNET_SCHEDULER_add_delayed (time_next, - & - ril_step_scheduler_task, - solver); - } -} - -/** - * Triggers one step per agent - * - * @param solver - */ -static void -ril_step (struct GAS_RIL_Handle *solver) -{ - struct RIL_Peer_Agent *cur; - - if (GNUNET_YES == solver->bulk_lock) - { - solver->bulk_changes++; - return; - } - - ril_inform (solver, GAS_OP_SOLVE_START, GAS_STAT_SUCCESS); - - LOG (GNUNET_ERROR_TYPE_DEBUG, " RIL step number %d\n", solver->step_count); - - if (0 == solver->step_count) - { - solver->step_time_last = GNUNET_TIME_absolute_get (); - } - - ril_calculate_discount (solver); - ril_networks_update_state (solver); - - // trigger one step per active, unblocked agent - for (cur = solver->agents_head; NULL != cur; cur = cur->next) - { - if (cur->is_active) - { - if (NULL == cur->address_inuse) - { - ril_try_unblock_agent (solver, cur, GNUNET_NO); - } - if (cur->address_inuse) - { - agent_step (cur); - } - } - } - - ril_networks_update_state (solver); - - solver->step_count++; - ril_step_schedule_next (solver); - - ril_inform (solver, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS); - - ril_inform (solver, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START, GAS_STAT_SUCCESS); - for (cur = solver->agents_head; NULL != cur; cur = cur->next) - { - if (cur->suggestion_issue) - { - solver->env->bandwidth_changed_cb (solver->env->cls, - cur->suggestion_address); - cur->suggestion_issue = GNUNET_NO; - } - } - ril_inform (solver, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP, GAS_STAT_SUCCESS); -} - -/** - * Initializes the matrix W of parameter vectors theta with small random numbers. - * - * @param agent The respective agent - */ -static void -agent_w_init (struct RIL_Peer_Agent *agent) -{ - int i; - int k; - - for (i = 0; i < agent->n; i++) - { - for (k = 0; k < agent->m; k++) - { - agent->W[i][k] = agent->envi->parameters.alpha * (1.0 - 2.0 - * ((double) - GNUNET_CRYPTO_random_u32 ( - GNUNET_CRYPTO_QUALITY_WEAK, - UINT32_MAX) - / (double) UINT32_MAX)); - } - } -} - -/** - * Initialize an agent without addresses and its knowledge base - * - * @param s ril solver - * @param peer the one in question - * @return handle to the new agent - */ -static struct RIL_Peer_Agent * -agent_init (void *s, const struct GNUNET_PeerIdentity *peer) -{ - int i; - struct GAS_RIL_Handle *solver = s; - struct RIL_Peer_Agent *agent = GNUNET_new (struct RIL_Peer_Agent); - - agent->envi = solver; - agent->peer = *peer; - agent->step_count = 0; - agent->is_active = GNUNET_NO; - agent->bw_in = RIL_MIN_BW; - agent->bw_out = RIL_MIN_BW; - agent->suggestion_issue = GNUNET_NO; - agent->n = RIL_ACTION_TYPE_NUM; - agent->m = 0; - agent->W = (double **) GNUNET_malloc (sizeof(double *) * agent->n); - agent->E = (double **) GNUNET_malloc (sizeof(double *) * agent->n); - for (i = 0; i < agent->n; i++) - { - agent->W[i] = (double *) GNUNET_malloc (sizeof(double) * agent->m); - agent->E[i] = (double *) GNUNET_malloc (sizeof(double) * agent->m); - } - agent_w_init (agent); - agent->eligibility_reset = GNUNET_NO; - agent->a_old = RIL_ACTION_INVALID; - agent->s_old = GNUNET_malloc (sizeof(double) * agent->m); - agent->address_inuse = NULL; - agent->objective_old = 0; - agent->nop_bonus = 0; - - return agent; -} - -/** - * Deallocate agent - * - * @param solver the solver handle - * @param agent the agent to retire - */ -static void -agent_die (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent) -{ - int i; - - for (i = 0; i < agent->n; i++) - { - GNUNET_free_non_null (agent->W[i]); - GNUNET_free_non_null (agent->E[i]); - } - GNUNET_free_non_null (agent->W); - GNUNET_free_non_null (agent->E); - GNUNET_free_non_null (agent->s_old); - GNUNET_free (agent); -} - -/** - * Returns the agent for a peer - * - * @param solver the solver handle - * @param peer the identity of the peer - * @param create whether or not to create an agent, if none is allocated yet - * @return the agent - */ -static struct RIL_Peer_Agent * -ril_get_agent (struct GAS_RIL_Handle *solver, const struct - GNUNET_PeerIdentity *peer, int create) -{ - struct RIL_Peer_Agent *cur; - - for (cur = solver->agents_head; NULL != cur; cur = cur->next) - { - if (0 == GNUNET_memcmp (peer, &cur->peer)) - { - return cur; - } - } - - if (create) - { - cur = agent_init (solver, peer); - GNUNET_CONTAINER_DLL_insert_tail (solver->agents_head, solver->agents_tail, - cur); - return cur; - } - return NULL; -} - -/** - * Determine whether at least the minimum bandwidth is set for the network. Otherwise the network is - * considered inactive and not used. Addresses in an inactive network are ignored. - * - * @param solver solver handle - * @param network the network type - * @return whether or not the network is considered active - */ -static int -ril_network_is_active (struct GAS_RIL_Handle *solver, enum GNUNET_NetworkType - network) -{ - struct RIL_Scope *net; - - net = ril_get_network (solver, network); - return net->bw_out_available >= RIL_MIN_BW; -} - -/** - * Cuts a slice out of a vector of elements. This is used to decrease the size of the matrix storing - * the reward function approximation. It copies the memory, which is not cut, to the new vector, - * frees the memory of the old vector, and redirects the pointer to the new one. - * - * @param old pointer to the pointer to the first element of the vector - * @param element_size byte size of the vector elements - * @param hole_start the first element to cut out - * @param hole_length the number of elements to cut out - * @param old_length the length of the old vector - */ -static void -ril_cut_from_vector (void **old, - size_t element_size, - unsigned int hole_start, - unsigned int hole_length, - unsigned int old_length) -{ - char *tmpptr; - char *oldptr = (char *) *old; - size_t size; - unsigned int bytes_before; - unsigned int bytes_hole; - unsigned int bytes_after; - - GNUNET_assert (old_length >= hole_length); - GNUNET_assert (old_length >= (hole_start + hole_length)); - - size = element_size * (old_length - hole_length); - - bytes_before = element_size * hole_start; - bytes_hole = element_size * hole_length; - bytes_after = element_size * (old_length - hole_start - hole_length); - - if (0 == size) - { - tmpptr = NULL; - } - else - { - tmpptr = GNUNET_malloc (size); - GNUNET_memcpy (tmpptr, oldptr, bytes_before); - GNUNET_memcpy (tmpptr + bytes_before, oldptr + (bytes_before + bytes_hole), - bytes_after); - } - if (NULL != *old) - { - GNUNET_free (*old); - } - *old = (void *) tmpptr; -} - -/* - * Solver API functions - * --------------------------- - */ - -/** - * Change relative preference for quality in solver - * - * @param solver the solver handle - * @param peer the peer to change the preference for - * @param kind the kind to change the preference - * @param pref_rel the normalized preference value for this kind over all clients - */ -static void -GAS_ril_address_change_preference (void *solver, - const struct GNUNET_PeerIdentity *peer, - enum GNUNET_ATS_PreferenceKind kind, - double pref_rel) -{ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_address_change_preference() Preference '%s' for peer '%s' changed to %.2f \n", - GNUNET_ATS_print_preference_type (kind), GNUNET_i2s (peer), pref_rel); - - struct GAS_RIL_Handle *s = solver; - - s->parameters.temperature = s->parameters.temperature_init; - s->parameters.epsilon = s->parameters.epsilon_init; - ril_step (s); -} - - -/** - * Add a new address for a peer to the solver - * - * The address is already contained in the addresses hashmap! - * - * @param solver the solver Handle - * @param address the address to add - * @param network network type of this address - */ -static void -GAS_ril_address_add (void *solver, - struct ATS_Address *address, - uint32_t network) -{ - struct GAS_RIL_Handle *s = solver; - struct RIL_Peer_Agent *agent; - struct RIL_Address_Wrapped *address_wrapped; - struct RIL_Scope *net; - unsigned int m_new; - unsigned int m_old; - unsigned int n_new; - unsigned int n_old; - int i; - unsigned int zero; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_address_add()\n"); - - net = ril_get_network (s, network); - address->solver_information = net; - - if (! ril_network_is_active (s, network)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_address_add() Did not add %s address %s for peer '%s', network does not have enough bandwidth\n", - address->plugin, address->addr, GNUNET_i2s (&address->peer)); - return; - } - - s->parameters.temperature = s->parameters.temperature_init; - s->parameters.epsilon = s->parameters.epsilon_init; - - agent = ril_get_agent (s, &address->peer, GNUNET_YES); - - // add address - address_wrapped = GNUNET_new (struct RIL_Address_Wrapped); - address_wrapped->address_naked = address; - GNUNET_CONTAINER_DLL_insert_tail (agent->addresses_head, - agent->addresses_tail, address_wrapped); - - // increase size of W - m_new = agent->m + ((s->parameters.rbf_divisor + 1) - * (s->parameters.rbf_divisor + 1)); - m_old = agent->m; - n_new = agent->n + 1; - n_old = agent->n; - - GNUNET_array_grow (agent->W, agent->n, n_new); - agent->n = n_old; - GNUNET_array_grow (agent->E, agent->n, n_new); - for (i = 0; i < n_new; i++) - { - if (i < n_old) - { - agent->m = m_old; - GNUNET_array_grow (agent->W[i], agent->m, m_new); - agent->m = m_old; - GNUNET_array_grow (agent->E[i], agent->m, m_new); - } - else - { - zero = 0; - GNUNET_array_grow (agent->W[i], zero, m_new); - zero = 0; - GNUNET_array_grow (agent->E[i], zero, m_new); - } - } - - // increase size of old state vector - agent->m = m_old; - GNUNET_array_grow (agent->s_old, agent->m, m_new); - - ril_try_unblock_agent (s, agent, GNUNET_NO); - - ril_step (s); - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_address_add() Added %s %s address %s for peer '%s'\n", - address->active ? "active" : "inactive", address->plugin, address->addr, - GNUNET_i2s (&address->peer)); -} - -/** - * Delete an address in the solver - * - * The address is not contained in the address hashmap anymore! - * - * @param solver the solver handle - * @param address the address to remove - */ -static void -GAS_ril_address_delete (void *solver, - struct ATS_Address *address) -{ - struct GAS_RIL_Handle *s = solver; - struct RIL_Peer_Agent *agent; - struct RIL_Address_Wrapped *address_wrapped; - int address_index; - unsigned int m_new; - unsigned int n_new; - int i; - struct RIL_Scope *net; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_address_delete() Delete %s %s address %s for peer '%s'\n", - address->active ? "active" : "inactive", - address->plugin, - address->addr, - GNUNET_i2s (&address->peer)); - - agent = ril_get_agent (s, &address->peer, GNUNET_NO); - if (NULL == agent) - { - net = address->solver_information; - GNUNET_assert (! ril_network_is_active (s, net->type)); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "No agent allocated for peer yet, since address was in inactive network\n"); - return; - } - - s->parameters.temperature = s->parameters.temperature_init; - s->parameters.epsilon = s->parameters.epsilon_init; - - address_index = agent_address_get_index (agent, address); - address_wrapped = agent_address_get_wrapped (agent, address); - - if (NULL == address_wrapped) - { - net = address->solver_information; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Address not considered by agent, address was in inactive network\n"); - return; - } - GNUNET_CONTAINER_DLL_remove (agent->addresses_head, - agent->addresses_tail, - address_wrapped); - GNUNET_free (address_wrapped); - - // decrease W - m_new = agent->m - ((s->parameters.rbf_divisor + 1) - * (s->parameters.rbf_divisor + 1)); - n_new = agent->n - 1; - - for (i = 0; i < agent->n; i++) - { - ril_cut_from_vector ((void **) &agent->W[i], sizeof(double), - address_index * ((s->parameters.rbf_divisor + 1) - * (s->parameters.rbf_divisor + 1)), - ((s->parameters.rbf_divisor + 1) - * (s->parameters.rbf_divisor + 1)), agent->m); - ril_cut_from_vector ((void **) &agent->E[i], sizeof(double), - address_index * ((s->parameters.rbf_divisor + 1) - * (s->parameters.rbf_divisor + 1)), - ((s->parameters.rbf_divisor + 1) - * (s->parameters.rbf_divisor + 1)), agent->m); - } - GNUNET_free_non_null (agent->W[RIL_ACTION_TYPE_NUM + address_index]); - GNUNET_free_non_null (agent->E[RIL_ACTION_TYPE_NUM + address_index]); - ril_cut_from_vector ((void **) &agent->W, sizeof(double *), - RIL_ACTION_TYPE_NUM + address_index, - 1, agent->n); - ril_cut_from_vector ((void **) &agent->E, sizeof(double *), - RIL_ACTION_TYPE_NUM + address_index, - 1, agent->n); - // correct last action - if (agent->a_old > (RIL_ACTION_TYPE_NUM + address_index)) - { - agent->a_old -= 1; - } - else if (agent->a_old == (RIL_ACTION_TYPE_NUM + address_index)) - { - agent->a_old = RIL_ACTION_INVALID; - } - // decrease old state vector - ril_cut_from_vector ((void **) &agent->s_old, sizeof(double), - address_index * ((s->parameters.rbf_divisor + 1) - * (s->parameters.rbf_divisor + 1)), - ((s->parameters.rbf_divisor + 1) - * (s->parameters.rbf_divisor + 1)), agent->m); - agent->m = m_new; - agent->n = n_new; - - if (agent->address_inuse == address) - { - if (NULL != agent->addresses_head) // if peer has an address left, use it - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Active address died, suggesting alternative!\n"); - envi_set_active_suggestion (s, - agent, - agent->addresses_head->address_naked, - agent->bw_in, - agent->bw_out, - GNUNET_YES); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Active address died, suggesting disconnect!\n"); - envi_set_active_suggestion (s, agent, NULL, 0, 0, GNUNET_NO); - } - } - ril_step (solver); - if (agent->suggestion_address == address) - { - agent->suggestion_issue = GNUNET_NO; - agent->suggestion_address = NULL; - } - GNUNET_assert (agent->address_inuse != address); -} - - -/** - * Update the properties of an address in the solver - * - * @param solver solver handle - * @param address the address - */ -static void -GAS_ril_address_property_changed (void *solver, - struct ATS_Address *address) -{ - struct GAS_RIL_Handle *s = solver; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Properties for peer '%s' address changed\n", - GNUNET_i2s (&address->peer)); - s->parameters.temperature = s->parameters.temperature_init; - s->parameters.epsilon = s->parameters.epsilon_init; - ril_step (s); -} - - -/** - * Give feedback about the current assignment - * - * @param solver the solver handle - * @param application the application - * @param peer the peer to change the preference for - * @param scope the time interval for this feedback: [now - scope .. now] - * @param kind the kind to change the preference - * @param score the score - */ -static void -GAS_ril_address_preference_feedback (void *solver, - struct GNUNET_SERVICE_Client *application, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_TIME_Relative scope, - enum GNUNET_ATS_PreferenceKind kind, - double score) -{ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_address_preference_feedback() Peer '%s' got a feedback of %+.3f from application %s for " - "preference %s for %d seconds\n", - GNUNET_i2s (peer), - "UNKNOWN", - GNUNET_ATS_print_preference_type (kind), - scope.rel_value_us / 1000000); -} - - -/** - * Start a bulk operation - * - * @param solver the solver - */ -static void -GAS_ril_bulk_start (void *solver) -{ - struct GAS_RIL_Handle *s = solver; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_bulk_start() lock: %d\n", s->bulk_lock + 1); - - s->bulk_lock++; -} - - -/** - * Bulk operation done - * - * @param solver the solver handle - */ -static void -GAS_ril_bulk_stop (void *solver) -{ - struct GAS_RIL_Handle *s = solver; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_bulk_stop() lock: %d\n", - s->bulk_lock - 1); - - if (s->bulk_lock < 1) - { - GNUNET_break (0); - return; - } - s->bulk_lock--; - - if (0 < s->bulk_changes) - { - ril_step (solver); - s->bulk_changes = 0; - } -} - - -/** - * Tell solver to notify ATS if the address to use changes for a specific - * peer using the bandwidth changed callback - * - * The solver must only notify about changes for peers with pending address - * requests! - * - * @param solver the solver handle - * @param peer the identity of the peer - */ -static void -GAS_ril_get_preferred_address (void *solver, - const struct GNUNET_PeerIdentity *peer) -{ - struct GAS_RIL_Handle *s = solver; - struct RIL_Peer_Agent *agent; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "API_get_preferred_address()\n"); - - agent = ril_get_agent (s, peer, GNUNET_YES); - - agent->is_active = GNUNET_YES; - envi_set_active_suggestion (solver, agent, agent->address_inuse, agent->bw_in, - agent->bw_out, GNUNET_YES); - - ril_try_unblock_agent (solver, agent, GNUNET_YES); - - if (agent->address_inuse) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_get_preferred_address() Activated agent for peer '%s' with %s address %s\n", - GNUNET_i2s (peer), agent->address_inuse->plugin, - agent->address_inuse->addr); - } - else - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_get_preferred_address() Activated agent for peer '%s', but no address available\n", - GNUNET_i2s (peer)); - s->parameters.temperature = s->parameters.temperature_init; - s->parameters.epsilon = s->parameters.epsilon_init; - } - if (NULL != agent->address_inuse) - s->env->bandwidth_changed_cb (s->env->cls, - agent->address_inuse); -} - - -/** - * Tell solver stop notifying ATS about changes for this peers - * - * The solver must only notify about changes for peers with pending address - * requests! - * - * @param solver the solver handle - * @param peer the peer - */ -static void -GAS_ril_stop_get_preferred_address (void *solver, - const struct GNUNET_PeerIdentity *peer) -{ - struct GAS_RIL_Handle *s = solver; - struct RIL_Peer_Agent *agent; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_stop_get_preferred_address()"); - - agent = ril_get_agent (s, peer, GNUNET_NO); - - if (NULL == agent) - { - GNUNET_break (0); - return; - } - if (GNUNET_NO == agent->is_active) - { - GNUNET_break (0); - return; - } - - s->parameters.temperature = s->parameters.temperature_init; - s->parameters.epsilon = s->parameters.epsilon_init; - - agent->is_active = GNUNET_NO; - - envi_set_active_suggestion (s, agent, agent->address_inuse, agent->bw_in, - agent->bw_out, - GNUNET_YES); - - ril_step (s); - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_stop_get_preferred_address() Paused agent for peer '%s'\n", - GNUNET_i2s (peer)); -} - - -/** - * Entry point for the plugin - * - * @param cls pointer to the 'struct GNUNET_ATS_PluginEnvironment' - */ -void * -libgnunet_plugin_ats_ril_init (void *cls) -{ - static struct GNUNET_ATS_SolverFunctions sf; - struct GNUNET_ATS_PluginEnvironment *env = cls; - struct GAS_RIL_Handle *solver = GNUNET_new (struct GAS_RIL_Handle); - struct RIL_Scope *cur; - int c; - char *string; - float f_tmp; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "API_init() Initializing RIL solver\n"); - - GNUNET_assert (NULL != env); - GNUNET_assert (NULL != env->cfg); - GNUNET_assert (NULL != env->stats); - GNUNET_assert (NULL != env->bandwidth_changed_cb); - GNUNET_assert (NULL != env->get_preferences); - - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "ats", - "RIL_RBF_DIVISOR", - &solver->parameters. - rbf_divisor)) - { - solver->parameters.rbf_divisor = RIL_DEFAULT_RBF_DIVISOR; - } - - if (GNUNET_OK - != GNUNET_CONFIGURATION_get_value_time (env->cfg, "ats", - "RIL_STEP_TIME_MIN", - &solver->parameters.step_time_min)) - { - solver->parameters.step_time_min = RIL_DEFAULT_STEP_TIME_MIN; - } - - if (GNUNET_OK - != GNUNET_CONFIGURATION_get_value_time (env->cfg, "ats", - "RIL_STEP_TIME_MAX", - &solver->parameters.step_time_max)) - { - solver->parameters.step_time_max = RIL_DEFAULT_STEP_TIME_MAX; - } - - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", - "RIL_ALGORITHM", - &string)) - { - GNUNET_STRINGS_utf8_toupper (string, string); - if (0 == strcmp (string, "SARSA")) - { - solver->parameters.algorithm = RIL_ALGO_SARSA; - } - if (0 == strcmp (string, "Q-LEARNING")) - { - solver->parameters.algorithm = RIL_ALGO_Q; - } - - GNUNET_free (string); - } - else - { - solver->parameters.algorithm = RIL_DEFAULT_ALGORITHM; - } - - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", - "RIL_SELECT", - &string)) - { - solver->parameters.select = ! strcmp (string, "EGREEDY") ? - RIL_SELECT_EGREEDY : RIL_SELECT_SOFTMAX; - GNUNET_free (string); - } - else - { - solver->parameters.select = RIL_DEFAULT_SELECT; - } - - - solver->parameters.beta = RIL_DEFAULT_DISCOUNT_BETA; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "RIL_DISCOUNT_BETA", - &f_tmp)) - { - if (f_tmp < 0.0) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "RIL_DISCOUNT_BETA", f_tmp); - } - else - { - solver->parameters.beta = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n", - "RIL_DISCOUNT_BETA", f_tmp); - } - } - - solver->parameters.gamma = RIL_DEFAULT_DISCOUNT_GAMMA; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "RIL_DISCOUNT_GAMMA", - &f_tmp)) - { - if ((f_tmp < 0.0) || (f_tmp > 1.0)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "RIL_DISCOUNT_GAMMA", f_tmp); - } - else - { - solver->parameters.gamma = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n", - "RIL_DISCOUNT_GAMMA", f_tmp); - } - } - - solver->parameters.alpha = RIL_DEFAULT_GRADIENT_STEP_SIZE; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "RIL_GRADIENT_STEP_SIZE", - &f_tmp)) - { - if ((f_tmp < 0.0) || (f_tmp > 1.0)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "RIL_GRADIENT_STEP_SIZE", f_tmp); - } - else - { - solver->parameters.alpha = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n", - "RIL_GRADIENT_STEP_SIZE", f_tmp); - } - } - - solver->parameters.lambda = RIL_DEFAULT_TRACE_DECAY; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "RIL_TRACE_DECAY", - &f_tmp)) - { - if ((f_tmp < 0.0) || (f_tmp > 1.0)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "RIL_TRACE_DECAY", f_tmp); - } - else - { - solver->parameters.lambda = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n", - "RIL_TRACE_DECAY", f_tmp); - } - } - - solver->parameters.epsilon_init = RIL_DEFAULT_EXPLORE_RATIO; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "RIL_EXPLORE_RATIO", - &f_tmp)) - { - if ((f_tmp < 0.0) || (f_tmp > 1.0)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "RIL_EXPLORE_RATIO", f_tmp); - } - else - { - solver->parameters.epsilon_init = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n", - "RIL_EXPLORE_RATIO", f_tmp); - } - } - - solver->parameters.epsilon_decay = RIL_DEFAULT_EXPLORE_DECAY; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "RIL_EXPLORE_DECAY", - &f_tmp)) - { - if ((f_tmp < 0.0) || (f_tmp > 1.0)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "RIL_EXPLORE_DECAY", f_tmp); - } - else - { - solver->parameters.epsilon_decay = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n", - "RIL_EXPLORE_DECAY", f_tmp); - } - } - - solver->parameters.temperature_init = RIL_DEFAULT_TEMPERATURE; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "RIL_TEMPERATURE", - &f_tmp)) - { - if (f_tmp <= 0.0) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "RIL_TEMPERATURE", f_tmp); - } - else - { - solver->parameters.temperature_init = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n", - "RIL_TEMPERATURE", f_tmp); - } - } - - solver->parameters.temperature_decay = RIL_DEFAULT_TEMPERATURE_DECAY; - if (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_float (env->cfg, "ats", - "RIL_TEMPERATURE_DECAY", - &f_tmp)) - { - if ((f_tmp <= 0.0) ||(solver->parameters.temperature_decay > 1) ) - { - LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"), - "RIL_TEMPERATURE_DECAY", f_tmp); - } - else - { - solver->parameters.temperature_decay = f_tmp; - LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n", - "RIL_TEMPERATURE_DECAY", f_tmp); - } - } - - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "ats", - "RIL_SIMULATE", - &solver->simulate)) - { - solver->simulate = GNUNET_NO; - } - - if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "ats", - "RIL_REPLACE_TRACES")) - { - solver->parameters.eligibility_trace_mode = RIL_E_REPLACE; - } - else - { - solver->parameters.eligibility_trace_mode = RIL_E_ACCUMULATE; - } - - if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", - "RIL_SOCIAL_WELFARE", - &string)) - { - solver->parameters.social_welfare = ! strcmp (string, "NASH") ? - RIL_WELFARE_NASH : - RIL_WELFARE_EGALITARIAN; - GNUNET_free (string); - } - else - { - solver->parameters.social_welfare = RIL_DEFAULT_WELFARE; - } - - solver->env = env; - sf.cls = solver; - sf.s_add = &GAS_ril_address_add; - sf.s_address_update_property = &GAS_ril_address_property_changed; - sf.s_get = &GAS_ril_get_preferred_address; - sf.s_get_stop = &GAS_ril_stop_get_preferred_address; - sf.s_pref = &GAS_ril_address_change_preference; - sf.s_feedback = &GAS_ril_address_preference_feedback; - sf.s_del = &GAS_ril_address_delete; - sf.s_bulk_start = &GAS_ril_bulk_start; - sf.s_bulk_stop = &GAS_ril_bulk_stop; - - solver->networks_count = env->network_count; - solver->network_entries = GNUNET_malloc (env->network_count * sizeof(struct - RIL_Scope)); - solver->step_count = 0; - solver->done = GNUNET_NO; - - for (c = 0; c < env->network_count; c++) - { - cur = &solver->network_entries[c]; - cur->type = c; - cur->bw_in_available = env->in_quota[c]; - cur->bw_out_available = env->out_quota[c]; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "init() Quotas for %s network: IN %llu - OUT %llu\n", - GNUNET_NT_to_string (cur->type), - cur->bw_in_available / 1024, - cur->bw_out_available / 1024); - } - - LOG (GNUNET_ERROR_TYPE_DEBUG, "init() Parameters:\n"); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "init() Algorithm = %s, alpha = %f, beta = %f, lambda = %f\n", - solver->parameters.algorithm ? "Q" : "SARSA", - solver->parameters.alpha, - solver->parameters.beta, - solver->parameters.lambda); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "init() exploration_ratio = %f, temperature = %f, ActionSelection = %s\n", - solver->parameters.epsilon, - solver->parameters.temperature, - solver->parameters.select ? "EGREEDY" : "SOFTMAX"); - LOG (GNUNET_ERROR_TYPE_DEBUG, "init() RBF_DIVISOR = %llu\n", - solver->parameters.rbf_divisor); - - return &sf; -} - - -/** - * Exit point for the plugin - * - * @param cls the solver handle - */ -void * -libgnunet_plugin_ats_ril_done (void *cls) -{ - struct GNUNET_ATS_SolverFunctions *sf = cls; - struct GAS_RIL_Handle *s = sf->cls; - struct RIL_Peer_Agent *cur_agent; - struct RIL_Peer_Agent *next_agent; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "API_done() Shutting down RIL solver\n"); - - s->done = GNUNET_YES; - - cur_agent = s->agents_head; - while (NULL != cur_agent) - { - next_agent = cur_agent->next; - GNUNET_CONTAINER_DLL_remove (s->agents_head, s->agents_tail, cur_agent); - agent_die (s, cur_agent); - cur_agent = next_agent; - } - - if (NULL != s->step_next_task_id) - { - GNUNET_SCHEDULER_cancel (s->step_next_task_id); - } - GNUNET_free (s->network_entries); - GNUNET_free (s); - - return NULL; -} - - -/* end of plugin_ats_ril.c */ diff --git a/src/ats/test_ats2_lib.c b/src/ats/test_ats2_lib.c deleted file mode 100644 index f2a8eb1ea..000000000 --- a/src/ats/test_ats2_lib.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2010-2015 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -/** - * @file ats/test_ats2_lib.c - * @brief test ATS library with a generic interpreter for running ATS tests - * @author Julius Bünger - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_ats_application_service.h" -#include "gnunet_ats_transport_service.h" -#include "gnunet_testing_lib.h" - -/** - * @brief Indicates the success of the whole test - */ -static int ret; - -/** - * @brief The time available until the test shuts down - */ -static struct GNUNET_TIME_Relative timeout; - -/** - * @brief ATS Application Handle - * - * Handle to the application-side of ATS. - */ -static struct GNUNET_ATS_ApplicationHandle *ah; - -/** - * @brief ATS Transport Handle - * - * Handle to the transport-side of ATS. - */ -static struct GNUNET_ATS_TransportHandle *th; - -/** - * @brief Another (dummy) peer. - * - * Used as the peer ATS shall allocate bandwidth to. - */ -static struct GNUNET_PeerIdentity other_peer; - -/** - * @brief Handle to the session record - */ -static struct GNUNET_ATS_SessionRecord *sr; - - -/** - * @brief Called whenever allocation changed - * - * Implements #GNUNET_ATS_AllocationCallback - * - * @param cls - * @param session - * @param bandwidth_out - * @param bandwidth_in - * - * @return - */ -static void -allocation_cb (void *cls, - struct GNUNET_ATS_Session *session, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, - struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "allocation_cb() called\n"); -} - - -/** - * @brief Called whenever suggestion is made - * - * Implements #GNUNET_ATS_SuggestionCallback - * - * @param cls - * @param pid - * @param address - */ -static void -suggestion_cb (void *cls, - const struct GNUNET_PeerIdentity *pid, - const char *address) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "suggestion_cb() called\n"); - ret = 0; -} - - -/** - * @brief Initialise both 'sides' of ATS - * - * Initialises the application and transportation side of ATS. - */ -static void -init_both (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - ah = GNUNET_ATS_application_init (cfg); - GNUNET_assert (NULL != ah); - th = GNUNET_ATS_transport_init (cfg, - &allocation_cb, - NULL, - &suggestion_cb, - NULL); - GNUNET_assert (NULL != ah); -} - - -/** - * @brief Disconnect both 'sides' of ATS - */ -static void -finish_both (void) -{ - GNUNET_ATS_application_done (ah); - ah = NULL; - GNUNET_ATS_transport_done (th); - th = NULL; -} - - -/** - * @brief Provide information about the start of an imaginary connection - */ -static void -provide_info_start (void) -{ - struct GNUNET_ATS_Properties prop = { - .delay = GNUNET_TIME_UNIT_FOREVER_REL, - .goodput_out = 1048576, - .goodput_in = 1048576, - .utilization_out = 0, - .utilization_in = 0, - .distance = 0, - .mtu = UINT32_MAX, - .nt = GNUNET_NT_UNSPECIFIED, - .cc = GNUNET_TRANSPORT_CC_UNKNOWN, - }; - - sr = GNUNET_ATS_session_add (th, - &other_peer, - "test-address", - NULL, - &prop); - GNUNET_assert (NULL != sr); -} - - -/** - * @brief Provide information about the end of an imaginary connection - */ -static void -provide_info_end (void) -{ - GNUNET_ATS_session_del (sr); -} - - -/** - * @brief Inform ATS about the need of a connection towards a peer - */ -static void -get_suggestion (void) -{ - struct GNUNET_ATS_ApplicationSuggestHandle *ash; - - ash = GNUNET_ATS_application_suggest (ah, - &other_peer, - GNUNET_MQ_PREFERENCE_NONE, - GNUNET_BANDWIDTH_VALUE_MAX); - GNUNET_assert (NULL != ash); -} - - -static void -on_shutdown (void *cls) -{ - provide_info_end (); - finish_both (); - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Function run once the ATS service has been started. - * - * @param cls NULL - * @param cfg configuration for the testcase - * @param peer handle to the peer - */ -static void -run (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Peer *peer) -{ - init_both (cfg); - provide_info_start (); - get_suggestion (); - (void) GNUNET_SCHEDULER_add_delayed (timeout, - &on_shutdown, - NULL); -} - - -/** - * @brief Starts the gnunet-testing peer - * - * @param argc - * @param argv[] - * - * @return - */ -int -main (int argc, - char *argv[]) -{ - ret = 1; - memset (&other_peer, 0, sizeof(struct GNUNET_PeerIdentity)); - timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, - 2); - if (0 != GNUNET_TESTING_peer_run ("test-ats2-lib", - "test_ats2_lib.conf", - &run, NULL)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Running the testing peer failed.\n"); - return 1; - } - if (0 != ret) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Global status indicates unsuccessful testrun - probably allocation_cb was not called.\n"); - ret = 77; // SKIP test, test not yet right! - } - return ret; -} - - - -/* end of test_ats2_lib.c */ diff --git a/src/ats/test_ats2_lib.conf b/src/ats/test_ats2_lib.conf deleted file mode 100644 index e24f5ea68..000000000 --- a/src/ats/test_ats2_lib.conf +++ /dev/null @@ -1,13 +0,0 @@ -@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf -@INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf - -[ats] -BINARY = gnunet-service-ats-new - -[core] -START_ON_DEMAND = NO -IMMEDIATE_START = NO - -[transport] -START_ON_DEMAND = NO -IMMEDIATE_START = NO diff --git a/src/ats/test_ats2_lib.h b/src/ats/test_ats2_lib.h deleted file mode 100644 index 090abc20d..000000000 --- a/src/ats/test_ats2_lib.h +++ /dev/null @@ -1,523 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2010-2015 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -/** - * @file ats/test_ats_lib.h - * @brief test ATS library with a generic interpreter for running ATS tests - * @author Christian Grothoff - */ -#ifndef TEST_ATS_LIB_H -#define TEST_ATS_LIB_H - -#include "gnunet_util_lib.h" -#include "gnunet_ats_application_service.h" -#include "gnunet_ats_transport_service.h" -#include "gnunet_testing_lib.h" - - -///** -// * Commands for the interpreter. -// */ -// enum CommandCode -// { -// /** -// * End the test (passing). -// */ -// CMD_END_PASS = 0, -// -// /** -// * Call #GNUNET_ATS_address_add(). -// */ -// CMD_ADD_ADDRESS, -// -// /** -// * Call #GNUNET_ATS_address_del(). -// */ -// CMD_DEL_ADDRESS, -// -// /** -// * Wait for ATS to suggest address. -// */ -// CMD_AWAIT_ADDRESS_SUGGESTION, -// -// /** -// * Wait for ATS to suggest disconnect. -// */ -// CMD_AWAIT_DISCONNECT_SUGGESTION, -// -// /** -// * Ask ATS to connect to a peer, using -// * #GNUNET_ATS_connectivity_suggest(). -// */ -// CMD_REQUEST_CONNECTION_START, -// -// /** -// * Tell ATS we no longer need a connection to a peer, using -// * #GNUNET_ATS_connectivity_suggest_cancel(). -// */ -// CMD_REQUEST_CONNECTION_STOP, -// -// /** -// * Wait for certain address information to be provided. -// */ -// CMD_AWAIT_ADDRESS_INFORMATION, -// -// /** -// * Update properties of an address, using -// * #GNUNET_ATS_address_update(). -// */ -// CMD_UPDATE_ADDRESS, -// -// /** -// * Add session to an address, using -// * #GNUNET_ATS_address_add_session(). -// */ -// CMD_ADD_SESSION, -// -// /** -// * Remove session from an address, using -// * #GNUNET_ATS_address_del_session(). -// */ -// CMD_DEL_SESSION, -// -// /** -// * Change performance preferences for a peer, testing -// * #GNUNET_ATS_performance_change_preference(). -// */ -// CMD_CHANGE_PREFERENCE, -// -// /** -// * Provide allocation quality feedback, testing -// * #GNUNET_ATS_performance_give_feedback(). -// */ -// CMD_PROVIDE_FEEDBACK, -// -// /** -// * Obtain list of all addresses, testing -// * #GNUNET_ATS_performance_list_addresses(). -// */ -// CMD_LIST_ADDRESSES, -// -// /** -// * Reserve bandwidth, testing -// * #GNUNET_ATS_reserve_bandwidth(). -// */ -// CMD_RESERVE_BANDWIDTH, -// -// /** -// * Wait for a bit. -// */ -// CMD_SLEEP -// -// }; -// -// -///** -// * Details for the #CMD_ADD_ADDRESS command. -// */ -// struct CommandAddAddress -// { -// /** -// * Number of the peer (used to generate PID). -// */ -// unsigned int pid; -// -// /** -// * Number of the address (used to generate binary address). -// */ -// unsigned int addr_num; -// -// /** -// * Session to supply, 0 for NULL. -// */ -// unsigned int session; -// -// /** -// * Flags to set for the address. -// */ -// enum GNUNET_HELLO_AddressInfo addr_flags; -// -// /** -// * Performance properties to supply. -// */ -// struct GNUNET_ATS_Properties properties; -// -// /** -// * Expect the operation to fail (duplicate). -// */ -// int expect_fail; -// -// /** -// * Here the result of the add address operation will be stored. -// */ -// struct GNUNET_ATS_AddressRecord *ar; -// }; -// -// -///** -// * Details for the #CMD_DEL_ADDRESS command. -// */ -// struct CommandDelAddress -// { -// /** -// * Label of the corresponding #CMD_ADD_ADDRESS that -// * we are now to remove. -// */ -// const char *add_label; -// }; -// -// -///** -// * Details for the #CMD_AWAIT_ADDRESS_SUGGESTION command. -// */ -// struct CommandAwaitAddressSuggestion -// { -// /** -// * For which peer do we expect a suggestion? -// */ -// unsigned int pid; -// -// /** -// * If we expect the address suggested to match a particular -// * addition, specify the label of the add operation here. Otherwise -// * use NULL for "any" available address. -// */ -// const char *add_label; -// -// }; -// -// -///** -// * Details for the #CMD_AWAIT_DISCONNECT_SUGGESTION command. -// */ -// struct CommandAwaitDisconnectSuggestion -// { -// /** -// * For which peer do we expect the disconnect? -// */ -// unsigned int pid; -// -// }; -// -// -///** -// * Details for the #CMD_REQUEST_CONNECTION_START command. -// */ -// struct CommandRequestConnectionStart -// { -// /** -// * Identity of the peer we would like to connect to. -// */ -// unsigned int pid; -// -// /** -// * Location where we store the handle returned from -// * #GNUNET_ATS_connectivity_suggest(). -// */ -// struct GNUNET_ATS_ConnectivitySuggestHandle *csh; -// }; -// -// -///** -// * Details for the #CMD_REQUEST_CONNECTION_STOP command. -// */ -// struct CommandRequestConnectionStop -// { -// /** -// * Label of the corresponding #CMD_REQUEST_CONNECTION_START that -// * we are now stopping. -// */ -// const char *connect_label; -// }; -// -// -///** -// * Details for the #CMD_AWAIT_ADDRESS_INFORMATION command. -// */ -// struct CommandAwaitAddressInformation -// { -// /** -// * For which address do we expect information? -// * The address is identified by the respective -// * label of the corresponding add operation. -// */ -// const char *add_label; -// -// /** -// * Label of a possible update operation that may -// * have modified the properties. NULL to use -// * the properties from the @e add_label. -// */ -// const char *update_label; -// -// }; -// -// -///** -// * Details for the #CMD_UPDATE_ADDRESS command. -// */ -// struct CommandUpdateAddress -// { -// /** -// * Label of the addresses's add operation. -// */ -// const char *add_label; -// -// /** -// * Performance properties to supply. -// */ -// struct GNUNET_ATS_Properties properties; -// -// }; -// -// -///** -// * Details for the #CMD_ADD_SESSION command. -// */ -// struct CommandAddSession -// { -// /** -// * Label of the addresses's add operation. -// */ -// const char *add_label; -// -// /** -// * Session to supply. -// */ -// unsigned int session; -// -// }; -// -// -///** -// * Details for the #CMD_DEL_SESSION command. -// */ -// struct CommandDelSession -// { -// /** -// * Label of the addresses's add operation. -// */ -// const char *add_session_label; -// -// }; -// -// -///** -// * Details for the #CMD_CHANGE_PREFERENCE command. -// */ -// struct CommandChangePreference -// { -// /** -// * Identity of the peer we have a preference change towards. -// */ -// unsigned int pid; -// -// /* FIXME: preference details! */ -// -// }; -// -// -///** -// * Details for the #CMD_PROVIDE_FEEDBACK command. -// */ -// struct CommandProvideFeedback -// { -// /** -// * Identity of the peer we have a feedback for. -// */ -// unsigned int pid; -// -// /** -// * Over which timeframe does the feedback apply? -// */ -// struct GNUNET_TIME_Relative scope; -// -// /* FIXME: feedback details! */ -// }; -// -// -///** -// * Details for the #CMD_LIST_ADDRESSES command. -// */ -// struct CommandListAddresses -// { -// /** -// * Identity of the peer we want a list for. -// */ -// unsigned int pid; -// -// /** -// * All addresses or just active? -// */ -// int all; -// -// /** -// * Minimum number of addresses the callback may report. -// */ -// unsigned int min_calls; -// -// /** -// * Maximum number of addresses the callback may report. -// */ -// unsigned int max_calls; -// -// /** -// * Minimum number of active addresses the callback may report. -// */ -// unsigned int min_active_calls; -// -// /** -// * Maximum number of active addresses the callback may report. -// */ -// unsigned int max_active_calls; -// -// /** -// * Number of calls the command invoked the callback with -// * an address marked as active. (Set by command). -// */ -// unsigned int active_calls; -// -// /** -// * Number of calls the command invoked the callback with -// * any address marked as available to ATS. (Set by command). -// */ -// unsigned int calls; -// -// /** -// * Location where we store the return value from -// * #GNUNET_ATS_performance_list_addresses(). -// */ -// struct GNUNET_ATS_AddressListHandle *alh; -// -// }; -// -// -///** -// * Details for the #CMD_RESERVE_BANDWIDTH command. -// */ -// struct CommandReserveBandwidth -// { -// /** -// * For which peer do we reserve bandwidth? -// */ -// unsigned int pid; -// -// /** -// * How much should we try to reserve? -// */ -// int32_t amount; -// -// /** -// * Should we expect this to work or fail? -// * #GNUNET_YES: must work -// * #GNUNET_NO: may work or fail -// * #GNUNET_SYSERR: must fail -// */ -// int expected_result; -// -// /** -// * Location where we store the return value from -// * #GNUNET_ATS_reserve_bandwidth(). -// */ -// struct GNUNET_ATS_ReservationContext *rc; -// -// }; -// -// -///** -// * Details for the #CMD_SLEEP command. -// */ -// struct CommandSleep -// { -// /** -// * How long should we wait before running the next command? -// */ -// struct GNUNET_TIME_Relative delay; -// }; -// -// -///** -// * A command for the test case interpreter. -// */ -// struct Command -// { -// /** -// * Command code to run. -// */ -// enum CommandCode code; -// -// /** -// * Commands can be given a label so we can reference them later. -// */ -// const char *label; -// -// /** -// * Additional arguments to commands, if any. -// */ -// union { -// -// struct CommandAddAddress add_address; -// -// struct CommandDelAddress del_address; -// -// struct CommandAwaitAddressSuggestion await_address_suggestion; -// -// struct CommandAwaitDisconnectSuggestion await_disconnect_suggestion; -// -// struct CommandRequestConnectionStart request_connection_start; -// -// struct CommandRequestConnectionStop request_connection_stop; -// -// struct CommandAwaitAddressInformation await_address_information; -// -// struct CommandUpdateAddress update_address; -// -// struct CommandAddSession add_session; -// -// struct CommandDelSession del_session; -// -// struct CommandChangePreference change_preference; -// -// struct CommandProvideFeedback provide_feedback; -// -// struct CommandListAddresses list_addresses; -// -// struct CommandReserveBandwidth reserve_bandwidth; -// -// struct CommandSleep sleep; -// -// } details; -// -// }; - - -/** - * Run ATS test. - * - * @param argc length of @a argv - * @param argv command line - * @param cmds commands to run with the interpreter - * @param timeout how long is the test allowed to take? - * @return 0 on success - */ -int -TEST_ATS_run (int argc, - char *argv[], - struct Command *cmds, - struct GNUNET_TIME_Relative timeout); - -#endif diff --git a/src/ats/test_ats_api_mlp.conf b/src/ats/test_ats_api_mlp.conf deleted file mode 100644 index d5f05a3c4..000000000 --- a/src/ats/test_ats_api_mlp.conf +++ /dev/null @@ -1,45 +0,0 @@ -@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_TMP/test-ats-mlp/ - -[ats] -# Enable MLP mode (default: NO) -MODE = mlp -# Network specific inbound/outbound quotas -# UNSPECIFIED -UNSPECIFIED_QUOTA_IN = unlimited -UNSPECIFIED_QUOTA_OUT = unlimited -# LOOPBACK -LOOPBACK_QUOTA_IN = unlimited -LOOPBACK_QUOTA_OUT = unlimited -# LAN -LAN_QUOTA_IN = unlimited -LAN_QUOTA_OUT = unlimited -# WAN -WAN_QUOTA_IN = 64 KiB -WAN_QUOTA_OUT = 64 KiB -# WLAN -WLAN_QUOTA_IN = 4096 -WLAN_QUOTA_OUT = 4096 - -# MLP specific settings -ATS_MIN_INTERVAL = 15000 -ATS_EXEC_INTERVAL = 30000 - -# MLP defaults -# MLP_MAX_DURATION = 3 s -# MLP_MAX_ITERATIONS = 1024 -# MLP_COEFFICIENT_D = 1.0 -# MLP_COEFFICIENT_U = 1.0 -# MLP_COEFFICIENT_R = 1.0 -# MLP_MIN_BANDWIDTH = 1024 -# MLP_MIN_CONNECTIONS = 4 - -# MLP Debugging settings -DUMP_MLP = NO -DUMP_SOLUTION = NO -DUMP_OVERWRITE = NO -DUMP_MIN_PEERS = 0 -DUMP_MIN_ADDRS = 0 -DUMP_OVERWRITE = NO diff --git a/src/ats/test_ats_api_ril.conf b/src/ats/test_ats_api_ril.conf deleted file mode 100644 index 5f5fb006b..000000000 --- a/src/ats/test_ats_api_ril.conf +++ /dev/null @@ -1,24 +0,0 @@ -@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf - -[PATHS] -GNUNET_TEST_HOME = $GNUNET_TMP/test-ats-ril/ - -[ats] -# Enable RIL mode (default: NO) -MODE = ril -# Network specific inbound/outbound quotas -# UNSPECIFIED -UNSPECIFIED_QUOTA_IN = unlimited -UNSPECIFIED_QUOTA_OUT = unlimited -# LOOPBACK -LOOPBACK_QUOTA_IN = unlimited -LOOPBACK_QUOTA_OUT = unlimited -# LAN -LAN_QUOTA_IN = unlimited -LAN_QUOTA_OUT = unlimited -# WAN -WAN_QUOTA_IN = 64 KiB -WAN_QUOTA_OUT = 64 KiB -# WLAN -WLAN_QUOTA_IN = 4096 -WLAN_QUOTA_OUT = 4096 diff --git a/src/ats/test_ats_solver_delayed_mlp.conf b/src/ats/test_ats_solver_delayed_mlp.conf deleted file mode 100644 index 632755570..000000000 --- a/src/ats/test_ats_solver_delayed_mlp.conf +++ /dev/null @@ -1,20 +0,0 @@ -@INLINE@ test_ats_solver_default.conf - -[ats] -PREFIX = ./test_delay -t 10 -- -MODE = mlp -# UNSPECIFIED -UNSPECIFIED_QUOTA_IN = 64 KiB -UNSPECIFIED_QUOTA_OUT = 64 KiB -# LOOPBACK -LOOPBACK_QUOTA_IN = unlimited -LOOPBACK_QUOTA_OUT = unlimited -# LAN -LAN_QUOTA_IN = unlimited -LAN_QUOTA_OUT = unlimited -# WAN -WAN_QUOTA_IN = 64 KiB -WAN_QUOTA_OUT = 64 KiB -# WLAN -WLAN_QUOTA_IN = 512 -WLAN_QUOTA_OUT = 512 diff --git a/src/ats/test_ats_solver_delayed_ril.conf b/src/ats/test_ats_solver_delayed_ril.conf deleted file mode 100644 index a43fffa4c..000000000 --- a/src/ats/test_ats_solver_delayed_ril.conf +++ /dev/null @@ -1,31 +0,0 @@ -@INLINE@ test_ats_solver_default.conf - -[ats] -PREFIX = ./test_delay -t 10 -- -MODE = ril -# UNSPECIFIED -UNSPECIFIED_QUOTA_IN = 64 KiB -UNSPECIFIED_QUOTA_OUT = 64 KiB -# LOOPBACK -LOOPBACK_QUOTA_IN = unlimited -LOOPBACK_QUOTA_OUT = unlimited -# LAN -LAN_QUOTA_IN = unlimited -LAN_QUOTA_OUT = unlimited -# WAN -WAN_QUOTA_IN = 64 KiB -WAN_QUOTA_OUT = 64 KiB -# WLAN -WLAN_QUOTA_IN = 512 -WLAN_QUOTA_OUT = 512 - -# Reinforcement Learning Parameters -RIL_STEP_TIME_MIN = 500 ms -RIL_STEP_TIME_MAX = 1000 ms - -RIL_ALGORITHM = Q -RIL_DISCOUNT_BETA = 0.7 -RIL_GRADIENT_STEP_SIZE = 0.3 -RIL_TRACE_DECAY = 0.2 -RIL_EXPLORE_RATIO = 0.1 -RIL_GLOBAL_REWARD_SHARE = 1 diff --git a/src/include/Makefile.am b/src/include/Makefile.am index d5c097341..9e0813425 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -29,7 +29,6 @@ gnunetinclude_HEADERS = \ gnunet_ats_application_service.h \ gnunet_ats_transport_service.h \ gnunet_ats_plugin.h \ - gnunet_ats_plugin_new.h \ gnunet_bandwidth_lib.h \ gnunet_bio_lib.h \ gnunet_block_lib.h \ diff --git a/src/include/gnunet_ats_plugin_new.h b/src/include/gnunet_ats_plugin_new.h deleted file mode 100644 index b371321fa..000000000 --- a/src/include/gnunet_ats_plugin_new.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2009-2015, 2018 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later - */ - -/** - * @author Christian Grothoff - * - * @file - * API for the ATS solvers. - * - * @defgroup ats-plugin ATS service plugin API - * Plugin API for the ATS service. - * - * Specifies the struct that is given to the plugin's entry method and the other - * struct that must be returned. Note that the destructors of ATS plugins will - * be given the value returned by the constructor and is expected to return a - * NULL pointer. - * - * @{ - */ -#ifndef PLUGIN_ATS_H -#define PLUGIN_ATS_H - -#include "gnunet_util_lib.h" -#include "gnunet_ats_application_service.h" -#include "gnunet_ats_transport_service.h" -#include "gnunet_statistics_service.h" - - -/** - * Preference being expressed by an application client. - */ -struct GNUNET_ATS_Preference -{ - /** - * Peer to get address suggestions for. - */ - struct GNUNET_PeerIdentity peer; - - /** - * How much bandwidth in bytes/second does the application expect? - */ - struct GNUNET_BANDWIDTH_Value32NBO bw; - - /** - * What type of performance preference does the client have? - */ - enum GNUNET_MQ_PreferenceKind pk; -}; - - -/** - * Opaque representation of a session the plugin can allocate bandwidth for. - */ -struct GNUNET_ATS_Session; - -/** - * Plugin-relevant information about a session. - */ -struct GNUNET_ATS_SessionData -{ - /** - * Peer the session is with. - */ - struct GNUNET_PeerIdentity peer; - - /** - * ATS performance characteristics for a session. - */ - struct GNUNET_ATS_Properties prop; - - /** - * Handle to the session that has the given properties. - */ - struct GNUNET_ATS_Session *session; - - /** - * Is the session inbound only? - */ - int inbound_only; -}; - -/** - * Internal representation of a preference by the plugin. - * (If desired, plugin may just use NULL.) - */ -struct GNUNET_ATS_PreferenceHandle; - -/** - * Internal representation of a session by the plugin. - * (If desired, plugin may just use NULL.) - */ -struct GNUNET_ATS_SessionHandle; - - -/** - * Solver functions. - * - * Each solver is required to set up and return an instance - * of this struct during initialization. - */ -struct GNUNET_ATS_SolverFunctions -{ - /** - * Closure to pass to all solver functions in this struct. - */ - void *cls; - - /** - * The plugin should begin to respect a new preference. - * - * @param cls the closure - * @param pref the preference to add - * @return plugin's internal representation, or NULL - */ - struct GNUNET_ATS_PreferenceHandle * - (*preference_add)(void *cls, - const struct GNUNET_ATS_Preference *pref); - - /** - * The plugin should end respecting a preference. - * - * @param cls the closure - * @param ph whatever @e preference_add returned - * @param pref the preference to delete - * @return plugin's internal representation, or NULL - */ - void - (*preference_del)(void *cls, - struct GNUNET_ATS_PreferenceHandle *ph, - const struct GNUNET_ATS_Preference *pref); - - /** - * Transport established a new session with performance - * characteristics given in @a data. - * - * @param cls closure - * @param data performance characteristics of @a sh - * @param address address information (for debugging) - * @return handle by which the plugin will identify this session - */ - struct GNUNET_ATS_SessionHandle * - (*session_add)(void *cls, - const struct GNUNET_ATS_SessionData *data, - const char *address); - - /** - * @a data changed for a given @a sh, solver should consider - * the updated performance characteristics. - * - * @param cls closure - * @param sh session this is about - * @param data performance characteristics of @a sh - */ - void - (*session_update)(void *cls, - struct GNUNET_ATS_SessionHandle *sh, - const struct GNUNET_ATS_SessionData *data); - - /** - * A session went away. Solver should update accordingly. - * - * @param cls closure - * @param sh session this is about - * @param data (last) performance characteristics of @a sh - */ - void - (*session_del)(void *cls, - struct GNUNET_ATS_SessionHandle *sh, - const struct GNUNET_ATS_SessionData *data); -}; - - -/** - * The ATS plugin will pass a pointer to a struct - * of this type as to the initialization function - * of the ATS plugins. - */ -struct GNUNET_ATS_PluginEnvironment -{ - /** - * Configuration handle to be used by the solver - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Statistics handle to be used by the solver - */ - struct GNUNET_STATISTICS_Handle *stats; - - /** - * Closure to pass to all callbacks in this struct. - */ - void *cls; - - /** - * Suggest to the transport that it should try establishing - * a connection using the given address. - * - * @param cls closure, NULL - * @param pid peer this is about - * @param address address the transport should try - */ - void - (*suggest_cb) (void *cls, - const struct GNUNET_PeerIdentity *pid, - const char *address); - - /** - * Tell the transport that it should allocate the given - * bandwidth to the specified session. - * - * @param cls closure, NULL - * @param session session this is about - * @param peer peer this is about - * @param bw_in suggested bandwidth for receiving - * @param bw_out suggested bandwidth for transmission - */ - void - (*allocate_cb) (void *cls, - struct GNUNET_ATS_Session *session, - const struct GNUNET_PeerIdentity *peer, - struct GNUNET_BANDWIDTH_Value32NBO bw_in, - struct GNUNET_BANDWIDTH_Value32NBO bw_out); -}; - - - -#endif - -/** @} */ /* end of group */ -- 2.25.1