aboutsummaryrefslogtreecommitdiff
path: root/src/ats
diff options
context:
space:
mode:
authorBertrand Marc <beberking@gmail.com>2012-06-06 20:47:48 +0200
committerBertrand Marc <beberking@gmail.com>2012-06-06 20:47:48 +0200
commit740b30688bd745a527f96f9116c19acb3480971a (patch)
tree2709a3f4dba11c174aa9e1ba3612e30c578e76a9 /src/ats
parent2b81464a43485fcc8ce079fafdee7b7a171835f4 (diff)
Imported Upstream version 0.9.3upstream/0.9.3
Diffstat (limited to 'src/ats')
-rw-r--r--src/ats/Makefile.am13
-rw-r--r--src/ats/Makefile.in35
-rw-r--r--src/ats/ats.conf.in18
-rw-r--r--src/ats/ats.h9
-rw-r--r--src/ats/ats_api_performance.c4
-rw-r--r--src/ats/ats_api_scheduling.c112
-rw-r--r--src/ats/gnunet-service-ats.c9
-rw-r--r--src/ats/gnunet-service-ats_addresses.c282
-rw-r--r--src/ats/gnunet-service-ats_addresses.h15
-rw-r--r--src/ats/gnunet-service-ats_addresses_mlp.c225
-rw-r--r--src/ats/gnunet-service-ats_addresses_mlp.h16
-rw-r--r--src/ats/gnunet-service-ats_performance.c2
-rw-r--r--src/ats/gnunet-service-ats_scheduling.c51
-rw-r--r--src/ats/gnunet-service-ats_scheduling.h13
-rw-r--r--src/ats/perf_ats_mlp.c372
-rw-r--r--src/ats/test_ats_api.conf30
-rw-r--r--src/ats/test_ats_api_reset_backoff.c308
-rw-r--r--src/ats/test_ats_api_scheduling.c13
-rw-r--r--src/ats/test_ats_mlp.c14
-rw-r--r--src/ats/test_ats_mlp_averaging.c14
20 files changed, 1236 insertions, 319 deletions
diff --git a/src/ats/Makefile.am b/src/ats/Makefile.am
index f4056fa..2e85848 100644
--- a/src/ats/Makefile.am
+++ b/src/ats/Makefile.am
@@ -32,7 +32,7 @@ libgnunetats_la_LIBADD = \
libgnunetats_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) \
- -version-info 1:0:1
+ -version-info 2:0:2
bin_PROGRAMS = \
@@ -54,6 +54,7 @@ gnunet_service_ats_LDADD = \
check_PROGRAMS = \
test_ats_api_scheduling \
+ test_ats_api_reset_backoff \
$(GN_MLP_TEST) \
$(GN_MLP_TEST_AVG) \
$(GN_MLP_PERF)
@@ -87,7 +88,7 @@ perf_ats_mlp_SOURCES = \
perf_ats_mlp_LDADD = \
$(GN_LIBGLPK) \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/statistics/libgnunetstatistics.la
+ $(top_builddir)/src/statistics/libgnunetstatistics.la
endif
test_ats_api_scheduling_SOURCES = \
@@ -96,6 +97,12 @@ test_ats_api_scheduling_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/ats/libgnunetats.la
+test_ats_api_reset_backoff_SOURCES = \
+ test_ats_api_reset_backoff.c
+test_ats_api_reset_backoff_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/ats/libgnunetats.la
+
#test_ats_api_scheduling_get_type_SOURCES = \
# test_ats_api_scheduling_get_type.c
#test_ats_api_scheduling_get_type_LDADD = \
@@ -117,5 +124,5 @@ test_ats_api_scheduling_LDADD = \
EXTRA_DIST = \
ats.h \
- test_ats_api.conf
+ test_ats_api.conf
diff --git a/src/ats/Makefile.in b/src/ats/Makefile.in
index 26610e1..7f74064 100644
--- a/src/ats/Makefile.in
+++ b/src/ats/Makefile.in
@@ -38,7 +38,8 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
bin_PROGRAMS = gnunet-service-ats$(EXEEXT)
-check_PROGRAMS = test_ats_api_scheduling$(EXEEXT) $(am__EXEEXT_1) \
+check_PROGRAMS = test_ats_api_scheduling$(EXEEXT) \
+ test_ats_api_reset_backoff$(EXEEXT) $(am__EXEEXT_1) \
$(am__EXEEXT_2) $(am__EXEEXT_3)
subdir = src/ats
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
@@ -134,6 +135,13 @@ perf_ats_mlp_OBJECTS = $(am_perf_ats_mlp_OBJECTS)
@HAVE_LIBGLPK_TRUE@perf_ats_mlp_DEPENDENCIES = $(am__DEPENDENCIES_1) \
@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \
@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la
+am_test_ats_api_reset_backoff_OBJECTS = \
+ test_ats_api_reset_backoff.$(OBJEXT)
+test_ats_api_reset_backoff_OBJECTS = \
+ $(am_test_ats_api_reset_backoff_OBJECTS)
+test_ats_api_reset_backoff_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/ats/libgnunetats.la
am_test_ats_api_scheduling_OBJECTS = \
test_ats_api_scheduling.$(OBJEXT)
test_ats_api_scheduling_OBJECTS = \
@@ -187,11 +195,13 @@ AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(libgnunetats_la_SOURCES) $(gnunet_service_ats_SOURCES) \
- $(perf_ats_mlp_SOURCES) $(test_ats_api_scheduling_SOURCES) \
- $(test_ats_mlp_SOURCES) $(test_ats_mlp_averaging_SOURCES)
+ $(perf_ats_mlp_SOURCES) $(test_ats_api_reset_backoff_SOURCES) \
+ $(test_ats_api_scheduling_SOURCES) $(test_ats_mlp_SOURCES) \
+ $(test_ats_mlp_averaging_SOURCES)
DIST_SOURCES = $(libgnunetats_la_SOURCES) \
$(am__gnunet_service_ats_SOURCES_DIST) \
$(am__perf_ats_mlp_SOURCES_DIST) \
+ $(test_ats_api_reset_backoff_SOURCES) \
$(test_ats_api_scheduling_SOURCES) \
$(am__test_ats_mlp_SOURCES_DIST) \
$(am__test_ats_mlp_averaging_SOURCES_DIST)
@@ -256,6 +266,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JAVAPORT = @JAVAPORT@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBADD_DL = @LIBADD_DL@
@@ -289,6 +300,7 @@ LT_DLLOADERS = @LT_DLLOADERS@
LT_DLPREOPEN = @LT_DLPREOPEN@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
+MONKEYPREFIX = @MONKEYPREFIX@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
@@ -427,7 +439,7 @@ libgnunetats_la_LIBADD = \
libgnunetats_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) \
- -version-info 1:0:1
+ -version-info 2:0:2
gnunet_service_ats_SOURCES = \
gnunet-service-ats.c gnunet-service-ats.h\
@@ -471,7 +483,7 @@ gnunet_service_ats_LDADD = \
@HAVE_LIBGLPK_TRUE@perf_ats_mlp_LDADD = \
@HAVE_LIBGLPK_TRUE@ $(GN_LIBGLPK) \
@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \
-@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la
+@HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la
test_ats_api_scheduling_SOURCES = \
test_ats_api_scheduling.c
@@ -480,6 +492,13 @@ test_ats_api_scheduling_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/ats/libgnunetats.la
+test_ats_api_reset_backoff_SOURCES = \
+ test_ats_api_reset_backoff.c
+
+test_ats_api_reset_backoff_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/ats/libgnunetats.la
+
#test_ats_api_scheduling_get_type_SOURCES = \
# test_ats_api_scheduling_get_type.c
@@ -500,7 +519,7 @@ test_ats_api_scheduling_LDADD = \
# $(top_builddir)/src/ats/libgnunetats.la
EXTRA_DIST = \
ats.h \
- test_ats_api.conf
+ test_ats_api.conf
all: all-am
@@ -629,6 +648,9 @@ gnunet-service-ats$(EXEEXT): $(gnunet_service_ats_OBJECTS) $(gnunet_service_ats_
perf_ats_mlp$(EXEEXT): $(perf_ats_mlp_OBJECTS) $(perf_ats_mlp_DEPENDENCIES)
@rm -f perf_ats_mlp$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(perf_ats_mlp_OBJECTS) $(perf_ats_mlp_LDADD) $(LIBS)
+test_ats_api_reset_backoff$(EXEEXT): $(test_ats_api_reset_backoff_OBJECTS) $(test_ats_api_reset_backoff_DEPENDENCIES)
+ @rm -f test_ats_api_reset_backoff$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_ats_api_reset_backoff_OBJECTS) $(test_ats_api_reset_backoff_LDADD) $(LIBS)
test_ats_api_scheduling$(EXEEXT): $(test_ats_api_scheduling_OBJECTS) $(test_ats_api_scheduling_DEPENDENCIES)
@rm -f test_ats_api_scheduling$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_OBJECTS) $(test_ats_api_scheduling_LDADD) $(LIBS)
@@ -654,6 +676,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_reservations.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_scheduling.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_ats_mlp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_reset_backoff.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_mlp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_mlp_averaging.Po@am__quote@
diff --git a/src/ats/ats.conf.in b/src/ats/ats.conf.in
index 6ea0d41..f81016e 100644
--- a/src/ats/ats.conf.in
+++ b/src/ats/ats.conf.in
@@ -10,10 +10,24 @@ ACCEPT_FROM6 = ::1;
UNIXPATH = /tmp/gnunet-service-ats.sock
UNIX_MATCH_UID = YES
UNIX_MATCH_GID = YES
+
+# Enable MLP mode (default: NO)
MLP = NO
-WAN_QUOTA_IN = 65536
-WAN_QUOTA_OUT = 65536
+# Network specific inbound/outbound quotas
+# 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 = 1 MiB
+WLAN_QUOTA_OUT = 1 MiB
# ATS options
+
DUMP_MLP = NO
DUMP_SOLUTION = NO
DUMP_OVERWRITE = NO
diff --git a/src/ats/ats.h b/src/ats/ats.h
index 30ca295..f4c3d9f 100644
--- a/src/ats/ats.h
+++ b/src/ats/ats.h
@@ -61,6 +61,15 @@ struct RequestAddressMessage
struct GNUNET_PeerIdentity peer;
};
+struct ResetBackoffMessage
+{
+ struct GNUNET_MessageHeader header;
+
+ uint32_t reserved GNUNET_PACKED;
+
+ struct GNUNET_PeerIdentity peer;
+};
+
struct AddressUpdateMessage
{
diff --git a/src/ats/ats_api_performance.c b/src/ats/ats_api_performance.c
index 848c7ec..c98e1c2 100644
--- a/src/ats/ats_api_performance.c
+++ b/src/ats/ats_api_performance.c
@@ -395,7 +395,7 @@ process_ats_message (void *cls, const struct GNUNET_MessageHeader *msg)
GNUNET_TIME_UNIT_FOREVER_REL);
return;
reconnect:
- GNUNET_CLIENT_disconnect (ph->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (ph->client);
ph->client = NULL;
ph->task =
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task,
@@ -493,7 +493,7 @@ GNUNET_ATS_performance_done (struct GNUNET_ATS_PerformanceHandle *ph)
}
if (NULL != ph->client)
{
- GNUNET_CLIENT_disconnect (ph->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (ph->client);
ph->client = NULL;
}
GNUNET_free (ph);
diff --git a/src/ats/ats_api_scheduling.c b/src/ats/ats_api_scheduling.c
index 78e8d61..5a4e883 100644
--- a/src/ats/ats_api_scheduling.c
+++ b/src/ats/ats_api_scheduling.c
@@ -27,7 +27,6 @@
#include "gnunet_ats_service.h"
#include "ats.h"
-#define DEBUG_ATS GNUNET_EXTRA_LOGGING
#define INTERFACE_PROCESSING_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
@@ -146,7 +145,6 @@ struct GNUNET_ATS_SchedulingHandle
*/
struct ATS_Network * net_tail;
-
/**
* Array of session objects (we need to translate them to numbers and back
* for the protocol; the offset in the array is the session number on the
@@ -163,7 +161,6 @@ struct GNUNET_ATS_SchedulingHandle
/**
* Task retrieving interfaces from the system
*/
-
GNUNET_SCHEDULER_TaskIdentifier interface_task;
@@ -213,7 +210,7 @@ static void
force_reconnect (struct GNUNET_ATS_SchedulingHandle *sh)
{
sh->reconnect = GNUNET_NO;
- GNUNET_CLIENT_disconnect (sh->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (sh->client);
sh->client = NULL;
sh->task =
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task,
@@ -319,10 +316,11 @@ static struct Session *
find_session (struct GNUNET_ATS_SchedulingHandle *sh, uint32_t session_id,
const struct GNUNET_PeerIdentity *peer)
{
-#if DEBUG_ATS
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Find session %u from peer %s in %p\n",
+
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api",
+ "Find session %u from peer %s in %p\n",
(unsigned int) session_id, GNUNET_i2s (peer), sh);
-#endif
+
if (session_id >= sh->session_array_size)
{
GNUNET_break (0);
@@ -366,11 +364,11 @@ get_session_id (struct GNUNET_ATS_SchedulingHandle *sh, struct Session *session,
unsigned int i;
unsigned int f;
-#if DEBUG_ATS
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api",
"Get session ID for session %p from peer %s in %p\n", session,
GNUNET_i2s (peer), sh);
-#endif
+
if (NULL == session)
return 0;
f = 0;
@@ -396,11 +394,11 @@ get_session_id (struct GNUNET_ATS_SchedulingHandle *sh, struct Session *session,
sh->session_array[f].session = session;
sh->session_array[f].peer = *peer;
sh->session_array[f].slot_used = GNUNET_YES;
-#if DEBUG_ATS
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api",
"Assigning session ID %u for session %p of peer %s in %p\n", f,
session, GNUNET_i2s (peer), sh);
-#endif
+
return f;
}
@@ -417,11 +415,13 @@ static void
remove_session (struct GNUNET_ATS_SchedulingHandle *sh, uint32_t session_id,
const struct GNUNET_PeerIdentity *peer)
{
-#if DEBUG_ATS
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Remove sessionID %u from peer %s in %p\n",
+ GNUNET_assert (peer != NULL);
+ GNUNET_assert (sh != NULL);
+
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api",
+ "Release sessionID %u from peer %s in %p\n",
(unsigned int) session_id, GNUNET_i2s (peer), sh);
-#endif
+
if (0 == session_id)
return;
GNUNET_assert (session_id < sh->session_array_size);
@@ -445,11 +445,11 @@ static void
release_session (struct GNUNET_ATS_SchedulingHandle *sh, uint32_t session_id,
const struct GNUNET_PeerIdentity *peer)
{
-#if DEBUG_ATS
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api",
"Release sessionID %u from peer %s in %p\n",
(unsigned int) session_id, GNUNET_i2s (peer), sh);
-#endif
+
if (session_id >= sh->session_array_size)
{
GNUNET_break (0);
@@ -552,11 +552,10 @@ process_ats_message (void *cls, const struct GNUNET_MessageHeader *msg)
s = find_session (sh, session_id, &m->peer);
if (s == NULL)
{
-#if DEBUG_ATS
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api",
"ATS tries to use outdated session `%s'\n",
GNUNET_i2s (&m->peer));
-#endif
GNUNET_CLIENT_receive (sh->client, &process_ats_message, sh,
GNUNET_TIME_UNIT_FOREVER_REL);
return;
@@ -618,10 +617,10 @@ reconnect (struct GNUNET_ATS_SchedulingHandle *sh)
do_transmit (sh);
}
+
/**
* delete the current network list
*/
-
static void
delete_networks (struct GNUNET_ATS_SchedulingHandle *sh)
{
@@ -734,7 +733,6 @@ interface_proc (void *cls, const char *name,
}
-
/**
* Periodically get list of addresses
* @param cls closure
@@ -752,15 +750,16 @@ get_addresses (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
sh);
}
+
/**
* Returns where the address is located: LAN or WAN or ...
+ *
* @param sh the scheduling handle
* @param addr address
* @param addrlen address length
* @return location as GNUNET_ATS_Information
*/
-
-const struct GNUNET_ATS_Information
+struct GNUNET_ATS_Information
GNUNET_ATS_address_get_type (struct GNUNET_ATS_SchedulingHandle * sh, const struct sockaddr * addr, socklen_t addrlen)
{
GNUNET_assert (sh != NULL);
@@ -807,7 +806,8 @@ GNUNET_ATS_address_get_type (struct GNUNET_ATS_SchedulingHandle * sh, const stru
if (((a4->sin_addr.s_addr & mask4->sin_addr.s_addr)) == net4->sin_addr.s_addr)
{
char * net = GNUNET_strdup (GNUNET_a2s ((const struct sockaddr *) net4, addrlen));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' is in network `%s'\n",
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api",
+ "`%s' is in network `%s'\n",
GNUNET_a2s ((const struct sockaddr *)a4, addrlen),
net);
GNUNET_free (net);
@@ -845,33 +845,12 @@ GNUNET_ATS_address_get_type (struct GNUNET_ATS_SchedulingHandle * sh, const stru
/* no local network found for this address, default: WAN */
if (type == GNUNET_ATS_NET_UNSPECIFIED)
type = GNUNET_ATS_NET_WAN;
-
-#if VERBOSE
- const char * range;
- switch (type) {
- case GNUNET_ATS_NET_WAN:
- range = "WAN";
- break;
- case GNUNET_ATS_NET_LAN:
- range = "LAN";
- break;
- case GNUNET_ATS_NET_LOOPBACK:
- range = "LOOPBACK";
- break;
- default:
-
- break;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "`%s' is in network `%s'\n",
- GNUNET_a2s ((const struct sockaddr *) addr, addrlen),
- range);
-#endif
-
ats.type = htonl (GNUNET_ATS_NETWORK_TYPE);
ats.value = htonl (type);
return (const struct GNUNET_ATS_Information) ats;
}
+
/**
* Initialize the ATS subsystem.
*
@@ -918,7 +897,7 @@ GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh)
}
if (NULL != sh->client)
{
- GNUNET_CLIENT_disconnect (sh->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (sh->client);
sh->client = NULL;
}
if (GNUNET_SCHEDULER_NO_TASK != sh->task)
@@ -938,6 +917,32 @@ GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh)
sh = NULL;
}
+/**
+ * We would like to reset the address suggestion block time for this
+ * peer
+ *
+ * @param sh handle
+ * @param peer identity of the peer we want to reset
+ */
+void
+GNUNET_ATS_reset_backoff (struct GNUNET_ATS_SchedulingHandle *sh,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ struct PendingMessage *p;
+ struct ResetBackoffMessage *m;
+
+ p = GNUNET_malloc (sizeof (struct PendingMessage) +
+ sizeof (struct ResetBackoffMessage));
+ p->size = sizeof (struct ResetBackoffMessage);
+ p->is_init = GNUNET_NO;
+ m = (struct ResetBackoffMessage *) &p[1];
+ m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_RESET_BACKOFF);
+ m->header.size = htons (sizeof (struct ResetBackoffMessage));
+ m->reserved = htonl (0);
+ m->peer = *peer;
+ GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p);
+ do_transmit (sh);
+}
/**
* We would like to establish a new connection with a peer. ATS
@@ -953,6 +958,8 @@ GNUNET_ATS_suggest_address (struct GNUNET_ATS_SchedulingHandle *sh,
struct PendingMessage *p;
struct RequestAddressMessage *m;
+ // FIXME: ATS needs to remember this in case of
+ // a disconnect!
p = GNUNET_malloc (sizeof (struct PendingMessage) +
sizeof (struct RequestAddressMessage));
p->size = sizeof (struct RequestAddressMessage);
@@ -993,6 +1000,7 @@ GNUNET_ATS_suggest_address_cancel (struct GNUNET_ATS_SchedulingHandle *sh,
do_transmit (sh);
}
+
/**
* We have updated performance statistics for a given address. Note
* that this function can be called for addresses that are currently
@@ -1117,10 +1125,10 @@ GNUNET_ATS_address_in_use (struct GNUNET_ATS_SchedulingHandle *sh,
memcpy (pm, address->address, address->address_length);
memcpy (&pm[address->address_length], address->transport_name, namelen);
GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p);
-
do_transmit (sh);
}
+
/**
* A session got destroyed, stop including it as a valid address.
*
diff --git a/src/ats/gnunet-service-ats.c b/src/ats/gnunet-service-ats.c
index 7deca0b..aef72f1 100644
--- a/src/ats/gnunet-service-ats.c
+++ b/src/ats/gnunet-service-ats.c
@@ -39,6 +39,9 @@
*/
struct GNUNET_STATISTICS_Handle *GSA_stats;
+static struct GNUNET_SERVER_Handle *GSA_server;
+
+
/**
* We have received a 'ClientStartMessage' from a client. Find out which
* type of client it is and notify the respective subsystem.
@@ -54,7 +57,6 @@ handle_ats_start (void *cls, struct GNUNET_SERVER_Client *client,
const struct ClientStartMessage *msg =
(const struct ClientStartMessage *) message;
enum StartFlag flag;
-
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ATS_START");
flag = ntohl (msg->start_flag);
switch (flag)
@@ -111,6 +113,7 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
GAS_scheduling_done ();
GAS_performance_done ();
GAS_reservations_done ();
+ GNUNET_SERVER_disconnect_notify_cancel (GSA_server, &client_disconnect_handler, NULL);
if (NULL != GSA_stats)
{
GNUNET_STATISTICS_destroy (GSA_stats, GNUNET_NO);
@@ -150,8 +153,12 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
sizeof (struct ReservationRequestMessage)},
{&GAS_handle_preference_change, NULL,
GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE, 0},
+ {&GAS_handle_reset_backoff, NULL,
+ GNUNET_MESSAGE_TYPE_ATS_RESET_BACKOFF,
+ sizeof (struct ResetBackoffMessage)},
{NULL, NULL, 0, 0}
};
+ GSA_server = server;
GSA_stats = GNUNET_STATISTICS_create ("ats", cfg);
GAS_reservations_init ();
GAS_performance_init (server);
diff --git a/src/ats/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c
index fb9bad0..9bf5ca6 100644
--- a/src/ats/gnunet-service-ats_addresses.c
+++ b/src/ats/gnunet-service-ats_addresses.c
@@ -37,6 +37,8 @@
#define VERBOSE GNUNET_NO
+#define ATS_BLOCKING_DELTA GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 100)
+
enum ATS_Mode
{
/*
@@ -66,6 +68,25 @@ static unsigned int active_addr_count;
static int ats_mode;
+static int running;
+
+
+static void
+send_bw_notification (struct ATS_Address *aa)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New bandwidth for peer %s is %u/%u\n",
+ GNUNET_i2s (&aa->peer), ntohl (aa->assigned_bw_in.value__),
+ ntohl (aa->assigned_bw_out.value__));
+ GAS_scheduling_transmit_address_suggestion (&aa->peer, aa->plugin, aa->addr,
+ aa->addr_len, aa->session_id,
+ aa->ats, aa->ats_count,
+ aa->assigned_bw_out,
+ aa->assigned_bw_in);
+ GAS_reservations_set_bandwidth (&aa->peer, aa->assigned_bw_in);
+ GAS_performance_notify_clients (&aa->peer, aa->plugin, aa->addr, aa->addr_len,
+ aa->ats, aa->ats_count, aa->assigned_bw_out,
+ aa->assigned_bw_in);
+}
/**
* Update a bandwidth assignment for a peer. This trivial method currently
@@ -90,18 +111,8 @@ update_bw_simple_it (void *cls, const GNUNET_HashCode * key, void *value)
aa->assigned_bw_in.value__ = htonl (wan_quota_in / active_addr_count);
aa->assigned_bw_out.value__ = htonl (wan_quota_out / active_addr_count);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New bandwidth for peer %s is %u/%u\n",
- GNUNET_i2s (&aa->peer), ntohl (aa->assigned_bw_in.value__),
- ntohl (aa->assigned_bw_out.value__));
- GAS_scheduling_transmit_address_suggestion (&aa->peer, aa->plugin, aa->addr,
- aa->addr_len, aa->session_id,
- aa->ats, aa->ats_count,
- aa->assigned_bw_out,
- aa->assigned_bw_in);
- GAS_reservations_set_bandwidth (&aa->peer, aa->assigned_bw_in);
- GAS_performance_notify_clients (&aa->peer, aa->plugin, aa->addr, aa->addr_len,
- aa->ats, aa->ats_count, aa->assigned_bw_out,
- aa->assigned_bw_in);
+ send_bw_notification (aa);
+
return GNUNET_OK;
}
@@ -159,9 +170,6 @@ create_address (const struct GNUNET_PeerIdentity *peer,
memcpy (&aa[1], plugin_addr, plugin_addr_len);
aa->plugin = GNUNET_strdup (plugin_name);
aa->session_id = session_id;
- aa->mlp_information = NULL;
- aa->next = NULL;
- aa->prev = NULL;
return aa;
}
@@ -332,6 +340,11 @@ GAS_addresses_update (const struct GNUNET_PeerIdentity *peer,
struct ATS_Address *old;
uint32_t i;
+ if (GNUNET_NO == running)
+ return;
+
+ GNUNET_assert (NULL != addresses);
+
aa = create_address (peer,
plugin_name,
plugin_addr, plugin_addr_len,
@@ -342,11 +355,10 @@ GAS_addresses_update (const struct GNUNET_PeerIdentity *peer,
aa->ats_count = atsi_count;
memcpy (aa->ats, atsi, atsi_count * sizeof (struct GNUNET_ATS_Information));
-#if DEBUG_ATS
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating address for peer `%s' %u\n",
GNUNET_i2s (peer),
session_id);
-#endif
+
/* Get existing address or address with session == 0 */
old = find_address (peer, aa);
if (old == NULL)
@@ -445,11 +457,11 @@ destroy_by_session_id (void *cls, const GNUNET_HashCode * key, void *value)
(aa->addr_len == info->addr_len) &&
(0 == memcmp (info->addr, aa->addr, aa->addr_len)))
{
-#if VERBOSE
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Deleting address for peer `%s': `%s' %u\n",
GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id);
-#endif
+
if (GNUNET_YES == destroy_address (aa))
recalculate_assigned_bw ();
return GNUNET_OK;
@@ -503,6 +515,9 @@ GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer,
{
struct ATS_Address *aa;
+ if (GNUNET_NO == running)
+ return;
+
GNUNET_break (0 < strlen (plugin_name));
aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id);
@@ -529,6 +544,49 @@ find_address_it (void *cls, const GNUNET_HashCode * key, void *value)
struct ATS_Address **ap = cls;
struct ATS_Address *aa = (struct ATS_Address *) value;
struct ATS_Address *ab = *ap;
+ struct GNUNET_TIME_Absolute now;
+
+ now = GNUNET_TIME_absolute_get();
+
+ if (aa->blocked_until.abs_value == GNUNET_TIME_absolute_max (now, aa->blocked_until).abs_value)
+ {
+ /* This address is blocked for suggestion */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Address %p blocked for suggestion for %llu ms \n",
+ aa,
+ GNUNET_TIME_absolute_get_difference(now, aa->blocked_until).rel_value);
+ return GNUNET_OK;
+ }
+
+ aa->block_interval = GNUNET_TIME_relative_add (aa->block_interval, ATS_BLOCKING_DELTA);
+ aa->blocked_until = GNUNET_TIME_absolute_add (now, aa->block_interval);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Address %p ready for suggestion, block interval now %llu \n", aa, aa->block_interval);
+
+ /* FIXME this is a hack */
+
+
+ if (NULL != ab)
+ {
+ if ((0 == strcmp (ab->plugin, "tcp")) &&
+ (0 == strcmp (aa->plugin, "tcp")))
+ {
+ if ((0 != ab->addr_len) &&
+ (0 == aa->addr_len))
+ {
+ /* saved address was an outbound address, but we have an inbound address */
+ *ap = aa;
+ return GNUNET_OK;
+ }
+ if (0 == ab->addr_len)
+ {
+ /* saved address was an inbound address, so do not overwrite */
+ return GNUNET_OK;
+ }
+ }
+ }
+ /* FIXME end of hack */
if (NULL == ab)
{
@@ -559,7 +617,7 @@ find_address_it (void *cls, const GNUNET_HashCode * key, void *value)
}
-void
+int
GAS_addresses_in_use (const struct GNUNET_PeerIdentity *peer,
const char *plugin_name, const void *plugin_addr,
size_t plugin_addr_len, uint32_t session_id, int in_use)
@@ -573,19 +631,34 @@ GAS_addresses_in_use (const struct GNUNET_PeerIdentity *peer,
struct ATS_Address *aa;
struct ATS_Address *old;
+ if (GNUNET_NO == running)
+ return GNUNET_SYSERR;
- aa = create_address(peer, plugin_name, plugin_addr, plugin_addr_len, session_id);
+ aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id);
old = find_exact_address (peer, aa);
free_address (aa);
- GNUNET_assert (old != NULL);
- GNUNET_assert (old->used != in_use);
+ if (NULL == old)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (old->used == in_use)
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Address in use called multiple times for peer `%s': %s -> %s \n",
+ GNUNET_i2s (peer),
+ (GNUNET_NO == old->used) ? "NO" : "YES",
+ (GNUNET_NO == in_use) ? "NO" : "YES");
+ return GNUNET_SYSERR;
+ }
old->used = in_use;
-
#if HAVE_LIBGLPK
if (ats_mode == MLP)
GAS_mlp_address_update (mlp, addresses, old);
#endif
+ return GNUNET_OK;
}
@@ -608,7 +681,7 @@ void request_address_mlp (const struct GNUNET_PeerIdentity *peer)
if (aa == NULL)
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer));
return;
}
@@ -617,18 +690,7 @@ void request_address_mlp (const struct GNUNET_PeerIdentity *peer)
aa->active = GNUNET_YES;
active_addr_count++;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New bandwidth for peer %s is %u/%u\n",
- GNUNET_i2s (&aa->peer), ntohl (aa->assigned_bw_in.value__),
- ntohl (aa->assigned_bw_out.value__));
- GAS_scheduling_transmit_address_suggestion (&aa->peer, aa->plugin, aa->addr,
- aa->addr_len, aa->session_id,
- aa->ats, aa->ats_count,
- aa->assigned_bw_out,
- aa->assigned_bw_in);
- GAS_reservations_set_bandwidth (&aa->peer, aa->assigned_bw_in);
- GAS_performance_notify_clients (&aa->peer, aa->plugin, aa->addr, aa->addr_len,
- aa->ats, aa->ats_count, aa->assigned_bw_out,
- aa->assigned_bw_in);
+ send_bw_notification (aa);
}
else
{
@@ -652,11 +714,14 @@ void request_address_simple (const struct GNUNET_PeerIdentity *peer)
&find_address_it, &aa);
if (aa == NULL)
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer));
return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
+ "Suggesting address %p for peer `%s'\n", aa, GNUNET_i2s (peer));
+
if (aa->active == GNUNET_NO)
{
aa->active = GNUNET_YES;
@@ -681,6 +746,9 @@ void request_address_simple (const struct GNUNET_PeerIdentity *peer)
void
GAS_addresses_request_address (const struct GNUNET_PeerIdentity *peer)
{
+ if (GNUNET_NO == running)
+ return;
+
if (ats_mode == SIMPLE)
{
request_address_simple (peer);
@@ -692,6 +760,30 @@ GAS_addresses_request_address (const struct GNUNET_PeerIdentity *peer)
}
+static int
+reset_address_it (void *cls, const GNUNET_HashCode * key, void *value)
+{
+ struct ATS_Address *aa = value;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Resetting interval for peer `%s' address %p from %llu to 0\n", GNUNET_i2s (&aa->peer), aa, aa->block_interval);
+
+ aa->blocked_until = GNUNET_TIME_UNIT_ZERO_ABS;
+ aa->block_interval = GNUNET_TIME_UNIT_ZERO;
+ return GNUNET_OK;
+}
+
+void
+GAS_addresses_handle_backoff_reset (const struct GNUNET_PeerIdentity *peer)
+{
+ GNUNET_break (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_get_multiple (addresses,
+ &peer->hashPubKey,
+ &reset_address_it,
+ NULL));
+}
+
+
+
// FIXME: this function should likely end up in the LP-subsystem and
// not with 'addresses' in the future...
void
@@ -699,6 +791,8 @@ GAS_addresses_change_preference (const struct GNUNET_PeerIdentity *peer,
enum GNUNET_ATS_PreferenceKind kind,
float score)
{
+ if (GNUNET_NO == running)
+ return;
#if HAVE_LIBGLPK
if (ats_mode == MLP)
GAS_mlp_address_change_preference (mlp, peer, kind, score);
@@ -717,42 +811,86 @@ void
GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
const struct GNUNET_STATISTICS_Handle *stats)
{
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_size (cfg, "ats",
- "WAN_QUOTA_IN",
- &wan_quota_in));
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_size (cfg, "ats",
- "WAN_QUOTA_OUT",
- &wan_quota_out));
-
- switch (GNUNET_CONFIGURATION_get_value_yesno (cfg, "ats", "MLP"))
- {
- /* MLP = YES */
- case GNUNET_YES:
+ int mode;
+
+ char *quota_wan_in_str;
+ char *quota_wan_out_str;
+
+ running = GNUNET_NO;
+
+ addresses = GNUNET_CONTAINER_multihashmap_create (128);
+ GNUNET_assert (NULL != addresses);
+
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_IN", &quota_wan_in_str))
+ {
+ if (0 == strcmp(quota_wan_in_str, "unlimited") ||
+ (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_wan_in_str, &wan_quota_in)))
+ wan_quota_in = (UINT32_MAX) /10;
+
+ GNUNET_free (quota_wan_in_str);
+ quota_wan_in_str = NULL;
+ }
+ else
+ {
+ wan_quota_in = (UINT32_MAX) /10;
+ }
+
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_OUT", &quota_wan_out_str))
+ {
+ if (0 == strcmp(quota_wan_out_str, "unlimited") ||
+ (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_wan_out_str, &wan_quota_out)))
+ wan_quota_out = (UINT32_MAX) /10;
+
+ GNUNET_free (quota_wan_out_str);
+ quota_wan_out_str = NULL;
+ }
+ else
+ {
+ wan_quota_out = (UINT32_MAX) /10;
+ }
+
+ mode = GNUNET_CONFIGURATION_get_value_yesno (cfg, "ats", "MLP");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MLP mode %u", mode);
+ switch (mode)
+ {
+ /* MLP = YES */
+ case GNUNET_YES:
#if HAVE_LIBGLPK
- ats_mode = MLP;
- /* Init the MLP solver with default values */
- mlp = GAS_mlp_init (cfg, stats, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS);
- break;
+ ats_mode = MLP;
+ /* Init the MLP solver with default values */
+ mlp = GAS_mlp_init (cfg, stats, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS);
+ if (NULL == mlp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP mode was configured, but libglpk is not installed, switching to simple mode\n");
+ GNUNET_STATISTICS_update (GSA_stats, "MLP mode enabled", 0, GNUNET_NO);
+ break;
+ }
+ else
+ {
+ GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 1, GNUNET_NO);
+ break;
+ }
#else
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP mode was configured, but libglpk is not installed, switching to simple mode");
- ats_mode = SIMPLE;
- break;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP mode was configured, but libglpk is not installed, switching to simple mode");
+ GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 0, GNUNET_NO);
+ ats_mode = SIMPLE;
+ break;
#endif
- /* MLP = NO */
- case GNUNET_NO:
- ats_mode = SIMPLE;
- break;
- /* No configuration value */
- case GNUNET_SYSERR:
- ats_mode = SIMPLE;
- break;
- default:
- break;
+ /* MLP = NO */
+ case GNUNET_NO:
+ GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 0, GNUNET_NO);
+ ats_mode = SIMPLE;
+ break;
+ /* No configuration value */
+ case GNUNET_SYSERR:
+ GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 0, GNUNET_NO);
+ ats_mode = SIMPLE;
+ break;
+ default:
+ break;
}
-
- addresses = GNUNET_CONTAINER_multihashmap_create (128);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS started with %s mode\n", (SIMPLE == ats_mode) ? "SIMPLE" : "MLP");
+ running = GNUNET_YES;
}
@@ -777,6 +915,9 @@ free_address_it (void *cls, const GNUNET_HashCode * key, void *value)
void
GAS_addresses_destroy_all ()
{
+ if (GNUNET_NO == running)
+ return;
+
if (addresses != NULL)
GNUNET_CONTAINER_multihashmap_iterate (addresses, &free_address_it, NULL);
GNUNET_assert (active_addr_count == 0);
@@ -790,6 +931,7 @@ void
GAS_addresses_done ()
{
GAS_addresses_destroy_all ();
+ running = GNUNET_NO;
GNUNET_CONTAINER_multihashmap_destroy (addresses);
addresses = NULL;
#if HAVE_LIBGLPK
diff --git a/src/ats/gnunet-service-ats_addresses.h b/src/ats/gnunet-service-ats_addresses.h
index 33ff586..fe07563 100644
--- a/src/ats/gnunet-service-ats_addresses.h
+++ b/src/ats/gnunet-service-ats_addresses.h
@@ -75,6 +75,16 @@ struct ATS_Address
struct GNUNET_BANDWIDTH_Value32NBO assigned_bw_out;
/**
+ * Blocking interval
+ */
+ struct GNUNET_TIME_Relative block_interval;
+
+ /**
+ * Time when address can be suggested again
+ */
+ struct GNUNET_TIME_Absolute blocked_until;
+
+ /**
* Is this the active address for this peer?
*/
int active;
@@ -102,10 +112,13 @@ GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
void
GAS_addresses_done (void);
+void
+GAS_addresses_handle_backoff_reset (const struct GNUNET_PeerIdentity *peer);
+
/**
* This address is now used or not used anymore
*/
-void
+int
GAS_addresses_in_use (const struct GNUNET_PeerIdentity *peer,
const char *plugin_name, const void *plugin_addr,
size_t plugin_addr_len, uint32_t session_id, int in_use);
diff --git a/src/ats/gnunet-service-ats_addresses_mlp.c b/src/ats/gnunet-service-ats_addresses_mlp.c
index 61aa733..8bfa010 100644
--- a/src/ats/gnunet-service-ats_addresses_mlp.c
+++ b/src/ats/gnunet-service-ats_addresses_mlp.c
@@ -505,7 +505,9 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON
* c 10) obey network specific quota
*/
+ /* Row for c4) minimum connection */
int min = mlp->n_min;
+ /* Number of minimum connections is min(|Peers|, n_min) */
if (mlp->n_min > mlp->c_p)
min = mlp->c_p;
@@ -565,6 +567,7 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON
mlp->ci++;
struct ATS_Peer * peer = mlp->peer_head;
+ /* For all peers */
while (peer != NULL)
{
struct ATS_Address *addr = peer->head;
@@ -590,16 +593,15 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON
/* Set -r */
ia[mlp->ci] = peer->r_c9;
ja[mlp->ci] = mlp->c_r;
- ar[mlp->ci] = -1;
+ ar[mlp->ci] = -peer->f;
mlp->ci++;
#endif
-
+ /* For all addresses of this peer */
while (addr != NULL)
{
mlpi = (struct MLP_information *) addr->mlp_information;
/* coefficient for c 2) */
-
ia[mlp->ci] = peer->r_c2;
ja[mlp->ci] = mlpi->c_n;
ar[mlp->ci] = 1;
@@ -625,8 +627,6 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON
}
/* c 7) For all quality metrics */
-
-
for (c = 0; c < mlp->m_q; c++)
{
struct ATS_Peer *tp;
@@ -640,7 +640,7 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON
glp_set_row_name (mlp->prob, mlp->r_q[c], name);
GNUNET_free (name);
/* Set row bound == 0 */
- glp_set_row_bnds (mlp->prob, mlp->r_q[c], GLP_LO, 0.0, 0.0);
+ glp_set_row_bnds (mlp->prob, mlp->r_q[c], GLP_FX, 0.0, 0.0);
ia[mlp->ci] = mlp->r_q[c];
ja[mlp->ci] = mlp->c_q[c];
@@ -657,7 +657,7 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON
ia[mlp->ci] = mlp->r_q[c];
ja[mlp->ci] = mlpi->c_b;
- ar[mlp->ci] = tp->f * value;
+ ar[mlp->ci] = tp->f_q[c] * value;
mlp->ci++;
}
}
@@ -747,7 +747,6 @@ mlp_create_problem (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_MultiHas
/* Adding invariant columns */
/* Diversity d column */
-
col = glp_add_cols (mlp->prob, 1);
mlp->c_d = col;
/* Column name */
@@ -758,7 +757,6 @@ mlp_create_problem (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_MultiHas
glp_set_col_bnds (mlp->prob, col, GLP_LO, 0.0, 0.0);
/* Utilization u column */
-
col = glp_add_cols (mlp->prob, 1);
mlp->c_u = col;
/* Column name */
@@ -806,14 +804,16 @@ mlp_create_problem (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_MultiHas
return res;
}
+
/**
* Solves the LP problem
*
* @param mlp the MLP Handle
+ * @param s_ctx context to return results
* @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
*/
static int
-mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp)
+mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContext *s_ctx)
{
int res;
struct GNUNET_TIME_Relative duration;
@@ -867,13 +867,13 @@ lp_solv:
duration = GNUNET_TIME_absolute_get_difference (start, end);
mlp->lp_solved++;
mlp->lp_total_duration =+ duration.rel_value;
+ s_ctx->lp_duration = duration;
GNUNET_STATISTICS_update (mlp->stats,"# LP problem solved", 1, GNUNET_NO);
- GNUNET_STATISTICS_set (mlp->stats,"# LP execution time", duration.rel_value, GNUNET_NO);
- GNUNET_STATISTICS_set (mlp->stats,"# LP execution time average",
+ GNUNET_STATISTICS_set (mlp->stats,"# LP execution time (ms)", duration.rel_value, GNUNET_NO);
+ GNUNET_STATISTICS_set (mlp->stats,"# LP execution time average (ms)",
mlp->lp_total_duration / mlp->lp_solved, GNUNET_NO);
-
/* Analyze problem status */
res = glp_get_status (mlp->prob);
switch (res) {
@@ -903,10 +903,11 @@ lp_solv:
* Solves the MLP problem
*
* @param mlp the MLP Handle
+ * @param s_ctx context to return results
* @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
*/
int
-mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp)
+mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContext *s_ctx)
{
int res;
struct GNUNET_TIME_Relative duration;
@@ -943,10 +944,11 @@ mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp)
duration = GNUNET_TIME_absolute_get_difference (start, end);
mlp->mlp_solved++;
mlp->mlp_total_duration =+ duration.rel_value;
+ s_ctx->mlp_duration = duration;
GNUNET_STATISTICS_update (mlp->stats,"# MLP problem solved", 1, GNUNET_NO);
- GNUNET_STATISTICS_set (mlp->stats,"# MLP execution time", duration.rel_value, GNUNET_NO);
- GNUNET_STATISTICS_set (mlp->stats,"# MLP execution time average",
+ GNUNET_STATISTICS_set (mlp->stats,"# MLP execution time (ms)", duration.rel_value, GNUNET_NO);
+ GNUNET_STATISTICS_set (mlp->stats,"# MLP execution time average (ms)",
mlp->mlp_total_duration / mlp->mlp_solved, GNUNET_NO);
/* Analyze problem status */
@@ -970,23 +972,24 @@ mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp)
return GNUNET_OK;
}
-int GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp);
+int GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContext *ctx);
+
static void
mlp_scheduler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct GAS_MLP_Handle *mlp = cls;
+ struct GAS_MLP_SolutionContext ctx;
mlp->mlp_task = GNUNET_SCHEDULER_NO_TASK;
if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
return;
-
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scheduled problem solving\n");
if (mlp->addr_in_problem != 0)
- GAS_mlp_solve_problem(mlp);
+ GAS_mlp_solve_problem(mlp, &ctx);
}
@@ -994,17 +997,34 @@ mlp_scheduler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
* Solves the MLP problem
*
* @param mlp the MLP Handle
+ * @param ctx solution context
* @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
*/
int
-GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp)
+GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContext *ctx)
{
int res;
- mlp->last_execution = GNUNET_TIME_absolute_get ();
+ /* Check if solving is already running */
+ if (GNUNET_YES == mlp->semaphore)
+ {
+ if (mlp->mlp_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel(mlp->mlp_task);
+ mlp->mlp_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ mlp->mlp_task = GNUNET_SCHEDULER_add_delayed (mlp->exec_interval, &mlp_scheduler, mlp);
+ return GNUNET_SYSERR;
+ }
+ mlp->semaphore = GNUNET_YES;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Problem solving\n");
+ mlp->last_execution = GNUNET_TIME_absolute_get ();
+ ctx->lp_result = GNUNET_SYSERR;
+ ctx->mlp_result = GNUNET_SYSERR;
+ ctx->lp_duration = GNUNET_TIME_UNIT_FOREVER_REL;
+ ctx->mlp_duration = GNUNET_TIME_UNIT_FOREVER_REL;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Solve LP problem\n");
#if WRITE_MLP
char * name;
static int i;
@@ -1014,7 +1034,14 @@ GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp)
GNUNET_free (name);
# endif
- res = mlp_solve_lp_problem (mlp);
+ res = mlp_solve_lp_problem (mlp, ctx);
+ ctx->lp_result = res;
+ if (res != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "LP Problem solving failed\n");
+ mlp->semaphore = GNUNET_NO;
+ return GNUNET_SYSERR;
+ }
#if WRITE_MLP
GNUNET_asprintf(&name, "problem_%i_lp_solution", i);
@@ -1022,31 +1049,24 @@ GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp)
GNUNET_free (name);
# endif
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Solve MLP problem\n");
+ res = mlp_solve_mlp_problem (mlp, ctx);
+ ctx->mlp_result = res;
if (res != GNUNET_OK)
{
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "LP Problem solving failed\n");
-
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP Problem solving failed\n");
+ mlp->semaphore = GNUNET_NO;
return GNUNET_SYSERR;
}
-
- res = mlp_solve_mlp_problem (mlp);
-
#if WRITE_MLP
GNUNET_asprintf(&name, "problem_%i_mlp_solution", i);
glp_print_mip (mlp->prob, name);
GNUNET_free (name);
# endif
- if (res != GNUNET_OK)
- {
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MLP Problem solving failed\n");
- return GNUNET_SYSERR;
- }
-
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Problem solved\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Problem solved %s (LP duration %llu / MLP duration %llu)\n",
+ (GNUNET_OK == res) ? "successfully" : "failed", ctx->lp_duration.rel_value, ctx->mlp_duration.rel_value);
/* Process result */
struct ATS_Peer *p = NULL;
struct ATS_Address *a = NULL;
@@ -1082,6 +1102,7 @@ GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp)
mlp->mlp_task = GNUNET_SCHEDULER_NO_TASK;
}
mlp->mlp_task = GNUNET_SCHEDULER_add_delayed (mlp->exec_interval, &mlp_scheduler, mlp);
+ mlp->semaphore = GNUNET_NO;
return res;
}
@@ -1105,20 +1126,46 @@ GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
double D;
double R;
double U;
- long long unsigned int tmp;
+ unsigned long long tmp;
unsigned int b_min;
unsigned int n_min;
struct GNUNET_TIME_Relative i_exec;
int c;
+ char * quota_out_str;
+ char * quota_in_str;
/* Init GLPK environment */
- GNUNET_assert (glp_init_env() == 0);
+ int res = glp_init_env();
+ switch (res) {
+ case 0:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n",
+ "initialization successful");
+ break;
+ case 1:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n",
+ "environment is already initialized");
+ break;
+ case 2:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n",
+ "initialization failed (insufficient memory)");
+ GNUNET_free(mlp);
+ return NULL;
+ break;
+ case 3:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n",
+ "initialization failed (unsupported programming model)");
+ GNUNET_free(mlp);
+ return NULL;
+ break;
+ default:
+ break;
+ }
/* Create initial MLP problem */
mlp->prob = glp_create_prob();
GNUNET_assert (mlp->prob != NULL);
- mlp->BIG_M = (double) (UINT32_MAX) /10;
+ mlp->BIG_M = (double) BIG_M_VALUE;
/* Get diversity coefficient from configuration */
if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (cfg, "ats",
@@ -1231,37 +1278,57 @@ GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
if ((entry_in == NULL) || (entry_out == NULL))
continue;
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_size (cfg, "ats", entry_out, &quota_out))
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, &quota_out_str))
+ {
+ if (0 == strcmp(quota_out_str, BIG_M_STRING) ||
+ (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &quota_out)))
+ quota_out = mlp->BIG_M;
+
+ GNUNET_free (quota_out_str);
+ quota_out_str = NULL;
+ }
+ else if (GNUNET_ATS_NET_UNSPECIFIED == quotas[c])
+ {
+ quota_out = mlp->BIG_M;
+ }
+ else
{
quota_out = mlp->BIG_M;
}
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_size (cfg, "ats", entry_in, &quota_in))
+
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, &quota_in_str))
+ {
+ if (0 == strcmp(quota_in_str, BIG_M_STRING) ||
+ (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &quota_in)))
+ quota_in = mlp->BIG_M;
+
+ GNUNET_free (quota_in_str);
+ quota_in_str = NULL;
+ }
+ else if (GNUNET_ATS_NET_UNSPECIFIED == quotas[c])
{
quota_in = mlp->BIG_M;
}
+ else
+ {
+ quota_in = mlp->BIG_M;
+ }
+
/* Check if defined quota could make problem unsolvable */
- if ((n_min * b_min) > quota_out)
+ if (((n_min * b_min) > quota_out) && (GNUNET_ATS_NET_UNSPECIFIED != quotas[c]))
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Inconsistent quota configuration value `%s': " \
- "outbound quota (%u Bps) too small for combination of minimum connections and minimum bandwidth per peer (%u * %u Bps = %u)\n", entry_out, quota_out, n_min, b_min, n_min * b_min);
- unsigned int default_min = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
- if ((quota_out / n_min) > default_min)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Reducing minimum bandwidth per peer to %u Bps\n",
- (quota_out / n_min));
- b_min = (quota_out / n_min);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Reducing minimum bandwidth per peer to %u Bps and minimum connections to %u \n",
- default_min, (quota_out / default_min));
- b_min = default_min;
- n_min = (quota_out / default_min);
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Inconsistent quota configuration value `%s': "
+ "outbound quota (%u Bps) too small for combination of minimum connections and minimum bandwidth per peer (%u * %u Bps = %u)\n", entry_out, quota_out, n_min, b_min, n_min * b_min);
+
+ GAS_mlp_done(mlp);
+ mlp = NULL;
+ return NULL;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found `%s' quota %llu and `%s' quota %llu\n",
entry_out, quota_out, entry_in, quota_in);
+ GNUNET_STATISTICS_update ((struct GNUNET_STATISTICS_Handle *) stats, entry_out, quota_out, GNUNET_NO);
+ GNUNET_STATISTICS_update ((struct GNUNET_STATISTICS_Handle *) stats, entry_in, quota_in, GNUNET_NO);
mlp->quota_out[c] = quota_out;
mlp->quota_in[c] = quota_in;
}
@@ -1302,7 +1369,7 @@ GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
#endif
mlp->control_param_mlp.tm_lim = max_duration.rel_value;
- mlp->last_execution = GNUNET_TIME_absolute_get_forever();
+ mlp->last_execution = GNUNET_TIME_UNIT_FOREVER_ABS;
mlp->co_D = D;
mlp->co_R = R;
@@ -1310,7 +1377,7 @@ GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
mlp->b_min = b_min;
mlp->n_min = n_min;
mlp->m_q = GNUNET_ATS_QualityPropertiesCount;
-
+ mlp->semaphore = GNUNET_NO;
return mlp;
}
@@ -1320,12 +1387,15 @@ update_quality (struct GAS_MLP_Handle *mlp, struct ATS_Address * address)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating quality metrics for peer `%s'\n",
GNUNET_i2s (&address->peer));
+ GNUNET_assert (NULL != address);
+ GNUNET_assert (NULL != address->mlp_information);
+ GNUNET_assert (NULL != address->ats);
+
struct MLP_information *mlpi = address->mlp_information;
struct GNUNET_ATS_Information *ats = address->ats;
GNUNET_assert (mlpi != NULL);
int c;
-
for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++)
{
int index = mlp_lookup_ats(address, mlp->q[c]);
@@ -1374,7 +1444,7 @@ update_quality (struct GAS_MLP_Handle *mlp, struct ATS_Address * address)
c3 ++;
}
}
- if (c3 > 0)
+ if ((c3 > 0) && (avg > 0))
/* avg = 1 / ((q[0] + ... + q[l]) /c3) => c3 / avg*/
mlpi->q_averaged[c] = (double) c3 / avg;
else
@@ -1399,7 +1469,7 @@ update_quality (struct GAS_MLP_Handle *mlp, struct ATS_Address * address)
c3 ++;
}
}
- if (c3 > 0)
+ if ((c3 > 0) && (avg > 0))
/* avg = 1 / ((q[0] + ... + q[l]) /c3) => c3 / avg*/
mlpi->q_averaged[c] = (double) c3 / avg;
else
@@ -1487,8 +1557,9 @@ GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult
{
int new;
struct MLP_information *mlpi;
+ struct GAS_MLP_SolutionContext ctx;
- GNUNET_STATISTICS_update (mlp->stats,"# LP address updates", 1, GNUNET_NO);
+ GNUNET_STATISTICS_update (mlp->stats, "# MLP address updates", 1, GNUNET_NO);
/* We add a new address */
if (address->mlp_information == NULL)
@@ -1514,6 +1585,7 @@ GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult
address->mlp_information = mlpi;
mlp->addr_in_problem ++;
+ GNUNET_STATISTICS_update (mlp->stats, "# addresses in MLP", 1, GNUNET_NO);
/* Check for and add peer */
struct ATS_Peer *peer = mlp_find_peer (mlp, &address->peer);
@@ -1540,6 +1612,7 @@ GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult
GNUNET_CONTAINER_DLL_insert (peer->head, peer->tail, address);
GNUNET_CONTAINER_DLL_insert (mlp->peer_head, mlp->peer_tail, peer);
mlp->c_p ++;
+ GNUNET_STATISTICS_update (mlp->stats, "# peers in MLP", 1, GNUNET_NO);
}
else
{
@@ -1549,7 +1622,6 @@ GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult
GNUNET_CONTAINER_DLL_insert (peer->head, peer->tail, address);
}
-
update_quality (mlp, address);
}
else
@@ -1570,7 +1642,7 @@ GAS_mlp_address_update (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult
mlp->presolver_required = GNUNET_YES;
}
if (mlp->auto_solve == GNUNET_YES)
- GAS_mlp_solve_problem (mlp);
+ GAS_mlp_solve_problem (mlp, &ctx);
}
/**
@@ -1587,6 +1659,7 @@ void
GAS_mlp_address_delete (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address)
{
GNUNET_STATISTICS_update (mlp->stats,"# LP address deletions", 1, GNUNET_NO);
+ struct GAS_MLP_SolutionContext ctx;
/* Free resources */
if (address->mlp_information != NULL)
@@ -1595,6 +1668,7 @@ GAS_mlp_address_delete (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult
address->mlp_information = NULL;
mlp->addr_in_problem --;
+ GNUNET_STATISTICS_update (mlp->stats, "# addresses in MLP", -1, GNUNET_NO);
}
/* Remove from peer list */
@@ -1613,6 +1687,7 @@ GAS_mlp_address_delete (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult
GNUNET_CONTAINER_DLL_remove (mlp->peer_head, mlp->peer_tail, head);
GNUNET_free (head);
mlp->c_p --;
+ GNUNET_STATISTICS_update (mlp->stats, "# peers in MLP", -1, GNUNET_NO);
}
/* Update problem */
@@ -1626,7 +1701,7 @@ GAS_mlp_address_delete (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_Mult
/* Recalculate */
mlp->presolver_required = GNUNET_YES;
if (mlp->auto_solve == GNUNET_YES)
- GAS_mlp_solve_problem (mlp);
+ GAS_mlp_solve_problem (mlp, &ctx);
}
}
@@ -1705,7 +1780,7 @@ void
GAS_mlp_done (struct GAS_MLP_Handle *mlp)
{
struct ATS_Peer * peer;
- struct ATS_Peer * tmp;
+ struct ATS_Address *addr;
GNUNET_assert (mlp != NULL);
@@ -1719,10 +1794,16 @@ GAS_mlp_done (struct GAS_MLP_Handle *mlp)
peer = mlp->peer_head;
while (peer != NULL)
{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up peer `%s'\n", GNUNET_i2s (&peer->id));
GNUNET_CONTAINER_DLL_remove(mlp->peer_head, mlp->peer_tail, peer);
- tmp = peer->next;
+ for (addr = peer->head; NULL != addr; addr = peer->head)
+ {
+ GNUNET_CONTAINER_DLL_remove(peer->head, peer->tail, addr);
+ GNUNET_free (addr->mlp_information);
+ addr->mlp_information = NULL;
+ }
GNUNET_free (peer);
- peer = tmp;
+ peer = mlp->peer_head;
}
mlp_delete_problem (mlp);
diff --git a/src/ats/gnunet-service-ats_addresses_mlp.h b/src/ats/gnunet-service-ats_addresses_mlp.h
index 8f60a85..d37eea7 100644
--- a/src/ats/gnunet-service-ats_addresses_mlp.h
+++ b/src/ats/gnunet-service-ats_addresses_mlp.h
@@ -36,6 +36,9 @@
#define DEBUG_MLP GNUNET_EXTRA_LOGGING
+#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, 3)
@@ -70,6 +73,14 @@ struct ATS_PreferedAddress
struct ATS_Address *address;
};
+struct GAS_MLP_SolutionContext
+{
+ int lp_result;
+ int mlp_result;
+ struct GNUNET_TIME_Relative lp_duration;
+ struct GNUNET_TIME_Relative mlp_duration;
+};
+
/**
* MLP Handle
*/
@@ -128,6 +139,8 @@ struct GAS_MLP_Handle
*/
int auto_solve;
+ int semaphore;
+
/* state information */
/**
@@ -318,10 +331,11 @@ GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
* Solves the MLP problem on demand
*
* @param mlp the MLP Handle
+ * @param ctx solution context
* @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
*/
int
-GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp);
+GAS_mlp_solve_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContext *ctx);
/**
diff --git a/src/ats/gnunet-service-ats_performance.c b/src/ats/gnunet-service-ats_performance.c
index b127656..7ab8e9a 100644
--- a/src/ats/gnunet-service-ats_performance.c
+++ b/src/ats/gnunet-service-ats_performance.c
@@ -166,7 +166,7 @@ GAS_performance_notify_clients (const struct GNUNET_PeerIdentity *peer,
sizeof (struct PeerInformationMessage) +
atsi_count * sizeof (struct GNUNET_ATS_Information) + plugin_addr_len +
plugin_name_length;
- char buf[msize];
+ char buf[msize] GNUNET_ALIGN;
struct GNUNET_ATS_Information *atsp;
char *addrp;
diff --git a/src/ats/gnunet-service-ats_scheduling.c b/src/ats/gnunet-service-ats_scheduling.c
index 72b72cd..0b66ac5 100644
--- a/src/ats/gnunet-service-ats_scheduling.c
+++ b/src/ats/gnunet-service-ats_scheduling.c
@@ -59,7 +59,6 @@ GAS_scheduling_add_client (struct GNUNET_SERVER_Client *client)
}
my_client = client;
GNUNET_SERVER_notification_context_add (nc, client);
- GNUNET_SERVER_client_keep (client);
return GNUNET_OK;
}
@@ -76,7 +75,6 @@ GAS_scheduling_remove_client (struct GNUNET_SERVER_Client *client)
if (my_client != client)
return;
GAS_addresses_destroy_all ();
- GNUNET_SERVER_client_drop (client);
my_client = NULL;
}
@@ -114,7 +112,7 @@ GAS_scheduling_transmit_address_suggestion (const struct GNUNET_PeerIdentity
sizeof (struct AddressSuggestionMessage) +
atsi_count * sizeof (struct GNUNET_ATS_Information) + plugin_addr_len +
plugin_name_length;
- char buf[msize];
+ char buf[msize] GNUNET_ALIGN;
struct GNUNET_ATS_Information *atsp;
char *addrp;
@@ -200,6 +198,30 @@ GAS_handle_request_address_cancel (void *cls,
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
+/**
+ * Handle 'reset backoff' messages from clients.
+ *
+ * @param cls unused, NULL
+ * @param client client that sent the request
+ * @param message the request message
+ */
+void
+GAS_handle_reset_backoff (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ const struct ResetBackoffMessage *msg =
+ (const struct ResetBackoffMessage *) message;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n",
+ "RESET_BACKOFF");
+ GNUNET_STATISTICS_update (GSA_stats, "# backoff reset requests received", 1,
+ GNUNET_NO);
+ GNUNET_break (0 == ntohl (msg->reserved));
+ GAS_addresses_handle_backoff_reset (&msg->peer);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
/**
* Handle 'address update' messages from clients.
@@ -274,6 +296,7 @@ GAS_handle_address_in_use (void *cls, struct GNUNET_SERVER_Client *client,
const struct AddressUseMessage *m;
const char *address;
const char *plugin_name;
+ int res;
uint16_t address_length;
uint16_t plugin_name_length;
@@ -309,10 +332,21 @@ GAS_handle_address_in_use (void *cls, struct GNUNET_SERVER_Client *client,
}
in_use = ntohs (m->in_use);
- GAS_addresses_in_use (&m->peer, plugin_name, address, address_length,
- ntohl (m->session_id), in_use);
+ res = GAS_addresses_in_use (&m->peer,
+ plugin_name,
+ address,
+ address_length,
+ ntohl (m->session_id),
+ in_use);
+
+ if (res == GNUNET_OK)
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ else
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ }
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
/**
@@ -401,8 +435,13 @@ GAS_scheduling_init (struct GNUNET_SERVER_Handle *server)
void
GAS_scheduling_done ()
{
+ if (NULL != my_client)
+ {
+ my_client = NULL;
+ }
GNUNET_SERVER_notification_context_destroy (nc);
nc = NULL;
+
}
diff --git a/src/ats/gnunet-service-ats_scheduling.h b/src/ats/gnunet-service-ats_scheduling.h
index 45fca2f..08a7f1b 100644
--- a/src/ats/gnunet-service-ats_scheduling.h
+++ b/src/ats/gnunet-service-ats_scheduling.h
@@ -51,6 +51,19 @@ GAS_scheduling_remove_client (struct GNUNET_SERVER_Client *client);
/**
+ * Handle 'reset backoff' messages from clients.
+ *
+ * @param cls unused, NULL
+ * @param client client that sent the request
+ * @param message the request message
+ */
+void
+GAS_handle_reset_backoff (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message);
+
+
+/**
* Transmit the given address suggestion and bandwidth update to all scheduling
* clients.
*
diff --git a/src/ats/perf_ats_mlp.c b/src/ats/perf_ats_mlp.c
index a15e4b4..b9ee5e4 100644
--- a/src/ats/perf_ats_mlp.c
+++ b/src/ats/perf_ats_mlp.c
@@ -18,8 +18,8 @@
Boston, MA 02111-1307, USA.
*/
/**
- * @file ats/test_ats_mlp.c
- * @brief test for the MLP solver
+ * @file ats/perf_ats_mlp
+ * @brief performance test for the MLP solver
* @author Christian Grothoff
* @author Matthias Wachs
@@ -29,110 +29,344 @@
#include "gnunet_statistics_service.h"
#include "gnunet-service-ats_addresses_mlp.h"
-#define VERBOSE GNUNET_YES
-#define VERBOSE_ARM GNUNET_NO
-
#define MLP_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3)
#define MLP_MAX_ITERATIONS INT_MAX
+#define DEF_PEERS 10
+#define DEF_ADDRESSES_PER_PEER 5
+#define DEF_ATS_VALUES 2
+#define DEF_ATS_MAX_DELAY 30
+#define DEF_ATS_MAX_DISTANCE 3
+
+static unsigned int peers;
+static unsigned int addresses;
+static unsigned int numeric;
+static unsigned int update_percentage;
+
+static int start;
+static int end;
+
+struct ATS_Peer *p;
+struct ATS_Address *a;
static int ret;
-struct GNUNET_STATISTICS_Handle * stats;
+static struct GNUNET_CONTAINER_MultiHashMap * amap;
-struct GNUNET_CONTAINER_MultiHashMap * addresses;
+static struct GAS_MLP_Handle *mlp;
-struct GAS_MLP_Handle *mlp;
-static void
-check (void *cls, char *const *args, const char *cfgfile,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
+
+
+GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
+
+struct PeerContext
{
-#if !HAVE_LIBGLPK
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed!");
- ret = 1;
- return;
-#endif
- struct ATS_Address addr[10];
+ struct GNUNET_PeerIdentity id;
- stats = GNUNET_STATISTICS_create("ats", cfg);
+ struct Address *addr;
+};
- addresses = GNUNET_CONTAINER_multihashmap_create (10);
+struct Address
+{
+ char *plugin;
+ size_t plugin_len;
- GNUNET_CRYPTO_hash_create_random(GNUNET_CRYPTO_QUALITY_WEAK, &addr[0].peer.hashPubKey);
- addr[0].mlp_information = NULL;
- addr[0].next = NULL;
- addr[0].prev = NULL;
- addr[0].plugin = strdup ("dummy");
+ void *addr;
+ size_t addr_len;
- addr[1].peer = addr[0].peer;
- addr[1].mlp_information = NULL;
- addr[1].next = NULL;
- addr[1].prev = NULL;
- addr[1].plugin = strdup ("dummy2");
+ struct GNUNET_ATS_Information *ats;
+ int ats_count;
- GNUNET_CONTAINER_multihashmap_put(addresses, &addr[0].peer.hashPubKey, &addr[0], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ void *session;
+};
- mlp = GAS_mlp_init (cfg, NULL, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS);
+void
+do_shutdown (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ unsigned int ca;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n");
+
+ if (NULL != mlp)
+ {
+ GAS_mlp_done (mlp);
+ mlp = NULL;
+ }
+
+ if (NULL != a)
+ {
+ for (ca=0; ca < (peers * addresses); ca++)
+ {
+ GNUNET_free (a[ca].plugin);
+ GNUNET_free (a[ca].ats);
+ }
+ }
+
+ if (NULL != amap)
+ GNUNET_CONTAINER_multihashmap_destroy(amap);
+ GNUNET_free_non_null (a);
+ GNUNET_free_non_null (p);
- /* Add a new address */
-#if 0
- GAS_mlp_address_update (mlp, addresses, &addr[0]);
+}
- GNUNET_assert (mlp != NULL);
- GNUNET_assert (mlp->addr_in_problem == 1);
+static void
+update_addresses (struct ATS_Address * a, unsigned int addrs, unsigned int percentage)
+{
+ if (percentage == 0)
+ return;
+
+ unsigned int ua = (addrs) * ((float) percentage / 100);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updating %u of %u addresses per peer\n", ua, addrs);
+
+ unsigned int updated[addrs];
+ unsigned int u_types[DEF_ATS_VALUES];
+ unsigned int updates = 0;
+ unsigned int u_type = 0;
+ unsigned int u_val = 0;
+ unsigned int cur = 0;
+
+ u_types[0] = 0;
+ u_types[1] = 0;
+
+ for (cur = 0; cur < addrs; cur ++)
+ {
+ updated[cur] = 0;
+ }
+ cur = 0;
+
+ while (updates < ua)
+ {
+ cur = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, addrs);
+ if (0 == updated[cur])
+ {
+ u_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_VALUES);
+ switch (u_type) {
+ case 0:
+ do
+ {
+ u_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DELAY);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating DELAY from %u to %u\n",a[cur].ats[u_type].value, u_val);
+ }
+ while (a[cur].ats[u_type].value == u_val);
+ break;
+ case 1:
+ do
+ {
+ u_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DISTANCE);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating DISTANCE from %u to %u\n",a[cur].ats[u_type].value, u_val);
+ }
+ while (a[cur].ats[u_type].value == u_val);
+ break;
+ default:
+ GNUNET_break (0);
+ break;
+ }
+ u_types[u_type]++;
+
+ a[cur].ats[u_type].value = u_val;
+ updated[cur] = 1;
+ GAS_mlp_address_update(mlp, amap, &a[cur]);
+ updates++;
+ }
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updated %u delay and %u distance values\n", u_types[0], u_types[1]);
- /* Update an new address */
- GAS_mlp_address_update (mlp, addresses, &addr[0]);
- GNUNET_assert (mlp->addr_in_problem == 1);
+}
- /* Add a second address for same peer */
- GNUNET_CONTAINER_multihashmap_put(addresses, &addr[0].peer.hashPubKey, &addr[1], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- GAS_mlp_address_update (mlp, addresses, &addr[1]);
- GNUNET_assert (mlp->addr_in_problem == 2);
- /* Delete an address */
- GNUNET_CONTAINER_multihashmap_remove (addresses, &addr[0].peer.hashPubKey, &addr[0]);
- GAS_mlp_address_delete (mlp, addresses, &addr[0]);
- GAS_mlp_address_delete (mlp, addresses, &addr[1]);
+static void
+check (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ unsigned int c = 0;
+ unsigned int c2 = 0;
+ unsigned int ca = 0;
+ int update = GNUNET_NO;
+ int range = GNUNET_NO;
+ int res;
+
+#if !HAVE_LIBGLPK
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed!");
+ ret = 1;
+ return;
#endif
- GAS_mlp_done (mlp);
- GNUNET_free (addr[0].plugin);
- GNUNET_free (addr[1].plugin);
- GNUNET_CONTAINER_multihashmap_destroy (addresses);
- GNUNET_STATISTICS_destroy(stats, GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up %u peers with %u addresses per peer\n", peers, addresses);
+
+ mlp = GAS_mlp_init (cfg, NULL, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS);
+ if (NULL == mlp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to init MLP\n");
+ ret = 1;
+ if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
+ GNUNET_SCHEDULER_cancel(shutdown_task);
+ shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+ }
+
+ if (peers == 0)
+ peers = DEF_PEERS;
+ if (addresses == 0)
+ addresses = DEF_ADDRESSES_PER_PEER;
+
+ p = GNUNET_malloc (peers * sizeof (struct ATS_Peer));
+ a = GNUNET_malloc (peers * addresses * sizeof (struct ATS_Address));
+
+ amap = GNUNET_CONTAINER_multihashmap_create(addresses * peers);
+
+ mlp->auto_solve = GNUNET_NO;
+ if (start == 0)
+ start = 0;
+ if (end == 0)
+ end = -1;
+ if ((start != -1) && (end != -1))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Solving problem starting from %u to %u\n", start , end);
+ range = GNUNET_YES;
+ }
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Solving problem for %u peers\n", peers);
+
+ if ((update_percentage >= 0) && (update_percentage <= 100))
+ {
+ update = GNUNET_YES;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Benchmarking with existing presolution and %u%% updated addresses\n", update_percentage);
+ }
+ else if ((update_percentage > 100) && (update_percentage != UINT_MAX))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Invalid percentage: %u\n", update_percentage);
+ ret = 1;
+ return;
+ }
+
+ for (c=0; c < peers; c++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up peer %u\n", c);
+ GNUNET_CRYPTO_hash_create_random(GNUNET_CRYPTO_QUALITY_NONCE, &p[c].id.hashPubKey);
+
+ for (c2=0; c2 < addresses; c2++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up address %u for peer %u\n", c2, c);
+ /* Setting required information */
+ a[ca].mlp_information = NULL;
+ a[ca].prev = NULL;
+ a[ca].next = NULL;
+
+ /* Setting address */
+ a[ca].peer = p[c].id;
+ a[ca].plugin = GNUNET_strdup("test");
+ a[ca].atsp_network_type = GNUNET_ATS_NET_LOOPBACK;
+
+ a[ca].ats = GNUNET_malloc (DEF_ATS_VALUES * sizeof (struct GNUNET_ATS_Information));
+ a[ca].ats[0].type = GNUNET_ATS_QUALITY_NET_DELAY;
+ a[ca].ats[0].value = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DELAY);
+ a[ca].ats[1].type = GNUNET_ATS_QUALITY_NET_DISTANCE;
+ a[ca].ats[1].value = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DISTANCE);
+ a[ca].ats_count = 2;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up address %u\n", ca);
+ GNUNET_CONTAINER_multihashmap_put (amap, &a[ca].peer.hashPubKey, &a[ca], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ GAS_mlp_address_update(mlp, amap, &a[ca]);
+ ca++;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Problem contains %u peers and %u adresses\n", mlp->c_p, mlp->addr_in_problem);
+
+ if (((GNUNET_YES == range) && (((start >= 0) && ((c+1) >= start)) && (c <= end))) || ((c+1) == peers))
+ {
+ GNUNET_assert ((c+1) == mlp->c_p);
+ GNUNET_assert ((c+1) * addresses == mlp->addr_in_problem);
+
+ /* Solving the problem */
+ struct GAS_MLP_SolutionContext ctx;
+
+ res = GAS_mlp_solve_problem(mlp, &ctx);
+
+ if (GNUNET_NO == update)
+ {
+ if (GNUNET_OK == res)
+ {
+ GNUNET_assert (GNUNET_OK == ctx.lp_result);
+ GNUNET_assert (GNUNET_OK == ctx.mlp_result);
+ if (GNUNET_YES == numeric)
+ printf ("%u;%u;%llu;%llu\n",mlp->c_p, mlp->addr_in_problem, (unsigned long long) ctx.lp_duration.rel_value, (unsigned long long) ctx.mlp_duration.rel_value);
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Problem solved for %u peers with %u address successfully (LP: %llu ms / MLP: %llu ms)\n",
+ mlp->c_p, mlp->addr_in_problem, ctx.lp_duration.rel_value, ctx.mlp_duration.rel_value);
+ }
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Solving problem with %u peers and %u addresses failed\n", c, c2);
+ }
+ else
+ {
+ struct GAS_MLP_SolutionContext uctx;
+ /* Update addresses */
+ update_addresses (a, (c+1) * c2, update_percentage);
+
+ /* Solve again */
+ res = GAS_mlp_solve_problem(mlp, &uctx);
+
+ if (GNUNET_OK == res)
+ {
+ GNUNET_assert (GNUNET_OK == uctx.lp_result);
+ GNUNET_assert (GNUNET_OK == uctx.mlp_result);
+ if (GNUNET_YES == numeric)
+ printf ("%u;%u;%llu;%llu;%llu;%llu\n",mlp->c_p, mlp->addr_in_problem,
+ (unsigned long long) ctx.lp_duration.rel_value, (unsigned long long) ctx.mlp_duration.rel_value,
+ (unsigned long long) uctx.lp_duration.rel_value, (unsigned long long) uctx.mlp_duration.rel_value);
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updated problem solved for %u peers with %u address successfully (Initial: LP/MLP: %llu/%llu ms, Update: %llu/%llu ms)\n",
+ mlp->c_p, mlp->addr_in_problem,
+ (unsigned long long) ctx.lp_duration.rel_value, (unsigned long long) ctx.mlp_duration.rel_value,
+ (unsigned long long) uctx.lp_duration.rel_value, (unsigned long long) uctx.mlp_duration.rel_value);
+ }
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Solving updated problem with %u peers and %u addresses failed\n", c, c2);
+ }
+ }
+ }
+
+ if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
+ GNUNET_SCHEDULER_cancel(shutdown_task);
+ shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
- ret = 0;
- return;
}
int
main (int argc, char *argv[])
{
-
- static char *const argv2[] = { "test_ats_mlp",
- "-c",
- "test_ats_api.conf",
-#if VERBOSE
- "-L", "DEBUG",
-#else
- "-L", "WARNING",
-#endif
- NULL
- };
-
+ /* Init invalid */
+ update_percentage = UINT_MAX;
static struct GNUNET_GETOPT_CommandLineOption options[] = {
+ {'a', "addresses", NULL,
+ gettext_noop ("addresses per peer"), 1,
+ &GNUNET_GETOPT_set_uint, &addresses},
+ {'p', "peers", NULL,
+ gettext_noop ("peers"), 1,
+ &GNUNET_GETOPT_set_uint, &peers},
+ {'n', "numeric", NULL,
+ gettext_noop ("numeric output only"), 0,
+ &GNUNET_GETOPT_set_one, &numeric},
+ {'e', "end", NULL,
+ gettext_noop ("end solving problem"), 1,
+ &GNUNET_GETOPT_set_uint, &end},
+ {'s', "start", NULL,
+ gettext_noop ("start solving problem"), 1,
+ &GNUNET_GETOPT_set_uint, &start},
+ {'u', "update", NULL,
+ gettext_noop ("benchmark with existing solution (address updates)"), 1,
+ &GNUNET_GETOPT_set_uint, &update_percentage},
GNUNET_GETOPT_OPTION_END
};
- GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
- "test_ats_mlp", "nohelp", options,
+
+ GNUNET_PROGRAM_run (argc, argv,
+ "perf_ats_mlp", "nohelp", options,
&check, NULL);
return ret;
}
-/* end of file test_ats_api_bandwidth_consumption.c */
+/* end of file perf_ats_mlp.c */
diff --git a/src/ats/test_ats_api.conf b/src/ats/test_ats_api.conf
index fa379c9..efd7fc9 100644
--- a/src/ats/test_ats_api.conf
+++ b/src/ats/test_ats_api.conf
@@ -9,8 +9,6 @@ UNIXPATH = /tmp/test-ats-scheduling-arm.sock
[ats]
#DEBUG = YES
#PREFIX = valgrind --leak-check=full
-#WAN_QUOTA_OUT = 4294967295
-#WAN_QUOTA_IN = 4294967295
AUTOSTART = YES
PORT = 12002
HOSTNAME = localhost
@@ -21,4 +19,30 @@ ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;
UNIXPATH = /tmp/test-ats-scheduling-ats.sock
UNIX_MATCH_UID = YES
-UNIX_MATCH_GID = YES \ No newline at end of file
+UNIX_MATCH_GID = YES
+
+# Enable MLP mode (default: NO)
+MLP = NO
+# Network specific inbound/outbound quotas
+# 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 = 1 MiB
+WLAN_QUOTA_OUT = 1 MiB
+
+# ATS extended options
+DUMP_MLP = NO
+DUMP_SOLUTION = NO
+DUMP_OVERWRITE = NO
+DUMP_MIN_PEERS = 0
+DUMP_MIN_ADDRS = 0
+DUMP_OVERWRITE = NO
+ATS_MIN_INTERVAL = 15000
+ATS_EXEC_INTERVAL = 30000
diff --git a/src/ats/test_ats_api_reset_backoff.c b/src/ats/test_ats_api_reset_backoff.c
new file mode 100644
index 0000000..38c18e1
--- /dev/null
+++ b/src/ats/test_ats_api_reset_backoff.c
@@ -0,0 +1,308 @@
+/*
+ This file is part of GNUnet.
+ (C) 2010,2011 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file ats/test_ats_api_reset_backoff.c
+ * @brief test case for block reset api
+ * @author Christian Grothoff
+ * @author Matthias Wachs
+ */
+#include "platform.h"
+#include "gnunet_ats_service.h"
+#include "ats.h"
+
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
+#define ATS_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 90)
+
+static GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+static GNUNET_SCHEDULER_TaskIdentifier suggest_timeout_task;
+
+static struct GNUNET_ATS_SchedulingHandle *ats;
+
+struct GNUNET_OS_Process *arm_proc;
+
+static int ret;
+
+struct Address
+{
+ char *plugin;
+ size_t plugin_len;
+
+ void *addr;
+ size_t addr_len;
+
+ struct GNUNET_ATS_Information *ats;
+ int ats_count;
+
+ void *session;
+};
+
+struct PeerContext
+{
+ struct GNUNET_PeerIdentity id;
+
+ struct Address *addr;
+};
+
+struct GNUNET_HELLO_Address hello_addr;
+struct Address address;
+struct PeerContext peer;
+struct GNUNET_ATS_Information atsi[2];
+
+static void
+stop_arm ()
+{
+ if (0 != GNUNET_OS_process_kill (arm_proc, SIGTERM))
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
+ GNUNET_OS_process_wait (arm_proc);
+ GNUNET_OS_process_destroy (arm_proc);
+ arm_proc = NULL;
+}
+
+
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+
+ if (suggest_timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (suggest_timeout_task);
+ suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ if (ats != NULL)
+ {
+ GNUNET_ATS_scheduling_done (ats);
+ ats = NULL;
+ }
+
+ ret = GNUNET_SYSERR;
+
+ stop_arm ();
+}
+
+
+static void
+end ()
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n");
+ if (die_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ if (suggest_timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (suggest_timeout_task);
+ suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ GNUNET_ATS_scheduling_done (ats);
+
+ ret = 0;
+
+ stop_arm ();
+}
+
+
+static void
+suggest_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting address for peer timed out\n");
+
+ if (die_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
+}
+
+static void
+address_suggest_cb (void *cls, const struct GNUNET_HELLO_Address *a,
+ struct Session *session,
+ struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
+ struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
+ const struct GNUNET_ATS_Information *atsi,
+ uint32_t ats_count)
+{
+ static int suggestions;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS suggests address `%s'\n",
+ GNUNET_i2s (&a->peer));
+
+ if (0 != memcmp (&a->peer, &peer.id,
+ sizeof (struct GNUNET_PeerIdentity)))
+ {
+ GNUNET_break (0);
+ if (die_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_SCHEDULER_add_now (&end_badly, NULL);
+ return;
+ }
+
+ if (0 != strcmp (a->transport_name, address.plugin))
+ {
+ GNUNET_break (0);
+ if (die_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_SCHEDULER_add_now (&end_badly, NULL);
+ return;
+ }
+
+ if (a->address_length != address.addr_len)
+ {
+ GNUNET_break (0);
+ if (die_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_SCHEDULER_add_now (&end_badly, NULL);
+ return;
+ }
+
+ if (0 != memcmp (a->address, address.addr,
+ a->address_length))
+ {
+ GNUNET_break (0);
+ if (die_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_SCHEDULER_add_now (&end_badly, NULL);
+ return;
+ }
+
+ if (session != address.session)
+ {
+ GNUNET_break (0);
+ if (die_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_SCHEDULER_add_now (&end_badly, NULL);
+ return;
+ }
+
+ suggestions ++;
+
+ if (2 == suggestions)
+ {
+ GNUNET_SCHEDULER_add_now(&end, NULL);
+ return;
+ }
+
+ if (suggest_timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (suggest_timeout_task);
+ suggest_timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ suggest_timeout_task = GNUNET_SCHEDULER_add_delayed(ATS_TIMEOUT, &suggest_timeout, NULL);
+}
+
+void
+start_arm (const char *cfgname)
+{
+ arm_proc =
+ GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm",
+ "gnunet-service-arm",
+ "-c", cfgname, NULL);
+}
+
+static void
+check (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ ret = GNUNET_SYSERR;
+
+ die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
+ start_arm (cfgfile);
+
+ ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL);
+
+ if (ats == NULL)
+ {
+ ret = GNUNET_SYSERR;
+ end ();
+ return;
+ }
+
+ /* set up peer */
+ GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
+ &peer.id.hashPubKey);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s (&peer.id));
+
+ address.plugin = "test";
+ address.session = NULL;
+ address.addr = GNUNET_strdup ("test");
+ address.addr_len = 4;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding address\n");
+
+ hello_addr.peer = peer.id;
+ hello_addr.transport_name = address.plugin;
+ hello_addr.address = address.addr;
+ hello_addr.address_length = address.addr_len;
+ GNUNET_ATS_address_update (ats, &hello_addr, address.session, NULL, 0);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting address for peer `%s'\n",
+ GNUNET_i2s (&peer.id));
+ /* Increase block timout far beyond ATS_TIMEOUT */
+ GNUNET_ATS_suggest_address (ats, &peer.id);
+
+ GNUNET_ATS_reset_backoff(ats, &peer.id);
+ GNUNET_ATS_suggest_address (ats, &peer.id);
+}
+
+int
+main (int argc, char *argv[])
+{
+ static char *const argv2[] = { "test_ats_api_scheduling",
+ "-c",
+ "test_ats_api.conf",
+ "-L", "WARNING",
+ NULL
+ };
+
+ static struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
+ "test_ats_api_scheduling", "nohelp", options, &check,
+ NULL);
+
+
+ return ret;
+}
+/* end of file test_ats_api_reset_backoff.c */
diff --git a/src/ats/test_ats_api_scheduling.c b/src/ats/test_ats_api_scheduling.c
index 892186c..c9d2206 100644
--- a/src/ats/test_ats_api_scheduling.c
+++ b/src/ats/test_ats_api_scheduling.c
@@ -34,10 +34,6 @@
#include "gnunet_ats_service.h"
#include "ats.h"
-#define VERBOSE GNUNET_NO
-
-#define VERBOSE_ARM GNUNET_NO
-
#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
static GNUNET_SCHEDULER_TaskIdentifier die_task;
@@ -81,7 +77,7 @@ stop_arm ()
if (0 != GNUNET_OS_process_kill (arm_proc, SIGTERM))
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
GNUNET_OS_process_wait (arm_proc);
- GNUNET_OS_process_close (arm_proc);
+ GNUNET_OS_process_destroy (arm_proc);
arm_proc = NULL;
}
@@ -158,9 +154,6 @@ start_arm (const char *cfgname)
arm_proc =
GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm",
"gnunet-service-arm",
-#if VERBOSE_ARM
- "-L", "DEBUG",
-#endif
"-c", cfgname, NULL);
}
@@ -241,11 +234,7 @@ main (int argc, char *argv[])
static char *const argv2[] = { "test_ats_api_scheduling",
"-c",
"test_ats_api.conf",
-#if VERBOSE
- "-L", "DEBUG",
-#else
"-L", "WARNING",
-#endif
NULL
};
diff --git a/src/ats/test_ats_mlp.c b/src/ats/test_ats_mlp.c
index 14df2d0..c467210 100644
--- a/src/ats/test_ats_mlp.c
+++ b/src/ats/test_ats_mlp.c
@@ -30,9 +30,6 @@
#include "gnunet_ats_service.h"
#include "gnunet-service-ats_addresses_mlp.h"
-#define VERBOSE GNUNET_YES
-#define VERBOSE_ARM GNUNET_NO
-
#define MLP_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3)
#define MLP_MAX_ITERATIONS INT_MAX
@@ -52,7 +49,7 @@ create_address (struct ATS_Address *addr, char * plugin, int ats_count, struct G
addr->mlp_information = NULL;
addr->next = NULL;
addr->prev = NULL;
- addr->plugin = strdup (plugin);
+ addr->plugin = GNUNET_strdup (plugin);
addr->ats_count = ats_count;
addr->ats = ats;
}
@@ -75,6 +72,7 @@ check (void *cls, char *const *args, const char *cfgfile,
#endif
struct ATS_Address addr[10];
struct ATS_PreferedAddress *res[10];
+ struct GAS_MLP_SolutionContext ctx;
stats = GNUNET_STATISTICS_create("ats", cfg);
@@ -140,7 +138,9 @@ check (void *cls, char *const *args, const char *cfgfile,
GAS_mlp_address_update (mlp, addresses, &addr[2]);
GNUNET_assert (mlp->addr_in_problem == 3);
- GNUNET_assert (GNUNET_OK == GAS_mlp_solve_problem(mlp));
+ GNUNET_assert (GNUNET_OK == GAS_mlp_solve_problem(mlp, &ctx));
+ GNUNET_assert (GNUNET_OK == ctx.lp_result);
+ GNUNET_assert (GNUNET_OK == ctx.mlp_result);
res[0] = GAS_mlp_get_preferred_address(mlp, addresses, &p[0]);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Preferred address `%s' outbound bandwidth: %u Bps\n",res[0]->address->plugin, res[0]->bandwidth_out);
@@ -176,11 +176,7 @@ main (int argc, char *argv[])
static char *const argv2[] = { "test_ats_mlp",
"-c",
"test_ats_api.conf",
-#if VERBOSE
- "-L", "DEBUG",
-#else
"-L", "WARNING",
-#endif
NULL
};
diff --git a/src/ats/test_ats_mlp_averaging.c b/src/ats/test_ats_mlp_averaging.c
index f7b7b1d..97e9aa7 100644
--- a/src/ats/test_ats_mlp_averaging.c
+++ b/src/ats/test_ats_mlp_averaging.c
@@ -30,9 +30,6 @@
#include "gnunet_ats_service.h"
#include "gnunet-service-ats_addresses_mlp.h"
-#define VERBOSE GNUNET_YES
-#define VERBOSE_ARM GNUNET_NO
-
#define MLP_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3)
#define MLP_MAX_ITERATIONS INT_MAX
@@ -52,7 +49,7 @@ create_address (struct ATS_Address *addr, char * plugin, int ats_count, struct G
addr->mlp_information = NULL;
addr->next = NULL;
addr->prev = NULL;
- addr->plugin = strdup (plugin);
+ addr->plugin = GNUNET_strdup (plugin);
addr->ats_count = ats_count;
addr->ats = ats;
}
@@ -76,6 +73,7 @@ check (void *cls, char *const *args, const char *cfgfile,
struct ATS_Address addr[10];
struct ATS_PreferedAddress *res[10];
struct MLP_information *mlpi;
+ struct GAS_MLP_SolutionContext ctx;
stats = GNUNET_STATISTICS_create("ats", cfg);
@@ -129,7 +127,9 @@ check (void *cls, char *const *args, const char *cfgfile,
GNUNET_assert (mlp->addr_in_problem == 1);
- GNUNET_assert (GNUNET_OK == GAS_mlp_solve_problem(mlp));
+ GNUNET_assert (GNUNET_OK == GAS_mlp_solve_problem(mlp, &ctx));
+ GNUNET_assert (GNUNET_OK == ctx.lp_result);
+ GNUNET_assert (GNUNET_OK == ctx.mlp_result);
res[0] = GAS_mlp_get_preferred_address(mlp, addresses, &p[0]);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Preferred address `%s' outbound bandwidth: %u Bps\n",res[0]->address->plugin, res[0]->bandwidth_out);
@@ -159,11 +159,7 @@ main (int argc, char *argv[])
static char *const argv2[] = { "test_ats_mlp",
"-c",
"test_ats_api.conf",
-#if VERBOSE
- "-L", "DEBUG",
-#else
"-L", "WARNING",
-#endif
NULL
};