aboutsummaryrefslogtreecommitdiff
path: root/src/ats
diff options
context:
space:
mode:
Diffstat (limited to 'src/ats')
-rw-r--r--src/ats/.gitignore6
-rw-r--r--src/ats/Makefile.am102
-rw-r--r--src/ats/ats.conf.in44
-rw-r--r--src/ats/ats.h492
-rw-r--r--src/ats/ats_api_connectivity.c367
-rw-r--r--src/ats/ats_api_performance.c996
-rw-r--r--src/ats/ats_api_scanner.c65
-rw-r--r--src/ats/ats_api_scheduling.c801
-rw-r--r--src/ats/experiments/example.exp104
-rw-r--r--src/ats/experiments/gnunet_ats_sim_default.conf18
-rw-r--r--src/ats/experiments/set_preference.exp95
-rw-r--r--src/ats/gnunet-ats-solver-eval.c3588
-rw-r--r--src/ats/gnunet-ats-solver-eval.h335
-rw-r--r--src/ats/gnunet-service-ats.c538
-rw-r--r--src/ats/gnunet-service-ats.h42
-rw-r--r--src/ats/gnunet-service-ats_addresses.c717
-rw-r--r--src/ats/gnunet-service-ats_addresses.h490
-rw-r--r--src/ats/gnunet-service-ats_connectivity.c222
-rw-r--r--src/ats/gnunet-service-ats_connectivity.h92
-rw-r--r--src/ats/gnunet-service-ats_normalization.c299
-rw-r--r--src/ats/gnunet-service-ats_normalization.h60
-rw-r--r--src/ats/gnunet-service-ats_performance.c282
-rw-r--r--src/ats/gnunet-service-ats_performance.h96
-rw-r--r--src/ats/gnunet-service-ats_plugins.c600
-rw-r--r--src/ats/gnunet-service-ats_plugins.h150
-rw-r--r--src/ats/gnunet-service-ats_preferences.c776
-rw-r--r--src/ats/gnunet-service-ats_preferences.h93
-rw-r--r--src/ats/gnunet-service-ats_reservations.c217
-rw-r--r--src/ats/gnunet-service-ats_reservations.h74
-rw-r--r--src/ats/gnunet-service-ats_scheduling.c209
-rw-r--r--src/ats/gnunet-service-ats_scheduling.h101
-rw-r--r--src/ats/perf_ats_simplistic_bandwidth.conf27
-rw-r--r--src/ats/perf_ats_simplistic_delay.conf8
-rw-r--r--src/ats/perf_ats_solver.c1510
-rw-r--r--src/ats/perf_ats_solver.conf28
-rw-r--r--src/ats/perf_ats_solver_proportional.conf0
-rw-r--r--src/ats/plugin_ats_proportional.c1243
-rw-r--r--src/ats/test_ats_api.c296
-rw-r--r--src/ats/test_ats_api.conf35
-rw-r--r--src/ats/test_ats_api_delayed.conf36
-rw-r--r--src/ats/test_ats_api_proportional.conf24
-rw-r--r--src/ats/test_ats_lib.c1107
-rw-r--r--src/ats/test_ats_lib.h512
-rw-r--r--src/ats/test_ats_reservation_api.c181
-rw-r--r--src/ats/test_ats_solver_default.conf2
-rw-r--r--src/ats/test_ats_solver_delayed_proportional.conf20
-rw-r--r--src/ats/test_ats_solver_proportional.conf19
-rwxr-xr-xsrc/ats/test_delay18
48 files changed, 0 insertions, 17137 deletions
diff --git a/src/ats/.gitignore b/src/ats/.gitignore
deleted file mode 100644
index fa72eb136..000000000
--- a/src/ats/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
1gnunet-service-ats
2test_ats_api_proportional
3test_ats_reservation_api_proportional
4test_ats_api_mlp
5test_ats_api_ril
6gnunet-service-ats-new
diff --git a/src/ats/Makefile.am b/src/ats/Makefile.am
deleted file mode 100644
index 85a2bb555..000000000
--- a/src/ats/Makefile.am
+++ /dev/null
@@ -1,102 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8libexecdir= $(pkglibdir)/libexec/
9
10pkgcfg_DATA = \
11 ats.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = -fprofile-arcs -ftest-coverage
15endif
16
17lib_LTLIBRARIES = \
18 libgnunetats.la
19
20plugin_LTLIBRARIES = \
21 libgnunet_plugin_ats_proportional.la
22
23libgnunetats_la_SOURCES = \
24 ats_api_connectivity.c \
25 ats_api_scheduling.c \
26 ats_api_scanner.c \
27 ats_api_performance.c
28libgnunetats_la_LIBADD = \
29 $(top_builddir)/src/hello/libgnunethello.la \
30 $(top_builddir)/src/util/libgnunetutil.la \
31 $(LTLIBINTL)
32libgnunetats_la_LDFLAGS = \
33 $(GN_LIB_LDFLAGS) \
34 -version-info 4:0:0
35
36libgnunet_plugin_ats_proportional_la_SOURCES = \
37 plugin_ats_proportional.c
38libgnunet_plugin_ats_proportional_la_LIBADD = \
39 libgnunetats.la \
40 $(top_builddir)/src/statistics/libgnunetstatistics.la \
41 $(top_builddir)/src/util/libgnunetutil.la \
42 $(top_builddir)/src/nt/libgnunetnt.la \
43 $(LTLIBINTL)
44libgnunet_plugin_ats_proportional_la_LDFLAGS = \
45 $(GN_PLUGIN_LDFLAGS)
46
47
48libexec_PROGRAMS = \
49 gnunet-service-ats
50
51gnunet_service_ats_SOURCES = \
52 gnunet-service-ats.c gnunet-service-ats.h \
53 gnunet-service-ats_addresses.c gnunet-service-ats_addresses.h \
54 gnunet-service-ats_connectivity.c gnunet-service-ats_connectivity.h \
55 gnunet-service-ats_normalization.c gnunet-service-ats_normalization.h \
56 gnunet-service-ats_performance.c gnunet-service-ats_performance.h \
57 gnunet-service-ats_plugins.c gnunet-service-ats_plugins.h \
58 gnunet-service-ats_preferences.c gnunet-service-ats_preferences.h \
59 gnunet-service-ats_scheduling.c gnunet-service-ats_scheduling.h \
60 gnunet-service-ats_reservations.c gnunet-service-ats_reservations.h
61gnunet_service_ats_LDADD = \
62 $(top_builddir)/src/nt/libgnunetnt.la \
63 $(top_builddir)/src/statistics/libgnunetstatistics.la \
64 $(top_builddir)/src/util/libgnunetutil.la \
65 libgnunetats.la \
66 $(GN_LIBINTL)
67
68TESTING_TESTS = \
69 test_ats_api_proportional \
70 test_ats_reservation_api_proportional
71
72check_PROGRAMS = \
73 $(TESTING_TESTS)
74
75if ENABLE_TEST_RUN
76AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
77TESTS = $(check_PROGRAMS)
78endif
79
80test_ats_api_proportional_SOURCES = \
81 test_ats_api.c \
82 test_ats_lib.c test_ats_lib.h
83test_ats_api_proportional_LDADD = \
84 $(top_builddir)/src/util/libgnunetutil.la \
85 $(top_builddir)/src/hello/libgnunethello.la \
86 $(top_builddir)/src/testing/libgnunettesting.la \
87 libgnunetats.la
88
89test_ats_reservation_api_proportional_SOURCES = \
90 test_ats_reservation_api.c \
91 test_ats_lib.c test_ats_lib.h
92test_ats_reservation_api_proportional_LDADD = \
93 $(top_builddir)/src/util/libgnunetutil.la \
94 $(top_builddir)/src/hello/libgnunethello.la \
95 $(top_builddir)/src/testing/libgnunettesting.la \
96 libgnunetats.la
97
98EXTRA_DIST = \
99 ats.h \
100 test_delay \
101 test_ats_api.conf \
102 test_ats_api_proportional.conf
diff --git a/src/ats/ats.conf.in b/src/ats/ats.conf.in
deleted file mode 100644
index 2c65869dd..000000000
--- a/src/ats/ats.conf.in
+++ /dev/null
@@ -1,44 +0,0 @@
1[ats]
2START_ON_DEMAND = @START_ON_DEMAND@
3@UNIXONLY@ PORT = 2098
4HOSTNAME = localhost
5BINARY = gnunet-service-ats
6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-ats.sock
9UNIX_MATCH_UID = NO
10UNIX_MATCH_GID = YES
11# PREFIX = valgrind
12# Designated assignment mode: PROPORTIONAL / MLP / RIL
13MODE = proportional
14
15# IMPORTANT: Do not lower those quotas below 10 MiB
16# Or your peer may not bootstrap correctly.
17# Network specific inbound/outbound quotas
18UNSPECIFIED_QUOTA_IN = unlimited
19UNSPECIFIED_QUOTA_OUT = unlimited
20# LOOPBACK
21LOOPBACK_QUOTA_IN = unlimited
22LOOPBACK_QUOTA_OUT = unlimited
23# LAN
24LAN_QUOTA_IN = unlimited
25LAN_QUOTA_OUT = unlimited
26# WAN
27WAN_QUOTA_IN = 10 MiB
28WAN_QUOTA_OUT = 10 MiB
29# WLAN
30WLAN_QUOTA_IN = unlimited
31WLAN_QUOTA_OUT = unlimited
32# BLUETOOTH
33BLUETOOTH_QUOTA_IN = 10 MiB
34BLUETOOTH_QUOTA_OUT = 10 MiB
35# ATS options
36
37# Proportional specific settings
38# How proportional to preferences is bandwidth distribution in a network
39# 1.0: Fair with respect to addresses without preferences
40# > 1.0: The bigger, the more respect is paid to preferences
41PROP_PROPORTIONALITY_FACTOR = 10.00
42# Should we stick to existing connections or prefer to switch?
43# [1.0...2.0], lower value prefers to switch, bigger value is more tolerant
44PROP_STABILITY_FACTOR = 1.25
diff --git a/src/ats/ats.h b/src/ats/ats.h
deleted file mode 100644
index 711c1c103..000000000
--- a/src/ats/ats.h
+++ /dev/null
@@ -1,492 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/ats.h
22 * @brief automatic transport selection messages
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 */
26#ifndef ATS_H
27#define ATS_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_ats_service.h"
31
32
33/**
34 * Flag used to indicate which type of client is connecting
35 * to the ATS service.
36 */
37enum StartFlag
38{
39 /**
40 * This is a scheduling client (aka transport service)
41 */
42 START_FLAG_SCHEDULING = 0,
43
44 /**
45 * Performance monitoring client that wants to learn about
46 * changes in performance characteristics.
47 */
48 START_FLAG_PERFORMANCE_WITH_PIC = 1,
49
50 /**
51 * Performance monitoring client that does NOT want to learn
52 * about changes in performance characteristics.
53 */
54 START_FLAG_PERFORMANCE_NO_PIC = 2,
55
56 /**
57 * Connection suggestion handle.
58 */
59 START_FLAG_CONNECTION_SUGGESTION = 3
60};
61
62
63GNUNET_NETWORK_STRUCT_BEGIN
64
65/**
66 * First message any client sends to ATS, used to self-identify
67 * (what type of client this is).
68 */
69struct ClientStartMessage
70{
71 /**
72 * Type is #GNUNET_MESSAGE_TYPE_ATS_START.
73 */
74 struct GNUNET_MessageHeader header;
75
76 /**
77 * NBO value of an `enum StartFlag`.
78 */
79 uint32_t start_flag GNUNET_PACKED;
80};
81
82
83/**
84 * Connectivity client to ATS service: we would like to have
85 * address suggestions for this peer.
86 */
87struct RequestAddressMessage
88{
89 /**
90 * Type is #GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS or
91 * #GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL to stop
92 * suggestions.
93 */
94 struct GNUNET_MessageHeader header;
95
96 /**
97 * How "strong" is our need for an address for this peer?
98 */
99 uint32_t strength GNUNET_PACKED;
100
101 /**
102 * Peer to get address suggestions for.
103 */
104 struct GNUNET_PeerIdentity peer;
105};
106
107
108/**
109 * Scheduling client to ATS service: here is another address you can use.
110 */
111struct AddressAddMessage
112{
113 /**
114 * Type is #GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD.
115 */
116 struct GNUNET_MessageHeader header;
117
118 /**
119 * Number of bytes in the address that follows this struct.
120 */
121 uint16_t address_length GNUNET_PACKED;
122
123 /**
124 * Number of bytes in the plugin name that follows this struct.
125 */
126 uint16_t plugin_name_length GNUNET_PACKED;
127
128 /**
129 * Identity of the peer that this address is for.
130 */
131 struct GNUNET_PeerIdentity peer;
132
133 /**
134 * Internal number this client will henceforth use to
135 * refer to this address.
136 */
137 uint32_t session_id GNUNET_PACKED;
138
139 /**
140 * Local-only information of the address, see
141 * `enum GNUNET_HELLO_AddressInfo`.
142 */
143 uint32_t address_local_info GNUNET_PACKED;
144
145 /**
146 * Performance properties of the address.
147 */
148 struct GNUNET_ATS_PropertiesNBO properties;
149
150 /* followed by:
151 * - char address[address_length]
152 * - char plugin_name[plugin_name_length] (including '\0'-termination).
153 */
154};
155
156
157/**
158 * Message used to notify ATS that the performance
159 * characteristics for an address have changed.
160 */
161struct AddressUpdateMessage
162{
163 /**
164 * Message of type #GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE.
165 */
166 struct GNUNET_MessageHeader header;
167
168 /**
169 * Internal number this client uses to refer to this address.
170 */
171 uint32_t session_id GNUNET_PACKED;
172
173 /**
174 * Which peer is this about? (Technically redundant, as the
175 * @e session_id should be sufficient, but enables ATS service
176 * to find the session faster).
177 */
178 struct GNUNET_PeerIdentity peer;
179
180 /**
181 * Performance properties of the address.
182 */
183 struct GNUNET_ATS_PropertiesNBO properties;
184};
185
186
187/**
188 * Message sent by ATS client to ATS service when an address
189 * was destroyed and must thus henceforth no longer be considered
190 * for scheduling.
191 */
192struct AddressDestroyedMessage
193{
194 /**
195 * Type is #GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED.
196 */
197 struct GNUNET_MessageHeader header;
198
199 /**
200 * Internal number this client uses to refer to this address.
201 */
202 uint32_t session_id GNUNET_PACKED;
203
204 /**
205 * Which peer is this about? (Technically redundant, as the
206 * @e session_id should be sufficient, but enables ATS service
207 * to find the session faster).
208 */
209 struct GNUNET_PeerIdentity peer;
210};
211
212
213/**
214 * Message sent by ATS service to client to confirm that it is done
215 * using the given session ID.
216 */
217struct GNUNET_ATS_SessionReleaseMessage
218{
219 /**
220 * Type is #GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE.
221 */
222 struct GNUNET_MessageHeader header;
223
224 /**
225 * Number the client used to identify the session.
226 */
227 uint32_t session_id GNUNET_PACKED;
228
229 /**
230 * Which peer is this about? (Technically redundant, as the
231 * @e session_id should be sufficient, but may enable client
232 * to find the session faster).
233 */
234 struct GNUNET_PeerIdentity peer;
235};
236
237
238/**
239 * ATS Service suggests to the transport service to use the address
240 * identified by the given @e session_id for the given @e peer with
241 * the given @e bandwidth_in and @e bandwidth_out limits from now on.
242 */
243struct AddressSuggestionMessage
244{
245 /**
246 * A message of type #GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION.
247 */
248 struct GNUNET_MessageHeader header;
249
250 /**
251 * Internal number this client uses to refer to the address this
252 * suggestion is about.
253 */
254 uint32_t session_id GNUNET_PACKED;
255
256 /**
257 * Which peer is this about? (Technically redundant, as the
258 * @e session_id should be sufficient, but may enable client
259 * to find the session faster and/or check consistency).
260 */
261 struct GNUNET_PeerIdentity peer;
262
263 /**
264 * How much bandwidth we are allowed for sending.
265 */
266 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
267
268 /**
269 * How much bandwidth we are allowed for receiving.
270 */
271 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
272};
273
274
275/**
276 *
277 */
278struct PeerInformationMessage
279{
280 /**
281 * Type is #GNUNET_MESSAGE_TYPE_ATS_PEER_INFORMATION
282 */
283 struct GNUNET_MessageHeader header;
284
285 /**
286 *
287 */
288 uint16_t address_length GNUNET_PACKED;
289
290 /**
291 *
292 */
293 uint16_t plugin_name_length GNUNET_PACKED;
294
295 /**
296 *
297 */
298 struct GNUNET_PeerIdentity peer;
299
300 /**
301 *
302 */
303 uint32_t address_active GNUNET_PACKED;
304
305 /**
306 *
307 */
308 uint32_t id GNUNET_PACKED;
309
310 /**
311 *
312 */
313 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
314
315 /**
316 *
317 */
318 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
319
320 /**
321 * Performance properties of the address.
322 */
323 struct GNUNET_ATS_PropertiesNBO properties;
324
325 /**
326 * Local-only information of the address, see
327 * `enum GNUNET_HELLO_AddressInfo`.
328 */
329 uint32_t address_local_info GNUNET_PACKED;
330
331 /* followed by:
332 * - char address[address_length]
333 * - char plugin_name[plugin_name_length] (including '\0'-termination).
334 */
335};
336
337
338/**
339 * Client to service: please give us an overview of the addresses.
340 */
341struct AddressListRequestMessage
342{
343 /**
344 * Type is #GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST
345 */
346 struct GNUNET_MessageHeader header;
347
348 /**
349 * ID used to match replies to this request.
350 */
351 uint32_t id GNUNET_PACKED;
352
353 /**
354 * Which peer do we care about? All zeros for all.
355 */
356 struct GNUNET_PeerIdentity peer;
357
358 /**
359 * #GNUNET_YES to get information about all addresses,
360 * #GNUNET_NO to only return addresses that are in use.
361 */
362 int32_t all GNUNET_PACKED;
363};
364
365
366/**
367 *
368 */
369struct ReservationRequestMessage
370{
371 /**
372 * Type is #GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST
373 */
374 struct GNUNET_MessageHeader header;
375
376 /**
377 *
378 */
379 int32_t amount GNUNET_PACKED;
380
381 /**
382 *
383 */
384 struct GNUNET_PeerIdentity peer;
385};
386
387
388/**
389 *
390 */
391struct ReservationResultMessage
392{
393 /**
394 * Type is #GNUNET_MESSAGE_TYPE_ATS_RESERVATION_RESULT
395 */
396 struct GNUNET_MessageHeader header;
397
398 /**
399 *
400 */
401 int32_t amount GNUNET_PACKED;
402
403 /**
404 *
405 */
406 struct GNUNET_PeerIdentity peer;
407
408 /**
409 *
410 */
411 struct GNUNET_TIME_RelativeNBO res_delay;
412};
413
414
415/**
416 * Variable-size entry in a `struct ChangePreferenceMessage` or
417 * `struct FeedbackPreferenceMessage`.
418 */
419struct PreferenceInformation
420{
421 /**
422 * An `enum GNUNET_ATS_PreferenceKind` in NBO.
423 */
424 uint32_t preference_kind GNUNET_PACKED;
425
426 /**
427 * Degree of preference (or appreciation) for this @e
428 * preference_kind being expressed.
429 */
430 float preference_value GNUNET_PACKED;
431};
432
433
434/**
435 * Client to ATS: I have a performance preference for a peer.
436 */
437struct ChangePreferenceMessage
438{
439 /**
440 * Type is #GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE.
441 */
442 struct GNUNET_MessageHeader header;
443
444 /**
445 * How many `struct PreferenceInformation` entries follow
446 * this struct?
447 */
448 uint32_t num_preferences GNUNET_PACKED;
449
450 /**
451 * Which peer is the preference being expressed for?
452 */
453 struct GNUNET_PeerIdentity peer;
454
455 /* followed by 'num_preferences'
456 * struct PreferenceInformation values */
457};
458
459
460/**
461 * Message containing application feedback for a peer
462 */
463struct FeedbackPreferenceMessage
464{
465 /**
466 * Type is #GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_FEEDBACK.
467 */
468 struct GNUNET_MessageHeader header;
469
470 /**
471 * Number of feedback values included
472 */
473 uint32_t num_feedback GNUNET_PACKED;
474
475 /**
476 * Relative time describing for which time interval this feedback is
477 */
478 struct GNUNET_TIME_RelativeNBO scope;
479
480 /**
481 * Peer this feedback is for
482 */
483 struct GNUNET_PeerIdentity peer;
484
485 /* followed by 'num_feedback'
486 * struct PreferenceInformation values */
487};
488
489GNUNET_NETWORK_STRUCT_END
490
491
492#endif
diff --git a/src/ats/ats_api_connectivity.c b/src/ats/ats_api_connectivity.c
deleted file mode 100644
index 1b8e82777..000000000
--- a/src/ats/ats_api_connectivity.c
+++ /dev/null
@@ -1,367 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/ats_api_connectivity.c
22 * @brief enable clients to ask ATS about establishing connections to peers
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 */
26#include "platform.h"
27#include "gnunet_ats_service.h"
28#include "ats.h"
29
30
31#define LOG(kind, ...) GNUNET_log_from (kind, "ats-connectivity-api", \
32 __VA_ARGS__)
33
34
35/**
36 * Handle for ATS address suggestion requests.
37 */
38struct GNUNET_ATS_ConnectivitySuggestHandle
39{
40 /**
41 * ID of the peer for which address suggestion was requested.
42 */
43 struct GNUNET_PeerIdentity id;
44
45 /**
46 * Connecitivity handle this suggestion handle belongs to.
47 */
48 struct GNUNET_ATS_ConnectivityHandle *ch;
49
50 /**
51 * How urgent is the request.
52 */
53 uint32_t strength;
54};
55
56
57/**
58 * Handle to the ATS subsystem for connectivity management.
59 */
60struct GNUNET_ATS_ConnectivityHandle
61{
62 /**
63 * Our configuration.
64 */
65 const struct GNUNET_CONFIGURATION_Handle *cfg;
66
67 /**
68 * Map with the identities of all the peers for which we would
69 * like to have address suggestions. The key is the PID, the
70 * value is currently the `struct GNUNET_ATS_ConnectivitySuggestHandle`
71 */
72 struct GNUNET_CONTAINER_MultiPeerMap *sug_requests;
73
74 /**
75 * Message queue for sending requests to the ATS service.
76 */
77 struct GNUNET_MQ_Handle *mq;
78
79 /**
80 * Task to trigger reconnect.
81 */
82 struct GNUNET_SCHEDULER_Task *task;
83
84 /**
85 * Reconnect backoff delay.
86 */
87 struct GNUNET_TIME_Relative backoff;
88};
89
90
91/**
92 * Re-establish the connection to the ATS service.
93 *
94 * @param ch handle to use to re-connect.
95 */
96static void
97reconnect (struct GNUNET_ATS_ConnectivityHandle *ch);
98
99
100/**
101 * Re-establish the connection to the ATS service.
102 *
103 * @param cls handle to use to re-connect.
104 */
105static void
106reconnect_task (void *cls)
107{
108 struct GNUNET_ATS_ConnectivityHandle *ch = cls;
109
110 ch->task = NULL;
111 reconnect (ch);
112}
113
114
115/**
116 * Disconnect from ATS and then reconnect.
117 *
118 * @param ch our handle
119 */
120static void
121force_reconnect (struct GNUNET_ATS_ConnectivityHandle *ch)
122{
123 if (NULL != ch->mq)
124 {
125 GNUNET_MQ_destroy (ch->mq);
126 ch->mq = NULL;
127 }
128 ch->backoff = GNUNET_TIME_STD_BACKOFF (ch->backoff);
129 ch->task = GNUNET_SCHEDULER_add_delayed (ch->backoff,
130 &reconnect_task,
131 ch);
132}
133
134
135/**
136 * We encountered an error handling the MQ to the
137 * ATS service. Reconnect.
138 *
139 * @param cls the `struct GNUNET_ATS_ConnectivityHandle`
140 * @param error details about the error
141 */
142static void
143error_handler (void *cls,
144 enum GNUNET_MQ_Error error)
145{
146 struct GNUNET_ATS_ConnectivityHandle *ch = cls;
147
148 LOG (GNUNET_ERROR_TYPE_DEBUG,
149 "ATS connection died (code %d), reconnecting\n",
150 (int) error);
151 force_reconnect (ch);
152}
153
154
155/**
156 * Transmit request for an address suggestion.
157 *
158 * @param cls the `struct GNUNET_ATS_ConnectivityHandle`
159 * @param peer peer to ask for an address suggestion for
160 * @param value the `struct GNUNET_ATS_SuggestHandle`
161 * @return #GNUNET_OK (continue to iterate), #GNUNET_SYSERR on
162 * failure (message queue no longer exists)
163 */
164static int
165transmit_suggestion (void *cls,
166 const struct GNUNET_PeerIdentity *peer,
167 void *value)
168{
169 struct GNUNET_ATS_ConnectivityHandle *ch = cls;
170 struct GNUNET_ATS_ConnectivitySuggestHandle *sh = value;
171 struct GNUNET_MQ_Envelope *ev;
172 struct RequestAddressMessage *m;
173
174 if (NULL == ch->mq)
175 return GNUNET_SYSERR;
176 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS);
177 m->strength = htonl (sh->strength);
178 m->peer = *peer;
179 GNUNET_MQ_send (ch->mq, ev);
180 return GNUNET_OK;
181}
182
183
184/**
185 * Re-establish the connection to the ATS service.
186 *
187 * @param ch handle to use to re-connect.
188 */
189static void
190reconnect (struct GNUNET_ATS_ConnectivityHandle *ch)
191{
192 static const struct GNUNET_MQ_MessageHandler handlers[] =
193 { { NULL, 0, 0 } };
194 struct GNUNET_MQ_Envelope *ev;
195 struct ClientStartMessage *init;
196
197 GNUNET_assert (NULL == ch->mq);
198 ch->mq = GNUNET_CLIENT_connect (ch->cfg,
199 "ats",
200 handlers,
201 &error_handler,
202 ch);
203 if (NULL == ch->mq)
204 {
205 force_reconnect (ch);
206 return;
207 }
208 ev = GNUNET_MQ_msg (init,
209 GNUNET_MESSAGE_TYPE_ATS_START);
210 init->start_flag = htonl (START_FLAG_CONNECTION_SUGGESTION);
211 GNUNET_MQ_send (ch->mq, ev);
212 if (NULL == ch->mq)
213 return;
214 GNUNET_CONTAINER_multipeermap_iterate (ch->sug_requests,
215 &transmit_suggestion,
216 ch);
217}
218
219
220/**
221 * Initialize the ATS connectivity suggestion client handle.
222 *
223 * @param cfg configuration to use
224 * @return ats connectivity handle, NULL on error
225 */
226struct GNUNET_ATS_ConnectivityHandle *
227GNUNET_ATS_connectivity_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
228{
229 struct GNUNET_ATS_ConnectivityHandle *ch;
230
231 ch = GNUNET_new (struct GNUNET_ATS_ConnectivityHandle);
232 ch->cfg = cfg;
233 ch->sug_requests = GNUNET_CONTAINER_multipeermap_create (32,
234 GNUNET_YES);
235 reconnect (ch);
236 return ch;
237}
238
239
240/**
241 * Function called to free all `struct GNUNET_ATS_ConnectivitySuggestHandle`s
242 * in the map.
243 *
244 * @param cls NULL
245 * @param key the key
246 * @param value the value to free
247 * @return #GNUNET_OK (continue to iterate)
248 */
249static int
250free_sug_handle (void *cls,
251 const struct GNUNET_PeerIdentity *key,
252 void *value)
253{
254 struct GNUNET_ATS_ConnectivitySuggestHandle *cur = value;
255
256 GNUNET_free (cur);
257 return GNUNET_OK;
258}
259
260
261/**
262 * Client is done with ATS connectivity management, release resources.
263 *
264 * @param ch handle to release
265 */
266void
267GNUNET_ATS_connectivity_done (struct GNUNET_ATS_ConnectivityHandle *ch)
268{
269 if (NULL != ch->mq)
270 {
271 GNUNET_MQ_destroy (ch->mq);
272 ch->mq = NULL;
273 }
274 if (NULL != ch->task)
275 {
276 GNUNET_SCHEDULER_cancel (ch->task);
277 ch->task = NULL;
278 }
279 GNUNET_CONTAINER_multipeermap_iterate (ch->sug_requests,
280 &free_sug_handle,
281 NULL);
282 GNUNET_CONTAINER_multipeermap_destroy (ch->sug_requests);
283 GNUNET_free (ch);
284}
285
286
287/**
288 * We would like to receive address suggestions for a peer. ATS will
289 * respond with a call to the continuation immediately containing an address or
290 * no address if none is available. ATS can suggest more addresses until we call
291 * #GNUNET_ATS_connectivity_suggest_cancel().
292 *
293 * @param ch handle
294 * @param peer identity of the peer we need an address for
295 * @param strength how urgent is the need for such a suggestion
296 * @return suggest handle, NULL if a request is already pending
297 */
298struct GNUNET_ATS_ConnectivitySuggestHandle *
299GNUNET_ATS_connectivity_suggest (struct GNUNET_ATS_ConnectivityHandle *ch,
300 const struct GNUNET_PeerIdentity *peer,
301 uint32_t strength)
302{
303 struct GNUNET_ATS_ConnectivitySuggestHandle *s;
304
305 s = GNUNET_new (struct GNUNET_ATS_ConnectivitySuggestHandle);
306 s->ch = ch;
307 s->id = *peer;
308 s->strength = strength;
309 if (GNUNET_OK !=
310 GNUNET_CONTAINER_multipeermap_put (ch->sug_requests,
311 &s->id,
312 s,
313 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
314 {
315 LOG (GNUNET_ERROR_TYPE_DEBUG,
316 "Not requesting ATS to suggest address for `%s', request already pending\n",
317 GNUNET_i2s (peer));
318 GNUNET_free (s);
319 return NULL;
320 }
321 LOG (GNUNET_ERROR_TYPE_DEBUG,
322 "Requesting ATS to suggest address for `%s'\n",
323 GNUNET_i2s (peer));
324 if (NULL == ch->mq)
325 return s;
326 (void) transmit_suggestion (ch,
327 &s->id,
328 s);
329 return s;
330}
331
332
333/**
334 * We no longer care about being connected to a peer.
335 *
336 * @param sh handle to stop
337 */
338void
339GNUNET_ATS_connectivity_suggest_cancel (struct
340 GNUNET_ATS_ConnectivitySuggestHandle *sh)
341{
342 struct GNUNET_ATS_ConnectivityHandle *ch = sh->ch;
343 struct GNUNET_MQ_Envelope *ev;
344 struct RequestAddressMessage *m;
345
346 LOG (GNUNET_ERROR_TYPE_DEBUG,
347 "Telling ATS we no longer care for an address for `%s'\n",
348 GNUNET_i2s (&sh->id));
349 GNUNET_assert (GNUNET_OK ==
350 GNUNET_CONTAINER_multipeermap_remove (ch->sug_requests,
351 &sh->id,
352 sh));
353 if (NULL == ch->mq)
354 {
355 GNUNET_free (sh);
356 return;
357 }
358 ev = GNUNET_MQ_msg (m,
359 GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL);
360 m->strength = htonl (0);
361 m->peer = sh->id;
362 GNUNET_MQ_send (ch->mq, ev);
363 GNUNET_free (sh);
364}
365
366
367/* end of ats_api_connectivity.c */
diff --git a/src/ats/ats_api_performance.c b/src/ats/ats_api_performance.c
deleted file mode 100644
index 7349fb989..000000000
--- a/src/ats/ats_api_performance.c
+++ /dev/null
@@ -1,996 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010, 2011, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/ats_api_performance.c
22 * @brief automatic transport selection and outbound bandwidth determination
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 */
26#include "platform.h"
27#include "gnunet_ats_service.h"
28#include "ats.h"
29
30
31#define LOG(kind, ...) GNUNET_log_from (kind, "ats-performance-api", \
32 __VA_ARGS__)
33
34
35/**
36 * Linked list of pending reservations.
37 */
38struct GNUNET_ATS_ReservationContext
39{
40 /**
41 * Kept in a DLL.
42 */
43 struct GNUNET_ATS_ReservationContext *next;
44
45 /**
46 * Kept in a DLL.
47 */
48 struct GNUNET_ATS_ReservationContext *prev;
49
50 /**
51 * Target peer.
52 */
53 struct GNUNET_PeerIdentity peer;
54
55 /**
56 * Desired reservation
57 */
58 int32_t size;
59
60 /**
61 * Function to call on result.
62 */
63 GNUNET_ATS_ReservationCallback rcb;
64
65 /**
66 * Closure for @e rcb
67 */
68 void *rcb_cls;
69
70 /**
71 * Do we need to undo this reservation if it succeeded? Set to
72 * #GNUNET_YES if a reservation is cancelled. (at that point, 'info'
73 * is also set to NULL; however, info will ALSO be NULL for the
74 * reservation context that is created to undo the original request,
75 * so 'info' being NULL cannot be used to check if undo is
76 * required).
77 */
78 int undo;
79};
80
81
82/**
83 * Linked list of pending reservations.
84 */
85struct GNUNET_ATS_AddressListHandle
86{
87 /**
88 * Kept in a DLL.
89 */
90 struct GNUNET_ATS_AddressListHandle *next;
91
92 /**
93 * Kept in a DLL.
94 */
95 struct GNUNET_ATS_AddressListHandle *prev;
96
97 /**
98 * Performance handle
99 */
100 struct GNUNET_ATS_PerformanceHandle *ph;
101
102 /**
103 * Callback
104 */
105 GNUNET_ATS_AddressInformationCallback cb;
106
107 /**
108 * Callback closure for @e cb
109 */
110 void *cb_cls;
111
112 /**
113 * Target peer.
114 */
115 struct GNUNET_PeerIdentity peer;
116
117 /**
118 * Return all or specific peer only
119 */
120 int all_peers;
121
122 /**
123 * Return all or used address only
124 */
125 int all_addresses;
126
127 /**
128 * Request multiplexing
129 */
130 uint32_t id;
131};
132
133
134/**
135 * ATS Handle to obtain and/or modify performance information.
136 */
137struct GNUNET_ATS_PerformanceHandle
138{
139 /**
140 * Our configuration.
141 */
142 const struct GNUNET_CONFIGURATION_Handle *cfg;
143
144 /**
145 * Callback to invoke when an address has performance changes.
146 */
147 GNUNET_ATS_AddressInformationCallback addr_info_cb;
148
149 /**
150 * Closure for @e addr_info_cb.
151 */
152 void *addr_info_cb_cls;
153
154 /**
155 * Connection to ATS service.
156 */
157 struct GNUNET_MQ_Handle *mq;
158
159 /**
160 * Head of linked list of pending reservation requests.
161 */
162 struct GNUNET_ATS_ReservationContext *reservation_head;
163
164 /**
165 * Tail of linked list of pending reservation requests.
166 */
167 struct GNUNET_ATS_ReservationContext *reservation_tail;
168
169 /**
170 * Head of linked list of pending address list requests.
171 */
172 struct GNUNET_ATS_AddressListHandle *addresslist_head;
173
174 /**
175 * Tail of linked list of pending address list requests.
176 */
177 struct GNUNET_ATS_AddressListHandle *addresslist_tail;
178
179 /**
180 * Current request for transmission to ATS.
181 */
182 struct GNUNET_CLIENT_TransmitHandle *th;
183
184 /**
185 * Task to trigger reconnect.
186 */
187 struct GNUNET_SCHEDULER_Task *task;
188
189 /**
190 * Reconnect backoff delay.
191 */
192 struct GNUNET_TIME_Relative backoff;
193
194 /**
195 * Monitor request multiplexing
196 */
197 uint32_t monitor_id;
198
199 /**
200 * Request multiplexing
201 */
202 uint32_t id;
203
204 /**
205 * Is the receive loop active?
206 */
207 int in_receive;
208};
209
210/**
211 * Re-establish the connection to the ATS service.
212 *
213 * @param ph handle to use to re-connect.
214 */
215static void
216reconnect (struct GNUNET_ATS_PerformanceHandle *ph);
217
218
219/**
220 * Re-establish the connection to the ATS service.
221 *
222 * @param cls handle to use to re-connect.
223 */
224static void
225reconnect_task (void *cls)
226{
227 struct GNUNET_ATS_PerformanceHandle *ph = cls;
228
229 ph->task = NULL;
230 reconnect (ph);
231}
232
233
234/**
235 * Reconnect to the ATS service, something went wrong.
236 *
237 * @param ph handle to reconnect
238 */
239static void
240do_reconnect (struct GNUNET_ATS_PerformanceHandle *ph)
241{
242 struct GNUNET_ATS_ReservationContext *rc;
243 struct GNUNET_ATS_AddressListHandle *alh;
244 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_zero;
245
246 if (NULL != ph->mq)
247 {
248 GNUNET_MQ_destroy (ph->mq);
249 ph->mq = NULL;
250 }
251 while (NULL != (rc = ph->reservation_head))
252 {
253 GNUNET_CONTAINER_DLL_remove (ph->reservation_head,
254 ph->reservation_tail,
255 rc);
256 if (NULL != rc->rcb)
257 rc->rcb (rc->rcb_cls,
258 NULL,
259 0,
260 GNUNET_TIME_UNIT_FOREVER_REL);
261 GNUNET_free (rc);
262 }
263 bandwidth_zero.value__ = htonl (0);
264 while (NULL != (alh = ph->addresslist_head))
265 {
266 GNUNET_CONTAINER_DLL_remove (ph->addresslist_head,
267 ph->addresslist_tail,
268 alh);
269 if (NULL != alh->cb)
270 alh->cb (alh->cb_cls,
271 NULL,
272 GNUNET_NO,
273 bandwidth_zero,
274 bandwidth_zero,
275 NULL);
276 GNUNET_free (alh);
277 }
278 if (NULL != ph->addr_info_cb)
279 {
280 /* Indicate reconnect */
281 ph->addr_info_cb (ph->addr_info_cb_cls,
282 NULL,
283 GNUNET_NO,
284 bandwidth_zero,
285 bandwidth_zero,
286 NULL);
287 }
288 ph->backoff = GNUNET_TIME_STD_BACKOFF (ph->backoff);
289 ph->task = GNUNET_SCHEDULER_add_delayed (ph->backoff,
290 &reconnect_task,
291 ph);
292}
293
294
295/**
296 * We received a peer information message. Validate and process it.
297 *
298 * @param cls our context with the callback
299 * @param pi the message
300 * @return #GNUNET_OK if the message was well-formed
301 */
302static int
303check_peer_information (void *cls,
304 const struct PeerInformationMessage *pi)
305{
306 const char *plugin_address;
307 const char *plugin_name;
308 uint16_t plugin_address_length;
309 uint16_t plugin_name_length;
310
311 plugin_address_length = ntohs (pi->address_length);
312 plugin_name_length = ntohs (pi->plugin_name_length);
313 plugin_address = (const char *) &pi[1];
314 plugin_name = &plugin_address[plugin_address_length];
315 if ((plugin_address_length + plugin_name_length
316 + sizeof(struct PeerInformationMessage) != ntohs (pi->header.size)) ||
317 (plugin_name[plugin_name_length - 1] != '\0'))
318 {
319 GNUNET_break (0);
320 return GNUNET_SYSERR;
321 }
322 return GNUNET_OK;
323}
324
325
326/**
327 * We received a peer information message. Validate and process it.
328 *
329 * @param cls our context with the callback
330 * @param pi the message
331 * @return #GNUNET_OK if the message was well-formed
332 */
333static void
334handle_peer_information (void *cls,
335 const struct PeerInformationMessage *pi)
336{
337 struct GNUNET_ATS_PerformanceHandle *ph = cls;
338 const char *plugin_address;
339 const char *plugin_name;
340 struct GNUNET_HELLO_Address address;
341 uint16_t plugin_address_length;
342 int addr_active;
343 struct GNUNET_ATS_Properties prop;
344
345 if (NULL == ph->addr_info_cb)
346 return;
347 plugin_address_length = ntohs (pi->address_length);
348 addr_active = (int) ntohl (pi->address_active);
349 plugin_address = (const char *) &pi[1];
350 plugin_name = &plugin_address[plugin_address_length];
351
352 GNUNET_ATS_properties_ntoh (&prop,
353 &pi->properties);
354 address.peer = pi->peer;
355 address.local_info = (enum GNUNET_HELLO_AddressInfo) ntohl (
356 pi->address_local_info);
357 address.address = plugin_address;
358 address.address_length = plugin_address_length;
359 address.transport_name = plugin_name;
360 ph->addr_info_cb (ph->addr_info_cb_cls,
361 &address,
362 addr_active,
363 pi->bandwidth_out,
364 pi->bandwidth_in,
365 &prop);
366}
367
368
369/**
370 * We received a reservation result message. Validate and process it.
371 *
372 * @param cls our context with the callback
373 * @param rr the message
374 */
375static void
376handle_reservation_result (void *cls,
377 const struct ReservationResultMessage *rr)
378{
379 struct GNUNET_ATS_PerformanceHandle *ph = cls;
380 struct GNUNET_ATS_ReservationContext *rc;
381 int32_t amount;
382
383 amount = ntohl (rr->amount);
384 rc = ph->reservation_head;
385 if (0 != GNUNET_memcmp (&rr->peer,
386 &rc->peer))
387 {
388 GNUNET_break (0);
389 reconnect (ph);
390 return;
391 }
392 GNUNET_CONTAINER_DLL_remove (ph->reservation_head,
393 ph->reservation_tail,
394 rc);
395 if ((0 == amount) ||
396 (NULL != rc->rcb))
397 {
398 /* tell client if not cancelled */
399 if (NULL != rc->rcb)
400 rc->rcb (rc->rcb_cls,
401 &rr->peer,
402 amount,
403 GNUNET_TIME_relative_ntoh (rr->res_delay));
404 GNUNET_free (rc);
405 return;
406 }
407 /* amount non-zero, but client cancelled, consider undo! */
408 if (GNUNET_YES != rc->undo)
409 {
410 GNUNET_free (rc);
411 return; /* do not try to undo failed undos or negative amounts */
412 }
413 GNUNET_free (rc);
414 (void) GNUNET_ATS_reserve_bandwidth (ph,
415 &rr->peer,
416 -amount,
417 NULL, NULL);
418}
419
420
421/**
422 * We received a PeerInformationMessage. Validate it.
423 *
424 * @param cls our context with the callback
425 * @param pi the message
426 * @return #GNUNET_OK if the message was well-formed
427 */
428static int
429check_address_list (void *cls,
430 const struct PeerInformationMessage *pi)
431{
432 const char *plugin_address;
433 const char *plugin_name;
434 uint16_t plugin_address_length;
435 uint16_t plugin_name_length;
436
437 plugin_address_length = ntohs (pi->address_length);
438 plugin_name_length = ntohs (pi->plugin_name_length);
439 plugin_address = (const char *) &pi[1];
440 plugin_name = &plugin_address[plugin_address_length];
441 if ((plugin_address_length + plugin_name_length
442 + sizeof(struct PeerInformationMessage) != ntohs (pi->header.size)) ||
443 (plugin_name[plugin_name_length - 1] != '\0'))
444 {
445 GNUNET_break (0);
446 return GNUNET_SYSERR;
447 }
448 return GNUNET_OK;
449}
450
451
452/**
453 * We received a #GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE.
454 * Process it.
455 *
456 * @param cls our context with the callback
457 * @param pi the message
458 */
459static void
460handle_address_list (void *cls,
461 const struct PeerInformationMessage *pi)
462{
463 struct GNUNET_ATS_PerformanceHandle *ph = cls;
464 struct GNUNET_ATS_AddressListHandle *alh;
465 struct GNUNET_ATS_AddressListHandle *next;
466 const char *plugin_address;
467 const char *plugin_name;
468 struct GNUNET_HELLO_Address address;
469 struct GNUNET_PeerIdentity allzeros;
470 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_zero;
471 struct GNUNET_ATS_Properties prop;
472 uint16_t plugin_address_length;
473 uint16_t plugin_name_length;
474 uint32_t active;
475 uint32_t id;
476
477 id = ntohl (pi->id);
478 active = ntohl (pi->address_active);
479 plugin_address_length = ntohs (pi->address_length);
480 plugin_name_length = ntohs (pi->plugin_name_length);
481 plugin_address = (const char *) &pi[1];
482 plugin_name = &plugin_address[plugin_address_length];
483 LOG (GNUNET_ERROR_TYPE_DEBUG,
484 "Received ATS_ADDRESSLIST_RESPONSE message for peer %s and plugin %s\n",
485 GNUNET_i2s (&pi->peer),
486 plugin_name);
487
488 next = ph->addresslist_head;
489 while (NULL != (alh = next))
490 {
491 next = alh->next;
492 if (alh->id == id)
493 break;
494 }
495 if (NULL == alh)
496 return; /* was canceled */
497
498 memset (&allzeros, '\0', sizeof(allzeros));
499 if ((GNUNET_YES == GNUNET_is_zero (&pi->peer)) &&
500 (0 == plugin_name_length) &&
501 (0 == plugin_address_length))
502 {
503 /* Done */
504 LOG (GNUNET_ERROR_TYPE_DEBUG,
505 "Received last message for ATS_ADDRESSLIST_RESPONSE\n");
506 bandwidth_zero.value__ = htonl (0);
507 GNUNET_CONTAINER_DLL_remove (ph->addresslist_head,
508 ph->addresslist_tail,
509 alh);
510 if (NULL != alh->cb)
511 alh->cb (alh->cb_cls,
512 NULL,
513 GNUNET_NO,
514 bandwidth_zero,
515 bandwidth_zero,
516 NULL);
517 GNUNET_free (alh);
518 return;
519 }
520
521 address.peer = pi->peer;
522 address.address = plugin_address;
523 address.address_length = plugin_address_length;
524 address.transport_name = plugin_name;
525 if (((GNUNET_YES == alh->all_addresses) ||
526 (GNUNET_YES == active)) &&
527 (NULL != alh->cb))
528 {
529 GNUNET_ATS_properties_ntoh (&prop,
530 &pi->properties);
531 alh->cb (alh->cb_cls,
532 &address,
533 active,
534 pi->bandwidth_out,
535 pi->bandwidth_in,
536 &prop);
537 }
538}
539
540
541/**
542 * Generic error handler, called with the appropriate error code and
543 * the same closure specified at the creation of the message queue.
544 * Not every message queue implementation supports an error handler.
545 *
546 * @param cls closure with the `struct GNUNET_ATS_PerformanceHandle *`
547 * @param error error code
548 */
549static void
550mq_error_handler (void *cls,
551 enum GNUNET_MQ_Error error)
552{
553 struct GNUNET_ATS_PerformanceHandle *ph = cls;
554
555 do_reconnect (ph);
556}
557
558
559/**
560 * Re-establish the connection to the ATS service.
561 *
562 * @param ph handle to use to re-connect.
563 */
564static void
565reconnect (struct GNUNET_ATS_PerformanceHandle *ph)
566{
567 struct GNUNET_MQ_MessageHandler handlers[] = {
568 GNUNET_MQ_hd_var_size (peer_information,
569 GNUNET_MESSAGE_TYPE_ATS_PEER_INFORMATION,
570 struct PeerInformationMessage,
571 ph),
572 GNUNET_MQ_hd_fixed_size (reservation_result,
573 GNUNET_MESSAGE_TYPE_ATS_RESERVATION_RESULT,
574 struct ReservationResultMessage,
575 ph),
576 GNUNET_MQ_hd_var_size (address_list,
577 GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE,
578 struct PeerInformationMessage,
579 ph),
580 GNUNET_MQ_handler_end ()
581 };
582 struct GNUNET_MQ_Envelope *env;
583 struct ClientStartMessage *init;
584
585 GNUNET_assert (NULL == ph->mq);
586 ph->mq = GNUNET_CLIENT_connect (ph->cfg,
587 "ats",
588 handlers,
589 &mq_error_handler,
590 ph);
591 if (NULL == ph->mq)
592 return;
593 env = GNUNET_MQ_msg (init,
594 GNUNET_MESSAGE_TYPE_ATS_START);
595 init->start_flag = htonl ((NULL == ph->addr_info_cb)
596 ? START_FLAG_PERFORMANCE_NO_PIC
597 : START_FLAG_PERFORMANCE_WITH_PIC);
598 GNUNET_MQ_send (ph->mq,
599 env);
600}
601
602
603/**
604 * Get handle to access performance API of the ATS subsystem.
605 *
606 * @param cfg configuration to use
607 * @param addr_info_cb callback called when performance characteristics for
608 * an address change
609 * @param addr_info_cb_cls closure for @a addr_info_cb
610 * @return ats performance context
611 */
612struct GNUNET_ATS_PerformanceHandle *
613GNUNET_ATS_performance_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
614 GNUNET_ATS_AddressInformationCallback addr_info_cb,
615 void *addr_info_cb_cls)
616{
617 struct GNUNET_ATS_PerformanceHandle *ph;
618
619 ph = GNUNET_new (struct GNUNET_ATS_PerformanceHandle);
620 ph->cfg = cfg;
621 ph->addr_info_cb = addr_info_cb;
622 ph->addr_info_cb_cls = addr_info_cb_cls;
623 reconnect (ph);
624 if (NULL == ph->mq)
625 {
626 GNUNET_free (ph);
627 return NULL;
628 }
629 return ph;
630}
631
632
633/**
634 * Client is done using the ATS performance subsystem, release resources.
635 *
636 * @param ph handle
637 */
638void
639GNUNET_ATS_performance_done (struct GNUNET_ATS_PerformanceHandle *ph)
640{
641 struct GNUNET_ATS_ReservationContext *rc;
642 struct GNUNET_ATS_AddressListHandle *alh;
643
644 while (NULL != (alh = ph->addresslist_head))
645 {
646 GNUNET_CONTAINER_DLL_remove (ph->addresslist_head,
647 ph->addresslist_tail,
648 alh);
649 GNUNET_free (alh);
650 }
651 while (NULL != (rc = ph->reservation_head))
652 {
653 GNUNET_CONTAINER_DLL_remove (ph->reservation_head,
654 ph->reservation_tail,
655 rc);
656 GNUNET_break (NULL == rc->rcb);
657 GNUNET_free (rc);
658 }
659 if (NULL != ph->task)
660 {
661 GNUNET_SCHEDULER_cancel (ph->task);
662 ph->task = NULL;
663 }
664 if (NULL != ph->mq)
665 {
666 GNUNET_MQ_destroy (ph->mq);
667 ph->mq = NULL;
668 }
669 GNUNET_free (ph);
670}
671
672
673/**
674 * Reserve inbound bandwidth from the given peer. ATS will look at
675 * the current amount of traffic we receive from the peer and ensure
676 * that the peer could add @a amount of data to its stream.
677 *
678 * @param ph performance handle
679 * @param peer identifies the peer
680 * @param amount reserve N bytes for receiving, negative
681 * amounts can be used to undo a (recent) reservation;
682 * @param rcb function to call with the resulting reservation information
683 * @param rcb_cls closure for @a rcb
684 * @return NULL on error
685 * @deprecated will be replaced soon
686 */
687struct GNUNET_ATS_ReservationContext *
688GNUNET_ATS_reserve_bandwidth (struct GNUNET_ATS_PerformanceHandle *ph,
689 const struct GNUNET_PeerIdentity *peer,
690 int32_t amount,
691 GNUNET_ATS_ReservationCallback rcb,
692 void *rcb_cls)
693{
694 struct GNUNET_ATS_ReservationContext *rc;
695 struct GNUNET_MQ_Envelope *env;
696 struct ReservationRequestMessage *m;
697
698 if (NULL == ph->mq)
699 return NULL;
700 rc = GNUNET_new (struct GNUNET_ATS_ReservationContext);
701 rc->size = amount;
702 rc->peer = *peer;
703 rc->rcb = rcb;
704 rc->rcb_cls = rcb_cls;
705 if ((NULL != rcb) &&
706 (amount > 0))
707 rc->undo = GNUNET_YES;
708 GNUNET_CONTAINER_DLL_insert_tail (ph->reservation_head,
709 ph->reservation_tail,
710 rc);
711 env = GNUNET_MQ_msg (m,
712 GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST);
713 m->amount = htonl (amount);
714 m->peer = *peer;
715 GNUNET_MQ_send (ph->mq,
716 env);
717 return rc;
718}
719
720
721/**
722 * Cancel request for reserving bandwidth.
723 *
724 * @param rc context returned by the original #GNUNET_ATS_reserve_bandwidth() call
725 */
726void
727GNUNET_ATS_reserve_bandwidth_cancel (struct GNUNET_ATS_ReservationContext *rc)
728{
729 rc->rcb = NULL;
730}
731
732
733/**
734 * Get information about addresses known to the ATS subsystem.
735 *
736 * @param ph the performance handle to use
737 * @param peer peer idm can be NULL for all peers
738 * @param all #GNUNET_YES to get information about all addresses or #GNUNET_NO to
739 * get only address currently used
740 * @param infocb callback to call with the addresses,
741 * will callback with address == NULL when done
742 * @param infocb_cls closure for @a infocb
743 * @return ats performance context
744 */
745struct GNUNET_ATS_AddressListHandle*
746GNUNET_ATS_performance_list_addresses (struct GNUNET_ATS_PerformanceHandle *ph,
747 const struct GNUNET_PeerIdentity *peer,
748 int all,
749 GNUNET_ATS_AddressInformationCallback
750 infocb,
751 void *infocb_cls)
752{
753 struct GNUNET_ATS_AddressListHandle *alh;
754 struct GNUNET_MQ_Envelope *env;
755 struct AddressListRequestMessage *m;
756
757 if (NULL == ph->mq)
758 return NULL;
759 if (NULL == infocb)
760 {
761 GNUNET_break (0);
762 return NULL;
763 }
764 alh = GNUNET_new (struct GNUNET_ATS_AddressListHandle);
765 alh->id = ph->id++;
766 alh->cb = infocb;
767 alh->cb_cls = infocb_cls;
768 alh->ph = ph;
769 alh->all_addresses = all;
770 if (NULL == peer)
771 {
772 alh->all_peers = GNUNET_YES;
773 }
774 else
775 {
776 alh->all_peers = GNUNET_NO;
777 alh->peer = *peer;
778 }
779 GNUNET_CONTAINER_DLL_insert (ph->addresslist_head,
780 ph->addresslist_tail,
781 alh);
782 env = GNUNET_MQ_msg (m,
783 GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST);
784 m->all = htonl (all);
785 m->id = htonl (alh->id);
786 if (NULL != peer)
787 m->peer = *peer;
788 GNUNET_MQ_send (ph->mq,
789 env);
790 return alh;
791}
792
793
794/**
795 * Cancel a pending address listing operation
796 *
797 * @param alh the handle of the request to cancel
798 */
799void
800GNUNET_ATS_performance_list_addresses_cancel (struct
801 GNUNET_ATS_AddressListHandle *alh)
802{
803 struct GNUNET_ATS_PerformanceHandle *ph = alh->ph;
804
805 GNUNET_CONTAINER_DLL_remove (ph->addresslist_head,
806 ph->addresslist_tail,
807 alh);
808 GNUNET_free (alh);
809}
810
811
812/**
813 * Convert a `enum GNUNET_ATS_PreferenceType` to a string
814 *
815 * @param type the preference type
816 * @return a string or NULL if invalid
817 */
818const char *
819GNUNET_ATS_print_preference_type (enum GNUNET_ATS_PreferenceKind type)
820{
821 const char *prefs[] = GNUNET_ATS_PreferenceTypeString;
822
823 if (type < GNUNET_ATS_PREFERENCE_END)
824 return prefs[type];
825 return NULL;
826}
827
828
829/**
830 * Change preferences for the given peer. Preference changes are forgotten if peers
831 * disconnect.
832 *
833 * @param ph performance handle
834 * @param peer identifies the peer
835 * @param ... #GNUNET_ATS_PREFERENCE_END-terminated specification of the desired changes
836 */
837void
838GNUNET_ATS_performance_change_preference (struct
839 GNUNET_ATS_PerformanceHandle *ph,
840 const struct
841 GNUNET_PeerIdentity *peer,
842 ...)
843{
844 struct GNUNET_MQ_Envelope *env;
845 struct ChangePreferenceMessage *m;
846 uint32_t count;
847 struct PreferenceInformation *pi;
848 va_list ap;
849 enum GNUNET_ATS_PreferenceKind kind;
850
851 if (NULL == ph->mq)
852 return;
853 count = 0;
854 va_start (ap, peer);
855 while (GNUNET_ATS_PREFERENCE_END !=
856 (kind = GNUNET_VA_ARG_ENUM (ap, GNUNET_ATS_PreferenceKind)))
857 {
858 switch (kind)
859 {
860 case GNUNET_ATS_PREFERENCE_BANDWIDTH:
861 count++;
862 (void) va_arg (ap, double);
863 break;
864
865 case GNUNET_ATS_PREFERENCE_LATENCY:
866 count++;
867 (void) va_arg (ap, double);
868 break;
869
870 default:
871 GNUNET_assert (0);
872 }
873 }
874 va_end (ap);
875 env = GNUNET_MQ_msg_extra (m,
876 count * sizeof(struct PreferenceInformation),
877 GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE);
878 m->num_preferences = htonl (count);
879 m->peer = *peer;
880 pi = (struct PreferenceInformation *) &m[1];
881 count = 0;
882 va_start (ap, peer);
883 while (GNUNET_ATS_PREFERENCE_END != (kind =
884 GNUNET_VA_ARG_ENUM (ap,
885 GNUNET_ATS_PreferenceKind)))
886 {
887 pi[count].preference_kind = htonl (kind);
888 switch (kind)
889 {
890 case GNUNET_ATS_PREFERENCE_BANDWIDTH:
891 pi[count].preference_value = (float) va_arg (ap, double);
892
893 count++;
894 break;
895
896 case GNUNET_ATS_PREFERENCE_LATENCY:
897 pi[count].preference_value = (float) va_arg (ap, double);
898
899 count++;
900 break;
901
902 default:
903 GNUNET_assert (0);
904 }
905 }
906 va_end (ap);
907 GNUNET_MQ_send (ph->mq,
908 env);
909}
910
911
912/**
913 * Send feedback to ATS on how good a the requirements for a peer and a
914 * preference is satisfied by ATS
915 *
916 * @param ph performance handle
917 * @param scope the time interval this valid for: [now - scope .. now]
918 * @param peer identifies the peer
919 * @param ... #GNUNET_ATS_PREFERENCE_END-terminated specification of the desired changes
920 */
921void
922GNUNET_ATS_performance_give_feedback (struct GNUNET_ATS_PerformanceHandle *ph,
923 const struct GNUNET_PeerIdentity *peer,
924 const struct GNUNET_TIME_Relative scope,
925 ...)
926{
927 struct GNUNET_MQ_Envelope *env;
928 struct FeedbackPreferenceMessage *m;
929 uint32_t count;
930 struct PreferenceInformation *pi;
931 va_list ap;
932 enum GNUNET_ATS_PreferenceKind kind;
933
934 if (NULL == ph->mq)
935 return;
936 count = 0;
937 va_start (ap, scope);
938 while (GNUNET_ATS_PREFERENCE_END !=
939 (kind = GNUNET_VA_ARG_ENUM (ap, GNUNET_ATS_PreferenceKind)))
940 {
941 switch (kind)
942 {
943 case GNUNET_ATS_PREFERENCE_BANDWIDTH:
944 count++;
945 (void) va_arg (ap, double);
946 break;
947
948 case GNUNET_ATS_PREFERENCE_LATENCY:
949 count++;
950 (void) va_arg (ap, double);
951 break;
952
953 default:
954 GNUNET_assert (0);
955 }
956 }
957 va_end (ap);
958 env = GNUNET_MQ_msg_extra (m,
959 count * sizeof(struct PreferenceInformation),
960 GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_FEEDBACK);
961 m->scope = GNUNET_TIME_relative_hton (scope);
962 m->num_feedback = htonl (count);
963 m->peer = *peer;
964 pi = (struct PreferenceInformation *) &m[1];
965 count = 0;
966 va_start (ap, scope);
967 while (GNUNET_ATS_PREFERENCE_END != (kind =
968 GNUNET_VA_ARG_ENUM (ap,
969 GNUNET_ATS_PreferenceKind)))
970 {
971 pi[count].preference_kind = htonl (kind);
972 switch (kind)
973 {
974 case GNUNET_ATS_PREFERENCE_BANDWIDTH:
975 pi[count].preference_value = (float) va_arg (ap, double);
976
977 count++;
978 break;
979
980 case GNUNET_ATS_PREFERENCE_LATENCY:
981 pi[count].preference_value = (float) va_arg (ap, double);
982
983 count++;
984 break;
985
986 default:
987 GNUNET_assert (0);
988 }
989 }
990 va_end (ap);
991 GNUNET_MQ_send (ph->mq,
992 env);
993}
994
995
996/* end of ats_api_performance.c */
diff --git a/src/ats/ats_api_scanner.c b/src/ats/ats_api_scanner.c
deleted file mode 100644
index 82114f888..000000000
--- a/src/ats/ats_api_scanner.c
+++ /dev/null
@@ -1,65 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/ats_api_scanner.c
22 * @brief LAN interface scanning to determine IPs in LAN
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 */
26#include "platform.h"
27#include "gnunet_ats_service.h"
28
29/**
30 * Convert ATS properties from host to network byte order.
31 *
32 * @param nbo[OUT] value written
33 * @param hbo value read
34 */
35void
36GNUNET_ATS_properties_hton (struct GNUNET_ATS_PropertiesNBO *nbo,
37 const struct GNUNET_ATS_Properties *hbo)
38{
39 nbo->utilization_out = htonl (hbo->utilization_out);
40 nbo->utilization_in = htonl (hbo->utilization_in);
41 nbo->scope = htonl ((uint32_t) hbo->scope);
42 nbo->distance = htonl (hbo->distance);
43 nbo->delay = GNUNET_TIME_relative_hton (hbo->delay);
44}
45
46
47/**
48 * Convert ATS properties from network to host byte order.
49 *
50 * @param hbo[OUT] value written
51 * @param nbo value read
52 */
53void
54GNUNET_ATS_properties_ntoh (struct GNUNET_ATS_Properties *hbo,
55 const struct GNUNET_ATS_PropertiesNBO *nbo)
56{
57 hbo->utilization_out = ntohl (nbo->utilization_out);
58 hbo->utilization_in = ntohl (nbo->utilization_in);
59 hbo->scope = ntohl ((uint32_t) nbo->scope);
60 hbo->distance = ntohl (nbo->distance);
61 hbo->delay = GNUNET_TIME_relative_ntoh (nbo->delay);
62}
63
64
65/* end of ats_api_scanner.c */
diff --git a/src/ats/ats_api_scheduling.c b/src/ats/ats_api_scheduling.c
deleted file mode 100644
index ea4b27653..000000000
--- a/src/ats/ats_api_scheduling.c
+++ /dev/null
@@ -1,801 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/ats_api_scheduling.c
22 * @brief automatic transport selection and outbound bandwidth determination
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 *
26 * TODO:
27 * - we could avoid a linear scan over the
28 * active addresses in some cases, so if
29 * there is need, we can still optimize here
30 * - we might want to split off the logic to
31 * determine LAN vs. WAN, as it has nothing
32 * to do with accessing the ATS service.
33 */
34#include "platform.h"
35#include "gnunet_ats_service.h"
36#include "ats.h"
37
38/**
39 * How frequently do we scan the interfaces for changes to the addresses?
40 */
41#define INTERFACE_PROCESSING_INTERVAL GNUNET_TIME_relative_multiply ( \
42 GNUNET_TIME_UNIT_MINUTES, 2)
43
44#define LOG(kind, ...) GNUNET_log_from (kind, "ats-scheduling-api", __VA_ARGS__)
45
46/**
47 * Session ID we use if there is no session / slot.
48 */
49#define NOT_FOUND 0
50
51
52/**
53 * Information we track per address, incoming or outgoing. It also
54 * doesn't matter if we have a session, any address that ATS is
55 * allowed to suggest right now should be tracked.
56 */
57struct GNUNET_ATS_AddressRecord
58{
59 /**
60 * Scheduling handle this address record belongs to.
61 */
62 struct GNUNET_ATS_SchedulingHandle *sh;
63
64 /**
65 * Address data.
66 */
67 struct GNUNET_HELLO_Address *address;
68
69 /**
70 * Session handle. NULL if we have an address but no
71 * active session for this address.
72 */
73 struct GNUNET_ATS_Session *session;
74
75 /**
76 * Performance data about the address.
77 */
78 struct GNUNET_ATS_PropertiesNBO properties;
79
80 /**
81 * Which slot (index) in the session array does
82 * this record correspond to?
83 * FIXME: a linear search on this is really crappy!
84 * Maybe switch to a 64-bit global counter and be
85 * done with it? Or does that then cause too much
86 * trouble on the ATS-service side?
87 */
88 uint32_t slot;
89
90 /**
91 * We're about to destroy this address record, just ATS does
92 * not know this yet. Once ATS confirms its destruction,
93 * we can clean up.
94 */
95 int in_destroy;
96};
97
98
99/**
100 * Handle to the ATS subsystem for bandwidth/transport scheduling information.
101 */
102struct GNUNET_ATS_SchedulingHandle
103{
104 /**
105 * Our configuration.
106 */
107 const struct GNUNET_CONFIGURATION_Handle *cfg;
108
109 /**
110 * Callback to invoke on suggestions.
111 */
112 GNUNET_ATS_AddressSuggestionCallback suggest_cb;
113
114 /**
115 * Closure for @e suggest_cb.
116 */
117 void *suggest_cb_cls;
118
119 /**
120 * Message queue for sending requests to the ATS service.
121 */
122 struct GNUNET_MQ_Handle *mq;
123
124 /**
125 * Array of session objects (we need to translate them to numbers and back
126 * for the protocol; the offset in the array is the session number on the
127 * network). Index 0 is always NULL and reserved to represent the NULL pointer.
128 * Unused entries are also NULL.
129 */
130 struct GNUNET_ATS_AddressRecord **session_array;
131
132 /**
133 * Task to trigger reconnect.
134 */
135 struct GNUNET_SCHEDULER_Task *task;
136
137 /**
138 * Reconnect backoff delay.
139 */
140 struct GNUNET_TIME_Relative backoff;
141
142 /**
143 * Size of the @e session_array.
144 */
145 unsigned int session_array_size;
146};
147
148
149/**
150 * Re-establish the connection to the ATS service.
151 *
152 * @param sh handle to use to re-connect.
153 */
154static void
155reconnect (struct GNUNET_ATS_SchedulingHandle *sh);
156
157
158/**
159 * Re-establish the connection to the ATS service.
160 *
161 * @param cls handle to use to re-connect.
162 */
163static void
164reconnect_task (void *cls)
165{
166 struct GNUNET_ATS_SchedulingHandle *sh = cls;
167
168 sh->task = NULL;
169 reconnect (sh);
170}
171
172
173/**
174 * Disconnect from ATS and then reconnect.
175 *
176 * @param sh our handle
177 */
178static void
179force_reconnect (struct GNUNET_ATS_SchedulingHandle *sh)
180{
181 if (NULL != sh->mq)
182 {
183 GNUNET_MQ_destroy (sh->mq);
184 sh->mq = NULL;
185 }
186 sh->suggest_cb (sh->suggest_cb_cls,
187 NULL, NULL, NULL,
188 GNUNET_BANDWIDTH_ZERO,
189 GNUNET_BANDWIDTH_ZERO);
190 sh->backoff = GNUNET_TIME_STD_BACKOFF (sh->backoff);
191 sh->task = GNUNET_SCHEDULER_add_delayed (sh->backoff,
192 &reconnect_task,
193 sh);
194}
195
196
197/**
198 * Find the session object corresponding to the given session ID.
199 *
200 * @param sh our handle
201 * @param session_id current session ID
202 * @param peer peer the session belongs to
203 * @return the session object (or NULL)
204 */
205static struct GNUNET_ATS_AddressRecord *
206find_session (struct GNUNET_ATS_SchedulingHandle *sh,
207 uint32_t session_id,
208 const struct GNUNET_PeerIdentity *peer)
209{
210 struct GNUNET_ATS_AddressRecord *ar;
211
212 if (session_id >= sh->session_array_size)
213 {
214 GNUNET_break (0);
215 return NULL;
216 }
217 if (0 == session_id)
218 return NULL;
219 ar = sh->session_array[session_id];
220 if (NULL == ar)
221 {
222 GNUNET_break (0);
223 return NULL;
224 }
225 if (NULL == ar->address)
226 {
227 /* address was destroyed in the meantime, this can happen
228 as we communicate asynchronously with the ATS service. */
229 return NULL;
230 }
231 if (0 != GNUNET_memcmp (peer,
232 &ar->address->peer))
233 {
234 GNUNET_break (0);
235 return NULL;
236 }
237 return ar;
238}
239
240
241/**
242 * Get an available session ID.
243 *
244 * @param sh our handle
245 * @return an unused slot, but never NOT_FOUND (0)
246 */
247static uint32_t
248find_empty_session_slot (struct GNUNET_ATS_SchedulingHandle *sh)
249{
250 static uint32_t off;
251 uint32_t i;
252
253 GNUNET_assert (0 != sh->session_array_size);
254 i = 0;
255 while (((NOT_FOUND == off) ||
256 (NULL != sh->session_array[off % sh->session_array_size])) &&
257 (i < sh->session_array_size))
258 {
259 off++;
260 i++;
261 }
262 if ((NOT_FOUND != off % sh->session_array_size) &&
263 (NULL == sh->session_array[off % sh->session_array_size]))
264 return off;
265 i = sh->session_array_size;
266 GNUNET_array_grow (sh->session_array,
267 sh->session_array_size,
268 sh->session_array_size * 2);
269 return i;
270}
271
272
273/**
274 * Get the ID for the given session object.
275 *
276 * @param sh our handle
277 * @param session session object
278 * @param address the address we are looking for
279 * @return the session id or NOT_FOUND for error
280 */
281static uint32_t
282find_session_id (struct GNUNET_ATS_SchedulingHandle *sh,
283 struct GNUNET_ATS_Session *session,
284 const struct GNUNET_HELLO_Address *address)
285{
286 uint32_t i;
287
288 if (NULL == address)
289 {
290 GNUNET_break (0);
291 return NOT_FOUND;
292 }
293 for (i = 1; i < sh->session_array_size; i++)
294 if ((NULL != sh->session_array[i]) &&
295 (GNUNET_NO == sh->session_array[i]->in_destroy) &&
296 ((session == sh->session_array[i]->session) ||
297 (NULL == sh->session_array[i]->session)) &&
298 (0 == GNUNET_memcmp (&address->peer,
299 &sh->session_array[i]->address->peer)) &&
300 (0 == GNUNET_HELLO_address_cmp (address,
301 sh->session_array[i]->address)))
302 return i;
303 return NOT_FOUND;
304}
305
306
307/**
308 * Release the session slot from the session table (ATS service is
309 * also done using it).
310 *
311 * @param sh our handle
312 * @param session_id identifies session that is no longer valid
313 */
314static void
315release_session (struct GNUNET_ATS_SchedulingHandle *sh,
316 uint32_t session_id)
317{
318 struct GNUNET_ATS_AddressRecord *ar;
319
320 if (NOT_FOUND == session_id)
321 return;
322 if (session_id >= sh->session_array_size)
323 {
324 GNUNET_break (0);
325 force_reconnect (sh);
326 return;
327 }
328 /* this slot should have been removed from remove_session before */
329 ar = sh->session_array[session_id];
330 if (NULL != ar->session)
331 {
332 GNUNET_break (0);
333 force_reconnect (sh);
334 return;
335 }
336 GNUNET_HELLO_address_free (ar->address);
337 GNUNET_free (ar);
338 sh->session_array[session_id] = NULL;
339}
340
341
342/**
343 * Type of a function to call when we receive a session release
344 * message from the service.
345 *
346 * @param cls the `struct GNUNET_ATS_SchedulingHandle`
347 * @param srm message received
348 */
349static void
350handle_ats_session_release (void *cls,
351 const struct GNUNET_ATS_SessionReleaseMessage *srm)
352{
353 struct GNUNET_ATS_SchedulingHandle *sh = cls;
354
355 /* Note: peer field in srm not necessary right now,
356 but might be good to have in the future */
357 release_session (sh,
358 ntohl (srm->session_id));
359}
360
361
362/**
363 * Type of a function to call when we receive a address suggestion
364 * message from the service.
365 *
366 * @param cls the `struct GNUNET_ATS_SchedulingHandle`
367 * @param m message received
368 */
369static void
370handle_ats_address_suggestion (void *cls,
371 const struct AddressSuggestionMessage *m)
372{
373 struct GNUNET_ATS_SchedulingHandle *sh = cls;
374 struct GNUNET_ATS_AddressRecord *ar;
375 uint32_t session_id;
376
377 session_id = ntohl (m->session_id);
378 if (0 == session_id)
379 {
380 GNUNET_break (0);
381 force_reconnect (sh);
382 return;
383 }
384 ar = find_session (sh,
385 session_id,
386 &m->peer);
387 if (NULL == ar)
388 {
389 GNUNET_break (0);
390 force_reconnect (sh);
391 return;
392 }
393 if (NULL == sh->suggest_cb)
394 return;
395 if (GNUNET_YES == ar->in_destroy)
396 {
397 /* ignore suggestion, as this address is dying, unless BW is 0,
398 in that case signal 'disconnect' via BW 0 */
399 if ((0 == ntohl (m->bandwidth_out.value__)) &&
400 (0 == ntohl (m->bandwidth_in.value__)))
401 {
402 LOG (GNUNET_ERROR_TYPE_DEBUG,
403 "ATS suggests disconnect from peer `%s' with BW %u/%u\n",
404 GNUNET_i2s (&ar->address->peer),
405 (unsigned int) ntohl (m->bandwidth_out.value__),
406 (unsigned int) ntohl (m->bandwidth_in.value__));
407 sh->suggest_cb (sh->suggest_cb_cls,
408 &m->peer,
409 NULL,
410 NULL,
411 m->bandwidth_out,
412 m->bandwidth_in);
413 }
414 return;
415 }
416 if ((NULL == ar->session) &&
417 (GNUNET_HELLO_address_check_option (ar->address,
418 GNUNET_HELLO_ADDRESS_INFO_INBOUND)))
419 {
420 GNUNET_break (0);
421 return;
422 }
423 sh->backoff = GNUNET_TIME_UNIT_ZERO;
424 LOG (GNUNET_ERROR_TYPE_DEBUG,
425 "ATS suggests address slot %u for peer `%s' using plugin %s\n",
426 ar->slot,
427 GNUNET_i2s (&ar->address->peer),
428 ar->address->transport_name);
429 sh->suggest_cb (sh->suggest_cb_cls,
430 &m->peer,
431 ar->address,
432 ar->session,
433 m->bandwidth_out,
434 m->bandwidth_in);
435}
436
437
438/**
439 * We encountered an error handling the MQ to the
440 * ATS service. Reconnect.
441 *
442 * @param cls the `struct GNUNET_ATS_SchedulingHandle`
443 * @param error details about the error
444 */
445static void
446error_handler (void *cls,
447 enum GNUNET_MQ_Error error)
448{
449 struct GNUNET_ATS_SchedulingHandle *sh = cls;
450
451 LOG (GNUNET_ERROR_TYPE_DEBUG,
452 "ATS connection died (code %d), reconnecting\n",
453 (int) error);
454 force_reconnect (sh);
455}
456
457
458/**
459 * Generate and transmit the `struct AddressAddMessage` for the given
460 * address record.
461 *
462 * @param sh the scheduling handle to use for transmission
463 * @param ar the address to inform the ATS service about
464 */
465static void
466send_add_address_message (struct GNUNET_ATS_SchedulingHandle *sh,
467 const struct GNUNET_ATS_AddressRecord *ar)
468{
469 struct GNUNET_MQ_Envelope *ev;
470 struct AddressAddMessage *m;
471 char *pm;
472 size_t namelen;
473 size_t msize;
474
475 if (NULL == sh->mq)
476 return; /* disconnected, skip for now */
477 GNUNET_break (GNUNET_NT_UNSPECIFIED != ar->properties.scope);
478 namelen = strlen (ar->address->transport_name) + 1;
479 msize = ar->address->address_length + namelen;
480 ev = GNUNET_MQ_msg_extra (m, msize, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD);
481 m->peer = ar->address->peer;
482 m->address_length = htons (ar->address->address_length);
483 m->address_local_info = htonl ((uint32_t) ar->address->local_info);
484 m->plugin_name_length = htons (namelen);
485 m->session_id = htonl (ar->slot);
486 m->properties = ar->properties;
487
488 LOG (GNUNET_ERROR_TYPE_DEBUG,
489 "Adding address for peer `%s', plugin `%s', session %p slot %u\n",
490 GNUNET_i2s (&ar->address->peer),
491 ar->address->transport_name,
492 ar->session,
493 ar->slot);
494 pm = (char *) &m[1];
495 GNUNET_memcpy (pm,
496 ar->address->address,
497 ar->address->address_length);
498 if (NULL != ar->address->transport_name)
499 GNUNET_memcpy (&pm[ar->address->address_length],
500 ar->address->transport_name,
501 namelen);
502 GNUNET_MQ_send (sh->mq, ev);
503}
504
505
506/**
507 * Re-establish the connection to the ATS service.
508 *
509 * @param sh handle to use to re-connect.
510 */
511static void
512reconnect (struct GNUNET_ATS_SchedulingHandle *sh)
513{
514 struct GNUNET_MQ_MessageHandler handlers[] = {
515 GNUNET_MQ_hd_fixed_size (ats_session_release,
516 GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE,
517 struct GNUNET_ATS_SessionReleaseMessage,
518 sh),
519 GNUNET_MQ_hd_fixed_size (ats_address_suggestion,
520 GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION,
521 struct AddressSuggestionMessage,
522 sh),
523 GNUNET_MQ_handler_end ()
524 };
525 struct GNUNET_MQ_Envelope *ev;
526 struct ClientStartMessage *init;
527 unsigned int i;
528 struct GNUNET_ATS_AddressRecord *ar;
529
530 GNUNET_assert (NULL == sh->mq);
531 sh->mq = GNUNET_CLIENT_connect (sh->cfg,
532 "ats",
533 handlers,
534 &error_handler,
535 sh);
536 if (NULL == sh->mq)
537 {
538 GNUNET_break (0);
539 force_reconnect (sh);
540 return;
541 }
542 ev = GNUNET_MQ_msg (init,
543 GNUNET_MESSAGE_TYPE_ATS_START);
544 init->start_flag = htonl (START_FLAG_SCHEDULING);
545 GNUNET_MQ_send (sh->mq, ev);
546 if (NULL == sh->mq)
547 return;
548 for (i = 0; i < sh->session_array_size; i++)
549 {
550 ar = sh->session_array[i];
551 if (NULL == ar)
552 continue;
553 send_add_address_message (sh, ar);
554 if (NULL == sh->mq)
555 return;
556 }
557}
558
559
560/**
561 * Initialize the ATS subsystem.
562 *
563 * @param cfg configuration to use
564 * @param suggest_cb notification to call whenever the suggestation changed
565 * @param suggest_cb_cls closure for @a suggest_cb
566 * @return ats context
567 */
568struct GNUNET_ATS_SchedulingHandle *
569GNUNET_ATS_scheduling_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
570 GNUNET_ATS_AddressSuggestionCallback suggest_cb,
571 void *suggest_cb_cls)
572{
573 struct GNUNET_ATS_SchedulingHandle *sh;
574
575 sh = GNUNET_new (struct GNUNET_ATS_SchedulingHandle);
576 sh->cfg = cfg;
577 sh->suggest_cb = suggest_cb;
578 sh->suggest_cb_cls = suggest_cb_cls;
579 GNUNET_array_grow (sh->session_array,
580 sh->session_array_size,
581 4);
582 reconnect (sh);
583 return sh;
584}
585
586
587/**
588 * Client is done with ATS scheduling, release resources.
589 *
590 * @param sh handle to release
591 */
592void
593GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh)
594{
595 struct GNUNET_ATS_AddressRecord *ar;
596 unsigned int i;
597
598 if (NULL != sh->mq)
599 {
600 GNUNET_MQ_destroy (sh->mq);
601 sh->mq = NULL;
602 }
603 if (NULL != sh->task)
604 {
605 GNUNET_SCHEDULER_cancel (sh->task);
606 sh->task = NULL;
607 }
608 for (i = 0; i < sh->session_array_size; i++)
609 {
610 if (NULL != (ar = sh->session_array[i]))
611 {
612 GNUNET_HELLO_address_free (ar->address);
613 GNUNET_free (ar);
614 sh->session_array[i] = NULL;
615 }
616 }
617 GNUNET_array_grow (sh->session_array,
618 sh->session_array_size,
619 0);
620 GNUNET_free (sh);
621}
622
623
624/**
625 * We have a new address ATS should know. Addresses have to be added
626 * with this function before they can be: updated, set in use and
627 * destroyed.
628 *
629 * @param sh handle
630 * @param address the address
631 * @param session session handle, can be NULL
632 * @param prop performance data for the address
633 * @return handle to the address representation inside ATS, NULL
634 * on error (i.e. ATS knows this exact address already)
635 */
636struct GNUNET_ATS_AddressRecord *
637GNUNET_ATS_address_add (struct GNUNET_ATS_SchedulingHandle *sh,
638 const struct GNUNET_HELLO_Address *address,
639 struct GNUNET_ATS_Session *session,
640 const struct GNUNET_ATS_Properties *prop)
641{
642 struct GNUNET_ATS_AddressRecord *ar;
643 size_t namelen;
644 size_t msize;
645 uint32_t s;
646
647 if (NULL == address)
648 {
649 /* we need a valid address */
650 GNUNET_break (0);
651 return NULL;
652 }
653 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
654 namelen = strlen (address->transport_name) + 1;
655 msize = address->address_length + namelen;
656 if ((msize + sizeof(struct AddressUpdateMessage) >=
657 GNUNET_MAX_MESSAGE_SIZE) ||
658 (address->address_length >= GNUNET_MAX_MESSAGE_SIZE) ||
659 (namelen >= GNUNET_MAX_MESSAGE_SIZE))
660 {
661 /* address too large for us, this should not happen */
662 GNUNET_break (0);
663 return NULL;
664 }
665
666 if (NOT_FOUND !=
667 find_session_id (sh,
668 session,
669 address))
670 {
671 /* Already existing, nothing todo, but this should not happen */
672 GNUNET_break (0);
673 return NULL;
674 }
675 s = find_empty_session_slot (sh);
676 ar = GNUNET_new (struct GNUNET_ATS_AddressRecord);
677 ar->sh = sh;
678 ar->slot = s;
679 ar->session = session;
680 ar->address = GNUNET_HELLO_address_copy (address);
681 GNUNET_ATS_properties_hton (&ar->properties,
682 prop);
683 sh->session_array[s] = ar;
684 send_add_address_message (sh, ar);
685 return ar;
686}
687
688
689/**
690 * An address was used to initiate a session.
691 *
692 * @param ar address record to update information for
693 * @param session session handle
694 */
695void
696GNUNET_ATS_address_add_session (struct GNUNET_ATS_AddressRecord *ar,
697 struct GNUNET_ATS_Session *session)
698{
699 GNUNET_break (NULL == ar->session);
700 ar->session = session;
701}
702
703
704/**
705 * A session was destroyed, disassociate it from the
706 * given address record. If this was an incoming
707 * address, destroy the address as well.
708 *
709 * @param ar address record to update information for
710 * @param session session handle
711 * @return #GNUNET_YES if the @a ar was destroyed because
712 * it was an incoming address,
713 * #GNUNET_NO if the @ar was kept because we can
714 * use it still to establish a new session
715 */
716int
717GNUNET_ATS_address_del_session (struct GNUNET_ATS_AddressRecord *ar,
718 struct GNUNET_ATS_Session *session)
719{
720 GNUNET_assert (session == ar->session);
721 ar->session = NULL;
722 if (GNUNET_HELLO_address_check_option (ar->address,
723 GNUNET_HELLO_ADDRESS_INFO_INBOUND))
724 {
725 GNUNET_ATS_address_destroy (ar);
726 return GNUNET_YES;
727 }
728 return GNUNET_NO;
729}
730
731
732/**
733 * We have updated performance statistics for a given address. Note
734 * that this function can be called for addresses that are currently
735 * in use as well as addresses that are valid but not actively in use.
736 * Furthermore, the peer may not even be connected to us right now (in
737 * which case the call may be ignored or the information may be stored
738 * for later use). Update bandwidth assignments.
739 *
740 * @param ar address record to update information for
741 * @param prop performance data for the address
742 */
743void
744GNUNET_ATS_address_update (struct GNUNET_ATS_AddressRecord *ar,
745 const struct GNUNET_ATS_Properties *prop)
746{
747 struct GNUNET_ATS_SchedulingHandle *sh = ar->sh;
748 struct GNUNET_MQ_Envelope *ev;
749 struct AddressUpdateMessage *m;
750
751 LOG (GNUNET_ERROR_TYPE_DEBUG,
752 "Updating address for peer `%s', plugin `%s', session %p slot %u\n",
753 GNUNET_i2s (&ar->address->peer),
754 ar->address->transport_name,
755 ar->session,
756 ar->slot);
757 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
758 GNUNET_ATS_properties_hton (&ar->properties,
759 prop);
760 if (NULL == sh->mq)
761 return; /* disconnected, skip for now */
762 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE);
763 m->session_id = htonl (ar->slot);
764 m->peer = ar->address->peer;
765 m->properties = ar->properties;
766 GNUNET_MQ_send (sh->mq,
767 ev);
768}
769
770
771/**
772 * An address got destroyed, stop using it as a valid address.
773 *
774 * @param ar address to destroy
775 */
776void
777GNUNET_ATS_address_destroy (struct GNUNET_ATS_AddressRecord *ar)
778{
779 struct GNUNET_ATS_SchedulingHandle *sh = ar->sh;
780 struct GNUNET_MQ_Envelope *ev;
781 struct AddressDestroyedMessage *m;
782
783 LOG (GNUNET_ERROR_TYPE_DEBUG,
784 "Deleting address for peer `%s', plugin `%s', slot %u session %p\n",
785 GNUNET_i2s (&ar->address->peer),
786 ar->address->transport_name,
787 ar->slot,
788 ar->session);
789 GNUNET_break (NULL == ar->session);
790 ar->session = NULL;
791 ar->in_destroy = GNUNET_YES;
792 if (NULL == sh->mq)
793 return;
794 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED);
795 m->session_id = htonl (ar->slot);
796 m->peer = ar->address->peer;
797 GNUNET_MQ_send (sh->mq, ev);
798}
799
800
801/* end of ats_api_scheduling.c */
diff --git a/src/ats/experiments/example.exp b/src/ats/experiments/example.exp
deleted file mode 100644
index a490e5ec6..000000000
--- a/src/ats/experiments/example.exp
+++ /dev/null
@@ -1,104 +0,0 @@
1[experiment]
2name = test
3max_duration = 15 s
4log_freq = 1000 ms
5cfg_file = experiments/gnunet_ats_sim_default.conf
6log_output_dir = data/
7log_append_time_stamp = no
8
9[episode-0]
10# Setup addresses
11
12# operations = address_add, address_del, start_set_property, stop_set_property,
13# start_set_preference, stop_preference, start_request, stop_request
14duration = 0
15op-0-operation = address_add
16op-0-address-id = 0
17op-0-peer-id = 0
18op-0-address-session = 0
19op-0-address-network = 0
20op-0-address = 0_0_test
21op-0-plugin = test
22
23op-1-operation = address_add
24op-1-address-id = 1
25op-1-peer-id = 1
26op-1-address-session = 0
27op-1-address-network = 0
28op-1-address = 1_1_test
29op-1-plugin = test
30
31op-2-operation = start_request
32op-2-peer-id = 0
33
34op-3-operation = start_request
35op-3-peer-id = 1
36
37[episode-1]
38# Set delay
39duration = 5 s
40
41op-0-operation = start_set_property
42op-0-address-id = 0
43op-0-peer-id = 0
44# constant, linear, sinus, random
45op-0-gen-type = random
46op-0-base-rate= 10000
47op-0-max-rate = 20000
48op-0-frequency = 1000 ms
49# bandwidth, latency
50# "TERMINATOR", "UTILIZATION_UP", "UTILIZATION_DOWN", "UTILIZATION_PAYLOAD_UP", "UTILIZATION_PAYLOAD_DOWN", "NETWORK_TYPE", "DELAY", "DISTANCE", "COST_WAN", "COST_LAN", "COST_WLAN"
51op-0-property = DELAY
52
53op-1-operation = start_set_property
54op-1-address-id = 1
55op-1-peer-id = 1
56# constant, linear, sinus, random
57op-1-gen-type = constant
58op-1-base-rate= 1
59op-1-max-rate = 1
60op-1-frequency = 1000 ms
61# bandwidth, latency
62# "TERMINATOR", "UTILIZATION_UP", "UTILIZATION_DOWN", "UTILIZATION_PAYLOAD_UP", "UTILIZATION_PAYLOAD_DOWN", "NETWORK_TYPE", "DELAY", "DISTANCE", "COST_WAN", "COST_LAN", "COST_WLAN"
63op-1-property = DELAY
64
65
66[episode-2]
67# Shutdown
68duration = 2 s
69op-0-operation = stop_set_property
70op-0-address-id = 0
71op-0-peer-id = 0
72op-0-property = DELAY
73
74op-1-operation = stop_set_property
75op-1-address-id = 1
76op-1-peer-id = 1
77op-1-property = DELAY
78
79[episode-3]
80# Shutdown
81duration = 2 s
82
83op-0-operation = stop_request
84op-0-peer-id = 0
85
86op-1-operation = stop_request
87op-1-peer-id = 1
88
89op-2-operation = address_del
90op-2-address-id = 0
91op-2-peer-id = 0
92op-2-address-session = 0
93op-2-address-network = 0
94op-2-address = 0_0_test
95op-2-plugin = test
96
97op-2-operation = address_del
98op-2-address-id = 1
99op-2-peer-id = 1
100op-2-address-session = 0
101op-2-address-network = 0
102op-2-address = 1_1_test
103op-2-plugin = test
104
diff --git a/src/ats/experiments/gnunet_ats_sim_default.conf b/src/ats/experiments/gnunet_ats_sim_default.conf
deleted file mode 100644
index 14e0a2e0b..000000000
--- a/src/ats/experiments/gnunet_ats_sim_default.conf
+++ /dev/null
@@ -1,18 +0,0 @@
1[ats]
2UNSPECIFIED_QUOTA_IN = 64 KiB
3UNSPECIFIED_QUOTA_OUT = 64 KiB
4# LOOPBACK
5LOOPBACK_QUOTA_IN = 64 KiB
6LOOPBACK_QUOTA_OUT = 64 KiB
7# LAN
8LAN_QUOTA_IN = 64 KiB
9LAN_QUOTA_OUT = 64 KiB
10# WAN
11WAN_QUOTA_IN = 64 KiB
12WAN_QUOTA_OUT = 64 KiB
13# WLAN
14WLAN_QUOTA_IN = 64 KiB
15WLAN_QUOTA_OUT = 64 KiB
16# BLUETOOTH
17BLUETOOTH_QUOTA_IN = 64 KiB
18BLUETOOTH_QUOTA_OUT = 64 KiB
diff --git a/src/ats/experiments/set_preference.exp b/src/ats/experiments/set_preference.exp
deleted file mode 100644
index 34f9af296..000000000
--- a/src/ats/experiments/set_preference.exp
+++ /dev/null
@@ -1,95 +0,0 @@
1# Example setting up two peers
2
3[experiment]
4name = test
5max_duration = 15 s
6log_freq = 1000 ms
7log_prefix = set_preference
8cfg_file = experiments/gnunet_ats_sim_default.conf
9
10[episode-0]
11# Setup addresses
12
13# operations = address_add, address_del, start_set_property, stop_set_property,
14# start_set_preference, stop_preference, start_request, stop_request
15duration = 1 s
16
17op-0-operation = address_add
18op-0-address-id = 0
19op-0-peer-id = 0
20op-0-address-session = 0
21op-0-address-network = lan
22op-0-address = 0_0_test
23op-0-plugin = test
24
25op-1-operation = address_add
26op-1-address-id = 1
27op-1-peer-id = 1
28op-1-address-session = 0
29op-1-address-network = lan
30op-1-address = 1_1_test
31op-1-plugin = test
32
33op-2-operation = start_request
34op-2-peer-id = 0
35
36op-3-operation = start_request
37op-3-peer-id = 1
38
39[episode-1]
40# Set delay
41duration = 20 s
42
43op-0-operation = start_set_preference
44op-0-address-id = 0
45op-0-peer-id = 0
46op-0-client-id = 1
47# constant, linear, sinus, random
48op-0-gen-type = linear
49op-0-base-rate= 1000
50op-0-max-rate = 10000
51op-0-period = 10 s
52op-0-frequency = 500 ms
53op-0-feedback_delay = 500 ms
54# BANDWIDTH, LATENCY
55op-0-pref = BANDWIDTH
56
57
58op-1-operation = start_set_preference
59op-1-address-id = 1
60op-1-peer-id = 1
61op-1-client-id = 1
62# constant, linear, sinus, random
63op-1-gen-type = constant
64op-1-base-rate= 1000
65op-1-max-rate = 1000
66op-1-period = 10 s
67op-1-frequency = 500 ms
68# BANDWIDTH, LATENCY
69op-1-pref = BANDWIDTH
70
71[episode-2]
72# Shutdown
73duration = 2 s
74
75op-0-operation = stop_request
76op-0-peer-id = 0
77
78op-1-operation = stop_request
79op-1-peer-id = 1
80
81op-2-operation = address_del
82op-2-address-id = 0
83op-2-peer-id = 0
84op-2-address-session = 0
85op-2-address-network = 0
86op-2-address = 0_0_test
87op-2-plugin = test
88
89op-3-operation = address_del
90op-3-address-id = 1
91op-3-peer-id = 1
92op-3-address-session = 0
93op-3-address-network = 0
94op-3-address = 1_1_test
95op-3-plugin = test
diff --git a/src/ats/gnunet-ats-solver-eval.c b/src/ats/gnunet-ats-solver-eval.c
deleted file mode 100644
index ba7994686..000000000
--- a/src/ats/gnunet-ats-solver-eval.c
+++ /dev/null
@@ -1,3588 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats-tests/ats-testing-experiment.c
22 * @brief ats benchmark: controlled experiment execution
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet-ats-solver-eval.h"
29#include "gnunet-service-ats_normalization.h"
30#include "gnunet-service-ats_preferences.c"
31
32#define BIG_M_STRING "unlimited"
33
34/**
35 * Handle for statistics.
36 */
37struct GNUNET_STATISTICS_Handle *GSA_stats;
38
39
40static struct Experiment *e;
41
42static struct LoggingHandle *l;
43
44static struct SolverHandle *sh;
45
46static struct TestPeer *peer_head;
47
48static struct TestPeer *peer_tail;
49
50static double default_properties[GNUNET_ATS_PropertyCount];
51static double default_preferences[GNUNET_ATS_PreferenceCount];
52
53/**
54 * cmd option -e: experiment file
55 */
56static char *opt_exp_file;
57
58static char *opt_solver;
59
60/**
61 * cmd option -l: enable logging
62 */
63static int opt_log;
64
65/**
66 * cmd option -p: enable plots
67 */
68static int opt_save;
69
70/**
71 * cmd option -v: verbose logs
72 */
73static int opt_verbose;
74
75/**
76 * cmd option -p: print logs
77 */
78static int opt_print;
79
80/**
81 * cmd option -d: disable normalization
82 */
83static int opt_disable_normalization;
84
85static int res;
86
87static void
88end_now ();
89
90
91static char *
92print_generator_type (enum GeneratorType g)
93{
94 switch (g)
95 {
96 case GNUNET_ATS_TEST_TG_CONSTANT:
97 return "CONSTANT";
98
99 case GNUNET_ATS_TEST_TG_LINEAR:
100 return "LINEAR";
101
102 case GNUNET_ATS_TEST_TG_RANDOM:
103 return "RANDOM";
104
105 case GNUNET_ATS_TEST_TG_SINUS:
106 return "SINUS";
107
108 default:
109 return "INVALID";
110 break;
111 }
112}
113
114
115static struct TestPeer *
116find_peer_by_id (int id)
117{
118 struct TestPeer *cur;
119
120 for (cur = peer_head; NULL != cur; cur = cur->next)
121 if (cur->id == id)
122 return cur;
123 return NULL;
124}
125
126
127static struct TestPeer *
128find_peer_by_pid (const struct GNUNET_PeerIdentity *pid)
129{
130 struct TestPeer *cur;
131
132 for (cur = peer_head; NULL != cur; cur = cur->next)
133 if (0 == GNUNET_memcmp (&cur->peer_id, pid))
134 return cur;
135 return NULL;
136}
137
138
139static struct TestAddress *
140find_address_by_id (struct TestPeer *peer, int aid)
141{
142 struct TestAddress *cur;
143
144 for (cur = peer->addr_head; NULL != cur; cur = cur->next)
145 if (cur->aid == aid)
146 return cur;
147 return NULL;
148}
149
150
151/**
152 * Logging
153 */
154void
155GNUNET_ATS_solver_logging_now (struct LoggingHandle *l)
156{
157 struct LoggingTimeStep *lts;
158 struct TestPeer *cur;
159 struct TestAddress *cur_addr;
160 struct LoggingPeer *log_p;
161 struct LoggingAddress *log_a;
162 int c;
163
164 lts = GNUNET_new (struct LoggingTimeStep);
165 GNUNET_CONTAINER_DLL_insert_tail (l->head, l->tail, lts);
166 lts->timestamp = GNUNET_TIME_absolute_get ();
167 if (NULL == lts->prev)
168 lts->delta = GNUNET_TIME_UNIT_ZERO;
169 else
170 lts->delta = GNUNET_TIME_absolute_get_duration (lts->prev->timestamp);
171
172 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging %llu, delta %llu\n",
173 lts->timestamp.abs_value_us, lts->delta.rel_value_us);
174
175
176 /* Store logging data here */
177 for (cur = peer_head; NULL != cur; cur = cur->next)
178 {
179 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
180 "Logging peer id %llu\n", cur->id);
181
182 log_p = GNUNET_new (struct LoggingPeer);
183 log_p->id = cur->id;
184 log_p->peer_id = cur->peer_id;
185 log_p->is_requested = cur->is_requested;
186 for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
187 {
188 log_p->pref_abs[c] = cur->pref_abs[c];
189 log_p->pref_norm[c] = cur->pref_norm[c];
190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
191 "\t %s = %.2f %.2f [abs/rel]\n",
192 GNUNET_ATS_print_preference_type (c),
193 log_p->pref_abs[c], log_p->pref_norm[c]);
194 }
195 GNUNET_CONTAINER_DLL_insert_tail (lts->head, lts->tail, log_p);
196
197 for (cur_addr = cur->addr_head; NULL != cur_addr; cur_addr = cur_addr->next)
198 {
199 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
200 "Logging peer id %llu address %llu\n",
201 cur->id, cur_addr->aid);
202 log_a = GNUNET_new (struct LoggingAddress);
203 log_a->aid = cur_addr->aid;
204 log_a->active = cur_addr->ats_addr->active;
205 log_a->network = cur_addr->network;
206 log_a->assigned_bw_in = cur_addr->ats_addr->assigned_bw_in;
207 log_a->assigned_bw_out = cur_addr->ats_addr->assigned_bw_out;
208 for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
209 {
210 log_a->prop_abs[c] = cur_addr->prop_abs[c];
211 log_a->prop_norm[c] = cur_addr->prop_norm[c];
212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
213 "\t %s = %.2f %.2f [abs/rel]\n",
214 GNUNET_ATS_print_property_type (c),
215 log_a->prop_abs[c],
216 log_a->prop_norm[c]);
217 }
218 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t Active = %i\n", log_a->active);
219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t BW in = %llu\n",
220 log_a->assigned_bw_in);
221 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "\t BW out = %llu\n",
222 log_a->assigned_bw_out);
223
224 GNUNET_CONTAINER_DLL_insert_tail (log_p->addr_head, log_p->addr_tail,
225 log_a);
226 }
227 }
228}
229
230
231static void
232logging_task (void *cls)
233{
234 struct LoggingHandle *l = cls;
235
236 l->logging_task = NULL;
237 GNUNET_ATS_solver_logging_now (l);
238 l->logging_task = GNUNET_SCHEDULER_add_delayed (l->log_freq,
239 &logging_task,
240 l);
241}
242
243
244struct LoggingHandle *
245GNUNET_ATS_solver_logging_start (struct GNUNET_TIME_Relative freq)
246{
247 struct LoggingHandle *l;
248
249 l = GNUNET_new (struct LoggingHandle);
250
251 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start logging every %s\n",
252 GNUNET_STRINGS_relative_time_to_string (freq, GNUNET_NO));
253 l->log_freq = freq;
254 l->logging_task = GNUNET_SCHEDULER_add_now (&logging_task, l);
255 return l;
256}
257
258
259void
260GNUNET_ATS_solver_logging_stop (struct LoggingHandle *l)
261{
262 if (NULL != l->logging_task)
263 GNUNET_SCHEDULER_cancel (l->logging_task);
264
265 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop logging\n");
266
267 l->logging_task = NULL;
268}
269
270
271static struct LoggingFileHandle *
272find_logging_file_handle (struct LoggingFileHandle *lf_head,
273 struct LoggingFileHandle *lf_tail,
274 int peer_id, int address_id)
275{
276 struct LoggingFileHandle *res;
277
278 for (res = lf_head; NULL != res; res = res->next)
279 if ((res->pid == peer_id) && (res->aid == address_id))
280 return res;
281 return NULL;
282}
283
284
285void
286GNUNET_ATS_solver_logging_write_to_disk (struct LoggingHandle *l, int
287 add_time_stamp,
288 char *output_dir)
289{
290 struct LoggingTimeStep *lts;
291 struct LoggingPeer *log_p;
292 struct LoggingAddress *log_a;
293 struct LoggingFileHandle *lf_head;
294 struct LoggingFileHandle *lf_tail;
295 struct LoggingFileHandle *cur;
296 struct LoggingFileHandle *next;
297 char *filename;
298 char *datastring;
299 char *propstring;
300 char *propstring_tmp;
301 char *prefstring;
302 char *prefstring_tmp;
303 int c;
304 int use_dir;
305
306 use_dir = GNUNET_NO;
307 if (NULL != output_dir)
308 {
309 if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (output_dir))
310 {
311 fprintf (stderr, "Failed to create directory `%s'\n", output_dir);
312 return;
313 }
314 else
315 {
316 fprintf (stderr, "Created directory `%s'\n", output_dir);
317 use_dir = GNUNET_YES;
318 }
319 }
320
321 lf_head = NULL;
322 lf_tail = NULL;
323
324 for (lts = l->head; NULL != lts; lts = lts->next)
325 {
326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing log step %llu\n",
327 (long long unsigned int) lts->timestamp.abs_value_us);
328
329 for (log_p = lts->head; NULL != log_p; log_p = log_p->next)
330 {
331 for (log_a = log_p->addr_head; NULL != log_a; log_a = log_a->next)
332 {
333 cur = find_logging_file_handle (lf_head, lf_tail, log_p->id,
334 log_a->aid);
335 if (NULL == cur)
336 {
337 cur = GNUNET_new (struct LoggingFileHandle);
338 cur->aid = log_a->aid;
339 cur->pid = log_p->id;
340
341 if (GNUNET_YES == add_time_stamp)
342 GNUNET_asprintf (&filename, "%s%s%s_%s_p%u_a%u_%llu.log",
343 (GNUNET_YES == use_dir) ? output_dir : "",
344 (GNUNET_YES == use_dir) ? DIR_SEPARATOR_STR : "",
345 e->log_prefix,
346 opt_solver,
347 cur->pid,
348 cur->aid,
349 l->head->timestamp.abs_value_us);
350 else
351 GNUNET_asprintf (&filename, "%s%s%s_%s_p%u_a%u.log",
352 (GNUNET_YES == use_dir) ? output_dir : "",
353 (GNUNET_YES == use_dir) ? DIR_SEPARATOR_STR : "",
354 e->log_prefix,
355 opt_solver,
356 cur->pid,
357 cur->aid);
358
359 fprintf (stderr,
360 "Add writing log data for peer %llu address %llu to file `%s'\n",
361 cur->pid, cur->aid, filename);
362
363
364 cur->f_hd = GNUNET_DISK_file_open (filename,
365 GNUNET_DISK_OPEN_READWRITE
366 | GNUNET_DISK_OPEN_CREATE
367 | GNUNET_DISK_OPEN_TRUNCATE,
368 GNUNET_DISK_PERM_USER_READ
369 | GNUNET_DISK_PERM_USER_WRITE
370 | GNUNET_DISK_PERM_GROUP_READ
371 | GNUNET_DISK_PERM_OTHER_READ);
372 if (NULL == cur->f_hd)
373 {
374 fprintf (stderr, "Cannot open `%s' to write log data!\n", filename);
375 GNUNET_free (filename);
376 GNUNET_free (cur);
377 goto cleanup;
378 }
379 GNUNET_free (filename);
380 GNUNET_CONTAINER_DLL_insert (lf_head, lf_tail, cur);
381
382 GNUNET_asprintf (&datastring,
383 "#time delta;log duration;peer_requested;addr net; addr_active; bw in; bw out; " \
384 "UTILIZATION_UP [abs/rel]; UTILIZATION_UP; UTILIZATION_DOWN; UTILIZATION_DOWN; " \
385 "UTILIZATION_PAYLOAD_UP; UTILIZATION_PAYLOAD_UP; UTILIZATION_PAYLOAD_DOWN; UTILIZATION_PAYLOAD_DOWN;" \
386 "DELAY; DELAY; " \
387 "DISTANCE ;DISTANCE ; COST_WAN; COST_WAN; COST_LAN; COST_LAN; " \
388 "COST_WLAN; COST_WLAN;COST_BT; COST_BT; PREF BW abs; PREF BW rel; PREF LATENCY abs; PREF LATENCY rel;\n");
389 GNUNET_DISK_file_write (cur->f_hd, datastring, strlen (datastring));
390 GNUNET_free (datastring);
391 }
392
393 prefstring = GNUNET_strdup ("");
394 for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
395 {
396 /*
397 fprintf(stderr,"\t %s = %.2f %.2f [abs/rel]\n",
398 GNUNET_ATS_print_preference_type(c),
399 log_p->pref_abs[c], log_p->pref_norm[c]);
400 */GNUNET_asprintf (&prefstring_tmp, "%s;%.3f;%.3f",
401 prefstring, log_p->pref_abs[c], log_p->pref_norm[c]);
402
403
404 GNUNET_free (prefstring);
405 prefstring = GNUNET_strdup (prefstring_tmp);
406 GNUNET_free (prefstring_tmp);
407 }
408
409
410 propstring = GNUNET_strdup ("");
411 for (c = 1; c < GNUNET_ATS_PropertyCount; c++)
412 {
413 if (GNUNET_ATS_NETWORK_TYPE == c)
414 continue;
415 /*
416 fprintf(stderr, "\t %s = %.2f %.2f [abs/rel]\n",
417 GNUNET_ATS_print_property_type(c),
418 log_a->prop_abs[c], log_a->prop_norm[c]);*/
419 GNUNET_asprintf (&propstring_tmp, "%s%.3f;%.3f;",
420 propstring,
421 log_a->prop_abs[c],
422 log_a->prop_norm[c]);
423 GNUNET_free (propstring);
424 propstring = GNUNET_strdup (propstring_tmp);
425 GNUNET_free (propstring_tmp);
426 }
427 GNUNET_asprintf (&datastring, "%llu;%llu;%u;%u;%i;%u;%u;%s;%s\n",
428 GNUNET_TIME_absolute_get_difference (
429 l->head->timestamp,
430 lts->timestamp).
431 rel_value_us / 1000, lts->delta,
432 log_p->is_requested, log_a->network, log_a->active,
433 log_a->assigned_bw_in, log_a->assigned_bw_out,
434 propstring,
435 prefstring);
436
437 GNUNET_DISK_file_write (cur->f_hd, datastring, strlen (datastring));
438 GNUNET_free (datastring);
439 GNUNET_free (prefstring);
440 GNUNET_free (propstring);
441 }
442 }
443 }
444
445 cleanup:
446 next = lf_head;
447 for (cur = next; NULL != cur; cur = next)
448 {
449 next = cur->next;
450 GNUNET_CONTAINER_DLL_remove (lf_head, lf_tail, cur);
451 if (NULL != cur->f_hd)
452 GNUNET_DISK_file_close (cur->f_hd);
453 GNUNET_free (cur);
454 }
455}
456
457
458void
459GNUNET_ATS_solver_logging_eval (struct LoggingHandle *l)
460{
461 struct LoggingTimeStep *lts;
462 struct LoggingPeer *log_p;
463 struct LoggingAddress *log_a;
464 int c;
465
466 for (lts = l->head; NULL != lts; lts = lts->next)
467 {
468 fprintf (stderr, "Log step %llu %llu: \n",
469 (long long unsigned int) lts->timestamp.abs_value_us,
470 (long long unsigned int) lts->delta.rel_value_us);
471
472 for (log_p = lts->head; NULL != log_p; log_p = log_p->next)
473 {
474 fprintf (stderr, "\tLogging peer pid %llu\n", log_p->id);
475 for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
476 {
477 fprintf (stderr, "\t %s = %.2f %.2f [abs/rel]\n",
478 GNUNET_ATS_print_preference_type (c),
479 log_p->pref_abs[c], log_p->pref_norm[c]);
480 }
481
482 for (log_a = log_p->addr_head; NULL != log_a; log_a = log_a->next)
483 {
484 fprintf (stderr, "\tPeer pid %llu address %llu: %u %u %u\n",
485 log_p->id, log_a->aid, log_a->active,
486 log_a->assigned_bw_in,
487 log_a->assigned_bw_out);
488
489 for (c = 1; c < GNUNET_ATS_PropertyCount; c++)
490 {
491 if (GNUNET_ATS_NETWORK_TYPE == c)
492 continue;
493 fprintf (stderr, "\t %s = %.2f %.2f [abs/rel]\n",
494 GNUNET_ATS_print_property_type (c),
495 log_a->prop_abs[c], log_a->prop_norm[c]);
496 }
497 }
498 }
499 }
500}
501
502
503void
504GNUNET_ATS_solver_logging_free (struct LoggingHandle *l)
505{
506 struct LoggingTimeStep *lts_cur;
507 struct LoggingTimeStep *lts_next;
508 struct LoggingPeer *log_p_cur;
509 struct LoggingPeer *log_p_next;
510 struct LoggingAddress *log_a_cur;
511 struct LoggingAddress *log_a_next;
512
513 if (NULL != l->logging_task)
514 GNUNET_SCHEDULER_cancel (l->logging_task);
515 l->logging_task = NULL;
516
517 lts_next = l->head;
518 while (NULL != (lts_cur = lts_next))
519 {
520 lts_next = lts_cur->next;
521
522 log_p_next = lts_cur->head;
523 while (NULL != (log_p_cur = log_p_next))
524 {
525 log_p_next = log_p_cur->next;
526
527 log_a_next = log_p_cur->addr_head;
528 while (NULL != (log_a_cur = log_a_next))
529 {
530 log_a_next = log_a_cur->next;
531
532 GNUNET_CONTAINER_DLL_remove (log_p_cur->addr_head, log_p_cur->addr_tail,
533 log_a_cur);
534 GNUNET_free (log_a_cur);
535 }
536
537 GNUNET_CONTAINER_DLL_remove (lts_cur->head, lts_cur->tail, log_p_cur);
538 GNUNET_free (log_p_cur);
539 }
540
541 GNUNET_CONTAINER_DLL_remove (l->head, l->tail, lts_cur);
542 GNUNET_free (lts_cur);
543 }
544
545 GNUNET_free (l);
546}
547
548
549/**
550 * Property Generators
551 */
552static struct PropertyGenerator *prop_gen_head;
553static struct PropertyGenerator *prop_gen_tail;
554
555
556static double
557get_property (struct PropertyGenerator *pg)
558{
559 struct GNUNET_TIME_Relative time_delta;
560 double delta_value;
561 double pref_value;
562
563 /* Calculate the current preference value */
564 switch (pg->type)
565 {
566 case GNUNET_ATS_TEST_TG_CONSTANT:
567 pref_value = pg->base_value;
568 break;
569
570 case GNUNET_ATS_TEST_TG_LINEAR:
571 time_delta = GNUNET_TIME_absolute_get_duration (pg->time_start);
572 /* Calculate point of time in the current period */
573 time_delta.rel_value_us = time_delta.rel_value_us
574 % pg->duration_period.rel_value_us;
575 delta_value = ((double) time_delta.rel_value_us
576 / pg->duration_period.rel_value_us) * (pg->max_value
577 - pg->base_value);
578 if ((pg->max_value < pg->base_value) &&
579 ((pg->max_value - pg->base_value) > pg->base_value))
580 {
581 /* This will cause an underflow */
582 GNUNET_break (0);
583 }
584 pref_value = pg->base_value + delta_value;
585 break;
586
587 case GNUNET_ATS_TEST_TG_RANDOM:
588 delta_value = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
589 10000 * (pg->max_value
590 - pg->base_value))
591 / 10000;
592 pref_value = pg->base_value + delta_value;
593 break;
594
595 case GNUNET_ATS_TEST_TG_SINUS:
596 time_delta = GNUNET_TIME_absolute_get_duration (pg->time_start);
597 /* Calculate point of time in the current period */
598 time_delta.rel_value_us = time_delta.rel_value_us
599 % pg->duration_period.rel_value_us;
600 if ((pg->max_value - pg->base_value) > pg->base_value)
601 {
602 /* This will cause an underflow for second half of sinus period,
603 * will be detected in general when experiments are loaded */
604 GNUNET_break (0);
605 }
606 delta_value = (pg->max_value - pg->base_value)
607 * sin ((2 * M_PI)
608 / ((double) pg->duration_period.rel_value_us)
609 * time_delta.rel_value_us);
610 pref_value = pg->base_value + delta_value;
611 break;
612
613 default:
614 pref_value = 0.0;
615 break;
616 }
617 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current property value is %f\n",
618 pref_value);
619 return pref_value;
620}
621
622
623static void
624set_prop_task (void *cls)
625{
626 struct PropertyGenerator *pg = cls;
627 struct TestPeer *p;
628 struct TestAddress *a;
629 double prop_value;
630 struct GNUNET_ATS_Information atsi;
631
632 pg->set_task = NULL;
633
634 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains_value (sh->addresses,
635 &pg->test_peer
636 ->peer_id,
637 pg->
638 test_address->
639 ats_addr))
640 {
641 GNUNET_break (0);
642 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
643 "Setting property generation for unknown address [%u:%u]\n",
644 pg->peer, pg->address_id);
645 return;
646 }
647 if (NULL == (p = find_peer_by_id (pg->peer)))
648 {
649 GNUNET_break (0);
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
651 "Setting property generation for unknown peer %u\n",
652 pg->peer);
653 return;
654 }
655 if (NULL == (a = find_address_by_id (p, pg->address_id)))
656 {
657 GNUNET_break (0);
658 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
659 "Setting property generation for unknown peer %u\n",
660 pg->peer);
661 return;
662 }
663
664 prop_value = get_property (pg);
665 a->prop_abs[pg->ats_property] = prop_value;
666
667 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
668 "Setting property for peer [%u] address [%u] for %s to %f\n",
669 pg->peer, pg->address_id,
670 GNUNET_ATS_print_property_type (pg->ats_property), prop_value);
671
672 atsi.type = htonl (pg->ats_property);
673 atsi.value = htonl ((uint32_t) prop_value);
674
675 /* set performance here! */
676 sh->sf->s_bulk_start (sh->sf->cls);
677 if (GNUNET_YES == opt_disable_normalization)
678 {
679 a->prop_abs[pg->ats_property] = prop_value;
680 a->prop_norm[pg->ats_property] = prop_value;
681 sh->sf->s_address_update_property (sh->sf->cls, a->ats_addr,
682 pg->ats_property, prop_value,
683 prop_value);
684 }
685 else
686 GAS_normalization_update_property (pg->test_address->ats_addr, &atsi, 1);
687 sh->sf->s_bulk_stop (sh->sf->cls);
688
689 pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
690 &set_prop_task, pg);
691}
692
693
694/**
695 * Set ats_property to 0 to find all pgs
696 */
697static struct PropertyGenerator *
698find_prop_gen (unsigned int peer, unsigned int address,
699 uint32_t ats_property)
700{
701 struct PropertyGenerator *cur;
702
703 for (cur = prop_gen_head; NULL != cur; cur = cur->next)
704 if ((cur->peer == peer) && (cur->address_id == address))
705 {
706 if ((cur->ats_property == ats_property) || (0 == ats_property))
707 return cur;
708 }
709 return NULL;
710}
711
712
713void
714GNUNET_ATS_solver_generate_property_stop (struct PropertyGenerator *pg)
715{
716 GNUNET_CONTAINER_DLL_remove (prop_gen_head, prop_gen_tail, pg);
717
718 if (NULL != pg->set_task)
719 {
720 GNUNET_SCHEDULER_cancel (pg->set_task);
721 pg->set_task = NULL;
722 }
723 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
724 "Removing old up preference generator peer [%u] address [%u] `%s'\n",
725 pg->peer, pg->address_id,
726 GNUNET_ATS_print_property_type (pg->ats_property));
727
728 GNUNET_free (pg);
729}
730
731
732/**
733 * Generate between the source master and the partner and set property with a
734 * value depending on the generator.
735 *
736 * @param peer source
737 * @param address_id partner
738 * @param test_peer the peer
739 * @param test_address the address
740 * @param type type of generator
741 * @param base_value base value
742 * @param value_rate maximum value
743 * @param period duration of a period of generation (~ 1/frequency)
744 * @param frequency how long to generate property
745 * @param ats_property ATS property to generate
746 * @return the property generator
747 */
748struct PropertyGenerator *
749GNUNET_ATS_solver_generate_property_start (unsigned int peer,
750 unsigned int address_id,
751 struct TestPeer *test_peer,
752 struct TestAddress *test_address,
753 enum GeneratorType type,
754 long int base_value,
755 long int value_rate,
756 struct GNUNET_TIME_Relative period,
757 struct GNUNET_TIME_Relative
758 frequency,
759 uint32_t ats_property)
760{
761 struct PropertyGenerator *pg;
762
763 pg = GNUNET_new (struct PropertyGenerator);
764 GNUNET_CONTAINER_DLL_insert (prop_gen_head, prop_gen_tail, pg);
765 pg->type = type;
766 pg->peer = peer;
767 pg->test_address = test_address;
768 pg->test_peer = test_peer;
769 pg->address_id = address_id;
770 pg->ats_property = ats_property;
771 pg->base_value = base_value;
772 pg->max_value = value_rate;
773 pg->duration_period = period;
774 pg->frequency = frequency;
775 pg->time_start = GNUNET_TIME_absolute_get ();
776
777 switch (type)
778 {
779 case GNUNET_ATS_TEST_TG_CONSTANT:
780 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
781 "Setting up %s property generator peer [%u] address [%u] `%s'" \
782 "max %u Bips\n",
783 print_generator_type (type), pg->peer, pg->address_id,
784 GNUNET_ATS_print_property_type (ats_property),
785 base_value);
786 break;
787
788 case GNUNET_ATS_TEST_TG_LINEAR:
789 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
790 "Setting up %s property generator peer [%u] address [%u] `%s' " \
791 "min %u Bips max %u Bips\n",
792 print_generator_type (type), pg->peer, pg->address_id,
793 GNUNET_ATS_print_property_type (ats_property),
794 base_value, value_rate);
795 break;
796
797 case GNUNET_ATS_TEST_TG_SINUS:
798 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
799 "Setting up %s property generator peer [%u] address [%u] `%s' " \
800 "baserate %u Bips, amplitude %u Bps\n",
801 print_generator_type (type), pg->peer, pg->address_id,
802 GNUNET_ATS_print_property_type (ats_property),
803 base_value, value_rate);
804 break;
805
806 case GNUNET_ATS_TEST_TG_RANDOM:
807 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
808 "Setting up %s property generator peer [%u] address [%u] `%s' " \
809 "min %u Bips max %u Bps\n",
810 print_generator_type (type), pg->peer, pg->address_id,
811 GNUNET_ATS_print_property_type (ats_property),
812 base_value, value_rate);
813 break;
814
815 default:
816 break;
817 }
818
819 pg->set_task = GNUNET_SCHEDULER_add_now (&set_prop_task, pg);
820 return pg;
821}
822
823
824/**
825 * Stop all preferences generators
826 */
827void
828GNUNET_ATS_solver_generate_property_stop_all ()
829{
830 struct PropertyGenerator *cur;
831 struct PropertyGenerator *next;
832
833 next = prop_gen_head;
834 for (cur = next; NULL != cur; cur = next)
835 {
836 next = cur->next;
837 GNUNET_ATS_solver_generate_property_stop (cur);
838 }
839}
840
841
842/**
843 * Preference Generators
844 */
845static struct PreferenceGenerator *pref_gen_head;
846static struct PreferenceGenerator *pref_gen_tail;
847
848
849static double
850get_preference (struct PreferenceGenerator *pg)
851{
852 struct GNUNET_TIME_Relative time_delta;
853 double delta_value;
854 double pref_value;
855
856 /* Calculate the current preference value */
857 switch (pg->type)
858 {
859 case GNUNET_ATS_TEST_TG_CONSTANT:
860 pref_value = pg->base_value;
861 break;
862
863 case GNUNET_ATS_TEST_TG_LINEAR:
864 time_delta = GNUNET_TIME_absolute_get_duration (pg->time_start);
865 /* Calculate point of time in the current period */
866 time_delta.rel_value_us = time_delta.rel_value_us
867 % pg->duration_period.rel_value_us;
868 delta_value = ((double) time_delta.rel_value_us
869 / pg->duration_period.rel_value_us) * (pg->max_value
870 - pg->base_value);
871 if ((pg->max_value < pg->base_value) &&
872 ((pg->max_value - pg->base_value) > pg->base_value))
873 {
874 /* This will cause an underflow */
875 GNUNET_break (0);
876 }
877 pref_value = pg->base_value + delta_value;
878 break;
879
880 case GNUNET_ATS_TEST_TG_RANDOM:
881 delta_value = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
882 10000 * (pg->max_value
883 - pg->base_value))
884 / 10000;
885 pref_value = pg->base_value + delta_value;
886 break;
887
888 case GNUNET_ATS_TEST_TG_SINUS:
889 time_delta = GNUNET_TIME_absolute_get_duration (pg->time_start);
890 /* Calculate point of time in the current period */
891 time_delta.rel_value_us = time_delta.rel_value_us
892 % pg->duration_period.rel_value_us;
893 if ((pg->max_value - pg->base_value) > pg->base_value)
894 {
895 /* This will cause an underflow for second half of sinus period,
896 * will be detected in general when experiments are loaded */
897 GNUNET_break (0);
898 }
899 delta_value = (pg->max_value - pg->base_value)
900 * sin ((2 * M_PI)
901 / ((double) pg->duration_period.rel_value_us)
902 * time_delta.rel_value_us);
903 pref_value = pg->base_value + delta_value;
904 break;
905
906 default:
907 pref_value = 0.0;
908 break;
909 }
910 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current preference value is %f\n",
911 pref_value);
912 return pref_value;
913}
914
915
916static void
917set_feedback_task (void *cls)
918{
919 struct PreferenceGenerator *pg = cls;
920 struct TestPeer *p;
921 double feedback;
922 uint32_t bw_acc_out;
923 uint32_t bw_acc_in;
924 uint32_t delay_acc_in;
925 struct GNUNET_TIME_Relative dur;
926 double p_new;
927
928 pg->feedback_task = NULL;
929
930 if (NULL == (p = find_peer_by_id (pg->peer)))
931 {
932 GNUNET_break (0);
933 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
934 "Setting feedback for unknown peer %u\n", pg->peer);
935 return;
936 }
937
938 switch (pg->kind)
939 {
940 case GNUNET_ATS_PREFERENCE_BANDWIDTH:
941 dur = GNUNET_TIME_absolute_get_duration (pg->feedback_last_bw_update);
942 bw_acc_in = dur.rel_value_us * pg->last_assigned_bw_in
943 + pg->feedback_bw_in_acc;
944 pg->feedback_bw_in_acc = 0;
945
946 bw_acc_out = dur.rel_value_us * pg->last_assigned_bw_out
947 + pg->feedback_bw_out_acc;
948 p_new = get_preference (pg);
949 feedback = (p_new / pg->pref_bw_old) * (bw_acc_in + bw_acc_out)
950 / (2 * GNUNET_TIME_absolute_get_duration (
951 pg->feedback_last).rel_value_us);
952
953 break;
954
955 case GNUNET_ATS_PREFERENCE_LATENCY:
956 dur = GNUNET_TIME_absolute_get_duration (pg->feedback_last_delay_update);
957 delay_acc_in = dur.rel_value_us * pg->last_delay_value
958 + pg->feedback_delay_acc;
959 pg->feedback_delay_acc = 0;
960
961 p_new = get_preference (pg);
962 feedback = (p_new / pg->pref_latency_old) * (delay_acc_in)
963 / (GNUNET_TIME_absolute_get_duration (
964 pg->feedback_last).rel_value_us);
965
966 break;
967
968 default:
969 GNUNET_break (0);
970 feedback = 0.0;
971 break;
972 }
973 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
974 "Giving feedback for peer [%u] for client %p pref %s of %.3f\n",
975 pg->peer, NULL + (pg->client_id),
976 GNUNET_ATS_print_preference_type (pg->kind),
977 feedback);
978
979 sh->sf->s_feedback (sh->sf->cls, NULL + (pg->client_id), &p->peer_id,
980 pg->feedback_frequency, pg->kind, feedback);
981 pg->feedback_last = GNUNET_TIME_absolute_get ();
982
983
984 pg->feedback_bw_out_acc = 0;
985 pg->feedback_bw_in_acc = 0;
986 pg->feedback_last_bw_update = GNUNET_TIME_absolute_get ();
987
988 pg->feedback_delay_acc = 0;
989 pg->feedback_last_delay_update = GNUNET_TIME_absolute_get ();
990
991
992 pg->feedback_task = GNUNET_SCHEDULER_add_delayed (pg->feedback_frequency,
993 &set_feedback_task, pg);
994}
995
996
997static void
998set_pref_task (void *cls)
999{
1000 struct PreferenceGenerator *pg = cls;
1001 struct TestPeer *p;
1002 double pref_value;
1003
1004 pg->set_task = NULL;
1005
1006 if (NULL == (p = find_peer_by_id (pg->peer)))
1007 {
1008 GNUNET_break (0);
1009 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1010 "Setting preference for unknown peer %u\n", pg->peer);
1011 return;
1012 }
1013
1014 pref_value = get_preference (pg);
1015 switch (pg->kind)
1016 {
1017 case GNUNET_ATS_PREFERENCE_BANDWIDTH:
1018 pg->pref_bw_old = pref_value;
1019 break;
1020
1021 case GNUNET_ATS_PREFERENCE_LATENCY:
1022 pg->pref_latency_old = pref_value;
1023 break;
1024
1025 default:
1026 break;
1027 }
1028
1029 p->pref_abs[pg->kind] = pref_value;
1030
1031 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1032 "Setting preference for peer [%u] for client %p pref %s to %f\n",
1033 pg->peer, NULL + (pg->client_id),
1034 GNUNET_ATS_print_preference_type (pg->kind), pref_value);
1035
1036 if (GNUNET_YES == opt_disable_normalization)
1037 {
1038 p->pref_abs[pg->kind] = pref_value;
1039 p->pref_norm[pg->kind] = pref_value;
1040 sh->sf->s_pref (sh->sf->cls, &p->peer_id, pg->kind, pref_value);
1041 }
1042 else
1043 update_preference (NULL + (pg->client_id),
1044 &p->peer_id,
1045 pg->kind,
1046 pref_value);
1047
1048 pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
1049 &set_pref_task,
1050 pg);
1051}
1052
1053
1054static struct PreferenceGenerator *
1055find_pref_gen (unsigned int peer, enum GNUNET_ATS_PreferenceKind kind)
1056{
1057 struct PreferenceGenerator *cur;
1058
1059 for (cur = pref_gen_head; NULL != cur; cur = cur->next)
1060 if (cur->peer == peer)
1061 {
1062 if ((cur->kind == kind) || (GNUNET_ATS_PREFERENCE_END == kind))
1063 return cur;
1064 }
1065 return NULL;
1066}
1067
1068
1069void
1070GNUNET_ATS_solver_generate_preferences_stop (struct PreferenceGenerator *pg)
1071{
1072 GNUNET_CONTAINER_DLL_remove (pref_gen_head, pref_gen_tail, pg);
1073
1074 if (NULL != pg->feedback_task)
1075 {
1076 GNUNET_SCHEDULER_cancel (pg->feedback_task);
1077 pg->feedback_task = NULL;
1078 }
1079
1080 if (NULL != pg->set_task)
1081 {
1082 GNUNET_SCHEDULER_cancel (pg->set_task);
1083 pg->set_task = NULL;
1084 }
1085 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1086 "Removing old up preference generator peer [%u] `%s'\n",
1087 pg->peer, GNUNET_ATS_print_preference_type (pg->kind));
1088
1089 GNUNET_free (pg);
1090}
1091
1092
1093static struct TestAddress*
1094find_active_address (struct TestPeer *p)
1095{
1096 struct TestAddress *cur;
1097
1098 for (cur = p->addr_head; NULL != cur; cur = cur->next)
1099 if (GNUNET_YES == cur->ats_addr->active)
1100 return cur;
1101 return NULL;
1102}
1103
1104
1105/**
1106 * Generate between the source master and the partner and set property with a
1107 * value depending on the generator.
1108 *
1109 * @param peer source
1110 * @param address_id partner
1111 * @param client_id the client
1112 * @param type type of generator
1113 * @param base_value base value
1114 * @param value_rate maximum value
1115 * @param period duration of a period of generation (~ 1/frequency)
1116 * @param frequency how long to generate property
1117 * @param kind ATS preference to generate
1118 * @param feedback_frequency how often to give feedback
1119 * @return the preference generator
1120 */
1121struct PreferenceGenerator *
1122GNUNET_ATS_solver_generate_preferences_start (unsigned int peer,
1123 unsigned int address_id,
1124 unsigned int client_id,
1125 enum GeneratorType type,
1126 long int base_value,
1127 long int value_rate,
1128 struct GNUNET_TIME_Relative
1129 period,
1130 struct GNUNET_TIME_Relative
1131 frequency,
1132 enum GNUNET_ATS_PreferenceKind
1133 kind,
1134 struct GNUNET_TIME_Relative
1135 feedback_frequency)
1136{
1137 struct PreferenceGenerator *pg;
1138 struct TestPeer *p;
1139
1140 if (NULL == (p = find_peer_by_id (peer)))
1141 {
1142 GNUNET_break (0);
1143 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1144 "Starting preference for unknown peer %u\n", peer);
1145 return NULL;
1146 }
1147
1148 pg = GNUNET_new (struct PreferenceGenerator);
1149 GNUNET_CONTAINER_DLL_insert (pref_gen_head, pref_gen_tail, pg);
1150 pg->type = type;
1151 pg->peer = peer;
1152 pg->client_id = client_id;
1153 pg->kind = kind;
1154 pg->base_value = base_value;
1155 pg->max_value = value_rate;
1156 pg->duration_period = period;
1157 pg->frequency = frequency;
1158 pg->time_start = GNUNET_TIME_absolute_get ();
1159 pg->feedback_frequency = feedback_frequency;
1160
1161 switch (type)
1162 {
1163 case GNUNET_ATS_TEST_TG_CONSTANT:
1164 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1165 "Setting up %s preference generator peer [%u] `%s' max %u Bips\n",
1166 print_generator_type (type), pg->peer,
1167 GNUNET_ATS_print_preference_type (kind),
1168 base_value);
1169 break;
1170
1171 case GNUNET_ATS_TEST_TG_LINEAR:
1172 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1173 "Setting up %s preference generator peer [%u] `%s' min %u Bips max %u Bips\n",
1174 print_generator_type (type), pg->peer,
1175 GNUNET_ATS_print_preference_type (kind),
1176 base_value, value_rate);
1177 break;
1178
1179 case GNUNET_ATS_TEST_TG_SINUS:
1180 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1181 "Setting up %s preference generator peer [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
1182 print_generator_type (type), pg->peer,
1183 GNUNET_ATS_print_preference_type (kind),
1184 base_value, value_rate);
1185 break;
1186
1187 case GNUNET_ATS_TEST_TG_RANDOM:
1188 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1189 "Setting up %s preference generator peer [%u] `%s' min %u Bips max %u Bps\n",
1190 print_generator_type (type), pg->peer,
1191 GNUNET_ATS_print_preference_type (kind),
1192 base_value, value_rate);
1193 break;
1194
1195 default:
1196 break;
1197 }
1198
1199 pg->set_task = GNUNET_SCHEDULER_add_now (&set_pref_task, pg);
1200 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
1201 feedback_frequency.rel_value_us)
1202 {
1203 struct TestAddress *addr = find_active_address (p);
1204
1205 pg->last_assigned_bw_in = p->assigned_bw_in;
1206 pg->last_assigned_bw_out = p->assigned_bw_out;
1207 pg->feedback_bw_in_acc = 0;
1208 pg->feedback_bw_out_acc = 0;
1209 pg->last_delay_value = addr->prop_norm[GNUNET_ATS_QUALITY_NET_DELAY];
1210 pg->feedback_delay_acc = 0;
1211
1212 pg->feedback_last_bw_update = GNUNET_TIME_absolute_get ();
1213 pg->feedback_last_delay_update = GNUNET_TIME_absolute_get ();
1214 pg->feedback_last = GNUNET_TIME_absolute_get ();
1215 pg->feedback_task = GNUNET_SCHEDULER_add_delayed (feedback_frequency,
1216 &set_feedback_task, pg);
1217 }
1218
1219 return pg;
1220}
1221
1222
1223/**
1224 * Stop all preferences generators
1225 */
1226void
1227GNUNET_ATS_solver_generate_preferences_stop_all ()
1228{
1229 struct PreferenceGenerator *cur;
1230 struct PreferenceGenerator *next;
1231
1232 next = pref_gen_head;
1233 for (cur = next; NULL != cur; cur = next)
1234 {
1235 next = cur->next;
1236 GNUNET_ATS_solver_generate_preferences_stop (cur);
1237 }
1238}
1239
1240
1241/**
1242 * Experiments
1243 */
1244static const char *
1245print_op (enum OperationType op)
1246{
1247 switch (op)
1248 {
1249 case SOLVER_OP_ADD_ADDRESS:
1250 return "ADD_ADDRESS";
1251
1252 case SOLVER_OP_DEL_ADDRESS:
1253 return "DEL_ADDRESS";
1254
1255 case SOLVER_OP_START_SET_PREFERENCE:
1256 return "START_SET_PREFERENCE";
1257
1258 case SOLVER_OP_STOP_SET_PREFERENCE:
1259 return "STOP_STOP_PREFERENCE";
1260
1261 case SOLVER_OP_START_SET_PROPERTY:
1262 return "START_SET_PROPERTY";
1263
1264 case SOLVER_OP_STOP_SET_PROPERTY:
1265 return "STOP_SET_PROPERTY";
1266
1267 case SOLVER_OP_START_REQUEST:
1268 return "START_REQUEST";
1269
1270 case SOLVER_OP_STOP_REQUEST:
1271 return "STOP_REQUEST";
1272
1273 default:
1274 break;
1275 }
1276 return "";
1277}
1278
1279
1280static struct Experiment *
1281create_experiment ()
1282{
1283 struct Experiment *e;
1284
1285 e = GNUNET_new (struct Experiment);
1286 e->name = NULL;
1287 e->start = NULL;
1288 e->total_duration = GNUNET_TIME_UNIT_ZERO;
1289 return e;
1290}
1291
1292
1293static void
1294free_experiment (struct Experiment *e)
1295{
1296 struct Episode *cur;
1297 struct Episode *next;
1298 struct GNUNET_ATS_TEST_Operation *cur_o;
1299 struct GNUNET_ATS_TEST_Operation *next_o;
1300
1301 next = e->start;
1302 for (cur = next; NULL != cur; cur = next)
1303 {
1304 next = cur->next;
1305
1306 next_o = cur->head;
1307 for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
1308 {
1309 next_o = cur_o->next;
1310 GNUNET_free (cur_o->address);
1311 GNUNET_free (cur_o->plugin);
1312 GNUNET_free (cur_o);
1313 }
1314 GNUNET_free (cur);
1315 }
1316
1317 GNUNET_free (e->name);
1318 GNUNET_free (e->log_prefix);
1319 GNUNET_free (e->log_output_dir);
1320 GNUNET_free (e->cfg_file);
1321 GNUNET_free (e);
1322}
1323
1324
1325static int
1326load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
1327 struct Episode *e,
1328 int op_counter,
1329 char *sec_name,
1330 const struct GNUNET_CONFIGURATION_Handle *cfg)
1331{
1332 char *op_name;
1333 char *op_network;
1334
1335 /* peer pid */
1336 GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
1337 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1338 sec_name, op_name,
1339 &o->peer_id))
1340 {
1341 fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
1342 op_counter, "ADD_ADDRESS", op_name);
1343 GNUNET_free (op_name);
1344 return GNUNET_SYSERR;
1345 }
1346 GNUNET_free (op_name);
1347
1348 /* address pid */
1349 GNUNET_asprintf (&op_name, "op-%u-address-id", op_counter);
1350 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1351 sec_name, op_name,
1352 &o->address_id))
1353 {
1354 fprintf (stderr,
1355 "Missing address-id in operation %u `%s' in episode `%s'\n",
1356 op_counter, "ADD_ADDRESS", op_name);
1357 GNUNET_free (op_name);
1358 return GNUNET_SYSERR;
1359 }
1360 GNUNET_free (op_name);
1361
1362 /* plugin */
1363 GNUNET_asprintf (&op_name, "op-%u-plugin", op_counter);
1364 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1365 sec_name, op_name,
1366 &o->plugin))
1367 {
1368 fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
1369 op_counter, "ADD_ADDRESS", op_name);
1370 GNUNET_free (op_name);
1371 return GNUNET_SYSERR;
1372 }
1373 GNUNET_free (op_name);
1374
1375 /* address */
1376 GNUNET_asprintf (&op_name, "op-%u-address", op_counter);
1377 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1378 sec_name, op_name,
1379 &o->address))
1380 {
1381 fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
1382 op_counter, "ADD_ADDRESS", op_name);
1383 GNUNET_free (op_name);
1384 return GNUNET_SYSERR;
1385 }
1386 GNUNET_free (op_name);
1387
1388 /* session */
1389 GNUNET_asprintf (&op_name, "op-%u-address-session", op_counter);
1390 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1391 sec_name, op_name,
1392 &o->
1393 address_session))
1394 {
1395 fprintf (stderr,
1396 "Missing address-session in operation %u `%s' in episode `%s'\n",
1397 op_counter, "ADD_ADDRESS", op_name);
1398 GNUNET_free (op_name);
1399 return GNUNET_SYSERR;
1400 }
1401 GNUNET_free (op_name);
1402
1403 /* network */
1404 GNUNET_asprintf (&op_name, "op-%u-address-network", op_counter);
1405 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1406 sec_name, op_name,
1407 &op_network))
1408 {
1409 fprintf (stderr,
1410 "Missing address-network in operation %u `%s' in episode `%s'\n",
1411 op_counter, "ADD_ADDRESS", op_name);
1412 GNUNET_free (op_name);
1413 return GNUNET_SYSERR;
1414 }
1415 else
1416 {
1417 GNUNET_break (GNUNET_OK == GNUNET_STRINGS_utf8_toupper (op_network,
1418 op_network));
1419 if (0 == strcmp (op_network, "UNSPECIFIED"))
1420 {
1421 o->address_network = GNUNET_NT_UNSPECIFIED;
1422 }
1423 else if (0 == strcmp (op_network, "LOOPBACK"))
1424 {
1425 o->address_network = GNUNET_NT_LOOPBACK;
1426 }
1427 else if (0 == strcmp (op_network, "LAN"))
1428 {
1429 o->address_network = GNUNET_NT_LAN;
1430 }
1431 else if (0 == strcmp (op_network, "WAN"))
1432 {
1433 o->address_network = GNUNET_NT_WAN;
1434 }
1435 else if (0 == strcmp (op_network, "WLAN"))
1436 {
1437 o->address_network = GNUNET_NT_WLAN;
1438 }
1439 else if (0 == strcmp (op_network, "BT"))
1440 {
1441 o->address_network = GNUNET_NT_BT;
1442 }
1443 else
1444 {
1445 fprintf (stderr,
1446 "Invalid address-network in operation %u `%s' in episode `%s': `%s'\n",
1447 op_counter, "ADD_ADDRESS", op_name, op_network);
1448 GNUNET_free (op_network);
1449 GNUNET_free (op_name);
1450 return GNUNET_SYSERR;
1451 }
1452 }
1453 GNUNET_free (op_network);
1454 GNUNET_free (op_name);
1455
1456 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1457 "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
1458 "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
1459
1460 return GNUNET_OK;
1461}
1462
1463
1464static int
1465load_op_del_address (struct GNUNET_ATS_TEST_Operation *o,
1466 struct Episode *e,
1467 int op_counter,
1468 char *sec_name,
1469 const struct GNUNET_CONFIGURATION_Handle *cfg)
1470{
1471 char *op_name;
1472
1473 // char *op_network;
1474
1475 /* peer pid */
1476 GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
1477 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1478 sec_name, op_name,
1479 &o->peer_id))
1480 {
1481 fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
1482 op_counter, "DEL_ADDRESS", op_name);
1483 GNUNET_free (op_name);
1484 return GNUNET_SYSERR;
1485 }
1486 GNUNET_free (op_name);
1487
1488 /* address pid */
1489 GNUNET_asprintf (&op_name, "op-%u-address-id", op_counter);
1490 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1491 sec_name, op_name,
1492 &o->address_id))
1493 {
1494 fprintf (stderr,
1495 "Missing address-id in operation %u `%s' in episode `%s'\n",
1496 op_counter, "DEL_ADDRESS", op_name);
1497 GNUNET_free (op_name);
1498 return GNUNET_SYSERR;
1499 }
1500 GNUNET_free (op_name);
1501
1502#if 0
1503 /* plugin */
1504 GNUNET_asprintf (&op_name, "op-%u-plugin", op_counter);
1505 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1506 sec_name, op_name,
1507 &o->plugin))
1508 {
1509 fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
1510 op_counter, "DEL_ADDRESS", op_name);
1511 GNUNET_free (op_name);
1512 return GNUNET_SYSERR;
1513 }
1514 GNUNET_free (op_name);
1515
1516 /* address */
1517 GNUNET_asprintf (&op_name, "op-%u-address", op_counter);
1518 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1519 sec_name, op_name,
1520 &o->address))
1521 {
1522 fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
1523 op_counter, "DEL_ADDRESS", op_name);
1524 GNUNET_free (op_name);
1525 return GNUNET_SYSERR;
1526 }
1527 GNUNET_free (op_name);
1528
1529 /* session */
1530 GNUNET_asprintf (&op_name, "op-%u-address-session", op_counter);
1531 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1532 sec_name, op_name,
1533 &o->
1534 address_session))
1535 {
1536 fprintf (stderr,
1537 "Missing address-session in operation %u `%s' in episode `%s'\n",
1538 op_counter, "DEL_ADDRESS", op_name);
1539 GNUNET_free (op_name);
1540 return GNUNET_SYSERR;
1541 }
1542 GNUNET_free (op_name);
1543#endif
1544
1545 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1546 "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
1547 "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
1548
1549 return GNUNET_OK;
1550}
1551
1552
1553static enum GNUNET_ATS_Property
1554parse_preference_string (const char *str)
1555{
1556 int c = 0;
1557 char *props[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
1558
1559 for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
1560 if (0 == strcmp (str, props[c]))
1561 return c;
1562 return 0;
1563}
1564
1565
1566static int
1567load_op_start_set_preference (struct GNUNET_ATS_TEST_Operation *o,
1568 struct Episode *e,
1569 int op_counter,
1570 char *sec_name,
1571 const struct GNUNET_CONFIGURATION_Handle *cfg)
1572{
1573 char *op_name;
1574 char *type;
1575 char *pref;
1576
1577 /* peer pid */
1578 GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
1579 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1580 sec_name, op_name,
1581 &o->peer_id))
1582 {
1583 fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
1584 op_counter, "START_SET_PREFERENCE", op_name);
1585 GNUNET_free (op_name);
1586 return GNUNET_SYSERR;
1587 }
1588 GNUNET_free (op_name);
1589
1590 /* address pid */
1591 GNUNET_asprintf (&op_name, "op-%u-client-id", op_counter);
1592 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1593 sec_name, op_name,
1594 &o->client_id))
1595 {
1596 fprintf (stderr, "Missing client-id in operation %u `%s' in episode `%s'\n",
1597 op_counter, "START_SET_PREFERENCE", op_name);
1598 GNUNET_free (op_name);
1599 return GNUNET_SYSERR;
1600 }
1601 GNUNET_free (op_name);
1602
1603 /* generator */
1604 GNUNET_asprintf (&op_name, "op-%u-gen-type", op_counter);
1605 if ((GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1606 sec_name,
1607 op_name, &type)))
1608 {
1609 fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
1610 op_counter, "START_SET_PREFERENCE", op_name);
1611 GNUNET_free (op_name);
1612 return GNUNET_SYSERR;
1613 }
1614
1615 /* Load arguments for set_rate, start_send, set_preference */
1616 if (0 == strcmp (type, "constant"))
1617 {
1618 o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1619 }
1620 else if (0 == strcmp (type, "linear"))
1621 {
1622 o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1623 }
1624 else if (0 == strcmp (type, "sinus"))
1625 {
1626 o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1627 }
1628 else if (0 == strcmp (type, "random"))
1629 {
1630 o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1631 }
1632 else
1633 {
1634 fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
1635 op_counter, op_name, e->id);
1636 GNUNET_free (type);
1637 GNUNET_free (op_name);
1638 return GNUNET_SYSERR;
1639 }
1640 GNUNET_free (type);
1641 GNUNET_free (op_name);
1642
1643
1644 /* Get base rate */
1645 GNUNET_asprintf (&op_name, "op-%u-base-rate", op_counter);
1646 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1647 sec_name, op_name,
1648 &o->base_rate))
1649 {
1650 fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1651 op_counter, op_name, e->id);
1652 GNUNET_free (op_name);
1653 return GNUNET_SYSERR;
1654 }
1655 GNUNET_free (op_name);
1656
1657
1658 /* Get max rate */
1659 GNUNET_asprintf (&op_name, "op-%u-max-rate", op_counter);
1660 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1661 sec_name, op_name,
1662 &o->max_rate))
1663 {
1664 if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1665 (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1666 (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1667 {
1668 fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1669 op_counter, op_name, e->id);
1670 GNUNET_free (op_name);
1671 return GNUNET_SYSERR;
1672 }
1673 }
1674 GNUNET_free (op_name);
1675
1676 /* Get period */
1677 GNUNET_asprintf (&op_name, "op-%u-period", op_counter);
1678 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1679 sec_name, op_name,
1680 &o->period))
1681 {
1682 o->period = e->duration;
1683 }
1684 GNUNET_free (op_name);
1685
1686 /* Get frequency */
1687 GNUNET_asprintf (&op_name, "op-%u-frequency", op_counter);
1688 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1689 sec_name, op_name,
1690 &o->frequency))
1691 {
1692 fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1693 op_counter, op_name, e->id);
1694 GNUNET_free (op_name);
1695 return GNUNET_SYSERR;
1696 }
1697 GNUNET_free (op_name);
1698
1699 /* Get preference */
1700 GNUNET_asprintf (&op_name, "op-%u-pref", op_counter);
1701 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1702 sec_name, op_name,
1703 &pref))
1704 {
1705 fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
1706 op_counter, op_name, e->id);
1707 GNUNET_free (op_name);
1708 return GNUNET_SYSERR;
1709 }
1710
1711 if (0 == (o->pref_type = parse_preference_string (pref)))
1712 {
1713 fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1714 op_counter, op_name, e->id);
1715 GNUNET_free (op_name);
1716 GNUNET_free (pref);
1717 return GNUNET_SYSERR;
1718 }
1719 GNUNET_free (pref);
1720 GNUNET_free (op_name);
1721
1722 /* Get feedback delay */
1723 GNUNET_asprintf (&op_name, "op-%u-feedback_delay", op_counter);
1724 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (cfg,
1725 sec_name, op_name,
1726 &o->feedback_delay))
1727 {
1728 fprintf (stderr,
1729 "Using feedback delay %llu in operation %u `%s' in episode %u\n",
1730 (long long unsigned int) o->feedback_delay.rel_value_us,
1731 op_counter, op_name, e->id);
1732 }
1733 else
1734 o->feedback_delay = GNUNET_TIME_UNIT_FOREVER_REL;
1735 GNUNET_free (op_name);
1736
1737 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1738 "Found operation %s: [%llu:%llu]: %s = %llu\n",
1739 "START_SET_PREFERENCE", o->peer_id, o->address_id,
1740 GNUNET_ATS_print_preference_type (o->pref_type), o->base_rate);
1741
1742 return GNUNET_OK;
1743}
1744
1745
1746static int
1747load_op_stop_set_preference (struct GNUNET_ATS_TEST_Operation *o,
1748 struct Episode *e,
1749 int op_counter,
1750 char *sec_name,
1751 const struct GNUNET_CONFIGURATION_Handle *cfg)
1752{
1753 char *op_name;
1754 char *pref;
1755
1756 /* peer pid */
1757 GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
1758 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1759 sec_name, op_name,
1760 &o->peer_id))
1761 {
1762 fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
1763 op_counter, "STOP_SET_PREFERENCE", op_name);
1764 GNUNET_free (op_name);
1765 return GNUNET_SYSERR;
1766 }
1767 GNUNET_free (op_name);
1768
1769 /* address pid */
1770 GNUNET_asprintf (&op_name, "op-%u-address-id", op_counter);
1771 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1772 sec_name, op_name,
1773 &o->address_id))
1774 {
1775 fprintf (stderr,
1776 "Missing address-id in operation %u `%s' in episode `%s'\n",
1777 op_counter, "STOP_SET_PREFERENCE", op_name);
1778 GNUNET_free (op_name);
1779 return GNUNET_SYSERR;
1780 }
1781 GNUNET_free (op_name);
1782
1783 /* Get preference */
1784 GNUNET_asprintf (&op_name, "op-%u-pref", op_counter);
1785 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1786 sec_name, op_name,
1787 &pref))
1788 {
1789 fprintf (stderr,
1790 "Missing preference in operation %u `%s' in episode `%s'\n",
1791 op_counter, "STOP_SET_PREFERENCE", op_name);
1792 GNUNET_free (op_name);
1793 return GNUNET_SYSERR;
1794 }
1795
1796 if (0 == (o->pref_type = parse_preference_string (pref)))
1797 {
1798 fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1799 op_counter, op_name, e->id);
1800 GNUNET_free (op_name);
1801 GNUNET_free (pref);
1802 return GNUNET_SYSERR;
1803 }
1804 GNUNET_free (pref);
1805 GNUNET_free (op_name);
1806
1807 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1808 "Found operation %s: [%llu:%llu]: %s\n",
1809 "STOP_SET_PREFERENCE", o->peer_id, o->address_id,
1810 GNUNET_ATS_print_preference_type (o->pref_type));
1811 return GNUNET_OK;
1812}
1813
1814
1815static enum GNUNET_ATS_Property
1816parse_property_string (const char *str)
1817{
1818 enum GNUNET_ATS_Property c;
1819
1820 for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
1821 if (0 == strcmp (str,
1822 GNUNET_ATS_print_property_type (c)))
1823 return c;
1824 return 0;
1825}
1826
1827
1828static int
1829load_op_start_set_property (struct GNUNET_ATS_TEST_Operation *o,
1830 struct Episode *e,
1831 int op_counter,
1832 char *sec_name,
1833 const struct GNUNET_CONFIGURATION_Handle *cfg)
1834{
1835 char *op_name;
1836 char *type;
1837 char *prop;
1838
1839 /* peer pid */
1840 GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
1841 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1842 sec_name, op_name,
1843 &o->peer_id))
1844 {
1845 fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
1846 op_counter, "START_SET_PROPERTY", op_name);
1847 GNUNET_free (op_name);
1848 return GNUNET_SYSERR;
1849 }
1850 GNUNET_free (op_name);
1851
1852 /* address pid */
1853 GNUNET_asprintf (&op_name, "op-%u-address-id", op_counter);
1854 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1855 sec_name, op_name,
1856 &o->address_id))
1857 {
1858 fprintf (stderr,
1859 "Missing address-id in operation %u `%s' in episode `%s'\n",
1860 op_counter, "START_SET_PROPERTY", op_name);
1861 GNUNET_free (op_name);
1862 return GNUNET_SYSERR;
1863 }
1864 GNUNET_free (op_name);
1865
1866 /* generator */
1867 GNUNET_asprintf (&op_name, "op-%u-gen-type", op_counter);
1868 if ((GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1869 sec_name,
1870 op_name, &type)))
1871 {
1872 fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
1873 op_counter, "START_SET_PROPERTY", op_name);
1874 GNUNET_free (op_name);
1875 return GNUNET_SYSERR;
1876 }
1877
1878 /* Load arguments for set_rate, start_send, set_preference */
1879 if (0 == strcmp (type, "constant"))
1880 {
1881 o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1882 }
1883 else if (0 == strcmp (type, "linear"))
1884 {
1885 o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1886 }
1887 else if (0 == strcmp (type, "sinus"))
1888 {
1889 o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1890 }
1891 else if (0 == strcmp (type, "random"))
1892 {
1893 o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1894 }
1895 else
1896 {
1897 fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
1898 op_counter, op_name, e->id);
1899 GNUNET_free (type);
1900 GNUNET_free (op_name);
1901 return GNUNET_SYSERR;
1902 }
1903 GNUNET_free (type);
1904 GNUNET_free (op_name);
1905
1906
1907 /* Get base rate */
1908 GNUNET_asprintf (&op_name, "op-%u-base-rate", op_counter);
1909 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1910 sec_name, op_name,
1911 &o->base_rate))
1912 {
1913 fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1914 op_counter, op_name, e->id);
1915 GNUNET_free (op_name);
1916 return GNUNET_SYSERR;
1917 }
1918 GNUNET_free (op_name);
1919
1920
1921 /* Get max rate */
1922 GNUNET_asprintf (&op_name, "op-%u-max-rate", op_counter);
1923 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1924 sec_name, op_name,
1925 &o->max_rate))
1926 {
1927 if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1928 (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1929 (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1930 {
1931 fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1932 op_counter, op_name, e->id);
1933 GNUNET_free (op_name);
1934 return GNUNET_SYSERR;
1935 }
1936 }
1937 GNUNET_free (op_name);
1938
1939 /* Get period */
1940 GNUNET_asprintf (&op_name, "op-%u-period", op_counter);
1941 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1942 sec_name, op_name,
1943 &o->period))
1944 {
1945 o->period = e->duration;
1946 }
1947 GNUNET_free (op_name);
1948
1949 /* Get frequency */
1950 GNUNET_asprintf (&op_name, "op-%u-frequency", op_counter);
1951 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1952 sec_name, op_name,
1953 &o->frequency))
1954 {
1955 fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1956 op_counter, op_name, e->id);
1957 GNUNET_free (op_name);
1958 return GNUNET_SYSERR;
1959 }
1960 GNUNET_free (op_name);
1961
1962 /* Get preference */
1963 GNUNET_asprintf (&op_name, "op-%u-property", op_counter);
1964 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1965 sec_name, op_name,
1966 &prop))
1967 {
1968 fprintf (stderr, "Missing property in operation %u `%s' in episode %u\n",
1969 op_counter, op_name, e->id);
1970 GNUNET_free (op_name);
1971 GNUNET_free (prop);
1972 return GNUNET_SYSERR;
1973 }
1974
1975 if (0 == (o->prop_type = parse_property_string (prop)))
1976 {
1977 fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1978 op_counter, op_name, e->id);
1979 GNUNET_free (op_name);
1980 GNUNET_free (prop);
1981 return GNUNET_SYSERR;
1982 }
1983
1984 GNUNET_free (prop);
1985 GNUNET_free (op_name);
1986
1987 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1988 "Found operation %s: [%llu:%llu] %s = %llu\n",
1989 "START_SET_PROPERTY", o->peer_id, o->address_id,
1990 GNUNET_ATS_print_property_type (o->prop_type), o->base_rate);
1991
1992 return GNUNET_OK;
1993}
1994
1995
1996static int
1997load_op_stop_set_property (struct GNUNET_ATS_TEST_Operation *o,
1998 struct Episode *e,
1999 int op_counter,
2000 char *sec_name,
2001 const struct GNUNET_CONFIGURATION_Handle *cfg)
2002{
2003 char *op_name;
2004 char *pref;
2005
2006 /* peer pid */
2007 GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
2008 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
2009 sec_name, op_name,
2010 &o->peer_id))
2011 {
2012 fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
2013 op_counter, "STOP_SET_PROPERTY", op_name);
2014 GNUNET_free (op_name);
2015 return GNUNET_SYSERR;
2016 }
2017 GNUNET_free (op_name);
2018
2019 /* address pid */
2020 GNUNET_asprintf (&op_name, "op-%u-address-id", op_counter);
2021 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
2022 sec_name, op_name,
2023 &o->address_id))
2024 {
2025 fprintf (stderr,
2026 "Missing address-id in operation %u `%s' in episode `%s'\n",
2027 op_counter, "STOP_SET_PROPERTY", op_name);
2028 GNUNET_free (op_name);
2029 return GNUNET_SYSERR;
2030 }
2031 GNUNET_free (op_name);
2032
2033 /* Get property */
2034 GNUNET_asprintf (&op_name, "op-%u-property", op_counter);
2035 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
2036 sec_name, op_name,
2037 &pref))
2038 {
2039 fprintf (stderr, "Missing property in operation %u `%s' in episode `%s'\n",
2040 op_counter, "STOP_SET_PROPERTY", op_name);
2041 GNUNET_free (op_name);
2042 GNUNET_free (pref);
2043 return GNUNET_SYSERR;
2044 }
2045
2046 if (0 == (o->prop_type = parse_property_string (pref)))
2047 {
2048 fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
2049 op_counter, op_name, e->id);
2050 GNUNET_free (op_name);
2051 GNUNET_free (pref);
2052 return GNUNET_SYSERR;
2053 }
2054
2055 GNUNET_free (pref);
2056 GNUNET_free (op_name);
2057
2058 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2059 "Found operation %s: [%llu:%llu] %s\n",
2060 "STOP_SET_PROPERTY", o->peer_id, o->address_id,
2061 GNUNET_ATS_print_property_type (o->prop_type));
2062
2063 return GNUNET_OK;
2064}
2065
2066
2067static int
2068load_op_start_request (struct GNUNET_ATS_TEST_Operation *o,
2069 struct Episode *e,
2070 int op_counter,
2071 char *sec_name,
2072 const struct GNUNET_CONFIGURATION_Handle *cfg)
2073{
2074 char *op_name;
2075
2076 /* peer pid */
2077 GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
2078 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
2079 sec_name, op_name,
2080 &o->peer_id))
2081 {
2082 fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
2083 op_counter, "START_REQUEST", op_name);
2084 GNUNET_free (op_name);
2085 return GNUNET_SYSERR;
2086 }
2087 GNUNET_free (op_name);
2088 return GNUNET_OK;
2089}
2090
2091
2092static int
2093load_op_stop_request (struct GNUNET_ATS_TEST_Operation *o,
2094 struct Episode *e,
2095 int op_counter,
2096 char *sec_name,
2097 const struct GNUNET_CONFIGURATION_Handle *cfg)
2098{
2099 char *op_name;
2100
2101 /* peer pid */
2102 GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
2103 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
2104 sec_name, op_name,
2105 &o->peer_id))
2106 {
2107 fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
2108 op_counter, "STOP_REQUEST", op_name);
2109 GNUNET_free (op_name);
2110 return GNUNET_SYSERR;
2111 }
2112 GNUNET_free (op_name);
2113 return GNUNET_OK;
2114}
2115
2116
2117static int
2118load_episode (struct Experiment *e, struct Episode *cur,
2119 struct GNUNET_CONFIGURATION_Handle *cfg)
2120{
2121 struct GNUNET_ATS_TEST_Operation *o;
2122 char *sec_name;
2123 char *op_name;
2124 char *op;
2125 int op_counter = 0;
2126 int res;
2127
2128 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Parsing episode %u\n", cur->id);
2129 GNUNET_asprintf (&sec_name, "episode-%u", cur->id);
2130
2131 while (1)
2132 {
2133 /* Load operation */
2134 GNUNET_asprintf (&op_name, "op-%u-operation", op_counter);
2135 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
2136 sec_name,
2137 op_name, &op))
2138 {
2139 GNUNET_free (op_name);
2140 break;
2141 }
2142 o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
2143 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "==== Parsing operation %u: `%s'\n",
2144 cur->id, op_name);
2145
2146 /* operations = set_rate, start_send, stop_send, set_preference */
2147 if (0 == strcmp (op, "address_add"))
2148 {
2149 o->type = SOLVER_OP_ADD_ADDRESS;
2150 res = load_op_add_address (o, cur,
2151 op_counter, sec_name, cfg);
2152 }
2153 else if (0 == strcmp (op, "address_del"))
2154 {
2155 o->type = SOLVER_OP_DEL_ADDRESS;
2156 res = load_op_del_address (o, cur,
2157 op_counter, sec_name, cfg);
2158 }
2159 else if (0 == strcmp (op, "start_set_property"))
2160 {
2161 o->type = SOLVER_OP_START_SET_PROPERTY;
2162 res = load_op_start_set_property (o, cur,
2163 op_counter, sec_name, cfg);
2164 }
2165 else if (0 == strcmp (op, "stop_set_property"))
2166 {
2167 o->type = SOLVER_OP_STOP_SET_PROPERTY;
2168 res = load_op_stop_set_property (o, cur,
2169 op_counter, sec_name, cfg);
2170 }
2171 else if (0 == strcmp (op, "start_set_preference"))
2172 {
2173 o->type = SOLVER_OP_START_SET_PREFERENCE;
2174 res = load_op_start_set_preference (o, cur,
2175 op_counter, sec_name, cfg);
2176 }
2177 else if (0 == strcmp (op, "stop_set_preference"))
2178 {
2179 o->type = SOLVER_OP_STOP_SET_PREFERENCE;
2180 res = load_op_stop_set_preference (o, cur,
2181 op_counter, sec_name, cfg);
2182 }
2183 else if (0 == strcmp (op, "start_request"))
2184 {
2185 o->type = SOLVER_OP_START_REQUEST;
2186 res = load_op_start_request (o, cur,
2187 op_counter, sec_name, cfg);
2188 }
2189 else if (0 == strcmp (op, "stop_request"))
2190 {
2191 o->type = SOLVER_OP_STOP_REQUEST;
2192 res = load_op_stop_request (o, cur,
2193 op_counter, sec_name, cfg);
2194 }
2195 else
2196 {
2197 fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
2198 op_counter, op, cur->id);
2199 res = GNUNET_SYSERR;
2200 }
2201
2202 GNUNET_free (op);
2203 GNUNET_free (op_name);
2204
2205 if (GNUNET_SYSERR == res)
2206 {
2207 GNUNET_free (o);
2208 GNUNET_free (sec_name);
2209 return GNUNET_SYSERR;
2210 }
2211
2212 GNUNET_CONTAINER_DLL_insert_tail (cur->head, cur->tail, o);
2213 op_counter++;
2214 }
2215 GNUNET_free (sec_name);
2216 return GNUNET_OK;
2217}
2218
2219
2220static int
2221load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
2222{
2223 int e_counter = 0;
2224 char *sec_name;
2225 struct GNUNET_TIME_Relative e_duration;
2226 struct Episode *cur;
2227 struct Episode *last;
2228
2229 e_counter = 0;
2230 last = NULL;
2231 while (1)
2232 {
2233 GNUNET_asprintf (&sec_name, "episode-%u", e_counter);
2234 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
2235 sec_name,
2236 "duration",
2237 &e_duration))
2238 {
2239 GNUNET_free (sec_name);
2240 break;
2241 }
2242
2243 cur = GNUNET_new (struct Episode);
2244 cur->duration = e_duration;
2245 cur->id = e_counter;
2246
2247 if (GNUNET_OK != load_episode (e, cur, cfg))
2248 {
2249 GNUNET_free (sec_name);
2250 GNUNET_free (cur);
2251 return GNUNET_SYSERR;
2252 }
2253
2254 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Found episode %u with duration %s \n",
2255 e_counter,
2256 GNUNET_STRINGS_relative_time_to_string (cur->duration,
2257 GNUNET_YES));
2258
2259 /* Update experiment */
2260 e->num_episodes++;
2261 e->total_duration = GNUNET_TIME_relative_add (e->total_duration,
2262 cur->duration);
2263 /* Put in linked list */
2264 if (NULL == last)
2265 e->start = cur;
2266 else
2267 last->next = cur;
2268
2269 GNUNET_free (sec_name);
2270 e_counter++;
2271 last = cur;
2272 }
2273 return e_counter;
2274}
2275
2276
2277static void
2278timeout_experiment (void *cls)
2279{
2280 struct Experiment *e = cls;
2281
2282 e->experiment_timeout_task = NULL;
2283 fprintf (stderr, "Experiment timeout!\n");
2284
2285 if (NULL != e->episode_timeout_task)
2286 {
2287 GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
2288 e->episode_timeout_task = NULL;
2289 }
2290
2291 e->e_done_cb (e, GNUNET_TIME_absolute_get_duration (e->start_time),
2292 GNUNET_SYSERR);
2293}
2294
2295
2296struct ATS_Address *
2297create_ats_address (const struct GNUNET_PeerIdentity *peer,
2298 const char *plugin_name,
2299 const void *plugin_addr,
2300 size_t plugin_addr_len,
2301 uint32_t session_id,
2302 uint32_t network)
2303{
2304 struct ATS_Address *aa = NULL;
2305
2306 aa = GNUNET_malloc (sizeof(struct ATS_Address) + plugin_addr_len + strlen (
2307 plugin_name) + 1);
2308 aa->atsi = GNUNET_new (struct GNUNET_ATS_Information);
2309 aa->atsi[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
2310 aa->atsi[0].value = htonl (network);
2311 aa->atsi_count = 1;
2312
2313 aa->peer = *peer;
2314 aa->addr_len = plugin_addr_len;
2315 aa->addr = &aa[1];
2316 aa->plugin = (char *) &aa[1] + plugin_addr_len;
2317 GNUNET_memcpy (&aa[1], plugin_addr, plugin_addr_len);
2318 GNUNET_memcpy (aa->plugin, plugin_name, strlen (plugin_name) + 1);
2319 aa->session_id = session_id;
2320
2321 return aa;
2322}
2323
2324
2325static void
2326enforce_add_address (struct GNUNET_ATS_TEST_Operation *op)
2327{
2328 struct TestPeer *p;
2329 struct TestAddress *a;
2330 int c;
2331
2332 if (NULL == (p = find_peer_by_id (op->peer_id)))
2333 {
2334 p = GNUNET_new (struct TestPeer);
2335 p->id = op->peer_id;
2336 p->assigned_bw_in = 0;
2337 p->assigned_bw_out = 0;
2338 memset (&p->peer_id, op->peer_id, sizeof(p->peer_id));
2339 for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
2340 {
2341 p->pref_abs[c] = DEFAULT_ABS_PREFERENCE;
2342 p->pref_norm[c] = DEFAULT_REL_PREFERENCE;
2343 }
2344
2345 GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, p);
2346 }
2347
2348 if (NULL != (find_address_by_id (p, op->address_id)))
2349 {
2350 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Duplicate address %u for peer %u\n",
2351 op->address_id, op->peer_id);
2352 return;
2353 }
2354
2355 a = GNUNET_new (struct TestAddress);
2356 a->aid = op->address_id;
2357 a->network = op->address_network;
2358 a->ats_addr = create_ats_address (&p->peer_id, op->plugin, op->address,
2359 strlen (op->address) + 1,
2360 op->address_session, op->address_network);
2361 memset (&p->peer_id, op->peer_id, sizeof(p->peer_id));
2362 GNUNET_CONTAINER_DLL_insert_tail (p->addr_head, p->addr_tail, a);
2363
2364 for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
2365 a->prop_norm[c] = DEFAULT_REL_QUALITY;
2366
2367 GNUNET_CONTAINER_multipeermap_put (sh->addresses, &p->peer_id, a->ats_addr,
2368 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2369
2370 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2371 "Adding address %u for peer %u in network `%s'\n",
2372 op->address_id, op->peer_id, GNUNET_NT_to_string (a->network));
2373
2374 sh->sf->s_add (sh->sf->cls, a->ats_addr, op->address_network);
2375}
2376
2377
2378static void
2379enforce_del_address (struct GNUNET_ATS_TEST_Operation *op)
2380{
2381 struct TestPeer *p;
2382 struct TestAddress *a;
2383 struct PropertyGenerator *pg;
2384
2385 if (NULL == (p = find_peer_by_id (op->peer_id)))
2386 {
2387 GNUNET_break (0);
2388 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2389 "Deleting address for unknown peer %u\n", op->peer_id);
2390 return;
2391 }
2392
2393 if (NULL == (a = find_address_by_id (p, op->address_id)))
2394 {
2395 GNUNET_break (0);
2396 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2397 "Deleting address for unknown peer %u\n", op->peer_id);
2398 return;
2399 }
2400
2401 while (NULL != (pg = find_prop_gen (p->id, a->aid, 0)))
2402 {
2403 GNUNET_ATS_solver_generate_property_stop (pg);
2404 }
2405
2406 GNUNET_assert (GNUNET_YES ==
2407 GNUNET_CONTAINER_multipeermap_remove (sh->addresses,
2408 &p->peer_id,
2409 a->ats_addr));
2410 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2411 "Removing address %u for peer %u\n",
2412 op->address_id,
2413 op->peer_id);
2414
2415 sh->sf->s_del (sh->sf->cls, a->ats_addr);
2416
2417 if (NULL != l)
2418 {
2419 GNUNET_ATS_solver_logging_now (l);
2420 }
2421 GNUNET_CONTAINER_DLL_remove (p->addr_head, p->addr_tail, a);
2422
2423 GNUNET_free (a->ats_addr->atsi);
2424 GNUNET_free (a->ats_addr);
2425 GNUNET_free (a);
2426}
2427
2428
2429static void
2430enforce_start_property (struct GNUNET_ATS_TEST_Operation *op)
2431{
2432 struct PropertyGenerator *pg;
2433 struct TestPeer *p;
2434 struct TestAddress *a;
2435
2436 if (NULL != (pg = find_prop_gen (op->peer_id, op->address_id, op->prop_type)))
2437 {
2438 GNUNET_ATS_solver_generate_property_stop (pg);
2439 GNUNET_free (pg);
2440 }
2441
2442 if (NULL == (p = find_peer_by_id (op->peer_id)))
2443 {
2444 GNUNET_break (0);
2445 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2446 "Starting property generation for unknown peer %u\n",
2447 op->peer_id);
2448 return;
2449 }
2450
2451 if (NULL == (a = find_address_by_id (p, op->address_id)))
2452 {
2453 GNUNET_break (0);
2454 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2455 "Setting property for unknown address %u\n", op->peer_id);
2456 return;
2457 }
2458
2459 GNUNET_ATS_solver_generate_property_start (op->peer_id,
2460 op->address_id,
2461 p, a,
2462 op->gen_type,
2463 op->base_rate,
2464 op->max_rate,
2465 op->period,
2466 op->frequency,
2467 op->prop_type);
2468}
2469
2470
2471static void
2472enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op)
2473{
2474 struct PropertyGenerator *pg = find_prop_gen (op->peer_id, op->address_id,
2475 op->prop_type);
2476
2477 if (NULL != pg)
2478 {
2479 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2480 "Stopping preference generation for peer %u address %u\n",
2481 op->peer_id,
2482 op->address_id);
2483 GNUNET_ATS_solver_generate_property_stop (pg);
2484 }
2485 else
2486 {
2487 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2488 "Cannot find preference generator for peer %u address %u\n",
2489 op->peer_id, op->address_id);
2490 GNUNET_break (0);
2491 }
2492}
2493
2494
2495static void
2496enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
2497{
2498 struct PreferenceGenerator *pg;
2499
2500 if (NULL != (pg = find_pref_gen (op->peer_id, op->pref_type)))
2501 {
2502 GNUNET_ATS_solver_generate_preferences_stop (pg);
2503 GNUNET_free (pg);
2504 }
2505
2506 if (NULL == (find_peer_by_id (op->peer_id)))
2507 {
2508 GNUNET_break (0);
2509 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2510 "Starting preference generation for unknown peer %u\n",
2511 op->peer_id);
2512 return;
2513 }
2514
2515 GNUNET_ATS_solver_generate_preferences_start (op->peer_id,
2516 op->address_id,
2517 op->client_id,
2518 op->gen_type,
2519 op->base_rate,
2520 op->max_rate,
2521 op->period,
2522 op->frequency,
2523 op->pref_type,
2524 op->frequency);
2525}
2526
2527
2528static void
2529enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
2530{
2531 struct PreferenceGenerator *pg = find_pref_gen (op->peer_id,
2532 op->pref_type);
2533
2534 if (NULL != pg)
2535 {
2536 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2537 "Stopping property generation for peer %u address %u\n",
2538 op->peer_id,
2539 op->address_id);
2540 GNUNET_ATS_solver_generate_preferences_stop (pg);
2541 }
2542 else
2543 {
2544 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2545 "Cannot find preference generator for peer %u address %u\n",
2546 op->peer_id, op->address_id);
2547 GNUNET_break (0);
2548 }
2549}
2550
2551
2552static void
2553enforce_start_request (struct GNUNET_ATS_TEST_Operation *op)
2554{
2555 struct TestPeer *p;
2556
2557 if (NULL == (p = find_peer_by_id (op->peer_id)))
2558 {
2559 GNUNET_break (0);
2560 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2561 "Requesting address for unknown peer %u\n", op->peer_id);
2562 return;
2563 }
2564
2565 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Requesting address for peer %u\n",
2566 op->peer_id);
2567 p->is_requested = GNUNET_YES;
2568
2569 sh->sf->s_get (sh->sf->cls, &p->peer_id);
2570}
2571
2572
2573static void
2574enforce_stop_request (struct GNUNET_ATS_TEST_Operation *op)
2575{
2576 struct TestPeer *p;
2577
2578 if (NULL == (p = find_peer_by_id (op->peer_id)))
2579 {
2580 GNUNET_break (0);
2581 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2582 "Requesting address for unknown peer %u\n", op->peer_id);
2583 return;
2584 }
2585
2586 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2587 "Stop requesting address for peer %u\n",
2588 op->peer_id);
2589 p->is_requested = GNUNET_NO;
2590 p->assigned_bw_in = 0;
2591 p->assigned_bw_out = 0;
2592 sh->sf->s_get_stop (sh->sf->cls, &p->peer_id);
2593
2594 if (NULL != l)
2595 {
2596 GNUNET_ATS_solver_logging_now (l);
2597 }
2598}
2599
2600
2601static void
2602enforce_episode (struct Episode *ep)
2603{
2604 struct GNUNET_ATS_TEST_Operation *cur;
2605
2606 for (cur = ep->head; NULL != cur; cur = cur->next)
2607 {
2608 switch (cur->type)
2609 {
2610 case SOLVER_OP_ADD_ADDRESS:
2611 fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
2612 print_op (cur->type), cur->peer_id, cur->address_id);
2613 enforce_add_address (cur);
2614 break;
2615
2616 case SOLVER_OP_DEL_ADDRESS:
2617 fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
2618 print_op (cur->type), cur->peer_id, cur->address_id);
2619 enforce_del_address (cur);
2620 break;
2621
2622 case SOLVER_OP_START_SET_PROPERTY:
2623 fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2624 print_op (cur->type), cur->peer_id, cur->address_id,
2625 cur->base_rate);
2626 enforce_start_property (cur);
2627 break;
2628
2629 case SOLVER_OP_STOP_SET_PROPERTY:
2630 fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2631 print_op (cur->type), cur->peer_id, cur->address_id,
2632 cur->base_rate);
2633 enforce_stop_property (cur);
2634 break;
2635
2636 case SOLVER_OP_START_SET_PREFERENCE:
2637 fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2638 print_op (cur->type), cur->peer_id, cur->address_id,
2639 cur->base_rate);
2640 enforce_start_preference (cur);
2641 break;
2642
2643 case SOLVER_OP_STOP_SET_PREFERENCE:
2644 fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2645 print_op (cur->type), cur->peer_id, cur->address_id,
2646 cur->base_rate);
2647 enforce_stop_preference (cur);
2648 break;
2649
2650 case SOLVER_OP_START_REQUEST:
2651 fprintf (stderr, "Enforcing operation: %s [%llu]\n",
2652 print_op (cur->type), cur->peer_id);
2653 enforce_start_request (cur);
2654 break;
2655
2656 case SOLVER_OP_STOP_REQUEST:
2657 fprintf (stderr, "Enforcing operation: %s [%llu]\n",
2658 print_op (cur->type), cur->peer_id);
2659 enforce_stop_request (cur);
2660 break;
2661
2662 default:
2663 break;
2664 }
2665 }
2666}
2667
2668
2669static void
2670timeout_episode (void *cls)
2671{
2672 struct Experiment *e = cls;
2673
2674 e->episode_timeout_task = NULL;
2675 if (NULL != e->ep_done_cb)
2676 e->ep_done_cb (e->cur);
2677
2678 /* Scheduling next */
2679 e->cur = e->cur->next;
2680 if (NULL == e->cur)
2681 {
2682 /* done */
2683 fprintf (stderr, "Last episode done!\n");
2684 if (NULL != e->experiment_timeout_task)
2685 {
2686 GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
2687 e->experiment_timeout_task = NULL;
2688 }
2689 e->e_done_cb (e, GNUNET_TIME_absolute_get_duration (e->start_time),
2690 GNUNET_OK);
2691 return;
2692 }
2693
2694 fprintf (stderr, "Running episode %u with timeout %s\n",
2695 e->cur->id,
2696 GNUNET_STRINGS_relative_time_to_string (e->cur->duration,
2697 GNUNET_YES));
2698 e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
2699 &timeout_episode, e);
2700 enforce_episode (e->cur);
2701}
2702
2703
2704void
2705GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
2706 GNUNET_ATS_TESTING_EpisodeDoneCallback
2707 ep_done_cb,
2708 GNUNET_ATS_TESTING_ExperimentDoneCallback
2709 e_done_cb)
2710{
2711 fprintf (stderr, "Running experiment `%s' with timeout %s\n", e->name,
2712 GNUNET_STRINGS_relative_time_to_string (e->max_duration,
2713 GNUNET_YES));
2714 e->e_done_cb = e_done_cb;
2715 e->ep_done_cb = ep_done_cb;
2716 e->start_time = GNUNET_TIME_absolute_get ();
2717
2718 /* Start total time out */
2719 e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
2720 &timeout_experiment,
2721 e);
2722
2723 /* Start */
2724 if (NULL == e->start)
2725 {
2726 GNUNET_break (0);
2727 return;
2728 }
2729
2730 e->cur = e->start;
2731 fprintf (stderr, "Running episode %u with timeout %s\n",
2732 e->cur->id,
2733 GNUNET_STRINGS_relative_time_to_string (e->cur->duration,
2734 GNUNET_YES));
2735 e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
2736 &timeout_episode, e);
2737 enforce_episode (e->cur);
2738}
2739
2740
2741void
2742GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
2743{
2744 if (NULL != e->experiment_timeout_task)
2745 {
2746 GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
2747 e->experiment_timeout_task = NULL;
2748 }
2749 if (NULL != e->episode_timeout_task)
2750 {
2751 GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
2752 e->episode_timeout_task = NULL;
2753 }
2754 if (NULL != e->cfg)
2755 {
2756 GNUNET_CONFIGURATION_destroy (e->cfg);
2757 e->cfg = NULL;
2758 }
2759 free_experiment (e);
2760}
2761
2762
2763struct Experiment *
2764GNUNET_ATS_solvers_experimentation_load (char *filename)
2765{
2766 struct Experiment *e;
2767 struct GNUNET_CONFIGURATION_Handle *cfg;
2768
2769 e = NULL;
2770
2771 cfg = GNUNET_CONFIGURATION_create ();
2772 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
2773 {
2774 fprintf (stderr, "Failed to load `%s'\n", filename);
2775 GNUNET_CONFIGURATION_destroy (cfg);
2776 return NULL;
2777 }
2778
2779 e = create_experiment ();
2780
2781 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "experiment",
2782 "name", &e->name))
2783 {
2784 fprintf (stderr, "Invalid %s \n", "name");
2785 free_experiment (e);
2786 return NULL;
2787 }
2788 else
2789 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment name: `%s'\n", e->name);
2790
2791 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "experiment",
2792 "log_prefix",
2793 &e->log_prefix))
2794 {
2795 fprintf (stderr, "Invalid %s \n", "log_prefix");
2796 free_experiment (e);
2797 return NULL;
2798 }
2799 else
2800 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging prefix: `%s'\n",
2801 e->log_prefix);
2802
2803 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg,
2804 "experiment",
2805 "log_output_dir",
2806 &e->
2807 log_output_dir))
2808 {
2809 e->log_output_dir = NULL;
2810 }
2811 else
2812 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2813 "Experiment logging output directory: `%s'\n",
2814 e->log_output_dir);
2815
2816
2817 if (GNUNET_SYSERR == (e->log_append_time_stamp =
2818 GNUNET_CONFIGURATION_get_value_yesno (cfg,
2819 "experiment",
2820 "log_append_time_stamp")))
2821 e->log_append_time_stamp = GNUNET_YES;
2822 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2823 "Experiment logging append timestamp: `%s'\n",
2824 (GNUNET_YES == e->log_append_time_stamp) ? "yes" : "no");
2825
2826
2827 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg,
2828 "experiment",
2829 "cfg_file",
2830 &e->cfg_file))
2831 {
2832 fprintf (stderr, "Invalid %s \n", "cfg_file");
2833 free_experiment (e);
2834 return NULL;
2835 }
2836 else
2837 {
2838 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment configuration: `%s'\n",
2839 e->cfg_file);
2840 e->cfg = GNUNET_CONFIGURATION_create ();
2841 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
2842 {
2843 fprintf (stderr, "Invalid configuration %s \n", "cfg_file");
2844 free_experiment (e);
2845 return NULL;
2846 }
2847 }
2848
2849 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, "experiment",
2850 "log_freq",
2851 &e->log_freq))
2852 {
2853 fprintf (stderr, "Invalid %s \n", "log_freq");
2854 free_experiment (e);
2855 return NULL;
2856 }
2857 else
2858 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging frequency: `%s'\n",
2859 GNUNET_STRINGS_relative_time_to_string (e->log_freq,
2860 GNUNET_YES));
2861
2862 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, "experiment",
2863 "max_duration",
2864 &e->max_duration))
2865 {
2866 fprintf (stderr, "Invalid %s", "max_duration");
2867 free_experiment (e);
2868 return NULL;
2869 }
2870 else
2871 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment duration: `%s'\n",
2872 GNUNET_STRINGS_relative_time_to_string (e->max_duration,
2873 GNUNET_YES));
2874
2875 if (GNUNET_SYSERR == load_episodes (e, cfg))
2876 {
2877 GNUNET_ATS_solvers_experimentation_stop (e);
2878 GNUNET_CONFIGURATION_destroy (cfg);
2879 e = NULL;
2880 fprintf (stderr, "Failed to load experiment\n");
2881 return NULL;
2882 }
2883 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2884 "Loaded %u episodes with total duration %s\n",
2885 e->num_episodes,
2886 GNUNET_STRINGS_relative_time_to_string (e->total_duration,
2887 GNUNET_YES));
2888
2889 GNUNET_CONFIGURATION_destroy (cfg);
2890 return e;
2891}
2892
2893
2894/**
2895 * Solver
2896 */
2897
2898static int
2899free_all_it (void *cls,
2900 const struct GNUNET_PeerIdentity *key,
2901 void *value)
2902{
2903 struct ATS_Address *address = value;
2904
2905 GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (
2906 sh->env.addresses,
2907 key, value));
2908 GNUNET_free (address);
2909
2910 return GNUNET_OK;
2911}
2912
2913
2914void
2915GNUNET_ATS_solvers_solver_stop (struct SolverHandle *sh)
2916{
2917 GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats,
2918 GNUNET_NO);
2919 GNUNET_PLUGIN_unload (sh->plugin, sh->sf);
2920 sh->sf = NULL;
2921 GAS_normalization_stop ();
2922
2923 GNUNET_CONTAINER_multipeermap_iterate (sh->addresses,
2924 &free_all_it,
2925 NULL);
2926 GNUNET_CONTAINER_multipeermap_destroy (sh->addresses);
2927 GNUNET_free (sh->plugin);
2928 GNUNET_free (sh);
2929}
2930
2931
2932/**
2933 * Load quotas for networks from configuration
2934 *
2935 * @param cfg configuration handle
2936 * @param out_dest where to write outbound quotas
2937 * @param in_dest where to write inbound quotas
2938 * @param dest_length length of inbound and outbound arrays
2939 * @return number of networks loaded
2940 */
2941unsigned int
2942GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
2943 unsigned long long *out_dest,
2944 unsigned long long *in_dest,
2945 int dest_length)
2946{
2947 char *entry_in = NULL;
2948 char *entry_out = NULL;
2949 char *quota_out_str;
2950 char *quota_in_str;
2951 int c;
2952 int res;
2953
2954 for (c = 0; (c < GNUNET_NT_COUNT) && (c < dest_length); c++)
2955 {
2956 in_dest[c] = 0;
2957 out_dest[c] = 0;
2958 GNUNET_asprintf (&entry_out,
2959 "%s_QUOTA_OUT",
2960 GNUNET_NT_to_string (c));
2961 GNUNET_asprintf (&entry_in,
2962 "%s_QUOTA_IN",
2963 GNUNET_NT_to_string (c));
2964
2965 /* quota out */
2966 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "ats",
2967 entry_out,
2968 &quota_out_str))
2969 {
2970 res = GNUNET_NO;
2971 if (0 == strcmp (quota_out_str, BIG_M_STRING))
2972 {
2973 out_dest[c] = GNUNET_ATS_MaxBandwidth;
2974 res = GNUNET_YES;
2975 }
2976 if ((GNUNET_NO == res) && (GNUNET_OK ==
2977 GNUNET_STRINGS_fancy_size_to_bytes (
2978 quota_out_str, &out_dest[c])))
2979 res = GNUNET_YES;
2980 if ((GNUNET_NO == res) && (GNUNET_OK ==
2981 GNUNET_CONFIGURATION_get_value_number (cfg,
2982 "ats",
2983 entry_out,
2984 &
2985 out_dest
2986 [c])))
2987 res = GNUNET_YES;
2988
2989 if (GNUNET_NO == res)
2990 {
2991 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2992 _ (
2993 "Could not load quota for network `%s': `%s', assigning default bandwidth %llu\n"),
2994 GNUNET_NT_to_string (c),
2995 quota_out_str,
2996 GNUNET_ATS_DefaultBandwidth);
2997 out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2998 }
2999 else
3000 {
3001 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3002 "Outbound quota configure for network `%s' is %llu\n",
3003 GNUNET_NT_to_string (c),
3004 out_dest[c]);
3005 }
3006 GNUNET_free (quota_out_str);
3007 }
3008 else
3009 {
3010 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3011 _ (
3012 "No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
3013 GNUNET_NT_to_string (c),
3014 GNUNET_ATS_DefaultBandwidth);
3015 out_dest[c] = GNUNET_ATS_DefaultBandwidth;
3016 }
3017
3018 /* quota in */
3019 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "ats",
3020 entry_in,
3021 &quota_in_str))
3022 {
3023 res = GNUNET_NO;
3024 if (0 == strcmp (quota_in_str, BIG_M_STRING))
3025 {
3026 in_dest[c] = GNUNET_ATS_MaxBandwidth;
3027 res = GNUNET_YES;
3028 }
3029 if ((GNUNET_NO == res) && (GNUNET_OK ==
3030 GNUNET_STRINGS_fancy_size_to_bytes (
3031 quota_in_str, &in_dest[c])))
3032 res = GNUNET_YES;
3033 if ((GNUNET_NO == res) && (GNUNET_OK ==
3034 GNUNET_CONFIGURATION_get_value_number (cfg,
3035 "ats",
3036 entry_in,
3037 &in_dest
3038 [c])))
3039 res = GNUNET_YES;
3040
3041 if (GNUNET_NO == res)
3042 {
3043 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3044 _ (
3045 "Could not load quota for network `%s': `%s', assigning default bandwidth %llu\n"),
3046 GNUNET_NT_to_string (c),
3047 quota_in_str,
3048 GNUNET_ATS_DefaultBandwidth);
3049 in_dest[c] = GNUNET_ATS_DefaultBandwidth;
3050 }
3051 else
3052 {
3053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3054 "Inbound quota configured for network `%s' is %llu\n",
3055 GNUNET_NT_to_string (c),
3056 in_dest[c]);
3057 }
3058 GNUNET_free (quota_in_str);
3059 }
3060 else
3061 {
3062 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3063 _ (
3064 "No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
3065 GNUNET_NT_to_string (c),
3066 GNUNET_ATS_DefaultBandwidth);
3067 out_dest[c] = GNUNET_ATS_DefaultBandwidth;
3068 }
3069 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3070 "Loaded quota for network `%s' (in/out): %llu %llu\n",
3071 GNUNET_NT_to_string (c),
3072 in_dest[c],
3073 out_dest[c]);
3074 GNUNET_free (entry_out);
3075 GNUNET_free (entry_in);
3076 }
3077 return GNUNET_NT_COUNT;
3078}
3079
3080
3081/**
3082 * Information callback for the solver
3083 *
3084 * @param cls the closure
3085 * @param op the solver operation
3086 * @param stat status of the solver operation
3087 * @param add additional solver information
3088 */
3089static void
3090solver_info_cb (void *cls,
3091 enum GAS_Solver_Operation op,
3092 enum GAS_Solver_Status stat,
3093 enum GAS_Solver_Additional_Information add)
3094{
3095 char *add_info;
3096
3097 switch (add)
3098 {
3099 case GAS_INFO_NONE:
3100 add_info = "GAS_INFO_NONE";
3101 break;
3102
3103 case GAS_INFO_FULL:
3104 add_info = "GAS_INFO_MLP_FULL";
3105 break;
3106
3107 case GAS_INFO_UPDATED:
3108 add_info = "GAS_INFO_MLP_UPDATED";
3109 break;
3110
3111 case GAS_INFO_PROP_ALL:
3112 add_info = "GAS_INFO_PROP_ALL";
3113 break;
3114
3115 case GAS_INFO_PROP_SINGLE:
3116 add_info = "GAS_INFO_PROP_SINGLE";
3117 break;
3118
3119 default:
3120 add_info = "INVALID";
3121 break;
3122 }
3123
3124 switch (op)
3125 {
3126 case GAS_OP_SOLVE_START:
3127 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3128 "Solver notifies `%s' with result `%s' `%s'\n",
3129 "GAS_OP_SOLVE_START",
3130 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
3131 return;
3132
3133 case GAS_OP_SOLVE_STOP:
3134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3135 "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
3136 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
3137 return;
3138
3139 case GAS_OP_SOLVE_SETUP_START:
3140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3141 "Solver notifies `%s' with result `%s'\n",
3142 "GAS_OP_SOLVE_SETUP_START",
3143 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
3144 return;
3145
3146 case GAS_OP_SOLVE_SETUP_STOP:
3147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3148 "Solver notifies `%s' with result `%s'\n",
3149 "GAS_OP_SOLVE_SETUP_STOP",
3150 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
3151 return;
3152
3153 case GAS_OP_SOLVE_MLP_LP_START:
3154 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3155 "Solver notifies `%s' with result `%s'\n",
3156 "GAS_OP_SOLVE_LP_START",
3157 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
3158 return;
3159
3160 case GAS_OP_SOLVE_MLP_LP_STOP:
3161 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3162 "Solver notifies `%s' with result `%s'\n",
3163 "GAS_OP_SOLVE_LP_STOP",
3164 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
3165 return;
3166
3167 case GAS_OP_SOLVE_MLP_MLP_START:
3168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3169 "Solver notifies `%s' with result `%s'\n",
3170 "GAS_OP_SOLVE_MLP_START",
3171 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
3172 return;
3173
3174 case GAS_OP_SOLVE_MLP_MLP_STOP:
3175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3176 "Solver notifies `%s' with result `%s'\n",
3177 "GAS_OP_SOLVE_MLP_STOP",
3178 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
3179 return;
3180
3181 case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
3182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3183 "Solver notifies `%s' with result `%s'\n",
3184 "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
3185 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
3186 return;
3187
3188 case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
3189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3190 "Solver notifies `%s' with result `%s'\n",
3191 "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
3192 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
3193 return;
3194
3195 default:
3196 break;
3197 }
3198}
3199
3200
3201static void
3202solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
3203{
3204 struct GNUNET_TIME_Relative duration;
3205 struct TestPeer *p;
3206 static struct PreferenceGenerator *pg;
3207 uint32_t delta;
3208
3209 if ((0 == address->assigned_bw_out) && (0 == address->assigned_bw_in))
3210 {
3211 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3212 "Solver notified to disconnect peer `%s'\n",
3213 GNUNET_i2s (&address->peer));
3214 }
3215 p = find_peer_by_pid (&address->peer);
3216 if (NULL == p)
3217 return;
3218 p->assigned_bw_out = address->assigned_bw_out;
3219 p->assigned_bw_in = address->assigned_bw_in;
3220
3221 for (pg = pref_gen_head; NULL != pg; pg = pg->next)
3222 {
3223 if (pg->peer == p->id)
3224 {
3225 duration = GNUNET_TIME_absolute_get_duration (
3226 pg->feedback_last_bw_update);
3227 delta = duration.rel_value_us * pg->last_assigned_bw_out;
3228 pg->feedback_bw_out_acc += delta;
3229
3230 delta = duration.rel_value_us * pg->last_assigned_bw_in;
3231 pg->feedback_bw_in_acc += delta;
3232
3233 pg->last_assigned_bw_in = address->assigned_bw_in;
3234 pg->last_assigned_bw_out = address->assigned_bw_out;
3235 pg->feedback_last_bw_update = GNUNET_TIME_absolute_get ();
3236 }
3237 }
3238
3239 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3240 "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
3241 GNUNET_i2s (&address->peer),
3242 address,
3243 address->assigned_bw_out,
3244 address->assigned_bw_in);
3245
3246 if (NULL != l)
3247 GNUNET_ATS_solver_logging_now (l);
3248
3249 return;
3250}
3251
3252
3253const double *
3254get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
3255{
3256 struct TestPeer *p;
3257
3258 if (GNUNET_YES == opt_disable_normalization)
3259 {
3260 if (NULL == (p = find_peer_by_pid (id)))
3261 return NULL;
3262 return p->pref_abs;
3263 }
3264 else
3265 return GAS_preference_get_by_peer (NULL,
3266 id);
3267}
3268
3269
3270struct SolverHandle *
3271GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
3272{
3273 struct SolverHandle *sh;
3274 char *solver_str;
3275
3276 switch (type)
3277 {
3278 case GNUNET_ATS_SOLVER_PROPORTIONAL:
3279 solver_str = "proportional";
3280 break;
3281
3282 case GNUNET_ATS_SOLVER_MLP:
3283 solver_str = "mlp";
3284 break;
3285
3286 case GNUNET_ATS_SOLVER_RIL:
3287 solver_str = "ril";
3288 break;
3289
3290 default:
3291 GNUNET_break (0);
3292 return NULL;
3293 break;
3294 }
3295
3296 sh = GNUNET_new (struct SolverHandle);
3297 GNUNET_asprintf (&sh->plugin,
3298 "libgnunet_plugin_ats_%s",
3299 solver_str);
3300 sh->addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
3301
3302 /* setup environment */
3303 sh->env.cfg = e->cfg;
3304 sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
3305 sh->env.addresses = sh->addresses;
3306 sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
3307 sh->env.get_preferences = &get_preferences_cb;
3308 sh->env.network_count = GNUNET_NT_COUNT;
3309 sh->env.info_cb = &solver_info_cb;
3310 sh->env.network_count = GNUNET_NT_COUNT;
3311
3312 /* start normalization */
3313 GAS_normalization_start ();
3314
3315 /* load quotas */
3316 if (GNUNET_NT_COUNT != GNUNET_ATS_solvers_load_quotas (e->cfg,
3317 sh->env.out_quota,
3318 sh->env.in_quota,
3319 GNUNET_NT_COUNT))
3320 {
3321 GNUNET_break (0);
3322 GNUNET_free (sh->plugin);
3323 GNUNET_free (sh);
3324 end_now ();
3325 return NULL;
3326 }
3327
3328 sh->sf = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
3329 if (NULL == sh->sf)
3330 {
3331 fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
3332 GNUNET_break (0);
3333 GNUNET_free (sh->plugin);
3334 GNUNET_free (sh);
3335 end_now ();
3336 return NULL;
3337 }
3338 return sh;
3339}
3340
3341
3342static void
3343done ()
3344{
3345 struct TestPeer *cur;
3346 struct TestPeer *next;
3347
3348 struct TestAddress *cur_a;
3349 struct TestAddress *next_a;
3350
3351 /* Stop logging */
3352 GNUNET_ATS_solver_logging_stop (l);
3353
3354 /* Stop all preference generation */
3355 GNUNET_ATS_solver_generate_preferences_stop_all ();
3356
3357 /* Stop all property generation */
3358 GNUNET_ATS_solver_generate_property_stop_all ();
3359
3360 if (opt_print)
3361 {
3362 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "== Printing log information \n");
3363 GNUNET_ATS_solver_logging_eval (l);
3364 }
3365 if (opt_save)
3366 {
3367 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "== Saving log information \n");
3368 GNUNET_ATS_solver_logging_write_to_disk (l, e->log_append_time_stamp,
3369 e->log_output_dir);
3370 }
3371
3372 if (NULL != l)
3373 {
3374 GNUNET_ATS_solver_logging_free (l);
3375 l = NULL;
3376 }
3377
3378 /* Clean up experiment */
3379 if (NULL != e)
3380 {
3381 GNUNET_ATS_solvers_experimentation_stop (e);
3382 e = NULL;
3383 }
3384
3385 next = peer_head;
3386 while (NULL != (cur = next))
3387 {
3388 next = cur->next;
3389 GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, cur);
3390 next_a = cur->addr_head;
3391 while (NULL != (cur_a = next_a))
3392 {
3393 next_a = cur_a->next;
3394 GNUNET_CONTAINER_DLL_remove (cur->addr_head, cur->addr_tail, cur_a);
3395 GNUNET_free (cur_a);
3396 }
3397 GNUNET_free (cur);
3398 }
3399 if (NULL != sh)
3400 {
3401 GNUNET_ATS_solvers_solver_stop (sh);
3402 sh = NULL;
3403 }
3404
3405 /* Shutdown */
3406 end_now ();
3407}
3408
3409
3410static void
3411experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,
3412 int success)
3413{
3414 if (GNUNET_OK == success)
3415 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
3416 GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
3417 else
3418 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
3419
3420 GNUNET_SCHEDULER_add_now (&done, NULL);
3421}
3422
3423
3424static void
3425episode_done_cb (struct Episode *ep)
3426{
3427 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
3428}
3429
3430
3431/**
3432 * Do shutdown
3433 */
3434static void
3435end_now ()
3436{
3437 if (NULL != e)
3438 {
3439 GNUNET_ATS_solvers_experimentation_stop (e);
3440 e = NULL;
3441 }
3442 if (NULL != sh)
3443 {
3444 GNUNET_ATS_solvers_solver_stop (sh);
3445 sh = NULL;
3446 }
3447}
3448
3449
3450static void
3451run (void *cls, char *const *args, const char *cfgfile,
3452 const struct GNUNET_CONFIGURATION_Handle *cfg)
3453{
3454 enum GNUNET_ATS_Solvers solver;
3455 int c;
3456
3457 if (NULL == opt_exp_file)
3458 {
3459 fprintf (stderr, "No experiment given ...\n");
3460 res = 1;
3461 end_now ();
3462 return;
3463 }
3464
3465 if (NULL == opt_solver)
3466 {
3467 fprintf (stderr, "No solver given ...\n");
3468 res = 1;
3469 end_now ();
3470 return;
3471 }
3472
3473 if (0 == strcmp (opt_solver, "mlp"))
3474 {
3475 solver = GNUNET_ATS_SOLVER_MLP;
3476 }
3477 else if (0 == strcmp (opt_solver, "proportional"))
3478 {
3479 solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
3480 }
3481 else if (0 == strcmp (opt_solver, "ril"))
3482 {
3483 solver = GNUNET_ATS_SOLVER_RIL;
3484 }
3485 else
3486 {
3487 fprintf (stderr, "No solver given ...");
3488 res = 1;
3489 end_now ();
3490 return;
3491 }
3492
3493 for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
3494 default_properties[c] = DEFAULT_REL_QUALITY;
3495
3496 for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
3497 default_preferences[c] = DEFAULT_REL_PREFERENCE;
3498
3499 /* load experiment */
3500 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Loading experiment\n");
3501 e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
3502 if (NULL == e)
3503 {
3504 fprintf (stderr, "Failed to load experiment ...\n");
3505 res = 1;
3506 end_now ();
3507 return;
3508 }
3509
3510 /* load solver */
3511 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Loading solver\n");
3512 sh = GNUNET_ATS_solvers_solver_start (solver);
3513 if (NULL == sh)
3514 {
3515 fprintf (stderr, "Failed to start solver ...\n");
3516 end_now ();
3517 res = 1;
3518 return;
3519 }
3520
3521 /* start logging */
3522 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Start logging \n");
3523 l = GNUNET_ATS_solver_logging_start (e->log_freq);
3524
3525 /* run experiment */
3526 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Running experiment \n");
3527 GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
3528 experiment_done_cb);
3529
3530 /* WAIT */
3531}
3532
3533
3534/**
3535 * Main function of the benchmark
3536 *
3537 * @param argc argument count
3538 * @param argv argument values
3539 */
3540int
3541main (int argc, char *argv[])
3542{
3543 opt_exp_file = NULL;
3544 opt_solver = NULL;
3545 opt_log = GNUNET_NO;
3546 opt_save = GNUNET_NO;
3547
3548 res = 0;
3549
3550 static struct GNUNET_GETOPT_CommandLineOption options[] = {
3551 GNUNET_GETOPT_option_string ('s',
3552 "solver",
3553 gettext_noop ("solver to use"),
3554 &opt_solver),
3555
3556 GNUNET_GETOPT_option_string ('e',
3557 "experiment"
3558 gettext_noop ("experiment to use"),
3559 &opt_exp_file),
3560
3561 GNUNET_GETOPT_option_verbose (&opt_verbose),
3562
3563 GNUNET_GETOPT_option_flag ('p',
3564 "print",
3565 gettext_noop ("print logging"),
3566 &opt_print),
3567
3568 GNUNET_GETOPT_option_flag ('f',
3569 "file",
3570 gettext_noop ("save logging to disk"),
3571 &opt_save),
3572
3573 GNUNET_GETOPT_option_flag ('d',
3574 "dn",
3575 gettext_noop ("disable normalization"),
3576 &opt_disable_normalization),
3577
3578 GNUNET_GETOPT_OPTION_END
3579 };
3580
3581 GNUNET_PROGRAM_run (argc, argv, "gnunet-ats-solver-eval",
3582 NULL, options, &run, argv[0]);
3583
3584 return res;
3585}
3586
3587
3588/* end of file ats-testing-experiment.c*/
diff --git a/src/ats/gnunet-ats-solver-eval.h b/src/ats/gnunet-ats-solver-eval.h
deleted file mode 100644
index 7d14bf761..000000000
--- a/src/ats/gnunet-ats-solver-eval.h
+++ /dev/null
@@ -1,335 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats-tests/ats-testing-experiment.c
22 * @brief ats benchmark: controlled experiment execution
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 */
26#ifndef GNUNET_ATS_SOLVER_EVAL_H
27#define GNUNET_ATS_SOLVER_EVAL_H
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_ats_plugin.h"
32#include "gnunet_ats_service.h"
33#include "gnunet-service-ats_addresses.h"
34#include "gnunet-service-ats_normalization.h"
35#include "test_ats_api_common.h"
36
37enum GeneratorType
38{
39 GNUNET_ATS_TEST_TG_LINEAR,
40 GNUNET_ATS_TEST_TG_CONSTANT,
41 GNUNET_ATS_TEST_TG_RANDOM,
42 GNUNET_ATS_TEST_TG_SINUS
43};
44
45
46enum OperationType
47{
48 SOLVER_OP_ADD_ADDRESS,
49 SOLVER_OP_DEL_ADDRESS,
50 SOLVER_OP_START_SET_PROPERTY,
51 SOLVER_OP_STOP_SET_PROPERTY,
52 SOLVER_OP_START_SET_PREFERENCE,
53 SOLVER_OP_STOP_SET_PREFERENCE,
54 SOLVER_OP_START_REQUEST,
55 SOLVER_OP_STOP_REQUEST,
56};
57
58struct SolverHandle
59{
60 /**
61 * Solver plugin name
62 */
63 char *plugin;
64
65 /**
66 * Solver environment
67 */
68 struct GNUNET_ATS_PluginEnvironment env;
69
70 /**
71 * Solver handle
72 */
73 struct GNUNET_ATS_SolverFunctions *sf;
74
75 /**
76 * Address hashmap
77 */
78 struct GNUNET_CONTAINER_MultiPeerMap *addresses;
79};
80
81enum GNUNET_ATS_Solvers
82{
83 GNUNET_ATS_SOLVER_PROPORTIONAL,
84 GNUNET_ATS_SOLVER_MLP,
85 GNUNET_ATS_SOLVER_RIL,
86};
87
88struct LoggingFileHandle
89{
90 /* DLL list for logging time steps */
91 struct LoggingFileHandle *next;
92 struct LoggingFileHandle *prev;
93
94 /* peer id */
95 long long unsigned int pid;
96
97 /* address id */
98 long long unsigned int aid;
99
100 struct GNUNET_DISK_FileHandle *f_hd;
101};
102
103struct LoggingTimeStep
104{
105 struct LoggingTimeStep *prev;
106 struct LoggingTimeStep *next;
107
108 struct LoggingPeer *head;
109 struct LoggingPeer *tail;
110
111 struct GNUNET_TIME_Absolute timestamp;
112 struct GNUNET_TIME_Relative delta;
113};
114
115struct LoggingPeer
116{
117 struct LoggingPeer *prev;
118 struct LoggingPeer *next;
119
120 long long unsigned int id;
121 struct GNUNET_PeerIdentity peer_id;
122 double pref_abs[GNUNET_ATS_PREFERENCE_END];
123 double pref_norm[GNUNET_ATS_PREFERENCE_END];
124 int is_requested;
125
126 struct LoggingAddress *addr_head;
127 struct LoggingAddress *addr_tail;
128};
129
130struct LoggingAddress
131{
132 struct LoggingAddress *next;
133 struct LoggingAddress *prev;
134
135 long long unsigned int aid;
136 int active;
137 uint32_t network;
138 uint32_t assigned_bw_in;
139 uint32_t assigned_bw_out;
140
141 double prop_abs[GNUNET_ATS_PropertyCount];
142 double prop_norm[GNUNET_ATS_PropertyCount];
143};
144
145
146struct TestPeer
147{
148 struct TestPeer *prev;
149 struct TestPeer *next;
150
151
152 long long unsigned int id;
153 int is_requested;
154 struct GNUNET_PeerIdentity peer_id;
155
156 double pref_abs[GNUNET_ATS_PreferenceCount];
157 double pref_norm[GNUNET_ATS_PreferenceCount];
158
159 uint32_t assigned_bw_in;
160 uint32_t assigned_bw_out;
161
162 struct TestAddress *addr_head;
163 struct TestAddress *addr_tail;
164};
165
166
167struct TestAddress
168{
169 struct TestAddress *next;
170 struct TestAddress *prev;
171
172 long long unsigned int aid;
173 struct ATS_Address *ats_addr;
174 uint32_t network;
175
176 double prop_abs[GNUNET_ATS_PropertyCount];
177 double prop_norm[GNUNET_ATS_PropertyCount];
178};
179
180struct Episode;
181
182struct Experiment;
183
184typedef void (*GNUNET_ATS_TESTING_EpisodeDoneCallback) (
185 struct Episode *e);
186
187typedef void (*GNUNET_ATS_TESTING_ExperimentDoneCallback) (struct Experiment *e,
188 struct
189 GNUNET_TIME_Relative
190 duration, int
191 success);
192
193/**
194 * An operation in an experiment
195 */
196struct GNUNET_ATS_TEST_Operation
197{
198 struct GNUNET_ATS_TEST_Operation *next;
199 struct GNUNET_ATS_TEST_Operation *prev;
200
201 long long unsigned int address_id;
202 long long unsigned int peer_id;
203 long long unsigned int client_id;
204
205 long long unsigned int address_session;
206 unsigned int address_network;
207 char*address;
208 char*plugin;
209
210
211 long long unsigned int base_rate;
212 long long unsigned int max_rate;
213 struct GNUNET_TIME_Relative period;
214 struct GNUNET_TIME_Relative frequency;
215 struct GNUNET_TIME_Relative feedback_delay;
216
217 enum OperationType type;
218 enum GeneratorType gen_type;
219 enum GNUNET_ATS_PreferenceKind pref_type;
220 // enum GNUNET_ATS_Property prop_type;
221};
222
223struct Episode
224{
225 int id;
226 struct Episode *next;
227 struct GNUNET_TIME_Relative duration;
228
229 struct GNUNET_ATS_TEST_Operation *head;
230 struct GNUNET_ATS_TEST_Operation *tail;
231};
232
233struct LoggingHandle
234{
235 struct GNUNET_SCHEDULER_Task *logging_task;
236 struct GNUNET_TIME_Relative log_freq;
237
238 /* DLL list for logging time steps */
239 struct LoggingTimeStep *head;
240 struct LoggingTimeStep *tail;
241};
242
243struct Experiment
244{
245 char *name;
246 char *log_prefix;
247 char *cfg_file;
248 char *log_output_dir;
249 int log_append_time_stamp;
250
251 struct GNUNET_TIME_Relative log_freq;
252 struct GNUNET_TIME_Relative max_duration;
253 struct GNUNET_TIME_Relative total_duration;
254 struct GNUNET_TIME_Absolute start_time;
255 unsigned int num_episodes;
256 struct Episode *start;
257
258 struct GNUNET_CONFIGURATION_Handle *cfg;
259
260 struct GNUNET_SCHEDULER_Task *experiment_timeout_task;
261 struct GNUNET_SCHEDULER_Task *episode_timeout_task;
262 struct Episode *cur;
263
264 GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb;
265 GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb;
266};
267
268struct PreferenceGenerator
269{
270 struct PreferenceGenerator *prev;
271 struct PreferenceGenerator *next;
272
273 enum GeneratorType type;
274
275 long long unsigned int peer;
276 unsigned int client_id;
277
278 enum GNUNET_ATS_PreferenceKind kind;
279
280 long int base_value;
281 long int max_value;
282 struct GNUNET_TIME_Relative duration_period;
283 struct GNUNET_TIME_Relative frequency;
284 struct GNUNET_TIME_Relative feedback_frequency;
285
286 struct GNUNET_SCHEDULER_Task *set_task;
287 struct GNUNET_SCHEDULER_Task *feedback_task;
288 struct GNUNET_TIME_Absolute next_ping_transmission;
289 struct GNUNET_TIME_Absolute time_start;
290
291
292 /* Feedback */
293 uint32_t feedback_bw_out_acc;
294 uint32_t feedback_bw_in_acc;
295 uint32_t feedback_delay_acc;
296
297 double pref_bw_old;
298 double pref_latency_old;
299
300 struct GNUNET_TIME_Absolute feedback_last;
301
302 struct GNUNET_TIME_Absolute feedback_last_bw_update;
303 struct GNUNET_TIME_Absolute feedback_last_delay_update;
304 uint32_t last_assigned_bw_in;
305 uint32_t last_assigned_bw_out;
306 double last_delay_value;
307};
308
309
310struct PropertyGenerator
311{
312 struct PropertyGenerator *prev;
313 struct PropertyGenerator *next;
314
315 enum GeneratorType type;
316
317 long long unsigned int peer;
318 long long unsigned int address_id;
319
320 struct TestPeer *test_peer;
321 struct TestAddress *test_address;
322 uint32_t ats_property;
323
324 long int base_value;
325 long int max_value;
326 struct GNUNET_TIME_Relative duration_period;
327 struct GNUNET_TIME_Relative frequency;
328
329 struct GNUNET_SCHEDULER_Task *set_task;
330 struct GNUNET_TIME_Absolute next_ping_transmission;
331 struct GNUNET_TIME_Absolute time_start;
332};
333
334#endif /* #ifndef GNUNET_ATS_SOLVER_EVAL_H */
335/* end of file ats-testing.h */
diff --git a/src/ats/gnunet-service-ats.c b/src/ats/gnunet-service-ats.c
deleted file mode 100644
index 5e27ecbd0..000000000
--- a/src/ats/gnunet-service-ats.c
+++ /dev/null
@@ -1,538 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/gnunet-service-ats.c
22 * @brief ats service
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet-service-ats.h"
29#include "gnunet-service-ats_addresses.h"
30#include "gnunet-service-ats_connectivity.h"
31#include "gnunet-service-ats_normalization.h"
32#include "gnunet-service-ats_performance.h"
33#include "gnunet-service-ats_preferences.h"
34#include "gnunet-service-ats_scheduling.h"
35#include "gnunet-service-ats_reservations.h"
36#include "gnunet-service-ats_plugins.h"
37#include "ats.h"
38
39/**
40 * Handle for statistics.
41 */
42struct GNUNET_STATISTICS_Handle *GSA_stats;
43
44
45/**
46 * We have received a `struct ClientStartMessage` from a client. Find
47 * out which type of client it is and notify the respective subsystem.
48 *
49 * @param cls handle to the client
50 * @param msg the start message
51 */
52static void
53handle_ats_start (void *cls,
54 const struct ClientStartMessage *msg)
55{
56 struct GNUNET_SERVICE_Client *client = cls;
57 enum StartFlag flag;
58
59 flag = ntohl (msg->start_flag);
60 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
61 "Received ATS_START (%d) message\n",
62 (int) flag);
63 switch (flag)
64 {
65 case START_FLAG_SCHEDULING:
66 if (GNUNET_OK !=
67 GAS_scheduling_add_client (client))
68 {
69 GNUNET_SERVICE_client_drop (client);
70 return;
71 }
72 break;
73
74 case START_FLAG_PERFORMANCE_WITH_PIC:
75 GAS_performance_add_client (client,
76 flag);
77 break;
78
79 case START_FLAG_PERFORMANCE_NO_PIC:
80 GAS_performance_add_client (client,
81 flag);
82 break;
83
84 case START_FLAG_CONNECTION_SUGGESTION:
85 /* This client won't receive messages from us, no need to 'add' */
86 break;
87
88 default:
89 GNUNET_break (0);
90 GNUNET_SERVICE_client_drop (client);
91 return;
92 }
93 GNUNET_SERVICE_client_continue (client);
94}
95
96
97/**
98 * Handle 'reservation request' messages from clients.
99 *
100 * @param cls client that sent the request
101 * @param message the request message
102 */
103static void
104handle_reservation_request (void *cls,
105 const struct ReservationRequestMessage *message)
106{
107 struct GNUNET_SERVICE_Client *client = cls;
108
109 GAS_handle_reservation_request (client,
110 message);
111 GNUNET_SERVICE_client_continue (client);
112}
113
114
115/**
116 * Check 'preference feedback' message is well-formed
117 *
118 * @param cls client that sent the request
119 * @param message the request message
120 * @return #GNUNET_OK if @a message is well-formed
121 */
122static int
123check_feedback (void *cls,
124 const struct FeedbackPreferenceMessage *message)
125{
126 uint16_t msize;
127 uint32_t nump;
128
129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
130 "Received PREFERENCE_FEEDBACK message\n");
131 msize = ntohs (message->header.size);
132 nump = ntohl (message->num_feedback);
133 if (msize !=
134 sizeof(struct FeedbackPreferenceMessage)
135 + nump * sizeof(struct PreferenceInformation))
136 {
137 GNUNET_break (0);
138 return GNUNET_SYSERR;
139 }
140 return GNUNET_OK;
141}
142
143
144/**
145 * Handle 'preference feedback' messages from clients.
146 *
147 * @param cls client that sent the request
148 * @param msg the request message
149 */
150static void
151handle_feedback (void *cls,
152 const struct FeedbackPreferenceMessage *msg)
153{
154 struct GNUNET_SERVICE_Client *client = cls;
155 const struct PreferenceInformation *pi;
156 uint32_t nump;
157
158 nump = ntohl (msg->num_feedback);
159 if (GNUNET_NO ==
160 GNUNET_CONTAINER_multipeermap_contains (GSA_addresses,
161 &msg->peer))
162 {
163 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
164 "Received PREFERENCE FEEDBACK for unknown peer `%s'\n",
165 GNUNET_i2s (&msg->peer));
166 GNUNET_SERVICE_client_continue (client);
167 return;
168 }
169
170 GNUNET_STATISTICS_update (GSA_stats,
171 "# preference feedbacks requests processed",
172 1,
173 GNUNET_NO);
174 pi = (const struct PreferenceInformation *) &msg[1];
175 for (uint32_t i = 0; i < nump; i++)
176 {
177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
178 "Received PREFERENCE FEEDBACK for peer `%s'\n",
179 GNUNET_i2s (&msg->peer));
180 GAS_plugin_notify_feedback (client,
181 &msg->peer,
182 GNUNET_TIME_relative_ntoh (msg->scope),
183 (enum GNUNET_ATS_PreferenceKind) ntohl (
184 pi[i].preference_kind),
185 pi[i].preference_value);
186 }
187 GNUNET_SERVICE_client_continue (client);
188}
189
190
191/**
192 * Handle 'request address list' messages from clients.
193 *
194 * @param cls client that sent the request
195 * @param message the request message
196 */
197static void
198handle_request_address_list (void *cls,
199 const struct AddressListRequestMessage *message)
200{
201 struct GNUNET_SERVICE_Client *client = cls;
202
203 GAS_handle_request_address_list (client,
204 message);
205 GNUNET_SERVICE_client_continue (client);
206}
207
208
209/**
210 * Handle 'request address' messages from clients.
211 *
212 * @param cls client that sent the request
213 * @param message the request message
214 */
215static void
216handle_request_address (void *cls,
217 const struct RequestAddressMessage *message)
218{
219 struct GNUNET_SERVICE_Client *client = cls;
220
221 GAS_handle_request_address (client,
222 message);
223 GNUNET_SERVICE_client_continue (client);
224}
225
226
227/**
228 * Cancel 'request address' messages from clients.
229 *
230 * @param cls client that sent the request
231 * @param message the request message
232 */
233static void
234handle_request_address_cancel (void *cls,
235 const struct RequestAddressMessage *message)
236{
237 struct GNUNET_SERVICE_Client *client = cls;
238
239 GAS_handle_request_address_cancel (client,
240 message);
241 GNUNET_SERVICE_client_continue (client);
242}
243
244
245/**
246 * Handle 'address add' messages from clients.
247 *
248 * @param cls client that sent the request
249 * @param m the request message
250 */
251static int
252check_address_add (void *cls,
253 const struct AddressAddMessage *m)
254{
255 const char *address;
256 const char *plugin_name;
257 uint16_t address_length;
258 uint16_t plugin_name_length;
259 uint16_t size;
260
261 size = ntohs (m->header.size);
262 address_length = ntohs (m->address_length);
263 plugin_name_length = ntohs (m->plugin_name_length);
264 address = (const char *) &m[1];
265 if (plugin_name_length != 0)
266 plugin_name = &address[address_length];
267 else
268 plugin_name = "";
269
270 if ((address_length + plugin_name_length
271 + sizeof(struct AddressAddMessage) != size) ||
272 ((plugin_name_length > 0) &&
273 (plugin_name[plugin_name_length - 1] != '\0')))
274 {
275 GNUNET_break (0);
276 return GNUNET_SYSERR;
277 }
278 return GNUNET_OK;
279}
280
281
282/**
283 * Handle 'address add' messages from clients.
284 *
285 * @param cls client that sent the request
286 * @param message the request message
287 */
288static void
289handle_address_add (void *cls,
290 const struct AddressAddMessage *message)
291{
292 struct GNUNET_SERVICE_Client *client = cls;
293
294 GAS_handle_address_add (message);
295 GNUNET_SERVICE_client_continue (client);
296}
297
298
299/**
300 * Handle 'address update' messages from clients.
301 *
302 * @param cls client that sent the request
303 * @param message the request message
304 */
305static void
306handle_address_update (void *cls,
307 const struct AddressUpdateMessage *message)
308{
309 struct GNUNET_SERVICE_Client *client = cls;
310
311 GAS_handle_address_update (message);
312 GNUNET_SERVICE_client_continue (client);
313}
314
315
316/**
317 * Handle 'address destroyed' messages from clients.
318 *
319 * @param cls client that sent the request
320 * @param message the request message
321 */
322static void
323handle_address_destroyed (void *cls,
324 const struct AddressDestroyedMessage *message)
325{
326 struct GNUNET_SERVICE_Client *client = cls;
327
328 GAS_handle_address_destroyed (message);
329 GNUNET_SERVICE_client_continue (client);
330}
331
332
333/**
334 * Check that 'change preference' message is well-formed.
335 *
336 * @param cls client that sent the request
337 * @param message the request message
338 * @return #GNUNET_OK if @a message is well-formed
339 */
340static int
341check_preference_change (void *cls,
342 const struct ChangePreferenceMessage *message)
343{
344 uint16_t msize;
345 uint32_t nump;
346
347 msize = ntohs (message->header.size);
348 nump = ntohl (message->num_preferences);
349 if ((msize !=
350 sizeof(struct ChangePreferenceMessage)
351 + nump * sizeof(struct PreferenceInformation)) ||
352 (UINT16_MAX / sizeof(struct PreferenceInformation) < nump))
353 {
354 GNUNET_break (0);
355 return GNUNET_SYSERR;
356 }
357 return GNUNET_OK;
358}
359
360
361/**
362 * Handle 'change preference' messages from clients.
363 *
364 * @param cls client that sent the request
365 * @param message the request message
366 */
367static void
368handle_preference_change (void *cls,
369 const struct ChangePreferenceMessage *message)
370{
371 struct GNUNET_SERVICE_Client *client = cls;
372
373 GAS_handle_preference_change (client,
374 message);
375 GNUNET_SERVICE_client_continue (client);
376}
377
378
379/**
380 * A client connected to us. Setup the local client
381 * record.
382 *
383 * @param cls unused
384 * @param client handle of the client
385 * @param mq message queue to talk to @a client
386 * @return @a client
387 */
388static void *
389client_connect_cb (void *cls,
390 struct GNUNET_SERVICE_Client *client,
391 struct GNUNET_MQ_Handle *mq)
392{
393 return client;
394}
395
396
397/**
398 * A client disconnected from us. Tear down the local client
399 * record.
400 *
401 * @param cls unused
402 * @param client handle of the client
403 * @param app_ctx
404 */
405static void
406client_disconnect_cb (void *cls,
407 struct GNUNET_SERVICE_Client *client,
408 void *app_ctx)
409{
410 if (NULL == client)
411 return;
412 GAS_scheduling_remove_client (client);
413 GAS_connectivity_remove_client (client);
414 GAS_preference_client_disconnect (client);
415}
416
417
418/**
419 * Task run during shutdown.
420 *
421 * @param cls unused
422 */
423static void
424cleanup_task (void *cls)
425{
426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
427 "ATS shutdown initiated\n");
428 GAS_connectivity_done ();
429 GAS_addresses_done ();
430 GAS_plugin_done ();
431 GAS_normalization_stop ();
432 GAS_performance_done ();
433 GAS_preference_done ();
434 GAS_reservations_done ();
435 if (NULL != GSA_stats)
436 {
437 GNUNET_STATISTICS_destroy (GSA_stats, GNUNET_NO);
438 GSA_stats = NULL;
439 }
440}
441
442
443/**
444 * Process template requests.
445 *
446 * @param cls closure
447 * @param cfg configuration to use
448 * @param service the initialized service
449 */
450static void
451run (void *cls,
452 const struct GNUNET_CONFIGURATION_Handle *cfg,
453 struct GNUNET_SERVICE_Handle *service)
454{
455 GSA_stats = GNUNET_STATISTICS_create ("ats",
456 cfg);
457 GAS_reservations_init ();
458 GAS_connectivity_init ();
459 GAS_preference_init ();
460 GAS_normalization_start ();
461 GAS_addresses_init ();
462 if (GNUNET_OK !=
463 GAS_plugin_init (cfg))
464 {
465 GNUNET_break (0);
466 GAS_addresses_done ();
467 GAS_normalization_stop ();
468 GAS_reservations_done ();
469 GAS_connectivity_done ();
470 GAS_preference_done ();
471 if (NULL != GSA_stats)
472 {
473 GNUNET_STATISTICS_destroy (GSA_stats,
474 GNUNET_NO);
475 GSA_stats = NULL;
476 }
477 return;
478 }
479 GAS_performance_init ();
480 GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
481 NULL);
482}
483
484
485/**
486 * Define "main" method using service macro.
487 */
488GNUNET_SERVICE_MAIN
489 ("ats",
490 GNUNET_SERVICE_OPTION_NONE,
491 &run,
492 &client_connect_cb,
493 &client_disconnect_cb,
494 NULL,
495 GNUNET_MQ_hd_fixed_size (ats_start,
496 GNUNET_MESSAGE_TYPE_ATS_START,
497 struct ClientStartMessage,
498 NULL),
499 GNUNET_MQ_hd_fixed_size (request_address,
500 GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS,
501 struct RequestAddressMessage,
502 NULL),
503 GNUNET_MQ_hd_fixed_size (request_address_cancel,
504 GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL,
505 struct RequestAddressMessage,
506 NULL),
507 GNUNET_MQ_hd_fixed_size (request_address_list,
508 GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST,
509 struct AddressListRequestMessage,
510 NULL),
511 GNUNET_MQ_hd_var_size (address_add,
512 GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD,
513 struct AddressAddMessage,
514 NULL),
515 GNUNET_MQ_hd_fixed_size (address_update,
516 GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE,
517 struct AddressUpdateMessage,
518 NULL),
519 GNUNET_MQ_hd_fixed_size (address_destroyed,
520 GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED,
521 struct AddressDestroyedMessage,
522 NULL),
523 GNUNET_MQ_hd_fixed_size (reservation_request,
524 GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST,
525 struct ReservationRequestMessage,
526 NULL),
527 GNUNET_MQ_hd_var_size (preference_change,
528 GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE,
529 struct ChangePreferenceMessage,
530 NULL),
531 GNUNET_MQ_hd_var_size (feedback,
532 GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_FEEDBACK,
533 struct FeedbackPreferenceMessage,
534 NULL),
535 GNUNET_MQ_handler_end ());
536
537
538/* end of gnunet-service-ats.c */
diff --git a/src/ats/gnunet-service-ats.h b/src/ats/gnunet-service-ats.h
deleted file mode 100644
index 85d522b9f..000000000
--- a/src/ats/gnunet-service-ats.h
+++ /dev/null
@@ -1,42 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats.h
23 * @brief ats service
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_ATS_H
28#define GNUNET_SERVICE_ATS_H
29
30#include "gnunet_statistics_service.h"
31
32#define GAS_normalization_queue_length 3
33
34#define BANDWIDTH_ZERO GNUNET_BANDWIDTH_value_init (0)
35
36/**
37 * Handle for statistics.
38 */
39extern struct GNUNET_STATISTICS_Handle *GSA_stats;
40
41
42#endif
diff --git a/src/ats/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c
deleted file mode 100644
index d02efd939..000000000
--- a/src/ats/gnunet-service-ats_addresses.c
+++ /dev/null
@@ -1,717 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_addresses.c
23 * @brief ats service address management
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet-service-ats_addresses.h"
29#include "gnunet-service-ats_performance.h"
30#include "gnunet-service-ats_normalization.h"
31#include "gnunet-service-ats_plugins.h"
32
33
34/**
35 * A multihashmap to store all addresses
36 */
37struct GNUNET_CONTAINER_MultiPeerMap *GSA_addresses;
38
39
40/**
41 * Update statistic on number of addresses.
42 */
43static void
44update_addresses_stat ()
45{
46 GNUNET_STATISTICS_set (GSA_stats,
47 "# addresses",
48 GNUNET_CONTAINER_multipeermap_size (GSA_addresses),
49 GNUNET_NO);
50}
51
52
53/**
54 * Free the given address
55 *
56 * @param addr address to destroy
57 */
58static void
59free_address (struct ATS_Address *addr)
60{
61 GNUNET_assert (GNUNET_YES ==
62 GNUNET_CONTAINER_multipeermap_remove (GSA_addresses,
63 &addr->peer,
64 addr));
65 update_addresses_stat ();
66 GAS_plugin_delete_address (addr);
67 GAS_performance_notify_all_clients (&addr->peer,
68 addr->plugin,
69 addr->addr,
70 addr->addr_len,
71 GNUNET_NO,
72 NULL,
73 addr->local_address_info,
74 GNUNET_BANDWIDTH_ZERO,
75 GNUNET_BANDWIDTH_ZERO);
76 GNUNET_free (addr->plugin);
77 GNUNET_free (addr);
78}
79
80
81/**
82 * Initialize @a norm. Sets all historic values to undefined.
83 *
84 * @param norm normalization data to initialize
85 */
86static void
87init_norm (struct GAS_NormalizationInfo *norm)
88{
89 unsigned int c;
90
91 for (c = 0; c < GAS_normalization_queue_length; c++)
92 norm->atsi_abs[c] = UINT64_MAX;
93}
94
95
96/**
97 * Create a ATS_address with the given information
98 *
99 * @param peer peer
100 * @param plugin_name plugin
101 * @param plugin_addr address
102 * @param plugin_addr_len address length
103 * @param local_address_info additional local info for the address
104 * @param session_id session identifier, can never be 0
105 * @return the ATS_Address
106 */
107static struct ATS_Address *
108create_address (const struct GNUNET_PeerIdentity *peer,
109 const char *plugin_name,
110 const void *plugin_addr,
111 size_t plugin_addr_len,
112 uint32_t local_address_info,
113 uint32_t session_id)
114{
115 struct ATS_Address *aa;
116
117 aa = GNUNET_malloc (sizeof(struct ATS_Address) + plugin_addr_len);
118 aa->peer = *peer;
119 aa->addr_len = plugin_addr_len;
120 aa->addr = &aa[1];
121 GNUNET_memcpy (&aa[1],
122 plugin_addr,
123 plugin_addr_len);
124 aa->plugin = GNUNET_strdup (plugin_name);
125 aa->session_id = session_id;
126 aa->local_address_info = local_address_info;
127 init_norm (&aa->norm_delay);
128 init_norm (&aa->norm_distance);
129 init_norm (&aa->norm_utilization_in);
130 init_norm (&aa->norm_utilization_out);
131 return aa;
132}
133
134
135/**
136 * Closure for #find_address_cb()
137 */
138struct FindAddressContext
139{
140 /**
141 * Session Id to look for.
142 */
143 uint32_t session_id;
144
145 /**
146 * Where to store matching address result.
147 */
148 struct ATS_Address *exact_address;
149};
150
151
152/**
153 * Find session matching given session ID.
154 *
155 * @param cls a `struct FindAddressContext`
156 * @param key peer id
157 * @param value the address to compare with
158 * @return #GNUNET_YES to continue, #GNUNET_NO if address is found
159 */
160static int
161find_address_cb (void *cls,
162 const struct GNUNET_PeerIdentity *key,
163 void *value)
164{
165 struct FindAddressContext *fac = cls;
166 struct ATS_Address *aa = value;
167
168 if (aa->session_id == fac->session_id)
169 {
170 fac->exact_address = aa;
171 return GNUNET_NO;
172 }
173 return GNUNET_YES;
174}
175
176
177/**
178 * Find the exact address
179 *
180 * @param peer peer
181 * @param session_id session id, can never be 0
182 * @return an ATS_address or NULL
183 */
184static struct ATS_Address *
185find_exact_address (const struct GNUNET_PeerIdentity *peer,
186 uint32_t session_id)
187{
188 struct FindAddressContext fac;
189
190 fac.exact_address = NULL;
191 fac.session_id = session_id;
192 GNUNET_CONTAINER_multipeermap_get_multiple (GSA_addresses,
193 peer,
194 &find_address_cb, &fac);
195 return fac.exact_address;
196}
197
198
199/**
200 * Add a new address for a peer.
201 *
202 * @param peer peer
203 * @param plugin_name transport plugin name
204 * @param plugin_addr plugin address
205 * @param plugin_addr_len length of the plugin address in @a plugin_addr
206 * @param local_address_info the local address for the address
207 * @param session_id session id, can be 0
208 * @param prop performance information for this address
209 */
210void
211GAS_addresses_add (const struct GNUNET_PeerIdentity *peer,
212 const char *plugin_name,
213 const void *plugin_addr,
214 size_t plugin_addr_len,
215 uint32_t local_address_info,
216 uint32_t session_id,
217 const struct GNUNET_ATS_Properties *prop)
218{
219 struct ATS_Address *new_address;
220
221 if (NULL != find_exact_address (peer,
222 session_id))
223 {
224 GNUNET_break (0);
225 return;
226 }
227 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
228 new_address = create_address (peer,
229 plugin_name,
230 plugin_addr,
231 plugin_addr_len,
232 local_address_info,
233 session_id);
234 /* Add a new address */
235 new_address->properties = *prop;
236 new_address->t_added = GNUNET_TIME_absolute_get ();
237 new_address->t_last_activity = GNUNET_TIME_absolute_get ();
238 GNUNET_assert (GNUNET_OK ==
239 GNUNET_CONTAINER_multipeermap_put (GSA_addresses,
240 peer,
241 new_address,
242 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
243 update_addresses_stat ();
244 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
245 "Adding new address for peer `%s' slot %u\n",
246 GNUNET_i2s (peer),
247 session_id);
248 /* Tell solver about new address */
249 GAS_plugin_solver_lock ();
250 GAS_plugin_new_address (new_address);
251 GAS_normalization_update_property (new_address); // FIXME: needed?
252 GAS_plugin_solver_unlock ();
253 /* Notify performance clients about new address */
254 GAS_performance_notify_all_clients (&new_address->peer,
255 new_address->plugin,
256 new_address->addr,
257 new_address->addr_len,
258 new_address->active,
259 &new_address->properties,
260 new_address->local_address_info,
261 GNUNET_BANDWIDTH_value_init (
262 new_address->assigned_bw_out),
263 GNUNET_BANDWIDTH_value_init (
264 new_address->assigned_bw_in));
265}
266
267
268/**
269 * Update an address with new performance information for a peer.
270 *
271 * @param peer peer
272 * @param session_id session id, never 0
273 * @param prop performance information for this address
274 */
275void
276GAS_addresses_update (const struct GNUNET_PeerIdentity *peer,
277 uint32_t session_id,
278 const struct GNUNET_ATS_Properties *prop)
279{
280 struct ATS_Address *aa;
281
282 /* Get existing address */
283 aa = find_exact_address (peer,
284 session_id);
285 if (NULL == aa)
286 {
287 GNUNET_break (0);
288 return;
289 }
290 if (NULL == aa->solver_information)
291 {
292 GNUNET_break (0);
293 return;
294 }
295 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
296 "Received ADDRESS_UPDATE for peer `%s' slot %u\n",
297 GNUNET_i2s (peer),
298 (unsigned int) session_id);
299 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
300 /* Update address */
301 aa->t_last_activity = GNUNET_TIME_absolute_get ();
302 aa->properties = *prop;
303 /* Notify performance clients about updated address */
304 GAS_performance_notify_all_clients (&aa->peer,
305 aa->plugin,
306 aa->addr,
307 aa->addr_len,
308 aa->active,
309 prop,
310 aa->local_address_info,
311 GNUNET_BANDWIDTH_value_init (
312 aa->assigned_bw_out),
313 GNUNET_BANDWIDTH_value_init (
314 aa->assigned_bw_in));
315
316 GAS_normalization_update_property (aa);
317}
318
319
320/**
321 * Remove an address for a peer.
322 *
323 * @param peer peer
324 * @param session_id session id, can never be 0
325 */
326void
327GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer,
328 uint32_t session_id)
329{
330 struct ATS_Address *ea;
331
332 /* Get existing address */
333 ea = find_exact_address (peer,
334 session_id);
335 if (NULL == ea)
336 {
337 GNUNET_break (0);
338 return;
339 }
340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
341 "Received ADDRESS_DESTROYED for peer `%s' session %u\n",
342 GNUNET_i2s (peer),
343 session_id);
344 free_address (ea);
345}
346
347
348/**
349 * Initialize address subsystem. The addresses subsystem manages the addresses
350 * known and current performance information. It has a solver component
351 * responsible for the resource allocation. It tells the solver about changes
352 * and receives updates when the solver changes the resource allocation.
353 */
354void
355GAS_addresses_init ()
356{
357 GSA_addresses
358 = GNUNET_CONTAINER_multipeermap_create (128,
359 GNUNET_NO);
360 update_addresses_stat ();
361}
362
363
364/**
365 * Destroy all addresses iterator
366 *
367 * @param cls NULL
368 * @param key peer identity (unused)
369 * @param value the 'struct ATS_Address' to free
370 * @return #GNUNET_OK (continue to iterate)
371 */
372static int
373destroy_all_address_it (void *cls,
374 const struct GNUNET_PeerIdentity *key,
375 void *value)
376{
377 struct ATS_Address *aa = value;
378
379 free_address (aa);
380 return GNUNET_OK;
381}
382
383
384/**
385 * Remove all addresses
386 */
387void
388GAS_addresses_destroy_all ()
389{
390 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
391 "Destroying all addresses\n");
392 if (NULL == GSA_addresses)
393 return;
394 if (0 ==
395 GNUNET_CONTAINER_multipeermap_size (GSA_addresses))
396 return;
397 GAS_plugin_solver_lock ();
398 GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
399 &destroy_all_address_it,
400 NULL);
401 GAS_plugin_solver_unlock ();
402}
403
404
405/**
406 * Shutdown address subsystem.
407 */
408void
409GAS_addresses_done ()
410{
411 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
412 "Shutting down addresses\n");
413 GAS_plugin_solver_lock ();
414 GAS_addresses_destroy_all ();
415 GAS_plugin_solver_unlock ();
416 GNUNET_CONTAINER_multipeermap_destroy (GSA_addresses);
417 GSA_addresses = NULL;
418}
419
420
421/**
422 * Closure for #peerinfo_it().
423 */
424struct PeerInfoIteratorContext
425{
426 /**
427 * Function to call for each address.
428 */
429 GNUNET_ATS_PeerInfo_Iterator it;
430
431 /**
432 * Closure for @e it.
433 */
434 void *it_cls;
435};
436
437
438/**
439 * Iterator to iterate over a peer's addresses
440 *
441 * @param cls a `struct PeerInfoIteratorContext`
442 * @param key the peer id
443 * @param value the `struct ATS_address`
444 * @return #GNUNET_OK to continue
445 */
446static int
447peerinfo_it (void *cls,
448 const struct GNUNET_PeerIdentity *key,
449 void *value)
450{
451 struct PeerInfoIteratorContext *pi_ctx = cls;
452 struct ATS_Address *addr = value;
453
454 pi_ctx->it (pi_ctx->it_cls,
455 &addr->peer,
456 addr->plugin,
457 addr->addr,
458 addr->addr_len,
459 addr->active,
460 &addr->properties,
461 addr->local_address_info,
462 GNUNET_BANDWIDTH_value_init (addr->assigned_bw_out),
463 GNUNET_BANDWIDTH_value_init (addr->assigned_bw_in));
464 return GNUNET_OK;
465}
466
467
468/**
469 * Return information all peers currently known to ATS
470 *
471 * @param peer the respective peer, NULL for 'all' peers
472 * @param pi_it the iterator to call for every peer
473 * @param pi_it_cls the closure for @a pi_it
474 */
475void
476GAS_addresses_get_peer_info (const struct GNUNET_PeerIdentity *peer,
477 GNUNET_ATS_PeerInfo_Iterator pi_it,
478 void *pi_it_cls)
479{
480 struct PeerInfoIteratorContext pi_ctx;
481
482 if (NULL == pi_it)
483 {
484 /* does not make sense without callback */
485 GNUNET_break (0);
486 return;
487 }
488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
489 "Returning information for %s from a total of %u known addresses\n",
490 (NULL == peer)
491 ? "all peers"
492 : GNUNET_i2s (peer),
493 (unsigned int) GNUNET_CONTAINER_multipeermap_size (
494 GSA_addresses));
495 pi_ctx.it = pi_it;
496 pi_ctx.it_cls = pi_it_cls;
497 if (NULL == peer)
498 GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
499 &peerinfo_it,
500 &pi_ctx);
501 else
502 GNUNET_CONTAINER_multipeermap_get_multiple (GSA_addresses,
503 peer,
504 &peerinfo_it, &pi_ctx);
505 pi_it (pi_it_cls,
506 NULL, NULL, NULL, 0,
507 GNUNET_NO,
508 NULL,
509 GNUNET_HELLO_ADDRESS_INFO_NONE,
510 GNUNET_BANDWIDTH_ZERO,
511 GNUNET_BANDWIDTH_ZERO);
512}
513
514
515/**
516 * Information we need for the callbacks to return a list of addresses
517 * back to the client.
518 */
519struct AddressIteration
520{
521 /**
522 * Actual handle to the client.
523 */
524 struct GNUNET_SERVICE_Client *client;
525
526 /**
527 * Are we sending all addresses, or only those that are active?
528 */
529 int all;
530
531 /**
532 * Which ID should be included in the response?
533 */
534 uint32_t id;
535};
536
537
538/**
539 * Send a #GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE with the
540 * given address details to the client identified in @a ai.
541 *
542 * @param ai our address information context (identifies the client)
543 * @param id the peer id this address is for
544 * @param plugin_name name of the plugin that supports this address
545 * @param plugin_addr address
546 * @param plugin_addr_len length of @a plugin_addr
547 * @param active #GNUNET_YES if this address is actively used
548 * @param prop performance information
549 * @param local_address_info flags for the address
550 * @param bandwidth_out current outbound bandwidth assigned to address
551 * @param bandwidth_in current inbound bandwidth assigned to address
552 */
553static void
554transmit_req_addr (struct AddressIteration *ai,
555 const struct GNUNET_PeerIdentity *id,
556 const char *plugin_name,
557 const void *plugin_addr,
558 size_t plugin_addr_len,
559 int active,
560 const struct GNUNET_ATS_Properties *prop,
561 enum GNUNET_HELLO_AddressInfo local_address_info,
562 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
563 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
564
565{
566 struct GNUNET_MQ_Envelope *env;
567 struct PeerInformationMessage *msg;
568 char *addrp;
569 size_t plugin_name_length;
570 size_t msize;
571
572 if (NULL != plugin_name)
573 plugin_name_length = strlen (plugin_name) + 1;
574 else
575 plugin_name_length = 0;
576 msize = plugin_addr_len + plugin_name_length;
577
578 GNUNET_assert (sizeof(struct PeerInformationMessage) + msize
579 < GNUNET_MAX_MESSAGE_SIZE);
580 env = GNUNET_MQ_msg_extra (msg,
581 msize,
582 GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE);
583 msg->id = htonl (ai->id);
584 if (NULL != id)
585 msg->peer = *id;
586 msg->address_length = htons (plugin_addr_len);
587 msg->address_active = ntohl (active);
588 msg->plugin_name_length = htons (plugin_name_length);
589 msg->bandwidth_out = bandwidth_out;
590 msg->bandwidth_in = bandwidth_in;
591 if (NULL != prop)
592 GNUNET_ATS_properties_hton (&msg->properties,
593 prop);
594 msg->address_local_info = htonl ((uint32_t) local_address_info);
595 addrp = (char *) &msg[1];
596 GNUNET_memcpy (addrp,
597 plugin_addr,
598 plugin_addr_len);
599 if (NULL != plugin_name)
600 strcpy (&addrp[plugin_addr_len],
601 plugin_name);
602 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (ai->client),
603 env);
604}
605
606
607/**
608 * Iterator for #GAS_addresses_get_peer_info(), called with peer-specific
609 * information to be passed back to the client.
610 *
611 * @param cls closure with our `struct AddressIteration *`
612 * @param id the peer id
613 * @param plugin_name plugin name
614 * @param plugin_addr address
615 * @param plugin_addr_len length of @a plugin_addr
616 * @param active is address actively used
617 * @param prop performance information
618 * @param local_address_info additional local info for the address
619 * @param bandwidth_out current outbound bandwidth assigned to address
620 * @param bandwidth_in current inbound bandwidth assigned to address
621 */
622static void
623req_addr_peerinfo_it (void *cls,
624 const struct GNUNET_PeerIdentity *id,
625 const char *plugin_name,
626 const void *plugin_addr,
627 size_t plugin_addr_len,
628 int active,
629 const struct GNUNET_ATS_Properties *prop,
630 enum GNUNET_HELLO_AddressInfo local_address_info,
631 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
632 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
633{
634 struct AddressIteration *ai = cls;
635
636 if ((NULL == id) &&
637 (NULL == plugin_name) &&
638 (NULL == plugin_addr))
639 {
640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
641 "Address iteration done for one peer\n");
642 return;
643 }
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
645 "Callback for %s peer `%s' plugin `%s' BW out %u, BW in %u\n",
646 (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE",
647 GNUNET_i2s (id),
648 plugin_name,
649 (unsigned int) ntohl (bandwidth_out.value__),
650 (unsigned int) ntohl (bandwidth_in.value__));
651 /* Transmit result (either if address is active, or if
652 client wanted all addresses) */
653 if ((GNUNET_YES != ai->all) &&
654 (GNUNET_YES != active))
655 return;
656 transmit_req_addr (ai,
657 id,
658 plugin_name,
659 plugin_addr, plugin_addr_len,
660 active,
661 prop,
662 local_address_info,
663 bandwidth_out,
664 bandwidth_in);
665}
666
667
668/**
669 * Handle 'address list request' messages from clients.
670 *
671 * @param cls client that sent the request
672 * @param alrm the request message
673 */
674void
675GAS_handle_request_address_list (struct GNUNET_SERVICE_Client *client,
676 const struct AddressListRequestMessage *alrm)
677{
678 struct AddressIteration ai;
679 struct GNUNET_PeerIdentity allzeros;
680
681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
682 "Received ADDRESSLIST_REQUEST message\n");
683 ai.all = ntohl (alrm->all);
684 ai.id = ntohl (alrm->id);
685 ai.client = client;
686
687 memset (&allzeros,
688 '\0',
689 sizeof(struct GNUNET_PeerIdentity));
690 if (GNUNET_YES == GNUNET_is_zero (&alrm->peer))
691 {
692 /* Return addresses for all peers */
693 GAS_addresses_get_peer_info (NULL,
694 &req_addr_peerinfo_it,
695 &ai);
696 }
697 else
698 {
699 /* Return addresses for a specific peer */
700 GAS_addresses_get_peer_info (&alrm->peer,
701 &req_addr_peerinfo_it,
702 &ai);
703 }
704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
705 "Finished handling `%s' message\n",
706 "ADDRESSLIST_REQUEST");
707 transmit_req_addr (&ai,
708 NULL, NULL, NULL,
709 0, GNUNET_NO,
710 NULL,
711 GNUNET_HELLO_ADDRESS_INFO_NONE,
712 GNUNET_BANDWIDTH_ZERO,
713 GNUNET_BANDWIDTH_ZERO);
714}
715
716
717/* end of gnunet-service-ats_addresses.c */
diff --git a/src/ats/gnunet-service-ats_addresses.h b/src/ats/gnunet-service-ats_addresses.h
deleted file mode 100644
index b39484f59..000000000
--- a/src/ats/gnunet-service-ats_addresses.h
+++ /dev/null
@@ -1,490 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2014 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_addresses.h
23 * @brief ats service address management
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_ATS_ADDRESSES_H
28#define GNUNET_SERVICE_ATS_ADDRESSES_H
29
30#include "gnunet_util_lib.h"
31#include "gnunet_ats_service.h"
32#include "gnunet-service-ats.h"
33#include "ats.h"
34
35/**
36 * NOTE: Do not change this documentation. This documentation is based on
37 * gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex
38 * use build_txt.sh to generate plaintext output
39 *
40 * 1 ATS addresses : ATS address management
41 *
42 * This ATS addresses ("addresses") component manages the addresses known to
43 * ATS service and suggests addresses to transport service when it is
44 * interested in address suggestion for a peer. ATS addresses also
45 * instantiates the bandwidth assignment mechanism (solver), notifies it
46 * about changes to addresses and forwards changes to bandwidth assignments
47 * to transport, depending if transport is interested in this change.
48 *
49 * 1.1 Input data
50 *
51 * 1.1.1 Addresses
52 *
53 * Addresses are added by specifying peer ID, plugin, address, address length
54 * and session, if available. ATS information can be specified if available.
55 *
56 * 1.1.2 Networks
57 *
58 * ATS specifies a fix set of networks an address can belong to. For each
59 * network an inbound and outbound quota will be specified. The available
60 * networks and additional helper variables are defined in
61 * gnunet_ats_service.h. At the moment 5 networks are defined:
62 * * GNUNET_NT_UNSPECIFIED
63 * * GNUNET_NT_LOOPBACK
64 * * GNUNET_NT_LAN
65 * * GNUNET_NT_WAN
66 * * GNUNET_NT_WLAN
67 *
68 * The total number of networks defined is stored in
69 * GNUNET_NT_COUNT GNUNET_ATS_NetworkType can be used array
70 * initializer for an int array, while GNUNET_ATS_NetworkType is an
71 * initializer for a char array containing a string description of all
72 * networks
73 *
74 * 1.1.3 Quotas
75 *
76 * An inbound and outbound quota for each of the networks mentioned in 1.1.2
77 * is loaded from ats configuration during initialization. This quota defines
78 * to total amount of inbound and outbound traffic allowed for a specific
79 * network. The configuration values used are in section ats:
80 * * "NETWORK"_QUOTA_IN = <value>
81 * * "NETWORK"_QUOTA_IN = <value>
82 *
83 * You can specify quotas by setting the <value> to a:
84 * * unrestricted: unlimited
85 * * number of bytes: e.g. 10240
86 * * fancy value: e.g. 64 Kib
87 *
88 * unlimited is defined as GNUNET_ATS_MaxBandwidthString and equivalent to
89 * the value GNUNET_ATS_MaxBandwidth Important predefined values for quotas
90 * are:
91 * * GNUNET_ATS_DefaultBandwidth: 65536
92 * * GNUNET_ATS_MaxBandwidth: UINT32_MAX
93 * * GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT: 1024
94 *
95 * Details of loading quotas and default values will be described on
96 *
97 * 1.1.4 Preference values
98 *
99 * 1.2 Data structures used
100 *
101 * Addresse uses struct ATS_Address for each address. The structs are stored
102 * in a linked list and provides a pointer void *solver_information for the
103 * solver to store address specific information. It provides the int values
104 * active which is set to GNUNET_YES if the address is select for transport
105 * use and used, representing that transport service is actively using this
106 * address. Address information are stored in peer, addr, addr_len, plugin.
107 *
108 * 1.3 Initialization
109 *
110 * During initialization a hashmap to store addresses is created. The quotas
111 * for all networks defined for ATS are loaded from configuration. For each
112 * network first the logic will check if the string
113 * GNUNET_ATS_MaxBandwidthString is configured, if not it will try to convert
114 * the configured value as a fancy size and if this fails it will try to use
115 * it as a value_number. If no configuration value is found it will assign
116 * GNUNET_ATS_DefaultBandwidth. The most important step is to load the
117 * configured solver using configuration "[ats]:MODE". Current solvers are
118 * MODE_PROPORTIONAL, MODE_MLP. Interaction is done using a solver API
119 *
120 * 1.4 Solver API
121 *
122 * Solver functions:
123 * * s_init: init the solver with required information
124 * * s_add: add a new address
125 * * s_update: update ATS values or session for an address
126 * * s_get: get preferred address for a peer
127 * * s_del: delete an address
128 * * s_pref: change preference value for a peer
129 * * s_done: shutdown solver
130 *
131 * Callbacks: addresses provides a bandwidth_changed_cb callback to the
132 * solver which is called when bandwidth assigned to peer has changed
133 *
134 * 1.5 Shutdown
135 *
136 * During shutdown all addresses are freed and the solver told to shutdown
137 *
138 * 1.6 Addresses and sessions
139 *
140 * Addresses consist of the address itself and a numerical session. When a
141 * new address without a session is added it has no session, so it gets
142 * session 0 assigned. When an address with a session is added and an address
143 * object with session 0 is found, this object is updated with the session
144 * otherwise a new address object with this session assigned is created.
145 *
146 * 1.6.1 Terminology
147 *
148 * Addresses a1,a2 with session s1, s2 are "exact" if:
149 * (a1 == a2)&&(s1 == s2)
150 * Addresses a1,a2 with session s1, s2 are "equivalent" if:
151 * (a1 == a2)&&((s1 == s2)||(s1 == 0)||(s2 == 0)
152 *
153 * 1.7 Address management
154 *
155 * Transport service notifies ATS about changes to the addresses known to
156 * it.
157 *
158 * 1.7.1 Adding an address
159 *
160 * When transport learns a new address it tells ATS and ATS is telling
161 * addresses about it using GAS_address_add. If not known to addresses it
162 * creates a new address object and calls solver's s_add. ATS information are
163 * deserialized and solver is notified about the session and ATS information
164 * using s_update.
165 *
166 * 1.7.2 Updating an address
167 *
168 * Addresses does an lookup up for the existing address with the given
169 * session. If disassembles included ATS information and notifies the solver
170 * using s_update about the update.
171 *
172 * 1.7.3 Deleting an address
173 *
174 * Addresses does an lookup for the exact address and session and if removes
175 * this address. If session != 0 the session is set to 0 and the address is
176 * kept. If session == 0, the addresses is removed.
177 *
178 * 1.7.4 Requesting an address suggestion
179 *
180 * The address client issues a request address message to be notified about
181 * address suggestions for a specific peer. Addresses asks the solver with
182 * s_get. If no address is available, it will not send a response, otherwise
183 * it will respond with the chosen address.
184 *
185 * 1.7.5 Address suggestions
186 *
187 * Addresses will notify the client automatically on any bandwidth_changed_cb
188 * by the solver if a address suggestion request is pending. If no address is
189 * available it will not respond at all If the client is not interested
190 * anymore, it has to cancel the address suggestion request.
191 *
192 * 1.7.6 Suggestions blocks and reset
193 *
194 * After suggesting an address it is blocked for ATS_BLOCKING_DELTA sec. to
195 * prevent the client from being thrashed. If the client requires immediately
196 * it can reset this block using GAS_addresses_handle_backoff_reset.
197 *
198 * 1.7.7 Address lifecycle
199 *
200 * * (add address)
201 * * (updated address)
202 * * (delete address)
203 *
204 * 1.8 Bandwidth assignment
205 *
206 * The addresses are used to perform resource allocation operations. ATS
207 * addresses takes care of instantiating the solver configured and notifies
208 * the respective solver about address changes and receives changes to the
209 * bandwidth assignment from the solver. The current bandwidth assignment is
210 * sent to transport. The specific solvers will be described in the specific
211 * section.
212 *
213 * 1.9 Changing peer preferences
214 *
215 * The bandwidth assigned to a peer can be influenced by setting a preference
216 * for a peer. The preference will be given to to the solver with s_pref which
217 * has to take care of the preference value
218 */
219
220
221/*
222 * How long will address suggestions blocked after a suggestion
223 */
224#define ATS_BLOCKING_DELTA GNUNET_TIME_relative_multiply ( \
225 GNUNET_TIME_UNIT_MILLISECONDS, 100)
226
227/**
228 * Information provided by ATS normalization
229 */
230struct GAS_NormalizationInfo
231{
232 /**
233 * Next index to use in averaging queue
234 */
235 unsigned int avg_queue_index;
236
237 /**
238 * Averaging queue
239 */
240 uint64_t atsi_abs[GAS_normalization_queue_length];
241
242 /**
243 * Averaged ATSI values from queue
244 */
245 uint64_t avg;
246
247 /**
248 * Normalized values from queue to a range of values [1.0...2.0]
249 */
250 double norm;
251};
252
253
254/**
255 * Address with additional information
256 */
257struct ATS_Address
258{
259 /**
260 * Peer ID this address is for.
261 */
262 struct GNUNET_PeerIdentity peer;
263
264 /**
265 * Address (in plugin-specific binary format).
266 */
267 const void *addr;
268
269 /**
270 * Plugin name
271 */
272 char *plugin;
273
274 /**
275 * Solver-specific information for this address
276 */
277 void *solver_information;
278
279 /**
280 * ATS performance information for this address
281 */
282 struct GNUNET_ATS_Properties properties;
283
284 /**
285 * Time when address had last activity (update, in uses)
286 */
287 struct GNUNET_TIME_Absolute t_last_activity;
288
289 /**
290 * Time when address was added
291 */
292 struct GNUNET_TIME_Absolute t_added;
293
294 /**
295 * Address length, number of bytes in @e addr.
296 */
297 size_t addr_len;
298
299 /**
300 * Session ID, can never be 0.
301 */
302 uint32_t session_id;
303
304 /**
305 * Field to store local flags.
306 */
307 enum GNUNET_HELLO_AddressInfo local_address_info;
308
309 /**
310 * ATS performance information for this address, size of the @e atsi array.
311 */
312 uint32_t atsi_count;
313
314 /**
315 * Inbound bandwidth assigned by solver
316 */
317 uint32_t assigned_bw_in;
318
319 /**
320 * Outbound bandwidth assigned by solver
321 */
322 uint32_t assigned_bw_out;
323
324 /**
325 * Inbound bandwidth assigned by solver in NBO
326 */
327 uint32_t last_notified_bw_in;
328
329 /**
330 * Outbound bandwidth assigned by solver in NBO
331 */
332 uint32_t last_notified_bw_out;
333
334 /**
335 * Is this the active address for this peer?
336 */
337 int active;
338
339 /**
340 * Normalized delay information for this address.
341 */
342 struct GAS_NormalizationInfo norm_delay;
343
344 /**
345 * Normalized distance information for this address.
346 */
347 struct GAS_NormalizationInfo norm_distance;
348
349 /**
350 * Normalized utilization inbound for this address.
351 */
352 struct GAS_NormalizationInfo norm_utilization_in;
353
354 /**
355 * Normalized utilization outbound for this address.
356 */
357 struct GAS_NormalizationInfo norm_utilization_out;
358};
359
360
361/**
362 * A multipeermap mapping peer identities to `struct ATS_Address`.
363 */
364extern struct GNUNET_CONTAINER_MultiPeerMap *GSA_addresses;
365
366
367/**
368 * Initialize address subsystem. The addresses subsystem manages the addresses
369 * known and current performance information.
370 */
371void
372GAS_addresses_init (void);
373
374
375/**
376 * Shutdown address subsystem.
377 */
378void
379GAS_addresses_done (void);
380
381
382/**
383 * Add a new address for a peer.
384 *
385 * @param peer peer
386 * @param plugin_name transport plugin name
387 * @param plugin_addr plugin address
388 * @param plugin_addr_len length of the @a plugin_addr
389 * @param local_address_info the local address for the address
390 * @param session_id session id, can never be 0.
391 * @param prop performance information for this address
392 */
393void
394GAS_addresses_add (const struct GNUNET_PeerIdentity *peer,
395 const char *plugin_name,
396 const void *plugin_addr,
397 size_t plugin_addr_len,
398 uint32_t local_address_info,
399 uint32_t session_id,
400 const struct GNUNET_ATS_Properties *prop);
401
402
403/**
404 * Update an address with new performance information for a peer.
405 *
406 * @param peer peer
407 * @param session_id session id, can never be 0
408 * @param prop performance information for this address
409 */
410void
411GAS_addresses_update (const struct GNUNET_PeerIdentity *peer,
412 uint32_t session_id,
413 const struct GNUNET_ATS_Properties *prop);
414
415
416/**
417 * Remove an address for a peer.
418 *
419 * @param peer peer
420 * @param session_id session id, can never be 0
421 */
422void
423GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer,
424 uint32_t session_id);
425
426
427/**
428 * Remove all addresses.
429 */
430void
431GAS_addresses_destroy_all (void);
432
433
434/**
435 * Iterator for #GAS_addresses_get_peer_info()
436 *
437 * @param cls closure
438 * @param id the peer id
439 * @param plugin_name plugin name
440 * @param plugin_addr address
441 * @param plugin_addr_len length of @a plugin_addr
442 * @param address_active is address actively used
443 * @param atsi ats performance information
444 * @param local_address_info flags for the address
445 * @param bandwidth_out current outbound bandwidth assigned to address
446 * @param bandwidth_in current inbound bandwidth assigned to address
447 */
448typedef void
449(*GNUNET_ATS_PeerInfo_Iterator) (void *cls,
450 const struct GNUNET_PeerIdentity *id,
451 const char *plugin_name,
452 const void *plugin_addr,
453 size_t plugin_addr_len,
454 const int address_active,
455 const struct GNUNET_ATS_Properties *prop,
456 enum GNUNET_HELLO_AddressInfo
457 local_address_info,
458 struct GNUNET_BANDWIDTH_Value32NBO
459 bandwidth_out,
460 struct GNUNET_BANDWIDTH_Value32NBO
461 bandwidth_in);
462
463
464/**
465 * Return information all peers currently known to ATS
466 *
467 * @param peer the respective peer
468 * @param pi_it the iterator to call for every peer
469 * @param pi_it_cls the closure for @a pi_it
470 */
471void
472GAS_addresses_get_peer_info (const struct GNUNET_PeerIdentity *peer,
473 GNUNET_ATS_PeerInfo_Iterator pi_it,
474 void *pi_it_cls);
475
476
477/**
478 * Handle 'address list request' messages from clients.
479 *
480 * @param client client that sent the request
481 * @param alrm the request message
482 */
483void
484GAS_handle_request_address_list (struct GNUNET_SERVICE_Client *client,
485 const struct AddressListRequestMessage *alrm);
486
487
488#endif
489
490/* end of gnunet-service-ats_addresses.h */
diff --git a/src/ats/gnunet-service-ats_connectivity.c b/src/ats/gnunet-service-ats_connectivity.c
deleted file mode 100644
index 5ee9b60f5..000000000
--- a/src/ats/gnunet-service-ats_connectivity.c
+++ /dev/null
@@ -1,222 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_connectivity.c
23 * @brief ats service, interaction with 'connecivity' API
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet-service-ats.h"
29#include "gnunet-service-ats_addresses.h"
30#include "gnunet-service-ats_connectivity.h"
31#include "gnunet-service-ats_plugins.h"
32#include "ats.h"
33
34
35/**
36 * Active connection requests.
37 */
38struct ConnectionRequest
39{
40 /**
41 * Client that made the request.
42 */
43 struct GNUNET_SERVICE_Client *client;
44
45 /* TODO: allow client to express a 'strength' for this request */
46};
47
48
49/**
50 * Address suggestion requests by peer.
51 */
52static struct GNUNET_CONTAINER_MultiPeerMap *connection_requests;
53
54
55/**
56 * Is the given peer in the list of peers for which we
57 * have an address request?
58 *
59 * @param cls unused, NULL
60 * @param peer peer to query for
61 * @return #GNUNET_YES if so, #GNUNET_NO if not
62 */
63unsigned int
64GAS_connectivity_has_peer (void *cls,
65 const struct GNUNET_PeerIdentity *peer)
66{
67 if (NULL == connection_requests)
68 return 0;
69 /* TODO: return sum of 'strength's of connectivity requests */
70 return GNUNET_CONTAINER_multipeermap_contains (connection_requests,
71 peer);
72}
73
74
75/**
76 * Handle #GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS messages from clients.
77 *
78 * @param client client that sent the request
79 * @param message the request message
80 */
81void
82GAS_handle_request_address (struct GNUNET_SERVICE_Client *client,
83 const struct RequestAddressMessage *msg)
84{
85 struct ConnectionRequest *cr;
86
87 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
88 "Received `%s' message\n",
89 "GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS");
90 /* FIXME: should not ignore "msg->strength" */
91 cr = GNUNET_new (struct ConnectionRequest);
92 cr->client = client;
93 (void) GNUNET_CONTAINER_multipeermap_put (connection_requests,
94 &msg->peer,
95 cr,
96 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
97 GAS_plugin_request_connect_start (&msg->peer);
98}
99
100
101/**
102 * Free the connection request from the map if the
103 * closure matches the client.
104 *
105 * @param cls the client to match
106 * @param pid peer for which the request was made
107 * @param value the `struct ConnectionRequest`
108 * @return #GNUNET_OK (continue to iterate)
109 */
110static int
111free_matching_requests (void *cls,
112 const struct GNUNET_PeerIdentity *pid,
113 void *value)
114{
115 struct GNUNET_SERVICE_Client *client = cls;
116 struct ConnectionRequest *cr = value;
117
118 if (cr->client == client)
119 {
120 GAS_plugin_request_connect_stop (pid);
121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
122 "Removed request pending for peer `%s\n",
123 GNUNET_i2s (pid));
124 GNUNET_assert (GNUNET_YES ==
125 GNUNET_CONTAINER_multipeermap_remove (connection_requests,
126 pid,
127 cr));
128 GNUNET_free (cr);
129 }
130 return GNUNET_OK;
131}
132
133
134/**
135 * Handle #GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL messages
136 * from clients.
137 *
138 * @param client the client that sent the request
139 * @param msg the request message
140 */
141void
142GAS_handle_request_address_cancel (struct GNUNET_SERVICE_Client *client,
143 const struct RequestAddressMessage *msg)
144{
145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
146 "Received GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL message for peer %s\n",
147 GNUNET_i2s (&msg->peer));
148 GNUNET_break (0 == ntohl (msg->strength));
149 GNUNET_CONTAINER_multipeermap_get_multiple (connection_requests,
150 &msg->peer,
151 &free_matching_requests,
152 client);
153}
154
155
156/**
157 * Unregister a client (which may have been a connectivity client,
158 * but this is not assured).
159 *
160 * @param client handle of the (now dead) client
161 */
162void
163GAS_connectivity_remove_client (struct GNUNET_SERVICE_Client *client)
164{
165 if (NULL != connection_requests)
166 GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
167 &free_matching_requests,
168 client);
169}
170
171
172/**
173 * Shutdown connectivity subsystem.
174 */
175void
176GAS_connectivity_init ()
177{
178 connection_requests
179 = GNUNET_CONTAINER_multipeermap_create (32,
180 GNUNET_NO);
181}
182
183
184/**
185 * Free the connection request from the map.
186 *
187 * @param cls NULL
188 * @param pid peer for which the request was made
189 * @param value the `struct ConnectionRequest`
190 * @return #GNUNET_OK (continue to iterate)
191 */
192static int
193free_request (void *cls,
194 const struct GNUNET_PeerIdentity *pid,
195 void *value)
196{
197 struct ConnectionRequest *cr = value;
198
199 free_matching_requests (cr->client,
200 pid,
201 cr);
202 return GNUNET_OK;
203}
204
205
206/**
207 * Shutdown connectivity subsystem.
208 */
209void
210GAS_connectivity_done ()
211{
212 GAS_plugin_solver_lock ();
213 GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
214 &free_request,
215 NULL);
216 GAS_plugin_solver_unlock ();
217 GNUNET_CONTAINER_multipeermap_destroy (connection_requests);
218 connection_requests = NULL;
219}
220
221
222/* end of gnunet-service-ats_connectivity.c */
diff --git a/src/ats/gnunet-service-ats_connectivity.h b/src/ats/gnunet-service-ats_connectivity.h
deleted file mode 100644
index 39453dfc8..000000000
--- a/src/ats/gnunet-service-ats_connectivity.h
+++ /dev/null
@@ -1,92 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/gnunet-service-ats_connectivity.h
22 * @brief ats service, interaction with 'connecivity' API
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_ATS_CONNECTIVITY_H
27#define GNUNET_SERVICE_ATS_CONNECTIVITY_H
28
29#include "ats.h"
30
31
32/**
33 * Is the given peer in the list of peers for which we
34 * have an address request?
35 *
36 * @param cls unused, NULL
37 * @param peer peer to query for
38 * @return #GNUNET_YES if so, #GNUNET_NO if not
39 */
40unsigned int
41GAS_connectivity_has_peer (void *cls,
42 const struct GNUNET_PeerIdentity *peer);
43
44
45/**
46 * Handle 'request address' messages from clients.
47 *
48 * @param client client that sent the request
49 * @param msg the request message
50 */
51void
52GAS_handle_request_address (struct GNUNET_SERVICE_Client *client,
53 const struct RequestAddressMessage *msg);
54
55
56/**
57 * Cancel 'request address' messages from clients.
58 *
59 * @param client client that sent the request
60 * @param msg the request message
61 */
62void
63GAS_handle_request_address_cancel (struct GNUNET_SERVICE_Client *client,
64 const struct RequestAddressMessage *msg);
65
66
67/**
68 * Unregister a client (which may have been a connectivity client,
69 * but this is not assured).
70 *
71 * @param client handle of the (now dead) client
72 */
73void
74GAS_connectivity_remove_client (struct GNUNET_SERVICE_Client *client);
75
76
77/**
78 * Initialize connectivity subsystem.
79 */
80void
81GAS_connectivity_init (void);
82
83
84/**
85 * Shutdown connectivity subsystem.
86 */
87void
88GAS_connectivity_done (void);
89
90
91#endif
92/* end of gnunet-service-ats_connectivity.h */
diff --git a/src/ats/gnunet-service-ats_normalization.c b/src/ats/gnunet-service-ats_normalization.c
deleted file mode 100644
index 36584e944..000000000
--- a/src/ats/gnunet-service-ats_normalization.c
+++ /dev/null
@@ -1,299 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_normalization.c
23 * @brief ats service address: management of ATS properties and preferences normalization
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include <float.h>
29#include "gnunet_ats_service.h"
30#include "gnunet-service-ats_addresses.h"
31#include "gnunet-service-ats_normalization.h"
32#include "gnunet-service-ats_plugins.h"
33
34#define LOG(kind, ...) GNUNET_log_from (kind, "ats-normalization", __VA_ARGS__)
35
36
37/**
38 * Range information for normalization of quality properties.
39 */
40struct PropertyRange
41{
42 /**
43 * Minimum value we see for this property across all addresses.
44 */
45 struct GNUNET_ATS_Properties min;
46
47 /**
48 * Maximum value we see for this property across all addresses.
49 */
50 struct GNUNET_ATS_Properties max;
51};
52
53
54/**
55 * Range information for all quality properties we see.
56 */
57static struct PropertyRange property_range;
58
59
60/**
61 * Add the value from @a atsi to the running average of the
62 * given @a ni quality property.
63 *
64 * @param current_val the updated value
65 * @param ni normalization information to update
66 */
67static void
68update_avg (uint64_t current_val,
69 struct GAS_NormalizationInfo *ni)
70{
71 double sum;
72 uint32_t count;
73 unsigned int c1;
74
75 ni->atsi_abs[ni->avg_queue_index++] = current_val;
76 if (GAS_normalization_queue_length == ni->avg_queue_index)
77 ni->avg_queue_index = 0;
78 count = 0;
79 sum = 0.0;
80 for (c1 = 0; c1 < GAS_normalization_queue_length; c1++)
81 {
82 if (UINT64_MAX != ni->atsi_abs[c1])
83 {
84 count++;
85 sum += (double) ni->atsi_abs[c1];
86 }
87 }
88 if (0 == count)
89 ni->avg = current_val; /* must be UINT64_MAX */
90 else
91 ni->avg = sum / count;
92}
93
94
95/**
96 * Function called for all addresses and peers to find the minimum and
97 * maximum (averaged) values for a given quality property. Given
98 * those, we can then calculate the normalized score.
99 *
100 * @param cls the `struct PropertyRange`
101 * @param h which peer are we looking at (ignored)
102 * @param k the address for that peer
103 * @return #GNUNET_OK (continue to iterate)
104 */
105static int
106find_min_max_it (void *cls,
107 const struct GNUNET_PeerIdentity *h,
108 void *k)
109{
110 struct PropertyRange *pr = cls;
111 const struct ATS_Address *a = k;
112
113 pr->max.utilization_out = GNUNET_MAX (pr->max.utilization_out,
114 a->properties.utilization_out);
115 pr->max.utilization_in = GNUNET_MAX (pr->max.utilization_in,
116 a->properties.utilization_in);
117 pr->max.distance = GNUNET_MAX (pr->max.distance,
118 a->properties.distance);
119 pr->max.delay = GNUNET_TIME_relative_max (pr->max.delay,
120 a->properties.delay);
121 pr->min.utilization_out = GNUNET_MIN (pr->min.utilization_out,
122 a->properties.utilization_out);
123 pr->min.utilization_in = GNUNET_MIN (pr->min.utilization_in,
124 a->properties.utilization_in);
125 pr->min.distance = GNUNET_MIN (pr->min.distance,
126 a->properties.distance);
127 pr->min.delay = GNUNET_TIME_relative_min (pr->min.delay,
128 a->properties.delay);
129 return GNUNET_OK;
130}
131
132
133/**
134 * Compute the normalized value from the given @a ni range
135 * data and the average value.
136 *
137 * @param min minimum value
138 * @param max maximum value
139 * @param ni normalization information to update
140 */
141static void
142update_norm (uint64_t min,
143 uint64_t max,
144 struct GAS_NormalizationInfo *ni)
145{
146 /* max - 2 * min + avg_value / (max - min) */
147 if (min < max)
148 ni->norm = DEFAULT_REL_QUALITY + (ni->avg - min) / (double) (max - min);
149 else
150 ni->norm = DEFAULT_REL_QUALITY;
151}
152
153
154/**
155 * Normalize the property value for a given address based
156 * on the range we know that property values have globally.
157 *
158 * @param cls NULL
159 * @param key which peer are we looking at (ignored)
160 * @param value the address for that peer, from where we get
161 * the original value and where we write the
162 * normalized value
163 * @return #GNUNET_OK (continue to iterate)
164 */
165static int
166normalize_address (void *cls,
167 const struct GNUNET_PeerIdentity *key,
168 void *value)
169{
170 struct ATS_Address *address = value;
171
172 update_norm (property_range.min.delay.rel_value_us,
173 property_range.max.delay.rel_value_us,
174 &address->norm_delay);
175 update_norm (property_range.min.distance,
176 property_range.max.distance,
177 &address->norm_distance);
178 update_norm (property_range.min.utilization_in,
179 property_range.max.utilization_in,
180 &address->norm_utilization_in);
181 update_norm (property_range.min.utilization_out,
182 property_range.max.utilization_out,
183 &address->norm_utilization_out);
184 return GNUNET_OK;
185}
186
187
188/**
189 * Notify about change in normalized property.
190 *
191 * @param cls NULL
192 * @param key which peer are we looking at (ignored)
193 * @param value the address for that peer
194 * @return #GNUNET_OK (continue to iterate)
195 */
196static int
197notify_change (void *cls,
198 const struct GNUNET_PeerIdentity *key,
199 void *value)
200{
201 struct ATS_Address *address = value;
202
203 GAS_plugin_notify_property_changed (address);
204 return GNUNET_OK;
205}
206
207
208/**
209 * Initialize property range to the values corresponding
210 * to an empty set.
211 *
212 * @param pr range to initialize
213 */
214static void
215init_range (struct PropertyRange *pr)
216{
217 memset (pr, 0, sizeof(struct PropertyRange));
218 pr->min.utilization_out = UINT32_MAX;
219 pr->min.utilization_in = UINT32_MAX;
220 pr->min.distance = UINT32_MAX;
221 pr->min.delay = GNUNET_TIME_UNIT_FOREVER_REL;
222}
223
224
225/**
226 * Update and normalize atsi performance information
227 *
228 * @param address the address to update
229 */
230void
231GAS_normalization_update_property (struct ATS_Address *address)
232{
233 const struct GNUNET_ATS_Properties *prop = &address->properties;
234 struct PropertyRange range;
235
236 LOG (GNUNET_ERROR_TYPE_DEBUG,
237 "Updating properties for peer `%s'\n",
238 GNUNET_i2s (&address->peer));
239 GAS_plugin_solver_lock ();
240 update_avg (prop->delay.rel_value_us,
241 &address->norm_delay);
242 update_avg (prop->distance,
243 &address->norm_distance);
244 update_avg (prop->utilization_in,
245 &address->norm_utilization_in);
246 update_avg (prop->utilization_in,
247 &address->norm_utilization_out);
248
249 init_range (&range);
250 GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
251 &find_min_max_it,
252 &range);
253 if (0 != GNUNET_memcmp (&range,
254 &property_range))
255 {
256 /* limits changed, (re)normalize all addresses */
257 property_range = range;
258 GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
259 &normalize_address,
260 NULL);
261 GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
262 &notify_change,
263 NULL);
264 }
265 else
266 {
267 /* renormalize just this one address */
268 normalize_address (NULL,
269 &address->peer,
270 address);
271 notify_change (NULL,
272 &address->peer,
273 address);
274 }
275 GAS_plugin_solver_unlock ();
276}
277
278
279/**
280 * Start the normalization component
281 */
282void
283GAS_normalization_start ()
284{
285 init_range (&property_range);
286}
287
288
289/**
290 * Stop the normalization component and free all items
291 */
292void
293GAS_normalization_stop ()
294{
295 /* nothing to do */
296}
297
298
299/* end of gnunet-service-ats_normalization.c */
diff --git a/src/ats/gnunet-service-ats_normalization.h b/src/ats/gnunet-service-ats_normalization.h
deleted file mode 100644
index 9c02586c2..000000000
--- a/src/ats/gnunet-service-ats_normalization.h
+++ /dev/null
@@ -1,60 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_normalization.h
23 * @brief ats service address: management of ATS properties and preferences normalization
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_ATS_NORMALIZATION_H
28#define GNUNET_SERVICE_ATS_NORMALIZATION_H
29#include "gnunet_ats_service.h"
30
31/**
32 * Value we return for a normalized quality score if we have no data.
33 */
34#define DEFAULT_REL_QUALITY 1.0
35
36
37/**
38 * Update and normalize a @a prop performance information
39 *
40 * @param address the address to update
41 */
42void
43GAS_normalization_update_property (struct ATS_Address *address);
44
45
46/**
47 * Start the normalization component
48 */
49void
50GAS_normalization_start (void);
51
52
53/**
54 * Stop the normalization component and free all items
55 */
56void
57GAS_normalization_stop (void);
58
59#endif
60/* end of gnunet-service-ats_normalization.h */
diff --git a/src/ats/gnunet-service-ats_performance.c b/src/ats/gnunet-service-ats_performance.c
deleted file mode 100644
index a4d7b36b6..000000000
--- a/src/ats/gnunet-service-ats_performance.c
+++ /dev/null
@@ -1,282 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/gnunet-service-ats_performance.c
22 * @brief ats service, interaction with 'performance' API
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - simplify functions by passing a `struct GNUNET_HELLO_Address`
28 */
29#include "platform.h"
30#include "gnunet-service-ats.h"
31#include "gnunet-service-ats_addresses.h"
32#include "gnunet-service-ats_performance.h"
33#include "ats.h"
34
35
36/**
37 * Context for sending messages to performance clients without PIC.
38 */
39static struct GNUNET_NotificationContext *nc_no_pic;
40
41/**
42 * Context for sending messages to performance clients with PIC.
43 */
44static struct GNUNET_NotificationContext *nc_pic;
45
46
47/**
48 * Transmit the given performance information to all performance
49 * clients.
50 *
51 * @param client client to send to, NULL for all
52 * @param peer peer for which this is an address suggestion
53 * @param plugin_name 0-termintated string specifying the transport plugin
54 * @param plugin_addr binary address for the plugin to use
55 * @param plugin_addr_len number of bytes in plugin_addr
56 * @param active #GNUNET_YES if this address is actively used
57 * to maintain a connection to a peer;
58 * #GNUNET_NO if the address is not actively used;
59 * #GNUNET_SYSERR if this address is no longer available for ATS
60 * @param prop performance data for the address
61 * @param local_address_info information about the local flags for the address
62 * @param bandwidth_out assigned outbound bandwidth
63 * @param bandwidth_in assigned inbound bandwidth
64 */
65static void
66notify_client (struct GNUNET_SERVICE_Client *client,
67 const struct GNUNET_PeerIdentity *peer,
68 const char *plugin_name,
69 const void *plugin_addr,
70 size_t plugin_addr_len,
71 int active,
72 const struct GNUNET_ATS_Properties *prop,
73 enum GNUNET_HELLO_AddressInfo local_address_info,
74 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
75 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
76{
77 struct PeerInformationMessage *msg;
78 size_t plugin_name_length = strlen (plugin_name) + 1;
79 size_t msize =
80 sizeof(struct PeerInformationMessage)
81 + plugin_addr_len
82 + plugin_name_length;
83 char buf[msize] GNUNET_ALIGN;
84 char *addrp;
85
86 if (NULL != prop)
87 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
88 GNUNET_assert (msize < GNUNET_MAX_MESSAGE_SIZE);
89 msg = (struct PeerInformationMessage *) buf;
90 msg->header.size = htons (msize);
91 msg->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_PEER_INFORMATION);
92 msg->id = htonl (0);
93 msg->peer = *peer;
94 msg->address_length = htons (plugin_addr_len);
95 msg->address_active = ntohl ((uint32_t) active);
96 msg->plugin_name_length = htons (plugin_name_length);
97 msg->bandwidth_out = bandwidth_out;
98 msg->bandwidth_in = bandwidth_in;
99 if (NULL != prop)
100 GNUNET_ATS_properties_hton (&msg->properties,
101 prop);
102 else
103 memset (&msg->properties,
104 0,
105 sizeof(struct GNUNET_ATS_Properties));
106 msg->address_local_info = htonl (local_address_info);
107 addrp = (char *) &msg[1];
108 GNUNET_memcpy (addrp, plugin_addr, plugin_addr_len);
109 strcpy (&addrp[plugin_addr_len], plugin_name);
110 if (NULL == client)
111 {
112 GNUNET_notification_context_broadcast (nc_pic,
113 &msg->header,
114 GNUNET_YES);
115 }
116 else
117 {
118 struct GNUNET_MQ_Envelope *env;
119
120 env = GNUNET_MQ_msg_copy (&msg->header);
121 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
122 env);
123 }
124}
125
126
127/**
128 * Transmit the given performance information to all performance
129 * clients.
130 *
131 * @param peer peer for which this is an address suggestion
132 * @param plugin_name 0-termintated string specifying the transport plugin
133 * @param plugin_addr binary address for the plugin to use
134 * @param plugin_addr_len number of bytes in @a plugin_addr
135 * @param active #GNUNET_YES if this address is actively used
136 * to maintain a connection to a peer;
137 * #GNUNET_NO if the address is not actively used;
138 * #GNUNET_SYSERR if this address is no longer available for ATS
139 * @param prop performance data for the address
140 * @param local_address_info information about the local flags for the address
141 * @param bandwidth_out assigned outbound bandwidth
142 * @param bandwidth_in assigned inbound bandwidth
143 */
144void
145GAS_performance_notify_all_clients (const struct GNUNET_PeerIdentity *peer,
146 const char *plugin_name,
147 const void *plugin_addr,
148 size_t plugin_addr_len,
149 int active,
150 const struct GNUNET_ATS_Properties *prop,
151 enum GNUNET_HELLO_AddressInfo
152 local_address_info,
153 struct GNUNET_BANDWIDTH_Value32NBO
154 bandwidth_out,
155 struct GNUNET_BANDWIDTH_Value32NBO
156 bandwidth_in)
157{
158 GNUNET_break ((NULL == prop) ||
159 (GNUNET_NT_UNSPECIFIED != prop->scope));
160 notify_client (NULL,
161 peer,
162 plugin_name,
163 plugin_addr,
164 plugin_addr_len,
165 active,
166 prop,
167 local_address_info,
168 bandwidth_out,
169 bandwidth_in);
170 GNUNET_STATISTICS_update (GSA_stats,
171 "# performance updates given to clients",
172 1,
173 GNUNET_NO);
174}
175
176
177/**
178 * Iterator for called from #GAS_addresses_get_peer_info()
179 *
180 * @param cls closure with the `struct GNUNET_SERVICE_Client *` to inform.
181 * @param id the peer id
182 * @param plugin_name plugin name
183 * @param plugin_addr address
184 * @param plugin_addr_len length of @a plugin_addr
185 * @param active is address actively used
186 * @param prop performance information
187 * @param local_address_info information about the local flags for the address
188 * @param bandwidth_out current outbound bandwidth assigned to address
189 * @param bandwidth_in current inbound bandwidth assigned to address
190 */
191static void
192peerinfo_it (void *cls,
193 const struct GNUNET_PeerIdentity *id,
194 const char *plugin_name,
195 const void *plugin_addr,
196 size_t plugin_addr_len,
197 int active,
198 const struct GNUNET_ATS_Properties *prop,
199 enum GNUNET_HELLO_AddressInfo local_address_info,
200 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
201 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
202{
203 struct GNUNET_SERVICE_Client *client = cls;
204
205 if (NULL == id)
206 return;
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
208 "Callback for peer `%s' plugin `%s' BW out %u, BW in %u \n",
209 GNUNET_i2s (id),
210 plugin_name,
211 (unsigned int) ntohl (bandwidth_out.value__),
212 (unsigned int) ntohl (bandwidth_in.value__));
213 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
214 notify_client (client,
215 id,
216 plugin_name,
217 plugin_addr,
218 plugin_addr_len,
219 active,
220 prop,
221 local_address_info,
222 bandwidth_out,
223 bandwidth_in);
224}
225
226
227/**
228 * Register a new performance client.
229 *
230 * @param client handle of the new client
231 * @param flag flag specifying the type of the client
232 */
233void
234GAS_performance_add_client (struct GNUNET_SERVICE_Client *client,
235 enum StartFlag flag)
236{
237 struct GNUNET_MQ_Handle *mq;
238
239 mq = GNUNET_SERVICE_client_get_mq (client);
240 if (START_FLAG_PERFORMANCE_WITH_PIC == flag)
241 {
242 GNUNET_notification_context_add (nc_pic,
243 mq);
244 GAS_addresses_get_peer_info (NULL,
245 &peerinfo_it,
246 client);
247 }
248 else
249 {
250 GNUNET_notification_context_add (nc_no_pic,
251 mq);
252 }
253}
254
255
256/**
257 * Initialize performance subsystem.
258 *
259 * @param server handle to our server
260 */
261void
262GAS_performance_init ()
263{
264 nc_no_pic = GNUNET_notification_context_create (32);
265 nc_pic = GNUNET_notification_context_create (32);
266}
267
268
269/**
270 * Shutdown performance subsystem.
271 */
272void
273GAS_performance_done ()
274{
275 GNUNET_notification_context_destroy (nc_no_pic);
276 nc_no_pic = NULL;
277 GNUNET_notification_context_destroy (nc_pic);
278 nc_pic = NULL;
279}
280
281
282/* end of gnunet-service-ats_performance.c */
diff --git a/src/ats/gnunet-service-ats_performance.h b/src/ats/gnunet-service-ats_performance.h
deleted file mode 100644
index 292c27c95..000000000
--- a/src/ats/gnunet-service-ats_performance.h
+++ /dev/null
@@ -1,96 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_performance.h
23 * @brief ats service, interaction with 'performance' API
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_ATS_PERFORMANCE_H
28#define GNUNET_SERVICE_ATS_PERFORMANCE_H
29
30#include "gnunet_util_lib.h"
31#include "gnunet_ats_service.h"
32#include "ats.h"
33
34
35/**
36 * Transmit the given performance information to all performance
37 * clients.
38 *
39 * @param peer peer for which this is an address suggestion
40 * @param plugin_name 0-termintated string specifying the transport plugin
41 * @param plugin_addr binary address for the plugin to use
42 * @param plugin_addr_len number of bytes in @a plugin_addr
43 * @param active #GNUNET_YES if this address is actively used
44 * to maintain a connection to a peer;
45 * #GNUNET_NO if the address is not actively used;
46 * #GNUNET_SYSERR if this address is no longer available for ATS
47 * @param prop performance data for the address
48 * @param local_address_info information about the local flags for the address
49 * @param bandwidth_out assigned outbound bandwidth
50 * @param bandwidth_in assigned inbound bandwidth
51 */
52void
53GAS_performance_notify_all_clients (const struct GNUNET_PeerIdentity *peer,
54 const char *plugin_name,
55 const void *plugin_addr,
56 size_t plugin_addr_len,
57 int active,
58 const struct GNUNET_ATS_Properties *prop,
59 enum GNUNET_HELLO_AddressInfo
60 local_address_info,
61 struct GNUNET_BANDWIDTH_Value32NBO
62 bandwidth_out,
63 struct GNUNET_BANDWIDTH_Value32NBO
64 bandwidth_in);
65
66
67/**
68 * Register a new performance client.
69 *
70 * @param client handle of the new client
71 * @param flag flag specifying the type of the client
72 */
73void
74GAS_performance_add_client (struct GNUNET_SERVICE_Client *client,
75 enum StartFlag flag);
76
77
78/**
79 * Initialize performance subsystem.
80 *
81 * @param server handle to our server
82 * @param addresses the address handle to use
83 */
84void
85GAS_performance_init (void);
86
87
88/**
89 * Shutdown performance subsystem.
90 */
91void
92GAS_performance_done (void);
93
94
95#endif
96/* end of gnunet-service-ats_performance.h */
diff --git a/src/ats/gnunet-service-ats_plugins.c b/src/ats/gnunet-service-ats_plugins.c
deleted file mode 100644
index d8d6be11d..000000000
--- a/src/ats/gnunet-service-ats_plugins.c
+++ /dev/null
@@ -1,600 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2014 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_plugins.c
23 * @brief ats service plugin management
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_ats_plugin.h"
29#include "gnunet-service-ats_connectivity.h"
30#include "gnunet-service-ats_performance.h"
31#include "gnunet-service-ats_preferences.h"
32#include "gnunet-service-ats_plugins.h"
33#include "gnunet-service-ats_reservations.h"
34#include "gnunet-service-ats_scheduling.h"
35#include "gnunet-service-ats_normalization.h"
36
37
38/**
39 * Solver handle.
40 */
41static struct GNUNET_ATS_SolverFunctions *sf;
42
43/**
44 * Solver environment.
45 */
46static struct GNUNET_ATS_PluginEnvironment env;
47
48/**
49 * Solver plugin name as string
50 */
51static char *plugin;
52
53
54/**
55 * The preference changed for a peer, update solver.
56 *
57 * @param peer the peer
58 * @param kind the ATS kind
59 * @param pref_rel the new relative preference value
60 */
61void
62GAS_plugin_notify_preference_changed (const struct GNUNET_PeerIdentity *peer,
63 enum GNUNET_ATS_PreferenceKind kind,
64 double pref_rel)
65{
66 sf->s_pref (sf->cls,
67 peer,
68 kind,
69 pref_rel);
70}
71
72
73/**
74 * The relative value for a property changed.
75 *
76 * @param address the peer for which a property changed
77 */
78void
79GAS_plugin_notify_property_changed (struct ATS_Address *address)
80{
81 sf->s_address_update_property (sf->cls,
82 address);
83}
84
85
86/**
87 * Solver information callback
88 *
89 * @param cls the closure
90 * @param op the operation
91 * @param status operation status
92 * @param add additional information
93 */
94static void
95solver_info_cb (void *cls,
96 enum GAS_Solver_Operation op,
97 enum GAS_Solver_Status status,
98 enum GAS_Solver_Additional_Information add)
99{
100 const char *add_info;
101
102 switch (add)
103 {
104 case GAS_INFO_NONE:
105 add_info = "GAS_INFO_NONE";
106 break;
107
108 case GAS_INFO_FULL:
109 add_info = "GAS_INFO_MLP_FULL";
110 break;
111
112 case GAS_INFO_UPDATED:
113 add_info = "GAS_INFO_MLP_UPDATED";
114 break;
115
116 case GAS_INFO_PROP_ALL:
117 add_info = "GAS_INFO_PROP_ALL";
118 break;
119
120 case GAS_INFO_PROP_SINGLE:
121 add_info = "GAS_INFO_PROP_SINGLE";
122 break;
123
124 default:
125 add_info = "INVALID";
126 break;
127 }
128 switch (op)
129 {
130 case GAS_OP_SOLVE_START:
131 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
132 "Solver notifies `%s' with result `%s' `%s'\n",
133 "GAS_OP_SOLVE_START",
134 (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL",
135 add_info);
136 return;
137
138 case GAS_OP_SOLVE_STOP:
139 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
140 "Solver notifies `%s' with result `%s'\n",
141 "GAS_OP_SOLVE_STOP",
142 (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
143 return;
144
145 case GAS_OP_SOLVE_SETUP_START:
146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
147 "Solver notifies `%s' with result `%s'\n",
148 "GAS_OP_SOLVE_SETUP_START",
149 (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
150 return;
151
152 case GAS_OP_SOLVE_SETUP_STOP:
153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
154 "Solver notifies `%s' with result `%s'\n",
155 "GAS_OP_SOLVE_SETUP_STOP",
156 (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
157 return;
158
159 case GAS_OP_SOLVE_MLP_LP_START:
160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
161 "Solver notifies `%s' with result `%s'\n",
162 "GAS_OP_SOLVE_LP_START",
163 (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
164 return;
165
166 case GAS_OP_SOLVE_MLP_LP_STOP:
167 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
168 "Solver notifies `%s' with result `%s'\n",
169 "GAS_OP_SOLVE_LP_STOP",
170 (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
171 return;
172
173 case GAS_OP_SOLVE_MLP_MLP_START:
174 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
175 "Solver notifies `%s' with result `%s'\n",
176 "GAS_OP_SOLVE_MLP_START",
177 (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
178 return;
179
180 case GAS_OP_SOLVE_MLP_MLP_STOP:
181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
182 "Solver notifies `%s' with result `%s'\n",
183 "GAS_OP_SOLVE_MLP_STOP",
184 (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
185 return;
186
187 case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
189 "Solver notifies `%s' with result `%s'\n",
190 "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
191 (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
192 return;
193
194 case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
196 "Solver notifies `%s' with result `%s'\n",
197 "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
198 (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
199 return;
200
201 default:
202 GNUNET_break (0);
203 break;
204 }
205}
206
207
208/**
209 * Callback for solver to notify about assignment changes
210 *
211 * @param cls NULL
212 * @param address the address with changes
213 */
214static void
215bandwidth_changed_cb (void *cls,
216 struct ATS_Address *address)
217{
218 long long diff_out;
219 long long diff_in;
220
221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
222 "Bandwidth assignment changed for peer %s to %u/%u\n",
223 GNUNET_i2s (&address->peer),
224 (unsigned int) address->assigned_bw_in,
225 (unsigned int) address->assigned_bw_out);
226 GAS_reservations_set_bandwidth (&address->peer,
227 GNUNET_BANDWIDTH_value_init (
228 address->assigned_bw_in));
229 /* Notify performance clients about changes to address */
230 GAS_performance_notify_all_clients (&address->peer,
231 address->plugin,
232 address->addr,
233 address->addr_len,
234 address->active,
235 &address->properties,
236 address->local_address_info,
237 GNUNET_BANDWIDTH_value_init (
238 address->assigned_bw_out),
239 GNUNET_BANDWIDTH_value_init (
240 address->assigned_bw_in));
241
242 if ((0 == address->assigned_bw_in) &&
243 (0 == address->assigned_bw_out))
244 {
245 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
246 "Telling transport to disconnect peer `%s'\n",
247 GNUNET_i2s (&address->peer));
248
249 /* Notify scheduling clients about suggestion */
250 GAS_scheduling_transmit_address_suggestion (&address->peer,
251 address->session_id,
252 GNUNET_BANDWIDTH_ZERO,
253 GNUNET_BANDWIDTH_ZERO);
254 return;
255 }
256
257 /* Do bandwidth stability check */
258 diff_out = llabs ((long long) address->assigned_bw_out
259 - (long long) address->last_notified_bw_out);
260 diff_in = llabs ((long long) address->assigned_bw_in
261 - (long long) address->last_notified_bw_in);
262 if ((diff_out < htonl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__)) &&
263 (diff_in < htonl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__)))
264 {
265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
266 "Bandwidth change too small, not notifying client\n");
267 return;
268 }
269
270 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
271 "Sending bandwidth update for peer `%s': %u/%u\n",
272 GNUNET_i2s (&address->peer),
273 address->assigned_bw_out,
274 address->assigned_bw_out);
275
276 /* *Notify scheduling clients about suggestion */
277 GAS_scheduling_transmit_address_suggestion (&address->peer,
278 address->session_id,
279 GNUNET_BANDWIDTH_value_init (
280 address->assigned_bw_out),
281 GNUNET_BANDWIDTH_value_init (
282 address->assigned_bw_in));
283
284 address->last_notified_bw_out = address->assigned_bw_out;
285 address->last_notified_bw_in = address->assigned_bw_in;
286}
287
288
289/**
290 * Convert quota from text to numeric value.
291 *
292 * @param quota_str the value found in the configuration
293 * @param direction direction of the quota
294 * @param network network the quota applies to
295 * @return numeric quota value to use
296 */
297static unsigned long long
298parse_quota (const char *quota_str,
299 const char *direction,
300 enum GNUNET_NetworkType network)
301{
302 int res;
303 unsigned long long ret;
304
305 res = GNUNET_NO;
306 if (0 == strcmp (quota_str, GNUNET_ATS_MaxBandwidthString))
307 {
308 ret = GNUNET_ATS_MaxBandwidth;
309 res = GNUNET_YES;
310 }
311 if ((GNUNET_NO == res) &&
312 (GNUNET_OK ==
313 GNUNET_STRINGS_fancy_size_to_bytes (quota_str,
314 &ret)))
315 res = GNUNET_YES;
316 if ((GNUNET_NO == res) &&
317 (1 ==
318 sscanf (quota_str,
319 "%llu",
320 &ret)))
321 res = GNUNET_YES;
322 if (GNUNET_NO == res)
323 {
324 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
325 _ (
326 "Could not load %s quota for network `%s': `%s', assigning default bandwidth %llu\n"),
327 direction,
328 GNUNET_NT_to_string (network),
329 quota_str,
330 (unsigned long long) GNUNET_ATS_DefaultBandwidth);
331 ret = GNUNET_ATS_DefaultBandwidth;
332 }
333 else
334 {
335 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
336 _ ("%s quota configured for network `%s' is %llu\n"),
337 direction,
338 GNUNET_NT_to_string (network),
339 ret);
340 }
341 return ret;
342}
343
344
345/**
346 * Load quota value from the configuration @a cfg for the
347 * given network @a type and @a direction.
348 *
349 * @param cfg configuration to parse
350 * @param type network type to parse for
351 * @param direction traffic direction to parse for
352 * @return quota to apply
353 */
354static unsigned long long
355load_quota (const struct GNUNET_CONFIGURATION_Handle *cfg,
356 enum GNUNET_NetworkType type,
357 const char *direction)
358{
359 char *entry;
360 char *quota_str;
361 unsigned long long ret;
362
363 GNUNET_asprintf (&entry,
364 "%s_QUOTA_%s",
365 GNUNET_NT_to_string (type),
366 direction);
367 if (GNUNET_OK ==
368 GNUNET_CONFIGURATION_get_value_string (cfg,
369 "ats",
370 entry,
371 &quota_str))
372 {
373 ret = parse_quota (quota_str,
374 direction,
375 type);
376 GNUNET_free (quota_str);
377 }
378 else
379 {
380 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
381 _ (
382 "No %s-quota configured for network `%s', assigning default bandwidth %llu\n"),
383 direction,
384 GNUNET_NT_to_string (type),
385 (unsigned long long) GNUNET_ATS_DefaultBandwidth);
386 ret = GNUNET_ATS_DefaultBandwidth;
387 }
388 GNUNET_free (entry);
389 return ret;
390}
391
392
393/**
394 * Load quotas for networks from configuration
395 *
396 * @param cfg configuration handle
397 * @param out_dest where to write outbound quotas
398 * @param in_dest where to write inbound quotas
399 * @param dest_length length of inbound and outbound arrays
400 * @return number of networks loaded
401 */
402static unsigned int
403load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
404 unsigned long long *out_dest,
405 unsigned long long *in_dest,
406 int dest_length)
407{
408 unsigned int c;
409
410 for (c = 0; (c < GNUNET_NT_COUNT) && (c < dest_length); c++)
411 {
412 in_dest[c] = load_quota (cfg,
413 c,
414 "out");
415 out_dest[c] = load_quota (cfg,
416 c,
417 "in");
418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
419 "Loaded quota for network `%s' (in/out): %llu %llu\n",
420 GNUNET_NT_to_string (c),
421 in_dest[c],
422 out_dest[c]);
423 }
424 return c;
425}
426
427
428/**
429 * Initialize plugins subsystem.
430 *
431 * @param cfg configuration to use
432 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (failed to load
433 * solver plugin)
434 */
435int
436GAS_plugin_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
437{
438 char *mode_str;
439
440 /* Figure out configured solution method */
441 if (GNUNET_SYSERR ==
442 GNUNET_CONFIGURATION_get_value_string (cfg,
443 "ats",
444 "MODE",
445 &mode_str))
446 {
447 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
448 "No resource assignment method configured, using proportional approach\n");
449 mode_str = GNUNET_strdup ("proportional");
450 }
451 env.cls = NULL;
452 env.info_cb = &solver_info_cb;
453 env.bandwidth_changed_cb = &bandwidth_changed_cb;
454 env.get_preferences = &GAS_preference_get_by_peer;
455 env.get_connectivity = &GAS_connectivity_has_peer;
456 env.cfg = cfg;
457 env.stats = GSA_stats;
458 env.addresses = GSA_addresses;
459 env.network_count = GNUNET_NT_COUNT;
460 load_quotas (cfg,
461 env.out_quota,
462 env.in_quota,
463 GNUNET_NT_COUNT);
464 GNUNET_asprintf (&plugin,
465 "libgnunet_plugin_ats_%s",
466 mode_str);
467 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
468 "Initializing solver `%s'\n",
469 mode_str);
470 GNUNET_free (mode_str);
471 if (NULL == (sf = GNUNET_PLUGIN_load (plugin, &env)))
472 {
473 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
474 _ ("Failed to initialize solver `%s'!\n"),
475 plugin);
476 return GNUNET_SYSERR;
477 }
478 return GNUNET_OK;
479}
480
481
482/**
483 * Shutdown address subsystem.
484 */
485void
486GAS_plugin_done ()
487{
488 GNUNET_PLUGIN_unload (plugin,
489 sf);
490 sf = NULL;
491 GNUNET_free (plugin);
492 plugin = NULL;
493}
494
495
496/**
497 * Tell the solver that the given address can now be used
498 * for talking to the respective peer.
499 *
500 * @param new_address the new address
501 */
502void
503GAS_plugin_new_address (struct ATS_Address *new_address)
504{
505 sf->s_add (sf->cls,
506 new_address,
507 new_address->properties.scope); /* FIXME: remove 3rd arg here! */
508}
509
510
511/**
512 * Tell the solver that the given address is no longer valid
513 * can cannot be used any longer.
514 *
515 * @param address address that was deleted
516 */
517void
518GAS_plugin_delete_address (struct ATS_Address *address)
519{
520 sf->s_del (sf->cls,
521 address);
522}
523
524
525/**
526 * Tell the solver that the given client has expressed its
527 * appreciation for the past performance of a given connection.
528 *
529 * @param application client providing the feedback
530 * @param peer peer the feedback is about
531 * @param scope timeframe the feedback applies to
532 * @param kind performance property the feedback relates to
533 * @param score_abs degree of the appreciation
534 */
535void
536GAS_plugin_notify_feedback (struct GNUNET_SERVICE_Client *application,
537 const struct GNUNET_PeerIdentity *peer,
538 const struct GNUNET_TIME_Relative scope,
539 enum GNUNET_ATS_PreferenceKind kind,
540 float score_abs)
541{
542 sf->s_feedback (sf->cls,
543 application,
544 peer,
545 scope,
546 kind,
547 score_abs);
548}
549
550
551/**
552 * Stop instant solving, there are many state updates
553 * happening in bulk right now.
554 */
555void
556GAS_plugin_solver_lock ()
557{
558 sf->s_bulk_start (sf->cls);
559}
560
561
562/**
563 * Resume instant solving, we are done with the bulk state updates.
564 */
565void
566GAS_plugin_solver_unlock ()
567{
568 sf->s_bulk_stop (sf->cls);
569}
570
571
572/**
573 * Notify the plugin that a request to connect to
574 * a particular peer was given to us.
575 *
576 * @param pid identity of peer we now care about
577 */
578void
579GAS_plugin_request_connect_start (const struct GNUNET_PeerIdentity *pid)
580{
581 sf->s_get (sf->cls,
582 pid);
583}
584
585
586/**
587 * Notify the plugin that a request to connect to
588 * a particular peer was dropped.
589 *
590 * @param pid identity of peer we care now less about
591 */
592void
593GAS_plugin_request_connect_stop (const struct GNUNET_PeerIdentity *pid)
594{
595 sf->s_get_stop (sf->cls,
596 pid);
597}
598
599
600/* end of gnunet-service-ats_plugins.c */
diff --git a/src/ats/gnunet-service-ats_plugins.h b/src/ats/gnunet-service-ats_plugins.h
deleted file mode 100644
index 0bd358917..000000000
--- a/src/ats/gnunet-service-ats_plugins.h
+++ /dev/null
@@ -1,150 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2014 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_plugins.h
23 * @brief ats service plugin management
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_ATS_PLUGINS_H
28#define GNUNET_SERVICE_ATS_PLUGINS_H
29
30#include "gnunet-service-ats_addresses.h"
31
32
33/**
34 * Initialize address subsystem. The addresses subsystem manages the addresses
35 * known and current performance information. It has a solver component
36 * responsible for the resource allocation. It tells the solver about changes
37 * and receives updates when the solver changes the resource allocation.
38 *
39 * @param cfg configuration to use
40 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (failed to load
41 * solver plugin)
42 */
43int
44GAS_plugin_init (const struct GNUNET_CONFIGURATION_Handle *cfg);
45
46
47/**
48 * Shutdown address subsystem.
49 */
50void
51GAS_plugin_done (void);
52
53
54/**
55 * The preference changed for a peer, update solver.
56 *
57 * @param peer the peer
58 * @param kind the ATS kind
59 * @param pref_rel the new relative preference value
60 */
61void
62GAS_plugin_notify_preference_changed (const struct GNUNET_PeerIdentity *peer,
63 enum GNUNET_ATS_PreferenceKind kind,
64 double pref_rel);
65
66
67/**
68 * The relative value for a property changed.
69 *
70 * @param address the peer
71 */
72void
73GAS_plugin_notify_property_changed (struct ATS_Address *address);
74
75
76/**
77 * Tell the solver that the given address can now be used
78 * for talking to the respective peer.
79 *
80 * @param new_address the new address
81 * @param addr_net network scope the address is in
82 */
83void
84GAS_plugin_new_address (struct ATS_Address *new_address);
85
86
87/**
88 * Tell the solver that the given address is no longer valid
89 * can cannot be used any longer.
90 *
91 * @param address address that was deleted
92 */
93void
94GAS_plugin_delete_address (struct ATS_Address *address);
95
96
97/**
98 * Tell the solver that the given client has expressed its
99 * appreciation for the past performance of a given connection.
100 *
101 * @param application client providing the feedback
102 * @param peer peer the feedback is about
103 * @param scope timeframe the feedback applies to
104 * @param kind performance property the feedback relates to
105 * @param score_abs degree of the appreciation
106 */
107void
108GAS_plugin_notify_feedback (struct GNUNET_SERVICE_Client *application,
109 const struct GNUNET_PeerIdentity *peer,
110 const struct GNUNET_TIME_Relative scope,
111 enum GNUNET_ATS_PreferenceKind kind,
112 float score_abs);
113
114
115/**
116 * Stop instant solving, there are many state updates
117 * happening in bulk right now.
118 */
119void
120GAS_plugin_solver_lock (void);
121
122
123/**
124 * Resume instant solving, we are done with the bulk state updates.
125 */
126void
127GAS_plugin_solver_unlock (void);
128
129
130/**
131 * Notify the plugin that a request to connect to
132 * a particular peer was given to us.
133 *
134 * @param pid identity of peer we now care about
135 */
136void
137GAS_plugin_request_connect_start (const struct GNUNET_PeerIdentity *pid);
138
139
140/**
141 * Notify the plugin that a request to connect to
142 * a particular peer was dropped.
143 *
144 * @param pid identity of peer we care now less about
145 */
146void
147GAS_plugin_request_connect_stop (const struct GNUNET_PeerIdentity *pid);
148
149
150#endif
diff --git a/src/ats/gnunet-service-ats_preferences.c b/src/ats/gnunet-service-ats_preferences.c
deleted file mode 100644
index 0869c65dc..000000000
--- a/src/ats/gnunet-service-ats_preferences.c
+++ /dev/null
@@ -1,776 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/gnunet-service-ats_preferences.c
22 * @brief manage preferences expressed by clients
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet-service-ats.h"
28#include "gnunet-service-ats_addresses.h"
29#include "gnunet-service-ats_performance.h"
30#include "gnunet-service-ats_plugins.h"
31#include "gnunet-service-ats_preferences.h"
32#include "gnunet-service-ats_reservations.h"
33#include "ats.h"
34
35#define LOG(kind, ...) GNUNET_log_from (kind, "ats-preferences", __VA_ARGS__)
36
37/**
38 * How frequently do we age preference values?
39 */
40#define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply ( \
41 GNUNET_TIME_UNIT_SECONDS, 10)
42
43/**
44 * By which factor do we age preferences expressed during
45 * each #PREF_AGING_INTERVAL?
46 */
47#define PREF_AGING_FACTOR 0.95
48
49/**
50 * What is the lowest threshold up to which preference values
51 * are aged, and below which we consider them zero and thus
52 * no longer subject to aging?
53 */
54#define PREF_EPSILON 0.01
55
56
57/**
58 * Relative preferences for a peer.
59 */
60struct PeerRelative
61{
62 /**
63 * Array of relative preference values, to be indexed by
64 * an `enum GNUNET_ATS_PreferenceKind`.
65 */
66 double f_rel[GNUNET_ATS_PREFERENCE_END];
67
68 /**
69 * Number of clients that are expressing a preference for
70 * this peer. When this counter reaches zero, this entry
71 * is freed.
72 */
73 unsigned int num_clients;
74};
75
76
77/**
78 * Default values, returned as our preferences if we do not
79 * have any preferences expressed for a peer.
80 */
81static struct PeerRelative defvalues;
82
83
84/**
85 * Preference information per peer and client.
86 */
87struct PreferencePeer
88{
89 /**
90 * Next in DLL of preference entries for the same client.
91 */
92 struct PreferencePeer *next;
93
94 /**
95 * Previous in DLL of preference entries for the same client.
96 */
97 struct PreferencePeer *prev;
98
99 /**
100 * Absolute preference values for all preference types
101 * as expressed by this client for this peer.
102 */
103 double f_abs[GNUNET_ATS_PREFERENCE_END];
104
105 /**
106 * Relative preference values for all preference types,
107 * normalized in [0..1] based on how the respective
108 * client scored other peers.
109 */
110 double f_rel[GNUNET_ATS_PREFERENCE_END];
111};
112
113
114/**
115 * Preference client, as in a client that expressed preferences
116 * for peers. This is the information we keep track of for each
117 * such client.
118 */
119struct PreferenceClient
120{
121 /**
122 * Next in client list
123 */
124 struct PreferenceClient *next;
125
126 /**
127 * Previous in client peer list
128 */
129 struct PreferenceClient *prev;
130
131 /**
132 * Client handle
133 */
134 struct GNUNET_SERVICE_Client *client;
135
136 /**
137 * Mapping peer identities to `struct PreferencePeer` entry
138 * for the respective peer.
139 */
140 struct GNUNET_CONTAINER_MultiPeerMap *peer2pref;
141
142 /**
143 * Array of sums of absolute preferences for all
144 * peers as expressed by this client.
145 */
146 double f_abs_sum[GNUNET_ATS_PREFERENCE_END];
147};
148
149
150/**
151 * Hashmap to store peer information for preference normalization.
152 * Maps the identity of a peer to a `struct PeerRelative` containing
153 * the current relative preference values for that peer.
154 */
155static struct GNUNET_CONTAINER_MultiPeerMap *preference_peers;
156
157/**
158 * Clients in DLL: head
159 */
160static struct PreferenceClient *pc_head;
161
162/**
163 * Clients in DLL: tail
164 */
165static struct PreferenceClient *pc_tail;
166
167/**
168 * Handle for task we run periodically to age preferences over time.
169 */
170static struct GNUNET_SCHEDULER_Task *aging_task;
171
172
173/**
174 * Closure for #sum_relative_preferences().
175 */
176struct SumContext
177{
178 /**
179 * Where to accumulate the result.
180 */
181 double f_rel_total;
182
183 /**
184 * Which kind of preference value are we adding up?
185 */
186 enum GNUNET_ATS_PreferenceKind kind;
187};
188
189
190/**
191 * Add the relative preference for the kind given to the
192 * closure.
193 *
194 * @param cls the `struct SumContext` with the kind and place
195 * to store the result
196 * @param peer ignored
197 * @param value the `struct PreferencePeer` for getting the rel pref.
198 * @return #GNUNET_OK
199 */
200static int
201sum_relative_preferences (void *cls,
202 const struct GNUNET_PeerIdentity *peer,
203 void *value)
204{
205 struct SumContext *sum_ctx = cls;
206 struct PreferencePeer *p_cur = value;
207
208 sum_ctx->f_rel_total += p_cur->f_rel[sum_ctx->kind];
209 return GNUNET_OK;
210}
211
212
213/**
214 * Update the total relative preference for a peer by summing
215 * up the relative preferences all clients have for this peer.
216 *
217 * @param id peer id of the peer for which we should do the update
218 * @param kind the kind of preference value to update
219 * @return the new relative preference
220 */
221static void
222update_relative_values_for_peer (const struct GNUNET_PeerIdentity *id,
223 enum GNUNET_ATS_PreferenceKind kind)
224{
225 struct PreferenceClient *c_cur;
226 struct SumContext sum_ctx;
227 struct PeerRelative *rp;
228
229 sum_ctx.f_rel_total = 0.0;
230 sum_ctx.kind = kind;
231 for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next)
232 GNUNET_CONTAINER_multipeermap_get_multiple (c_cur->peer2pref,
233 id,
234 &sum_relative_preferences,
235 &sum_ctx);
236 LOG (GNUNET_ERROR_TYPE_DEBUG,
237 "Total relative preference for peer `%s' for `%s' is %.3f\n",
238 GNUNET_i2s (id),
239 GNUNET_ATS_print_preference_type (kind),
240 sum_ctx.f_rel_total);
241 rp = GNUNET_CONTAINER_multipeermap_get (preference_peers,
242 id);
243 GNUNET_assert (NULL != rp);
244 if (rp->f_rel[kind] != sum_ctx.f_rel_total)
245 {
246 rp->f_rel[kind] = sum_ctx.f_rel_total;
247 GAS_plugin_notify_preference_changed (id,
248 kind,
249 rp->f_rel[kind]);
250 }
251}
252
253
254/**
255 * Free a peer's `struct PeerRelative`.
256 *
257 * @param cls unused
258 * @param key the key
259 * @param value the `struct PeerRelative` to free.
260 * @return #GNUNET_OK to continue
261 */
262static int
263free_peer (void *cls,
264 const struct GNUNET_PeerIdentity *key,
265 void *value)
266{
267 struct PeerRelative *rp = value;
268
269 GNUNET_assert (GNUNET_YES ==
270 GNUNET_CONTAINER_multipeermap_remove (preference_peers,
271 key,
272 value));
273 GNUNET_free (rp);
274 return GNUNET_OK;
275}
276
277
278/**
279 * Free `struct PreferencePeer` entry in map.
280 *
281 * @param cls the `struct PreferenceClient` with the map
282 * @param key the peer the entry is for
283 * @param value the `struct PreferencePeer` entry to free
284 * @return #GNUNET_OK (continue to iterate)
285 */
286static int
287free_preference (void *cls,
288 const struct GNUNET_PeerIdentity *key,
289 void *value)
290{
291 struct PreferenceClient *pc = cls;
292 struct PreferencePeer *p = value;
293 struct PeerRelative *pr;
294
295 GNUNET_assert (GNUNET_OK ==
296 GNUNET_CONTAINER_multipeermap_remove (pc->peer2pref,
297 key,
298 p));
299 GNUNET_free (p);
300 pr = GNUNET_CONTAINER_multipeermap_get (preference_peers,
301 key);
302 GNUNET_assert (NULL != pr);
303 GNUNET_assert (pr->num_clients > 0);
304 pr->num_clients--;
305 if (0 == pr->num_clients)
306 {
307 free_peer (NULL,
308 key,
309 pr);
310 }
311 return GNUNET_OK;
312}
313
314
315/**
316 * Closure for #age_values().
317 */
318struct AgeContext
319{
320 /**
321 * Counter of values remaining to update, incremented for each value
322 * changed (to a new non-zero value).
323 */
324 unsigned int values_to_update;
325
326 /**
327 * Client we are currently aging values for.
328 */
329 struct PreferenceClient *cur_client;
330};
331
332
333/**
334 * Age preference values of the given peer.
335 *
336 * @param cls a `
337 * @param peer peer being aged
338 * @param value the `struct PreferencePeer` for the peer
339 * @return #GNUNET_OK (continue to iterate)
340 */
341static int
342age_values (void *cls,
343 const struct GNUNET_PeerIdentity *peer,
344 void *value)
345{
346 struct AgeContext *ac = cls;
347 struct PreferencePeer *p = value;
348 unsigned int i;
349 int dead;
350
351 dead = GNUNET_YES;
352 for (i = 0; i < GNUNET_ATS_PREFERENCE_END; i++)
353 {
354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
355 "Aging preference for peer `%s'\n",
356 GNUNET_i2s (peer));
357 if (p->f_abs[i] > DEFAULT_ABS_PREFERENCE)
358 p->f_abs[i] *= PREF_AGING_FACTOR;
359 if (p->f_abs[i] <= DEFAULT_ABS_PREFERENCE + PREF_EPSILON)
360 {
361 p->f_abs[i] = DEFAULT_ABS_PREFERENCE;
362 p->f_rel[i] = DEFAULT_REL_PREFERENCE;
363 update_relative_values_for_peer (peer,
364 i);
365 }
366 else
367 {
368 ac->values_to_update++;
369 dead = GNUNET_NO;
370 }
371 }
372 if (GNUNET_YES == dead)
373 {
374 /* all preferences are zero, remove this entry */
375 free_preference (ac->cur_client,
376 peer,
377 p);
378 }
379 return GNUNET_OK;
380}
381
382
383/**
384 * Reduce absolute preferences since they got old.
385 *
386 * @param cls unused
387 */
388static void
389preference_aging (void *cls)
390{
391 struct AgeContext ac;
392
393 aging_task = NULL;
394 GAS_plugin_solver_lock ();
395 ac.values_to_update = 0;
396 for (ac.cur_client = pc_head; NULL != ac.cur_client; ac.cur_client =
397 ac.cur_client->next)
398 GNUNET_CONTAINER_multipeermap_iterate (ac.cur_client->peer2pref,
399 &age_values,
400 &ac);
401 GAS_plugin_solver_unlock ();
402 if (ac.values_to_update > 0)
403 {
404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
405 "Rescheduling aging task due to %u elements remaining to age\n",
406 ac.values_to_update);
407 if (NULL == aging_task)
408 aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL,
409 &preference_aging,
410 NULL);
411 }
412 else
413 {
414 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
415 "No values to age left, not rescheduling aging task\n");
416 }
417}
418
419
420/**
421 * Closure for #update_rel_sum() and #update_abs_sum().
422 */
423struct UpdateContext
424{
425 /**
426 * Preference client with the sum of all absolute scores.
427 */
428 struct PreferenceClient *pc;
429
430 /**
431 * Which kind are we updating?
432 */
433 enum GNUNET_ATS_PreferenceKind kind;
434};
435
436
437/**
438 * Compute updated absolute score for the client based on the
439 * current absolute scores for each peer.
440 *
441 * @param cls a `struct UpdateContext`
442 * @param peer peer being updated
443 * @param value the `struct PreferencePeer` for the peer
444 * @return #GNUNET_OK (continue to iterate)
445 */
446static int
447update_abs_sum (void *cls,
448 const struct GNUNET_PeerIdentity *peer,
449 void *value)
450{
451 struct UpdateContext *uc = cls;
452 struct PreferencePeer *p_cur = value;
453
454 uc->pc->f_abs_sum[uc->kind] += p_cur->f_abs[uc->kind];
455 return GNUNET_OK;
456}
457
458
459/**
460 * Compute updated relative score for each peer based on the
461 * current absolute score given by this client.
462 *
463 * @param cls a `struct UpdateContext`
464 * @param peer peer being updated
465 * @param value the `struct PreferencePeer` for the peer (updated)
466 * @return #GNUNET_OK (continue to iterate)
467 */
468static int
469update_rel_sum (void *cls,
470 const struct GNUNET_PeerIdentity *peer,
471 void *value)
472{
473 struct UpdateContext *uc = cls;
474 struct PreferencePeer *p_cur = value;
475
476 p_cur->f_rel[uc->kind] = p_cur->f_abs[uc->kind] / uc->pc->f_abs_sum[uc->kind];
477 LOG (GNUNET_ERROR_TYPE_DEBUG,
478 "Client has relative preference for %s for peer `%s' of %.3f\n",
479 GNUNET_ATS_print_preference_type (uc->kind),
480 GNUNET_i2s (peer),
481 p_cur->f_rel[uc->kind]);
482 return GNUNET_OK;
483}
484
485
486/**
487 * Recalculate preference for a specific ATS property
488 *
489 * @param c the preference client
490 * @param kind the preference kind
491 * @return the result
492 */
493static void
494recalculate_relative_preferences (struct PreferenceClient *c,
495 enum GNUNET_ATS_PreferenceKind kind)
496{
497 struct UpdateContext uc;
498
499 /* For this client: sum of absolute preference values for this preference */
500 uc.kind = kind;
501 uc.pc = c;
502 c->f_abs_sum[kind] = 0.0;
503
504 /* For all peers: calculate sum of absolute preferences */
505 GNUNET_CONTAINER_multipeermap_iterate (c->peer2pref,
506 &update_abs_sum,
507 &uc);
508 LOG (GNUNET_ERROR_TYPE_DEBUG,
509 "Client has sum of total preferences for %s of %.3f\n",
510 GNUNET_ATS_print_preference_type (kind),
511 c->f_abs_sum[kind]);
512
513 /* For all peers: calculate relative preference */
514 GNUNET_CONTAINER_multipeermap_iterate (c->peer2pref,
515 &update_rel_sum,
516 &uc);
517}
518
519
520/**
521 * The relative preferences of one of the clients have
522 * changed, update the global preferences for the given
523 * peer and notify the plugin.
524 *
525 * @param cls the kind of preference to calculate the
526 * new global relative preference values for
527 * @param key the peer to update relative preference values for
528 * @param value a `struct PeerRelative`, unused
529 */
530static int
531update_iterator (void *cls,
532 const struct GNUNET_PeerIdentity *key,
533 void *value)
534{
535 enum GNUNET_ATS_PreferenceKind *kind = cls;
536
537 update_relative_values_for_peer (key,
538 *kind);
539 return GNUNET_OK;
540}
541
542
543/**
544 * Update the absolute preference and calculate the
545 * new relative preference value.
546 *
547 * @param client the client with this preference
548 * @param peer the peer to change the preference for
549 * @param kind the kind to change the preference
550 * @param score_abs the normalized score
551 */
552static void
553update_preference (struct GNUNET_SERVICE_Client *client,
554 const struct GNUNET_PeerIdentity *peer,
555 enum GNUNET_ATS_PreferenceKind kind,
556 float score_abs)
557{
558 struct PreferenceClient *c_cur;
559 struct PreferencePeer *p_cur;
560 struct PeerRelative *r_cur;
561 unsigned int i;
562
563 if (kind >= GNUNET_ATS_PREFERENCE_END)
564 {
565 GNUNET_break (0);
566 return;
567 }
568 LOG (GNUNET_ERROR_TYPE_DEBUG,
569 "Client changes preference for peer `%s' for `%s' to %.2f\n",
570 GNUNET_i2s (peer),
571 GNUNET_ATS_print_preference_type (kind),
572 score_abs);
573
574 /* Find preference client */
575 for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next)
576 if (client == c_cur->client)
577 break;
578 /* Not found: create new preference client */
579 if (NULL == c_cur)
580 {
581 c_cur = GNUNET_new (struct PreferenceClient);
582 c_cur->client = client;
583 c_cur->peer2pref = GNUNET_CONTAINER_multipeermap_create (16,
584 GNUNET_NO);
585 for (i = 0; i < GNUNET_ATS_PREFERENCE_END; i++)
586 c_cur->f_abs_sum[i] = DEFAULT_ABS_PREFERENCE;
587 GNUNET_CONTAINER_DLL_insert (pc_head,
588 pc_tail,
589 c_cur);
590 }
591
592 /* check global peer entry exists */
593 if (NULL ==
594 (r_cur = GNUNET_CONTAINER_multipeermap_get (preference_peers,
595 peer)))
596 {
597 /* Create struct for peer */
598 r_cur = GNUNET_new (struct PeerRelative);
599 for (i = 0; i < GNUNET_ATS_PREFERENCE_END; i++)
600 r_cur->f_rel[i] = DEFAULT_REL_PREFERENCE;
601 GNUNET_assert (GNUNET_OK ==
602 GNUNET_CONTAINER_multipeermap_put (preference_peers,
603 peer,
604 r_cur,
605 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
606 }
607
608 /* Find entry for peer */
609 p_cur = GNUNET_CONTAINER_multipeermap_get (c_cur->peer2pref,
610 peer);
611 if (NULL == p_cur)
612 {
613 /* Not found: create new peer entry */
614 p_cur = GNUNET_new (struct PreferencePeer);
615 for (i = 0; i < GNUNET_ATS_PREFERENCE_END; i++)
616 {
617 /* Default value per peer absolute preference for a preference*/
618 p_cur->f_abs[i] = DEFAULT_ABS_PREFERENCE;
619 /* Default value per peer relative preference for a quality */
620 p_cur->f_rel[i] = DEFAULT_REL_PREFERENCE;
621 }
622 GNUNET_assert (GNUNET_YES ==
623 GNUNET_CONTAINER_multipeermap_put (c_cur->peer2pref,
624 peer,
625 p_cur,
626 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
627 r_cur->num_clients++;
628 }
629
630 p_cur->f_abs[kind] += score_abs;
631 recalculate_relative_preferences (c_cur, kind);
632 GNUNET_CONTAINER_multipeermap_iterate (preference_peers,
633 &update_iterator,
634 &kind);
635
636 if (NULL == aging_task)
637 aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL,
638 &preference_aging,
639 NULL);
640}
641
642
643/**
644 * Handle 'preference change' messages from clients.
645 *
646 * @param client the client that sent the request
647 * @param msg the request message
648 */
649void
650GAS_handle_preference_change (struct GNUNET_SERVICE_Client *client,
651 const struct ChangePreferenceMessage *msg)
652{
653 const struct PreferenceInformation *pi;
654 uint32_t nump;
655
656 nump = ntohl (msg->num_preferences);
657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
658 "Received PREFERENCE_CHANGE message for peer `%s'\n",
659 GNUNET_i2s (&msg->peer));
660 GNUNET_STATISTICS_update (GSA_stats,
661 "# preference change requests processed",
662 1,
663 GNUNET_NO);
664 pi = (const struct PreferenceInformation *) &msg[1];
665 GAS_plugin_solver_lock ();
666 for (uint32_t i = 0; i < nump; i++)
667 update_preference (client,
668 &msg->peer,
669 (enum GNUNET_ATS_PreferenceKind) ntohl (
670 pi[i].preference_kind),
671 pi[i].preference_value);
672 GAS_plugin_solver_unlock ();
673}
674
675
676/**
677 * Initialize preferences subsystem.
678 */
679void
680GAS_preference_init ()
681{
682 unsigned int i;
683
684 preference_peers = GNUNET_CONTAINER_multipeermap_create (16,
685 GNUNET_NO);
686 for (i = 0; i < GNUNET_ATS_PREFERENCE_END; i++)
687 defvalues.f_rel[i] = DEFAULT_REL_PREFERENCE;
688}
689
690
691/**
692 * Shutdown preferences subsystem.
693 */
694void
695GAS_preference_done ()
696{
697 struct PreferenceClient *pc;
698 struct PreferenceClient *next_pc;
699
700 if (NULL != aging_task)
701 {
702 GNUNET_SCHEDULER_cancel (aging_task);
703 aging_task = NULL;
704 }
705 next_pc = pc_head;
706 while (NULL != (pc = next_pc))
707 {
708 next_pc = pc->next;
709 GNUNET_CONTAINER_DLL_remove (pc_head,
710 pc_tail,
711 pc);
712 GNUNET_CONTAINER_multipeermap_iterate (pc->peer2pref,
713 &free_preference,
714 pc);
715 GNUNET_CONTAINER_multipeermap_destroy (pc->peer2pref);
716 GNUNET_free (pc);
717 }
718 GNUNET_CONTAINER_multipeermap_iterate (preference_peers,
719 &free_peer,
720 NULL);
721 GNUNET_CONTAINER_multipeermap_destroy (preference_peers);
722}
723
724
725/**
726 * Get the normalized preference values for a specific peer or
727 * the default values if
728 *
729 * @param cls ignored
730 * @param id the peer
731 * @return pointer to the values, can be indexed with GNUNET_ATS_PreferenceKind,
732 * default preferences if peer does not exist
733 */
734const double *
735GAS_preference_get_by_peer (void *cls,
736 const struct GNUNET_PeerIdentity *id)
737{
738 struct PeerRelative *rp;
739
740 if (NULL ==
741 (rp = GNUNET_CONTAINER_multipeermap_get (preference_peers,
742 id)))
743 {
744 return defvalues.f_rel;
745 }
746 return rp->f_rel;
747}
748
749
750/**
751 * A performance client disconnected
752 *
753 * @param client the client
754 */
755void
756GAS_preference_client_disconnect (struct GNUNET_SERVICE_Client *client)
757{
758 struct PreferenceClient *c_cur;
759
760 for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next)
761 if (client == c_cur->client)
762 break;
763 if (NULL == c_cur)
764 return;
765 GNUNET_CONTAINER_DLL_remove (pc_head,
766 pc_tail,
767 c_cur);
768 GNUNET_CONTAINER_multipeermap_iterate (c_cur->peer2pref,
769 &free_preference,
770 c_cur);
771 GNUNET_CONTAINER_multipeermap_destroy (c_cur->peer2pref);
772 GNUNET_free (c_cur);
773}
774
775
776/* end of gnunet-service-ats_preferences.c */
diff --git a/src/ats/gnunet-service-ats_preferences.h b/src/ats/gnunet-service-ats_preferences.h
deleted file mode 100644
index 49bf2ddbd..000000000
--- a/src/ats/gnunet-service-ats_preferences.h
+++ /dev/null
@@ -1,93 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2014 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/gnunet-service-ats_preferences.h
22 * @brief manage preferences expressed by clients
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_ATS_PREFERENCES_H
27#define GNUNET_SERVICE_ATS_PREFERENCES_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_ats_service.h"
31#include "gnunet-service-ats.h"
32#include "gnunet_statistics_service.h"
33#include "ats.h"
34
35/**
36 * Default preference value we assume if we know nothing.
37 */
38#define DEFAULT_ABS_PREFERENCE 0.0
39
40/**
41 * Default relative preference value we assume if we know nothing.
42 */
43#define DEFAULT_REL_PREFERENCE 0.0
44
45
46/**
47 * Handle 'preference change' messages from clients.
48 *
49 * @param client the client that sent the request
50 * @param msg the request message
51 */
52void
53GAS_handle_preference_change (struct GNUNET_SERVICE_Client *client,
54 const struct ChangePreferenceMessage *msg);
55
56
57/**
58 * Initialize preferences subsystem.
59 */
60void
61GAS_preference_init (void);
62
63
64/**
65 * Shutdown preferences subsystem.
66 */
67void
68GAS_preference_done (void);
69
70
71/**
72 * Get the normalized preference values for a specific peer.
73 *
74 * @param cls ignored
75 * @param id the peer
76 * @return pointer to the values, can be indexed
77 * with `enum GNUNET_ATS_PreferenceKind`, never NULL
78 */
79const double *
80GAS_preference_get_by_peer (void *cls,
81 const struct GNUNET_PeerIdentity *id);
82
83
84/**
85 * A performance client disconnected
86 *
87 * @param client the disconnecting client
88 */
89void
90GAS_preference_client_disconnect (struct GNUNET_SERVICE_Client *client);
91
92
93#endif
diff --git a/src/ats/gnunet-service-ats_reservations.c b/src/ats/gnunet-service-ats_reservations.c
deleted file mode 100644
index a50e9d5b7..000000000
--- a/src/ats/gnunet-service-ats_reservations.c
+++ /dev/null
@@ -1,217 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/gnunet-service-ats_reservations.c
22 * @brief ats service, inbound bandwidth reservation management
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet-service-ats_reservations.h"
27#include "gnunet-service-ats.h"
28#include "ats.h"
29
30/**
31 * Number of seconds that available bandwidth carries over
32 * (can accumulate). Note that the
33 * test_ats_reservation_api test depends on this value!
34 */
35#define MAX_BANDWIDTH_CARRY_S 5
36
37
38/**
39 * Map of peer identities to `struct GNUNET_BANDWIDTH_Tracker *`s
40 */
41static struct GNUNET_CONTAINER_MultiPeerMap *trackers;
42
43
44/**
45 * Reserve the given amount of incoming bandwidth (in bytes) from the
46 * given peer. If a reservation is not possible right now, return how
47 * long the client should wait before trying again.
48 *
49 * @param peer peer to reserve bandwidth from
50 * @param amount number of bytes to reserve
51 * @return 0 if the reservation was successful, FOREVER if the
52 * peer is not connected, otherwise the time to wait
53 * until the reservation might succeed
54 */
55static struct GNUNET_TIME_Relative
56reservations_reserve (const struct GNUNET_PeerIdentity *peer,
57 int32_t amount)
58{
59 struct GNUNET_BANDWIDTH_Tracker *tracker;
60 struct GNUNET_TIME_Relative ret;
61
62 tracker = GNUNET_CONTAINER_multipeermap_get (trackers,
63 peer);
64 if (NULL == tracker)
65 {
66 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
67 "Not connected, allowing reservation of %d bytes\n",
68 (int) amount);
69 return GNUNET_TIME_UNIT_ZERO; /* not connected, satisfy now */
70 }
71 if (amount >= 0)
72 {
73 ret = GNUNET_BANDWIDTH_tracker_get_delay (tracker, amount);
74 if (ret.rel_value_us > 0)
75 {
76 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
77 "Delay to satisfy reservation for %d bytes is %s\n",
78 (int) amount,
79 GNUNET_STRINGS_relative_time_to_string (ret,
80 GNUNET_YES));
81 return ret;
82 }
83 }
84 (void) GNUNET_BANDWIDTH_tracker_consume (tracker, amount);
85 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
86 "Reserved %d bytes\n",
87 (int) amount);
88 return GNUNET_TIME_UNIT_ZERO;
89}
90
91
92/**
93 * Set the amount of bandwidth the other peer could currently transmit
94 * to us (as far as we know) to the given value.
95 *
96 * @param peer identity of the peer
97 * @param bandwidth_in currently available bandwidth from that peer to
98 * this peer (estimate)
99 */
100void
101GAS_reservations_set_bandwidth (const struct GNUNET_PeerIdentity *peer,
102 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
103{
104 struct GNUNET_BANDWIDTH_Tracker *tracker;
105
106 tracker = GNUNET_CONTAINER_multipeermap_get (trackers, peer);
107 if (0 == ntohl (bandwidth_in.value__))
108 {
109 if (NULL == tracker)
110 return;
111 GNUNET_assert (GNUNET_YES ==
112 GNUNET_CONTAINER_multipeermap_remove (trackers,
113 peer,
114 tracker));
115 GNUNET_free (tracker);
116 return;
117 }
118 if (NULL == tracker)
119 {
120 tracker = GNUNET_new (struct GNUNET_BANDWIDTH_Tracker);
121 GNUNET_BANDWIDTH_tracker_init (tracker,
122 NULL,
123 NULL,
124 bandwidth_in,
125 MAX_BANDWIDTH_CARRY_S);
126 GNUNET_assert (GNUNET_OK ==
127 GNUNET_CONTAINER_multipeermap_put (trackers,
128 peer,
129 tracker,
130 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
131 return;
132 }
133 GNUNET_BANDWIDTH_tracker_update_quota (tracker,
134 bandwidth_in);
135}
136
137
138/**
139 * Handle 'reservation request' messages from clients.
140 *
141 * @param client client that sent the request
142 * @param msg the request message
143 */
144void
145GAS_handle_reservation_request (struct GNUNET_SERVICE_Client *client,
146 const struct ReservationRequestMessage *msg)
147{
148 struct GNUNET_MQ_Envelope *env;
149 struct ReservationResultMessage *result;
150 int32_t amount;
151 struct GNUNET_TIME_Relative res_delay;
152
153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
154 "Received RESERVATION_REQUEST message\n");
155 amount = (int32_t) ntohl (msg->amount);
156 res_delay = reservations_reserve (&msg->peer, amount);
157 if (res_delay.rel_value_us > 0)
158 amount = 0;
159 env = GNUNET_MQ_msg (result,
160 GNUNET_MESSAGE_TYPE_ATS_RESERVATION_RESULT);
161 result->amount = htonl (amount);
162 result->peer = msg->peer;
163 result->res_delay = GNUNET_TIME_relative_hton (res_delay);
164 GNUNET_STATISTICS_update (GSA_stats,
165 "# reservation requests processed",
166 1,
167 GNUNET_NO);
168 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
169 env);
170}
171
172
173/**
174 * Initialize reservations subsystem.
175 */
176void
177GAS_reservations_init ()
178{
179 trackers = GNUNET_CONTAINER_multipeermap_create (128,
180 GNUNET_NO);
181}
182
183
184/**
185 * Free memory of bandwidth tracker.
186 *
187 * @param cls NULL
188 * @param key peer identity (unused)
189 * @param value the `struct GNUNET_BANDWIDTH_Tracker` to free
190 * @return #GNUNET_OK (continue to iterate)
191 */
192static int
193free_tracker (void *cls,
194 const struct GNUNET_PeerIdentity *key,
195 void *value)
196{
197 struct GNUNET_BANDWIDTH_Tracker *tracker = value;
198
199 GNUNET_free (tracker);
200 return GNUNET_OK;
201}
202
203
204/**
205 * Shutdown reservations subsystem.
206 */
207void
208GAS_reservations_done ()
209{
210 GNUNET_CONTAINER_multipeermap_iterate (trackers,
211 &free_tracker,
212 NULL);
213 GNUNET_CONTAINER_multipeermap_destroy (trackers);
214}
215
216
217/* end of gnunet-service-ats_reservations.c */
diff --git a/src/ats/gnunet-service-ats_reservations.h b/src/ats/gnunet-service-ats_reservations.h
deleted file mode 100644
index d95945697..000000000
--- a/src/ats/gnunet-service-ats_reservations.h
+++ /dev/null
@@ -1,74 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_reservations.h
23 * @brief ats service, inbound bandwidth reservation management
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_ATS_RESERVATIONS_H
27#define GNUNET_SERVICE_ATS_RESERVATIONS_H
28
29#include "gnunet_util_lib.h"
30#include "ats.h"
31
32
33/**
34 * Set the amount of bandwidth the other peer could currently transmit
35 * to us (as far as we know) to the given value.
36 *
37 * @param peer identity of the peer
38 * @param bandwidth_in currently available bandwidth from that peer to
39 * this peer (estimate)
40 */
41void
42GAS_reservations_set_bandwidth (const struct GNUNET_PeerIdentity *peer,
43 struct GNUNET_BANDWIDTH_Value32NBO
44 bandwidth_in);
45
46
47/**
48 * Handle 'reservation request' messages from clients.
49 *
50 * @param client client that sent the request
51 * @param message the request message
52 */
53void
54GAS_handle_reservation_request (struct GNUNET_SERVICE_Client *client,
55 const struct
56 ReservationRequestMessage *message);
57
58
59/**
60 * Initialize reservations subsystem.
61 *
62 * @param server handle to our server
63 */
64void
65GAS_reservations_init (void);
66
67
68/**
69 * Shutdown reservations subsystem.
70 */
71void
72GAS_reservations_done (void);
73
74#endif
diff --git a/src/ats/gnunet-service-ats_scheduling.c b/src/ats/gnunet-service-ats_scheduling.c
deleted file mode 100644
index 456c222a9..000000000
--- a/src/ats/gnunet-service-ats_scheduling.c
+++ /dev/null
@@ -1,209 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_scheduling.c
23 * @brief ats service, interaction with 'scheduling' API
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet-service-ats_addresses.h"
29#include "gnunet-service-ats_scheduling.h"
30#include "ats.h"
31
32/**
33 * Actual handle to the client.
34 */
35static struct GNUNET_SERVICE_Client *my_client;
36
37
38/**
39 * Register a new scheduling client.
40 *
41 * @param client handle of the new client
42 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
43 */
44int
45GAS_scheduling_add_client (struct GNUNET_SERVICE_Client *client)
46{
47 if (NULL != my_client)
48 {
49 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
50 "This ATS already has a scheduling client, refusing new scheduling client for now.\n");
51 return GNUNET_SYSERR;
52 }
53 my_client = client;
54 return GNUNET_OK;
55}
56
57
58/**
59 * Unregister a client (which may have been a scheduling client,
60 * but this is not assured).
61 *
62 * @param client handle of the (now dead) client
63 */
64void
65GAS_scheduling_remove_client (struct GNUNET_SERVICE_Client *client)
66{
67 if (my_client != client)
68 return;
69 GAS_addresses_destroy_all ();
70 my_client = NULL;
71}
72
73
74/**
75 * Transmit the given address suggestion and bandwidth update to all scheduling
76 * clients.
77 *
78 * @param peer peer for which this is an address suggestion
79 * @param session_id session ID to use for the given client
80 * @param bandwidth_out assigned outbound bandwidth
81 * @param bandwidth_in assigned inbound bandwidth
82 */
83void
84GAS_scheduling_transmit_address_suggestion (const struct
85 GNUNET_PeerIdentity *peer,
86 uint32_t session_id,
87 struct GNUNET_BANDWIDTH_Value32NBO
88 bandwidth_out,
89 struct GNUNET_BANDWIDTH_Value32NBO
90 bandwidth_in)
91{
92 struct GNUNET_MQ_Envelope *env;
93 struct AddressSuggestionMessage *msg;
94
95 if (NULL == my_client)
96 return;
97 GNUNET_STATISTICS_update (GSA_stats,
98 "# address suggestions made",
99 1,
100 GNUNET_NO);
101 env = GNUNET_MQ_msg (msg,
102 GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION);
103 msg->peer = *peer;
104 msg->session_id = htonl (session_id);
105 msg->bandwidth_out = bandwidth_out;
106 msg->bandwidth_in = bandwidth_in;
107 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
108 "ATS sends quota for peer `%s': (in/out) %u/%u\n",
109 GNUNET_i2s (peer),
110 (unsigned int) ntohl (bandwidth_in.value__),
111 (unsigned int) ntohl (bandwidth_out.value__));
112 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (my_client),
113 env);
114}
115
116
117/**
118 * Handle 'address add' messages from clients.
119 *
120 * @param m the request message
121 */
122void
123GAS_handle_address_add (const struct AddressAddMessage *m)
124{
125 const char *address;
126 const char *plugin_name;
127 uint16_t address_length;
128 uint16_t plugin_name_length;
129 struct GNUNET_ATS_Properties prop;
130
131 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
132 "Received `%s' message\n",
133 "ADDRESS_ADD");
134 address_length = ntohs (m->address_length);
135 plugin_name_length = ntohs (m->plugin_name_length);
136 address = (const char *) &m[1];
137 if (plugin_name_length != 0)
138 plugin_name = &address[address_length];
139 else
140 plugin_name = "";
141 GNUNET_STATISTICS_update (GSA_stats,
142 "# addresses created",
143 1,
144 GNUNET_NO);
145 GNUNET_ATS_properties_ntoh (&prop,
146 &m->properties);
147 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop.scope);
148 GAS_addresses_add (&m->peer,
149 plugin_name,
150 address,
151 address_length,
152 ntohl (m->address_local_info),
153 ntohl (m->session_id),
154 &prop);
155}
156
157
158/**
159 * Handle 'address update' messages from clients.
160 *
161 * @param m the request message
162 */
163void
164GAS_handle_address_update (const struct AddressUpdateMessage *m)
165{
166 struct GNUNET_ATS_Properties prop;
167
168 GNUNET_STATISTICS_update (GSA_stats,
169 "# address updates received",
170 1,
171 GNUNET_NO);
172 GNUNET_ATS_properties_ntoh (&prop,
173 &m->properties);
174 GAS_addresses_update (&m->peer,
175 ntohl (m->session_id),
176 &prop);
177}
178
179
180/**
181 * Handle 'address destroyed' messages from clients.
182 *
183 * @param m the request message
184 */
185void
186GAS_handle_address_destroyed (const struct AddressDestroyedMessage *m)
187{
188 struct GNUNET_MQ_Envelope *env;
189 struct GNUNET_ATS_SessionReleaseMessage *srm;
190
191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
192 "Received `%s' message\n",
193 "ADDRESS_DESTROYED");
194 GNUNET_STATISTICS_update (GSA_stats,
195 "# addresses destroyed",
196 1,
197 GNUNET_NO);
198 GAS_addresses_destroy (&m->peer,
199 ntohl (m->session_id));
200 env = GNUNET_MQ_msg (srm,
201 GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE);
202 srm->session_id = m->session_id;
203 srm->peer = m->peer;
204 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (my_client),
205 env);
206}
207
208
209/* end of gnunet-service-ats_scheduling.c */
diff --git a/src/ats/gnunet-service-ats_scheduling.h b/src/ats/gnunet-service-ats_scheduling.h
deleted file mode 100644
index d68306988..000000000
--- a/src/ats/gnunet-service-ats_scheduling.h
+++ /dev/null
@@ -1,101 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file ats/gnunet-service-ats_scheduling.h
23 * @brief ats service, interaction with 'scheduling' API
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_ATS_SCHEDULING_H
28#define GNUNET_SERVICE_ATS_SCHEDULING_H
29
30#include "gnunet_util_lib.h"
31
32
33/**
34 * Register a new scheduling client.
35 *
36 * @param client handle of the new client
37 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
38 */
39int
40GAS_scheduling_add_client (struct GNUNET_SERVICE_Client *client);
41
42
43/**
44 * Unregister a client (which may have been a scheduling client,
45 * but this is not assured).
46 *
47 * @param client handle of the (now dead) client
48 */
49void
50GAS_scheduling_remove_client (struct GNUNET_SERVICE_Client *client);
51
52
53/**
54 * Transmit the given address suggestion and bandwidth update to all scheduling
55 * clients.
56 *
57 * @param peer peer for which this is an address suggestion
58 * @param session_id session ID to use
59 * @param bandwidth_out assigned outbound bandwidth
60 * @param bandwidth_in assigned inbound bandwidth
61 */
62void
63GAS_scheduling_transmit_address_suggestion (const struct
64 GNUNET_PeerIdentity *peer,
65 uint32_t session_id,
66 struct GNUNET_BANDWIDTH_Value32NBO
67 bandwidth_out,
68 struct GNUNET_BANDWIDTH_Value32NBO
69 bandwidth_in);
70
71
72/**
73 * Handle 'address add' messages from clients.
74 *
75 * @param client client that sent the request
76 * @param m the request message
77 */
78void
79GAS_handle_address_add (const struct AddressAddMessage *m);
80
81
82/**
83 * Handle 'address update' messages from clients.
84 *
85 * @param m the request message
86 */
87void
88GAS_handle_address_update (const struct AddressUpdateMessage *m);
89
90
91/**
92 * Handle 'address destroyed' messages from clients.
93 *
94 * @param m the request message
95 */
96void
97GAS_handle_address_destroyed (const struct AddressDestroyedMessage *m);
98
99
100#endif
101/* end of gnunet-service-ats_scheduling.h */
diff --git a/src/ats/perf_ats_simplistic_bandwidth.conf b/src/ats/perf_ats_simplistic_bandwidth.conf
deleted file mode 100644
index cec5b36f5..000000000
--- a/src/ats/perf_ats_simplistic_bandwidth.conf
+++ /dev/null
@@ -1,27 +0,0 @@
1[hostlist]
2SERVERS =
3
4[transport-udp]
5BROADCAST = NO
6
7[peerinfo]
8USE_INCLUDED_HELLOS = NO
9
10# Network specific inbound/outbound quotas
11UNSPECIFIED_QUOTA_IN = 128 KiB
12UNSPECIFIED_QUOTA_OUT = 128 KiB
13# LOOPBACK
14LOOPBACK_QUOTA_IN = 128 KiB
15LOOPBACK_QUOTA_OUT = 128 KiB
16# LAN
17LAN_QUOTA_IN = 128 KiB
18LAN_QUOTA_OUT = 128 KiB
19# WAN
20WAN_QUOTA_IN = 128 KiB
21WAN_QUOTA_OUT = 128 KiB
22# WLAN
23WLAN_QUOTA_IN = 128 KiB
24WLAN_QUOTA_OUT = 128 KiB
25# BLUETOOTH
26BLUETOOTH_QUOTA_IN = 128 KiB
27BLUETOOTH_QUOTA_OUT = 128 KiB
diff --git a/src/ats/perf_ats_simplistic_delay.conf b/src/ats/perf_ats_simplistic_delay.conf
deleted file mode 100644
index a5127d25f..000000000
--- a/src/ats/perf_ats_simplistic_delay.conf
+++ /dev/null
@@ -1,8 +0,0 @@
1[hostlist]
2SERVERS =
3
4[transport-udp]
5BROADCAST = NO
6
7[peerinfo]
8USE_INCLUDED_HELLOS = NO
diff --git a/src/ats/perf_ats_solver.c b/src/ats/perf_ats_solver.c
deleted file mode 100644
index 363d0cfc9..000000000
--- a/src/ats/perf_ats_solver.c
+++ /dev/null
@@ -1,1510 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010,2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/perf_ats_solver.c
22 * @brief generic performance test for ATS solvers
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_statistics_service.h"
29#include "gnunet-service-ats_addresses.h"
30#include "gnunet-service-ats_plugins.h"
31#include "gnunet-service-ats_normalization.h"
32#include "gnunet-service-ats_preferences.h"
33#include "gnunet_ats_service.h"
34#include "gnunet_ats_plugin.h"
35#include "test_ats_api_common.h"
36
37#define DEFAULT_UPDATE_PERCENTAGE 20
38#define DEFAULT_PEERS_START 10
39#define DEFAULT_PEERS_END 10
40#define DEFAULT_ADDRESSES 10
41#define DEFAULT_ATS_COUNT 2
42
43
44/**
45 * Handle for statistics.
46 */
47struct GNUNET_STATISTICS_Handle *GSA_stats;
48
49/**
50 * Handle for ATS address component
51 */
52struct PerfHandle
53{
54 /**
55 * Performance peers
56 */
57 struct PerfPeer *peers;
58
59 /**
60 * Solver handle
61 */
62 struct GNUNET_ATS_SolverFunctions *sf;
63
64 /**
65 * Statistics stat;
66 */
67 struct GNUNET_STATISTICS_Handle *stat;
68
69 /**
70 * A multihashmap to store all addresses
71 */
72 struct GNUNET_CONTAINER_MultiPeerMap *addresses;
73
74 /**
75 * Solver functions
76 * */
77 struct GNUNET_ATS_PluginEnvironment env;
78
79 /**
80 * Array for results for each iteration with length iterations
81 */
82 struct Iteration *iterations_results;
83
84 /**
85 * The current result
86 */
87 struct Result *current_result;
88
89 /**
90 * Current number of peers benchmarked
91 */
92 int current_p;
93
94 /**
95 * Current number of addresses benchmarked
96 */
97 int current_a;
98
99 /**
100 * Solver description as string
101 */
102 char *ats_string;
103
104 /**
105 * Configured ATS solver
106 */
107 int ats_mode;
108
109 /**
110 * #peers to start benchmarking with
111 */
112 int N_peers_start;
113
114 /**
115 * #peers to end benchmarking with
116 */
117 int N_peers_end;
118
119 /**
120 * #addresses to benchmarking with
121 */
122 int N_address;
123
124 /**
125 * Percentage of peers to update
126 */
127 int opt_update_percent;
128
129 /**
130 * Create gnuplot file
131 */
132 int create_datafile;
133
134 /**
135 * Measure updates
136 */
137 int measure_updates;
138
139 /**
140 * Number of iterations
141 */
142 int total_iterations;
143
144 /**
145 * Current iteration
146 */
147 int current_iteration;
148
149 /**
150 * Is a bulk operation running?
151 */
152 int bulk_running;
153
154 /**
155 * Is a bulk operation running?
156 */
157 int expecting_solution;
158
159 /**
160 * Was the problem just updates?
161 */
162 int performed_update;
163};
164
165/**
166 * Data structure to store results for a single iteration
167 */
168struct Iteration
169{
170 struct Result **results_array;
171
172 struct Result **update_results_array;
173};
174
175
176/**
177 * Result for a solver calculation
178 */
179struct Result
180{
181 /**
182 * Previous element in the linked list
183 */
184 struct Result *prev;
185
186 /**
187 * Next element in the linked list
188 */
189 struct Result *next;
190
191 /**
192 * Number of peers this solution included
193 */
194 int peers;
195
196 /**
197 * Number of addresses per peer this solution included
198 */
199 int addresses;
200
201 /**
202 * Is this an update or a full solution
203 */
204 int update;
205
206 /**
207 * Was the solution valid or did the solver fail
208 */
209 int valid;
210
211 /**
212 * Result of the solver
213 */
214 enum GAS_Solver_Additional_Information info;
215
216 /**
217 * Duration of setting up the problem in the solver
218 */
219 struct GNUNET_TIME_Relative d_setup_full;
220
221 /**
222 * Duration of solving the LP problem in the solver
223 * MLP solver only
224 */
225 struct GNUNET_TIME_Relative d_lp_full;
226
227 /**
228 * Duration of solving the MLP problem in the solver
229 * MLP solver only
230 */
231 struct GNUNET_TIME_Relative d_mlp_full;
232
233 /**
234 * Duration of solving whole problem in the solver
235 */
236 struct GNUNET_TIME_Relative d_total_full;
237
238 /**
239 * Start time of setting up the problem in the solver
240 */
241 struct GNUNET_TIME_Absolute s_setup;
242
243 /**
244 * Start time of solving the LP problem in the solver
245 * MLP solver only
246 */
247 struct GNUNET_TIME_Absolute s_lp;
248
249 /**
250 * Start time of solving the MLP problem in the solver
251 * MLP solver only
252 */
253 struct GNUNET_TIME_Absolute s_mlp;
254
255 /**
256 * Start time of solving whole problem in the solver
257 */
258 struct GNUNET_TIME_Absolute s_total;
259
260 /**
261 * End time of setting up the problem in the solver
262 */
263 struct GNUNET_TIME_Absolute e_setup;
264
265 /**
266 * End time of solving the LP problem in the solver
267 * MLP solver only
268 */
269 struct GNUNET_TIME_Absolute e_lp;
270
271 /**
272 * End time of solving the MLP problem in the solver
273 * MLP solver only
274 */
275 struct GNUNET_TIME_Absolute e_mlp;
276
277 /**
278 * End time of solving whole problem in the solver
279 */
280 struct GNUNET_TIME_Absolute e_total;
281};
282
283/**
284 * Peer used for the benchmarking
285 */
286struct PerfPeer
287{
288 /**
289 * Peer identitity
290 */
291 struct GNUNET_PeerIdentity id;
292
293 /**
294 * Head of linked list of addresses used with this peer
295 */
296 struct ATS_Address *head;
297
298 /**
299 * Head of linked list of addresses used with this peer
300 */
301 struct ATS_Address *tail;
302};
303
304
305/**
306 * ATS performance handle
307 */
308static struct PerfHandle ph;
309
310/**
311 * Return value
312 */
313static int ret;
314
315
316/**
317 * Do shutdown
318 */
319static void
320end_now (int res)
321{
322 if (NULL != ph.stat)
323 {
324 GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
325 ph.stat = NULL;
326 }
327
328 GNUNET_free (ph.peers);
329 GNUNET_free (ph.iterations_results);
330
331 GAS_normalization_stop ();
332 GAS_preference_done ();
333 ret = res;
334}
335
336
337/**
338 * Create a peer used for benchmarking
339 *
340 * @param cp the number of the peer
341 */
342static void
343perf_create_peer (int cp)
344{
345 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
346 &ph.peers[cp].id, sizeof(struct
347 GNUNET_PeerIdentity));
348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating peer #%u: %s \n", cp,
349 GNUNET_i2s (&ph.peers[cp].id));
350}
351
352
353/**
354 * Perform an update for an address
355 *
356 * @param cur the address to update
357 */
358static void
359perf_update_address (struct ATS_Address *cur)
360{
361 int r_type;
362 int abs_val;
363 double rel_val;
364
365 r_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
366 switch (r_type)
367 {
368 case 0:
369 abs_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
370 rel_val = (100 + (double) abs_val) / 100;
371
372 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
373 "Updating peer `%s' address %p type %s abs val %u rel val %.3f\n",
374 GNUNET_i2s (&cur->peer), cur,
375 "GNUNET_ATS_QUALITY_NET_DELAY",
376 abs_val, rel_val);
377 ph.sf->s_address_update_property (ph.sf->cls, cur,
378 GNUNET_ATS_QUALITY_NET_DELAY,
379 abs_val, rel_val);
380 break;
381
382 case 1:
383 abs_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10);
384 rel_val = (100 + (double) abs_val) / 100;
385
386 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
387 "Updating peer `%s' address %p type %s abs val %u rel val %.3f\n",
388 GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DISTANCE",
389 abs_val, rel_val);
390 ph.sf->s_address_update_property (ph.sf->cls, cur,
391 GNUNET_ATS_QUALITY_NET_DISTANCE,
392 abs_val, rel_val);
393 break;
394
395 default:
396 break;
397 }
398}
399
400
401static void
402bandwidth_changed_cb (void *cls,
403 struct ATS_Address *address)
404{
405 if ((0 == address->assigned_bw_out) && (0 == address->assigned_bw_in))
406 return;
407
408 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
409 "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
410 GNUNET_i2s (&address->peer),
411 address,
412 address->assigned_bw_out,
413 address->assigned_bw_in);
414 if (GNUNET_YES == ph.bulk_running)
415 GNUNET_break (0);
416 return;
417}
418
419
420static const double *
421get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
422{
423 return GAS_preference_get_by_peer (NULL, id);
424}
425
426
427static void
428perf_address_initial_update (void *dead,
429 struct GNUNET_CONTAINER_MultiPeerMap *addresses,
430 struct ATS_Address *address)
431{
432 double delay;
433 double distance;
434 uint32_t random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
435
436 delay = (100 + (double) random) / 100;
437 ph.sf->s_address_update_property (ph.sf->cls,
438 address, GNUNET_ATS_QUALITY_NET_DELAY,
439 100, delay);
440
441 random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
442 distance = (100 + (double) random) / 100;
443
444 ph.sf->s_address_update_property (ph.sf->cls, address,
445 GNUNET_ATS_QUALITY_NET_DISTANCE,
446 10, distance);
447
448 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
449 "Initial update address %p : %.2f %.2f\n",
450 address, delay, distance);
451}
452
453
454struct DUA_Ctx
455{
456 int r;
457 int c_cur_a;
458};
459
460
461static int
462do_update_address (void *cls,
463 const struct GNUNET_PeerIdentity *pid,
464 void *value)
465{
466 struct DUA_Ctx *ctx = cls;
467 struct ATS_Address *addr = value;
468
469 if (ctx->c_cur_a == ctx->r)
470 perf_update_address (addr);
471 ctx->c_cur_a++;
472 return GNUNET_OK;
473}
474
475
476/**
477 * Update a certain percentage of peers
478 *
479 * @param cp the current number of peers
480 * @param ca the current number of addresses
481 * @param percentage_peers the percentage of peers to update
482 */
483static void
484perf_update_all_addresses (unsigned int cp, unsigned int ca, unsigned int
485 percentage_peers)
486{
487 int c_peer;
488 int c_select;
489 int c_cur_p;
490 int r;
491 int count;
492 unsigned int m[cp];
493 struct DUA_Ctx dua_ctx;
494
495 count = cp * ((double) percentage_peers / 100);
496 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
497 "Updating %u of %u peers \n", count, cp);
498
499 for (c_peer = 0; c_peer < cp; c_peer++)
500 m[c_peer] = 0;
501
502 c_select = 0;
503
504 while (c_select < count)
505 {
506 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, cp);
507 if (0 == m[r])
508 {
509 m[r] = 1;
510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
511 "Updating peer [%u] \n", r);
512 c_select++;
513 }
514 }
515 for (c_cur_p = 0; c_cur_p < cp; c_cur_p++)
516 {
517 if (1 == m[c_cur_p])
518 {
519 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, ca);
520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
521 "Updating peer [%u] address [%u]\n", c_cur_p, r);
522
523 dua_ctx.c_cur_a = 0;
524 dua_ctx.r = r;
525 GNUNET_CONTAINER_multipeermap_get_multiple (ph.addresses,
526 &ph.peers[c_cur_p].id,
527 &do_update_address,
528 &dua_ctx);
529 }
530 }
531}
532
533
534/**
535 * Create an address for a peer
536 *
537 * @param cp index of the peer
538 * @param ca index of the address
539 * @return the address
540 */
541static struct ATS_Address *
542perf_create_address (int cp, int ca)
543{
544 struct ATS_Address *a;
545
546 a = create_address (&ph.peers[cp].id,
547 "Test 1", "test 1", strlen ("test 1") + 1, 0);
548 GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a,
549 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
550 return a;
551}
552
553
554/**
555 * Information callback for the solver
556 *
557 * @param op the solver operation
558 * @param stat status of the solver operation
559 * @param add additional solver information
560 */
561static void
562solver_info_cb (void *cls,
563 enum GAS_Solver_Operation op,
564 enum GAS_Solver_Status stat,
565 enum GAS_Solver_Additional_Information add)
566{
567 char *add_info;
568
569 switch (add)
570 {
571 case GAS_INFO_NONE:
572 add_info = "GAS_INFO_NONE";
573 break;
574
575 case GAS_INFO_FULL:
576 add_info = "GAS_INFO_MLP_FULL";
577 break;
578
579 case GAS_INFO_UPDATED:
580 add_info = "GAS_INFO_MLP_UPDATED";
581 break;
582
583 case GAS_INFO_PROP_ALL:
584 add_info = "GAS_INFO_PROP_ALL";
585 break;
586
587 case GAS_INFO_PROP_SINGLE:
588 add_info = "GAS_INFO_PROP_SINGLE";
589 break;
590
591 default:
592 add_info = "INVALID";
593 break;
594 }
595
596 struct Result *tmp;
597 switch (op)
598 {
599 case GAS_OP_SOLVE_START:
600 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
601 "Solver notifies `%s' with result `%s' `%s'\n",
602 "GAS_OP_SOLVE_START",
603 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
604 if (GNUNET_NO == ph.expecting_solution)
605 {
606 /* We do not expect a solution at the moment */
607 GNUNET_break (0);
608 return;
609 }
610
611 if ((GAS_STAT_SUCCESS == stat) && (NULL == ph.current_result))
612 {
613 tmp = GNUNET_new (struct Result);
614 /* Create new result */
615 if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update))
616 {
617 ph.current_result = tmp;
618 // fprintf (stderr,"UPDATE %u %u\n",ph.current_iteration-1, ph.current_p);
619 ph.iterations_results[ph.current_iteration
620 - 1].update_results_array[ph.current_p] = tmp;
621 }
622 else
623 {
624 ph.current_result = tmp;
625 // fprintf (stderr,"FULL %u %u\n",ph.current_iteration-1, ph.current_p);
626 ph.iterations_results[ph.current_iteration
627 - 1].results_array[ph.current_p] = tmp;
628 }
629
630 ph.current_result->addresses = ph.current_a;
631 ph.current_result->peers = ph.current_p;
632 ph.current_result->s_total = GNUNET_TIME_absolute_get ();
633 ph.current_result->d_total_full = GNUNET_TIME_UNIT_FOREVER_REL;
634 ph.current_result->d_setup_full = GNUNET_TIME_UNIT_FOREVER_REL;
635 ph.current_result->d_lp_full = GNUNET_TIME_UNIT_FOREVER_REL;
636 ph.current_result->d_mlp_full = GNUNET_TIME_UNIT_FOREVER_REL;
637 ph.current_result->info = add;
638 if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update))
639 {
640 ph.current_result->update = GNUNET_YES;
641 }
642 else
643 {
644 ph.current_result->update = GNUNET_NO;
645 }
646 }
647 return;
648
649 case GAS_OP_SOLVE_STOP:
650 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
651 "Solver notifies `%s' with result `%s', `%s'\n",
652 "GAS_OP_SOLVE_STOP",
653 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
654 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
655 {
656 /* We do not expect a solution at the moment */
657 GNUNET_break (0);
658 return;
659 }
660
661 if (GAS_STAT_SUCCESS == stat)
662 ph.current_result->valid = GNUNET_YES;
663 else
664 ph.current_result->valid = GNUNET_NO;
665
666 if (NULL != ph.current_result)
667 {
668 /* Finalize result */
669 ph.current_result->e_total = GNUNET_TIME_absolute_get ();
670 ph.current_result->d_total_full = GNUNET_TIME_absolute_get_difference (
671 ph.current_result->s_total, ph.current_result->e_total);
672 }
673 ph.current_result = NULL;
674 return;
675
676 case GAS_OP_SOLVE_SETUP_START:
677 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
678 "Solver notifies `%s' with result `%s'\n",
679 "GAS_OP_SOLVE_SETUP_START",
680 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
681 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
682 {
683 GNUNET_break (0);
684 return;
685 }
686
687 if (GAS_STAT_SUCCESS == stat)
688 ph.current_result->valid = GNUNET_YES;
689 else
690 ph.current_result->valid = GNUNET_NO;
691
692 ph.current_result->s_setup = GNUNET_TIME_absolute_get ();
693 return;
694
695 case GAS_OP_SOLVE_SETUP_STOP:
696 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
697 "Solver notifies `%s' with result `%s'\n",
698 "GAS_OP_SOLVE_SETUP_STOP",
699 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
700 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
701 {
702 GNUNET_break (0);
703 return;
704 }
705
706 if (GAS_STAT_SUCCESS == stat)
707 ph.current_result->valid = GNUNET_YES;
708 else
709 ph.current_result->valid = GNUNET_NO;
710
711 ph.current_result->e_setup = GNUNET_TIME_absolute_get ();
712 ph.current_result->d_setup_full = GNUNET_TIME_absolute_get_difference (
713 ph.current_result->s_setup, ph.current_result->e_setup);
714 return;
715
716 case GAS_OP_SOLVE_MLP_LP_START:
717 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
718 "Solver notifies `%s' with result `%s'\n",
719 "GAS_OP_SOLVE_LP_START",
720 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
721 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
722 {
723 GNUNET_break (0);
724 return;
725 }
726
727 if (GAS_STAT_SUCCESS == stat)
728 ph.current_result->valid = GNUNET_YES;
729 else
730 ph.current_result->valid = GNUNET_NO;
731
732 ph.current_result->s_lp = GNUNET_TIME_absolute_get ();
733 return;
734
735 case GAS_OP_SOLVE_MLP_LP_STOP:
736 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
737 "Solver notifies `%s' with result `%s'\n",
738 "GAS_OP_SOLVE_LP_STOP",
739 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
740 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
741 {
742 GNUNET_break (0);
743 return;
744 }
745
746 if (GAS_STAT_SUCCESS == stat)
747 ph.current_result->valid = GNUNET_YES;
748 else
749 ph.current_result->valid = GNUNET_NO;
750
751 ph.current_result->e_lp = GNUNET_TIME_absolute_get ();
752 ph.current_result->d_lp_full = GNUNET_TIME_absolute_get_difference (
753 ph.current_result->s_lp, ph.current_result->e_lp);
754 return;
755
756 case GAS_OP_SOLVE_MLP_MLP_START:
757 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
758 "Solver notifies `%s' with result `%s'\n",
759 "GAS_OP_SOLVE_MLP_START",
760 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
761 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
762 {
763 GNUNET_break (0);
764 return;
765 }
766
767 if (GAS_STAT_SUCCESS == stat)
768 ph.current_result->valid = GNUNET_YES;
769 else
770 ph.current_result->valid = GNUNET_NO;
771
772 ph.current_result->s_mlp = GNUNET_TIME_absolute_get ();
773 return;
774
775 case GAS_OP_SOLVE_MLP_MLP_STOP:
776 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
777 "Solver notifies `%s' with result `%s'\n",
778 "GAS_OP_SOLVE_MLP_STOP",
779 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
780 if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
781 {
782 GNUNET_break (0);
783 return;
784 }
785
786 if (GAS_STAT_SUCCESS == stat)
787 ph.current_result->valid = GNUNET_YES;
788 else
789 ph.current_result->valid = GNUNET_NO;
790
791 ph.current_result->e_mlp = GNUNET_TIME_absolute_get ();
792 ph.current_result->d_mlp_full = GNUNET_TIME_absolute_get_difference (
793 ph.current_result->s_mlp, ph.current_result->e_mlp);
794 return;
795
796 case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
797 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
798 "Solver notifies `%s' with result `%s'\n",
799 "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
800 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
801 return;
802
803 case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
804 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
805 "Solver notifies `%s' with result `%s'\n",
806 "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
807 (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
808 if (GAS_STAT_SUCCESS != stat)
809 {
810 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
811 "Solver `%s' failed to update problem with %u peers and %u address!\n",
812 ph.ats_string, ph.current_p, ph.current_a);
813 }
814
815 return;
816
817 default:
818 break;
819 }
820}
821
822
823/**
824 * Evaluate results for a specific iteration
825 *
826 * @param iteration the iteration to evaluate
827 */
828static void
829evaluate (int iteration)
830{
831 struct Result *cur;
832 int cp;
833
834 for (cp = ph.N_peers_start; cp <= ph.N_peers_end; cp++)
835 {
836 cur = ph.iterations_results[ph.current_iteration - 1].results_array[cp];
837 if (0 == cp)
838 continue;
839 if (NULL == cur)
840 {
841 GNUNET_break (0);
842 fprintf (stderr,
843 "Missing result for %u peers\n", cp);
844 continue;
845 }
846
847
848 if (GNUNET_NO == cur->valid)
849 {
850 fprintf (stderr,
851 "Total time to solve %s for %u peers %u addresses: %s\n",
852 (GNUNET_YES == cur->update) ? "updated" : "full",
853 cur->peers, cur->addresses, "Failed to solve!");
854 continue;
855 }
856
857
858 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
859 cur->d_total_full.rel_value_us)
860 {
861 fprintf (stderr,
862 "Total time to solve %s for %u peers %u addresses: %llu us\n",
863 (GNUNET_YES == cur->update) ? "updated" : "full",
864 cur->peers, cur->addresses,
865 (unsigned long long) cur->d_total_full.rel_value_us);
866 }
867
868
869 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
870 cur->d_setup_full.rel_value_us)
871 {
872 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
873 "Total time to setup %s %u peers %u addresses: %llu us\n",
874 (GNUNET_YES == cur->update) ? "updated" : "full",
875 cur->peers, cur->addresses,
876 (unsigned long long) cur->d_setup_full.rel_value_us);
877 }
878
879 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
880 cur->d_lp_full.rel_value_us)
881 {
882 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
883 "Total time to solve %s LP for %u peers %u addresses: %llu us\n",
884 (GNUNET_YES == cur->update) ? "updated" : "full",
885 cur->peers,
886 cur->addresses,
887 (unsigned long long ) cur->d_lp_full.rel_value_us);
888 }
889
890 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
891 cur->d_mlp_full.rel_value_us)
892 {
893 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
894 "Total time to solve %s MLP for %u peers %u addresses: %llu us\n",
895 (GNUNET_YES == cur->update) ? "updated" : "full",
896 cur->peers, cur->addresses,
897 (unsigned long long ) cur->d_mlp_full.rel_value_us);
898 }
899 }
900}
901
902
903static unsigned int
904get_connectivity_cb (void *cls,
905 const struct GNUNET_PeerIdentity *peer)
906{
907 return GNUNET_CONTAINER_multipeermap_contains (ph.addresses,
908 peer);
909}
910
911
912/**
913 * Evaluate average results for all iterations
914 */
915static void
916write_all_iterations (void)
917{
918 int c_iteration;
919 int c_peer;
920
921 struct GNUNET_DISK_FileHandle *f_full;
922 struct GNUNET_DISK_FileHandle *f_update;
923 char *data_fn_full;
924 char *data_fn_update;
925 char *data;
926
927 f_full = NULL;
928 f_update = NULL;
929
930 data_fn_full = NULL;
931
932 if (GNUNET_NO == ph.create_datafile)
933 return;
934
935 GNUNET_asprintf (&data_fn_full,
936 "perf_%s_full_%u-%u_%u_%u.data",
937 ph.ats_string,
938 ph.total_iterations,
939 ph.N_peers_start,
940 ph.N_peers_end,
941 ph.N_address);
942 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
943 "Using data file `%s'\n",
944 data_fn_full);
945
946 f_full = GNUNET_DISK_file_open (data_fn_full,
947 GNUNET_DISK_OPEN_WRITE
948 | GNUNET_DISK_OPEN_CREATE,
949 GNUNET_DISK_PERM_USER_EXEC
950 | GNUNET_DISK_PERM_USER_READ
951 | GNUNET_DISK_PERM_USER_WRITE);
952 if (NULL == f_full)
953 {
954 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
955 "Cannot open data file `%s'\n",
956 data_fn_full);
957 GNUNET_free (data_fn_full);
958 return;
959 }
960
961 data =
962 "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
963 if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data, strlen (data)))
964 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
965 "Cannot write data to log file `%s'\n",
966 data_fn_full);
967
968 data_fn_update = NULL;
969 if (GNUNET_YES == ph.measure_updates)
970 {
971 GNUNET_asprintf (&data_fn_update, "perf_%s_update_%u-%u_%u_%u.data",
972 ph.ats_string,
973 ph.total_iterations,
974 ph.N_peers_start,
975 ph.N_peers_end,
976 ph.N_address);
977 f_update = GNUNET_DISK_file_open (data_fn_update,
978 GNUNET_DISK_OPEN_WRITE
979 | GNUNET_DISK_OPEN_CREATE,
980 GNUNET_DISK_PERM_USER_EXEC
981 | GNUNET_DISK_PERM_USER_READ
982 | GNUNET_DISK_PERM_USER_WRITE);
983 if (NULL == f_update)
984 {
985 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
986 "Cannot open gnuplot file `%s'\n", data_fn_update);
987 GNUNET_free (data_fn_update);
988 if (NULL != f_full)
989 GNUNET_DISK_file_close (f_full);
990 GNUNET_free (data_fn_full);
991 return;
992 }
993
994 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
995 "Using update data file `%s'\n",
996 data_fn_update);
997
998 data =
999 "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
1000 if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen (data)))
1001 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1002 "Cannot write data to log file `%s'\n",
1003 data_fn_update);
1004 }
1005
1006 for (c_peer = ph.N_peers_start; c_peer <= ph.N_peers_end; c_peer++)
1007 {
1008 char *data_str;
1009 char *data_tmp;
1010 char *data_upd_str;
1011 char *data_upd_tmp;
1012 GNUNET_asprintf (&data_str, "%u;%u", c_peer, ph.N_address);
1013 if (ph.measure_updates)
1014 GNUNET_asprintf (&data_upd_str, "%u;%u", c_peer, ph.N_address);
1015 for (c_iteration = 0; c_iteration < ph.total_iterations; c_iteration++)
1016 {
1017 struct Result *cur_full_res;
1018 struct Result *cur_upd_res;
1019
1020
1021 // fprintf (stderr, "P: %u I: %u == %p \n", c_peer, c_iteration, cur_res);
1022 cur_full_res = ph.iterations_results[c_iteration].results_array[c_peer];
1023 if (c_peer == 0)
1024 continue;
1025 if (NULL == cur_full_res)
1026 continue;
1027
1028 if (ph.measure_updates)
1029 {
1030 cur_upd_res =
1031 ph.iterations_results[c_iteration].update_results_array[c_peer];
1032 data_upd_tmp = GNUNET_strdup (data_upd_str);
1033 GNUNET_free (data_upd_str);
1034 if (GNUNET_YES == cur_full_res->valid)
1035 {
1036 GNUNET_asprintf (&data_upd_str, "%s;%llu", data_upd_tmp,
1037 (NULL == cur_upd_res) ? 0 :
1038 cur_upd_res->d_total_full.rel_value_us);
1039 }
1040 else
1041 {
1042 GNUNET_asprintf (&data_upd_str, "%s;", data_upd_tmp);
1043 }
1044 GNUNET_free (data_upd_tmp);
1045 }
1046
1047 // fprintf (stderr, "P: %u I: %u: P %i A %i\n", c_peer, c_iteration, cur_res->peers, cur_res->addresses);
1048 // fprintf (stderr, "D total: %llu\n", (long long unsigned int) cur_res->d_total.rel_value_us);
1049
1050 data_tmp = GNUNET_strdup (data_str);
1051 GNUNET_free (data_str);
1052 if (GNUNET_YES == cur_full_res->valid)
1053 {
1054 GNUNET_asprintf (&data_str, "%s;%llu", data_tmp,
1055 cur_full_res->d_total_full.rel_value_us);
1056 }
1057 else
1058 {
1059 GNUNET_asprintf (&data_str, "%s;", data_tmp);
1060 }
1061
1062 GNUNET_free (data_tmp);
1063 }
1064 data_tmp = GNUNET_strdup (data_str);
1065 GNUNET_free (data_str);
1066 GNUNET_asprintf (&data_str, "%s\n", data_tmp);
1067 GNUNET_free (data_tmp);
1068
1069 fprintf (stderr, "Result full solution: %s\n", data_str);
1070 if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data_str, strlen (
1071 data_str)))
1072 GNUNET_break (0);
1073 GNUNET_free (data_str);
1074
1075 if (ph.measure_updates)
1076 {
1077 data_upd_tmp = GNUNET_strdup (data_upd_str);
1078 GNUNET_free (data_upd_str);
1079 GNUNET_asprintf (&data_upd_str, "%s\n", data_upd_tmp);
1080 GNUNET_free (data_upd_tmp);
1081
1082 fprintf (stderr, "Result updated solution: `%s'\n", data_upd_str);
1083 if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data_upd_str,
1084 strlen (data_upd_str)))
1085 GNUNET_break (0);
1086 GNUNET_free (data_upd_str);
1087 }
1088 }
1089
1090 if ((NULL != f_full) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_full)))
1091 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
1092 data_fn_full);
1093 GNUNET_free (data_fn_full);
1094
1095 if ((NULL != f_update) && (GNUNET_SYSERR == GNUNET_DISK_file_close (
1096 f_update)))
1097 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
1098 data_fn_update);
1099 GNUNET_free (data_fn_update);
1100}
1101
1102
1103static int
1104do_delete_address (void *cls,
1105 const struct GNUNET_PeerIdentity *pid,
1106 void *value)
1107{
1108 struct ATS_Address *cur = value;
1109
1110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1111 "Deleting addresses for peer %u\n",
1112 pid);
1113 GNUNET_assert (GNUNET_OK ==
1114 GNUNET_CONTAINER_multipeermap_remove (ph.addresses,
1115 pid,
1116 cur));
1117 ph.sf->s_del (ph.sf->cls, cur);
1118 GNUNET_free (cur->atsi);
1119 GNUNET_free (cur);
1120 return GNUNET_OK;
1121}
1122
1123
1124/**
1125 * Run a performance iteration
1126 */
1127static void
1128perf_run_iteration (void)
1129{
1130 int cp;
1131 int ca;
1132 int count_p = ph.N_peers_end;
1133 int count_a = ph.N_address;
1134 struct ATS_Address *cur_addr;
1135 uint32_t net;
1136
1137 ph.iterations_results[ph.current_iteration - 1].results_array =
1138 GNUNET_malloc ((count_p + 1) * sizeof(struct Result *));
1139 if (ph.measure_updates)
1140 ph.iterations_results[ph.current_iteration - 1].update_results_array =
1141 GNUNET_malloc ((count_p + 1) * sizeof(struct Result *));
1142 ph.peers = GNUNET_malloc ((count_p) * sizeof(struct PerfPeer));
1143 for (cp = 0; cp < count_p; cp++)
1144 perf_create_peer (cp);
1145 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1146 "Iteration %u of %u, added %u peers\n", ph.current_iteration,
1147 ph.total_iterations, cp);
1148
1149 for (cp = 0; cp < count_p; cp++)
1150 {
1151 fprintf (stderr, "%u..", cp);
1152 if (GNUNET_NO == ph.bulk_running)
1153 {
1154 ph.bulk_running = GNUNET_YES;
1155 ph.sf->s_bulk_start (ph.sf->cls);
1156 }
1157 ph.current_p = cp + 1;
1158 for (ca = 0; ca < count_a; ca++)
1159 {
1160 cur_addr = perf_create_address (cp, ca);
1161 /* Add address */
1162
1163 /* Random network selection */
1164 // net = 1 + GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_NT_COUNT - 1);
1165 /* Random equally distributed network selection */
1166 net = 1 + (ca % (GNUNET_NT_COUNT - 1));
1167 /* fprintf (stderr, "Network: %u `%s'\n",
1168 * mod_net , GNUNET_NT_to_string(mod_net)); */
1169
1170 cur_addr->atsi = GNUNET_new (struct GNUNET_ATS_Information);
1171 cur_addr->atsi_count = 1;
1172 cur_addr->atsi[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
1173 cur_addr->atsi[0].value = htonl (net);
1174 ph.sf->s_add (ph.sf->cls, cur_addr, net);
1175
1176 ph.current_a = ca + 1;
1177 perf_address_initial_update (NULL, ph.addresses, cur_addr);
1178 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1179 "Adding address for peer %u address %u in network %s\n", cp,
1180 ca,
1181 GNUNET_NT_to_string (net));
1182 }
1183 /* Notify solver about request */
1184 ph.sf->s_get (ph.sf->cls, &ph.peers[cp].id);
1185
1186 if (cp + 1 >= ph.N_peers_start)
1187 {
1188 /* Disable bulk to solve the problem */
1189 if (GNUNET_YES == ph.bulk_running)
1190 {
1191 ph.expecting_solution = GNUNET_YES;
1192 ph.bulk_running = GNUNET_NO;
1193 ph.sf->s_bulk_stop (ph.sf->cls);
1194 }
1195 else
1196 GNUNET_break (0);
1197
1198 /* Problem is solved by the solver here due to unlocking */
1199 ph.expecting_solution = GNUNET_NO;
1200
1201 /* Update the problem */
1202 if ((0 < ph.opt_update_percent) && (GNUNET_YES == ph.measure_updates))
1203 {
1204 /* Update */
1205 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1206 "Updating problem with %u peers and %u addresses\n", cp + 1,
1207 ca);
1208
1209 ph.expecting_solution = GNUNET_YES;
1210 ph.performed_update = GNUNET_YES;
1211 if (GNUNET_NO == ph.bulk_running)
1212 {
1213 ph.bulk_running = GNUNET_YES;
1214 ph.sf->s_bulk_start (ph.sf->cls);
1215 }
1216 perf_update_all_addresses (cp + 1, ca, ph.opt_update_percent);
1217 ph.bulk_running = GNUNET_NO;
1218 ph.sf->s_bulk_stop (ph.sf->cls);
1219 /* Problem is solved by the solver here due to unlocking */
1220 ph.performed_update = GNUNET_NO;
1221 ph.expecting_solution = GNUNET_NO;
1222 }
1223 GNUNET_assert (GNUNET_NO == ph.bulk_running);
1224 }
1225 }
1226 fprintf (stderr, "\n");
1227 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1228 "Done, cleaning up addresses\n");
1229 if (GNUNET_NO == ph.bulk_running)
1230 {
1231 ph.sf->s_bulk_start (ph.sf->cls);
1232 ph.bulk_running = GNUNET_YES;
1233 }
1234
1235 for (cp = 0; cp < count_p; cp++)
1236 {
1237 GNUNET_CONTAINER_multipeermap_get_multiple (ph.addresses,
1238 &ph.peers[cp].id,
1239 &do_delete_address,
1240 NULL);
1241 }
1242 if (GNUNET_NO == ph.bulk_running)
1243 {
1244 ph.sf->s_bulk_stop (ph.sf->cls);
1245 ph.bulk_running = GNUNET_NO;
1246 }
1247
1248 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1249 "Iteration done\n");
1250 GNUNET_free (ph.peers);
1251}
1252
1253
1254static void
1255run (void *cls, char *const *args, const char *cfgfile,
1256 const struct GNUNET_CONFIGURATION_Handle *cfg)
1257{
1258 GNUNET_log_setup ("perf-ats-solver", "WARNING", NULL);
1259 char *sep;
1260 char *src_filename = GNUNET_strdup (__FILE__);
1261 char *test_filename = cls;
1262 char *solver;
1263 char *plugin;
1264 struct GNUNET_CONFIGURATION_Handle *solver_cfg;
1265 unsigned long long quotas_in[GNUNET_NT_COUNT];
1266 unsigned long long quotas_out[GNUNET_NT_COUNT];
1267 int c;
1268 int c2;
1269
1270 /* Extract test name */
1271 if (NULL == (sep = (strstr (src_filename, ".c"))))
1272 {
1273 GNUNET_free (src_filename);
1274 GNUNET_break (0);
1275 ret = 1;
1276 return;
1277 }
1278 sep[0] = '\0';
1279
1280 if (NULL != (sep = strstr (test_filename, ".exe")))
1281 sep[0] = '\0';
1282
1283 if (NULL == (solver = strstr (test_filename, src_filename)))
1284 {
1285 GNUNET_free (src_filename);
1286 GNUNET_break (0);
1287 ret = 1;
1288 return;
1289 }
1290 solver += strlen (src_filename) + 1;
1291
1292 if (0 == strcmp (solver, "proportional"))
1293 {
1294 ph.ats_string = "proportional";
1295 }
1296 else if (0 == strcmp (solver, "mlp"))
1297 {
1298 ph.ats_string = "mlp";
1299 }
1300 else if ((0 == strcmp (solver, "ril")))
1301 {
1302 ph.ats_string = "ril";
1303 }
1304 else
1305 {
1306 GNUNET_free (src_filename);
1307 GNUNET_break (0);
1308 ret = 1;
1309 return;
1310 }
1311 GNUNET_free (src_filename);
1312
1313 /* Calculate peers */
1314 if ((0 == ph.N_peers_start) && (0 == ph.N_peers_end))
1315 {
1316 ph.N_peers_start = DEFAULT_PEERS_START;
1317 ph.N_peers_end = DEFAULT_PEERS_END;
1318 }
1319 if (0 == ph.N_address)
1320 ph.N_address = DEFAULT_ADDRESSES;
1321
1322
1323 if (ph.N_peers_start != ph.N_peers_end)
1324 fprintf (stderr,
1325 "Benchmarking solver `%s' with %u to %u peers and %u addresses in %u iterations\n",
1326 ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address,
1327 ph.total_iterations);
1328 else
1329 fprintf (stderr,
1330 "Benchmarking solver `%s' with %u peers and %u addresses in %u iterations\n",
1331 ph.ats_string, ph.N_peers_end, ph.N_address, ph.total_iterations);
1332
1333 if (0 == ph.opt_update_percent)
1334 ph.opt_update_percent = DEFAULT_UPDATE_PERCENTAGE;
1335
1336 /* Load quotas */
1337 solver_cfg = GNUNET_CONFIGURATION_create ();
1338 if ((NULL == solver_cfg) || (GNUNET_SYSERR == (GNUNET_CONFIGURATION_load (
1339 solver_cfg,
1340 "perf_ats_solver.conf"))))
1341 {
1342 GNUNET_break (0);
1343 end_now (1);
1344 return;
1345 }
1346 if (GNUNET_NT_COUNT != load_quotas (solver_cfg,
1347 quotas_out, quotas_in, GNUNET_NT_COUNT))
1348 {
1349 GNUNET_break (0);
1350 end_now (1);
1351 return;
1352 }
1353
1354 /* Create array of DLL to store results for iterations */
1355 ph.iterations_results = GNUNET_malloc (sizeof(struct Iteration)
1356 * ph.total_iterations);
1357
1358 /* Load solver */
1359 ph.env.cfg = solver_cfg;
1360 ph.stat = GNUNET_STATISTICS_create ("ats", cfg);
1361 ph.env.stats = ph.stat;
1362 ph.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1363 ph.env.addresses = ph.addresses;
1364 ph.env.bandwidth_changed_cb = bandwidth_changed_cb;
1365 ph.env.get_connectivity = &get_connectivity_cb;
1366 ph.env.get_preferences = &get_preferences_cb;
1367 ph.env.network_count = GNUNET_NT_COUNT;
1368 ph.env.info_cb = &solver_info_cb;
1369
1370 for (c = 0; c < GNUNET_NT_COUNT; c++)
1371 {
1372 ph.env.out_quota[c] = quotas_out[c];
1373 ph.env.in_quota[c] = quotas_in[c];
1374 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1375 "Loading network quotas: `%s' %llu %llu \n",
1376 GNUNET_NT_to_string (c),
1377 ph.env.out_quota[c],
1378 ph.env.in_quota[c]);
1379 }
1380 GAS_normalization_start ();
1381 GAS_preference_init ();
1382
1383 GNUNET_asprintf (&plugin,
1384 "libgnunet_plugin_ats_%s",
1385 ph.ats_string);
1386 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1387 _ ("Initializing solver `%s'\n"),
1388 ph.ats_string);
1389 if (NULL == (ph.sf = GNUNET_PLUGIN_load (plugin, &ph.env)))
1390 {
1391 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1392 _ ("Failed to initialize solver `%s'!\n"),
1393 plugin);
1394 ret = 1;
1395 return;
1396 }
1397
1398 /* Do the benchmark */
1399 for (ph.current_iteration = 1; ph.current_iteration <= ph.total_iterations;
1400 ph.current_iteration++)
1401 {
1402 fprintf (stderr,
1403 "Iteration %u of %u starting\n",
1404 ph.current_iteration,
1405 ph.total_iterations);
1406 perf_run_iteration ();
1407 evaluate (ph.current_iteration);
1408 fprintf (stderr,
1409 "Iteration %u of %u done\n",
1410 ph.current_iteration,
1411 ph.total_iterations);
1412 }
1413 if (ph.create_datafile)
1414 write_all_iterations ();
1415
1416 /* Unload solver*/
1417 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1418 _ ("Unloading solver `%s'\n"),
1419 ph.ats_string);
1420 GNUNET_PLUGIN_unload (plugin, ph.sf);
1421 ph.sf = NULL;
1422 GNUNET_free (plugin);
1423 for (c = 0; c < ph.total_iterations; c++)
1424 {
1425 for (c2 = ph.N_peers_start; c2 < ph.N_peers_end; c2++)
1426 {
1427 if (0 == c2)
1428 continue;
1429 if (ph.measure_updates)
1430 GNUNET_free (
1431 ph.iterations_results[c].update_results_array[c2]);
1432 GNUNET_free (ph.iterations_results[c].results_array[c2]);
1433 }
1434 if (ph.measure_updates)
1435 GNUNET_free (ph.iterations_results[c].update_results_array);
1436 GNUNET_free (ph.iterations_results[c].results_array);
1437 }
1438 GNUNET_free (ph.iterations_results);
1439
1440 GNUNET_CONFIGURATION_destroy (solver_cfg);
1441 GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
1442}
1443
1444
1445/**
1446 * Main function of the benchmark
1447 *
1448 * @param argc argument count
1449 * @param argv argument values
1450 */
1451int
1452main (int argc, char *argv[])
1453{
1454 /* extract command line arguments */
1455 ph.opt_update_percent = 0;
1456 ph.N_peers_start = 0;
1457 ph.N_peers_end = 0;
1458 ph.N_address = 0;
1459 ph.ats_string = NULL;
1460 ph.create_datafile = GNUNET_NO;
1461 ph.measure_updates = GNUNET_NO;
1462 ph.total_iterations = 1;
1463
1464 static struct GNUNET_GETOPT_CommandLineOption options[] = {
1465 GNUNET_GETOPT_option_uint ('a',
1466 "addresses",
1467 gettext_noop ("addresses to use"),
1468 &ph.N_address),
1469
1470 GNUNET_GETOPT_option_uint ('s',
1471 "start",
1472 gettext_noop ("start with peer"),
1473 &ph.N_peers_start),
1474
1475 GNUNET_GETOPT_option_uint ('e',
1476 "end",
1477 gettext_noop ("end with peer"),
1478 &ph.N_peers_end),
1479
1480 GNUNET_GETOPT_option_uint ('i',
1481 "iterations",
1482 gettext_noop (
1483 "number of iterations used for averaging (default: 1)"),
1484 &ph.total_iterations),
1485
1486 GNUNET_GETOPT_option_uint ('p',
1487 "percentage",
1488 gettext_noop (
1489 "update a fix percentage of addresses"),
1490 &ph.opt_update_percent),
1491
1492 GNUNET_GETOPT_option_flag ('d',
1493 "data",
1494 gettext_noop ("create data file"),
1495 &ph.create_datafile),
1496
1497 GNUNET_GETOPT_option_flag ('u',
1498 "update",
1499 gettext_noop ("measure updates"),
1500 &ph.measure_updates),
1501
1502 GNUNET_GETOPT_OPTION_END
1503 };
1504
1505 GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
1506 return ret;
1507}
1508
1509
1510/* end of file perf_ats_solver.c */
diff --git a/src/ats/perf_ats_solver.conf b/src/ats/perf_ats_solver.conf
deleted file mode 100644
index a535891df..000000000
--- a/src/ats/perf_ats_solver.conf
+++ /dev/null
@@ -1,28 +0,0 @@
1[ats]
2# Network specific inbound/outbound quotas
3UNSPECIFIED_QUOTA_IN = 1000000
4UNSPECIFIED_QUOTA_OUT = 1000000
5# LOOPBACK
6LOOPBACK_QUOTA_IN = 10000000
7LOOPBACK_QUOTA_OUT = 10000000
8# LAN
9LAN_QUOTA_IN = 10000000
10LAN_QUOTA_OUT = 10000000
11# WAN
12WAN_QUOTA_IN = 10000000
13WAN_QUOTA_OUT = 10000000
14# WLAN
15WLAN_QUOTA_IN = 10000000
16WLAN_QUOTA_OUT = 10000000
17# BLUETOOTH
18BLUETOOTH_QUOTA_IN = 10000000
19BLUETOOTH_QUOTA_OUT = 10000000
20
21# Proportional specific settings
22# How proportional to preferences is bandwidth distribution in a network
23# 1: Fair with respect to addresses without preferences
24# > 10: The bigger, the more respect is paid to preferences
25PROP_PROPORTIONALITY_FACTOR = 2.00
26# Should we stick to existing connections are prefer to switch?
27# [10...200], lower value prefers to switch, bigger value is more tolerant
28PROP_STABILITY_FACTOR = 1.25
diff --git a/src/ats/perf_ats_solver_proportional.conf b/src/ats/perf_ats_solver_proportional.conf
deleted file mode 100644
index e69de29bb..000000000
--- a/src/ats/perf_ats_solver_proportional.conf
+++ /dev/null
diff --git a/src/ats/plugin_ats_proportional.c b/src/ats/plugin_ats_proportional.c
deleted file mode 100644
index d3062a5c0..000000000
--- a/src/ats/plugin_ats_proportional.c
+++ /dev/null
@@ -1,1243 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/plugin_ats_proportional.c
22 * @brief ATS proportional solver
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_statistics_service.h"
28#include "gnunet_ats_service.h"
29#include "gnunet_ats_plugin.h"
30#include "gnunet-service-ats_addresses.h"
31
32#define LOG(kind, ...) GNUNET_log_from (kind, "ats-proportional", __VA_ARGS__)
33
34/**
35 * How much do we value stability over adaptation by default. A low
36 * value (close to 1.0) means we adapt as soon as possible, a larger
37 * value means that we have to have the respective factor of an
38 * advantage (or delay) before we adapt and sacrifice stability.
39 */
40#define PROP_STABILITY_FACTOR 1.25
41
42
43/**
44 * Default value to assume for the proportionality factor, if none is
45 * given in the configuration. This factor determines how strong the
46 * bandwidth allocation will orient itself on the application
47 * preferences. A lower factor means a more balanced bandwidth
48 * distribution while a larger number means a distribution more in
49 * line with application (bandwidth) preferences.
50 */
51#define PROPORTIONALITY_FACTOR 2.0
52
53
54/**
55 * Address information stored for the proportional solver in the
56 * `solver_information` member of `struct GNUNET_ATS_Address`.
57 *
58 * They are also stored in the respective `struct Network`'s linked
59 * list.
60 */
61struct AddressWrapper
62{
63 /**
64 * Next in DLL
65 */
66 struct AddressWrapper *next;
67
68 /**
69 * Previous in DLL
70 */
71 struct AddressWrapper *prev;
72
73 /**
74 * The address
75 */
76 struct ATS_Address *addr;
77
78 /**
79 * Network scope this address is in
80 */
81 struct Network *network;
82
83 /**
84 * Inbound quota
85 */
86 uint32_t calculated_quota_in;
87
88 /**
89 * Outbound quota
90 */
91 uint32_t calculated_quota_out;
92
93 /**
94 * When was this address activated
95 */
96 struct GNUNET_TIME_Absolute activated;
97};
98
99
100/**
101 * Representation of a network
102 */
103struct Network
104{
105 /**
106 * Network description
107 */
108 const char *desc;
109
110 /**
111 * String for statistics total addresses
112 */
113 char *stat_total;
114
115 /**
116 * String for statistics active addresses
117 */
118 char *stat_active;
119
120 /**
121 * Linked list of addresses in this network: head
122 */
123 struct AddressWrapper *head;
124
125 /**
126 * Linked list of addresses in this network: tail
127 */
128 struct AddressWrapper *tail;
129
130 /**
131 * Total inbound quota
132 */
133 unsigned long long total_quota_in;
134
135 /**
136 * Total outbound quota
137 */
138 unsigned long long total_quota_out;
139
140 /**
141 * ATS network type
142 */
143 enum GNUNET_NetworkType type;
144
145 /**
146 * Number of active addresses for this network
147 */
148 unsigned int active_addresses;
149
150 /**
151 * Number of total addresses for this network
152 */
153 unsigned int total_addresses;
154};
155
156
157/**
158 * A handle for the proportional solver
159 */
160struct GAS_PROPORTIONAL_Handle
161{
162 /**
163 * Our execution environment.
164 */
165 struct GNUNET_ATS_PluginEnvironment *env;
166
167 /**
168 * Networks array
169 */
170 struct Network *network_entries;
171
172 /**
173 * Proportionality factor
174 */
175 double prop_factor;
176
177 /**
178 * Stability factor
179 */
180 double stability_factor;
181
182 /**
183 * Bulk lock counter. If zero, we are not locked.
184 */
185 unsigned int bulk_lock;
186
187 /**
188 * Number of changes made while solver was locked. We really only
189 * use 0/non-zero to check on unlock if we have to run the update.
190 */
191 unsigned int bulk_requests;
192
193 /**
194 * Number of active addresses for solver
195 */
196 unsigned int active_addresses;
197};
198
199
200/**
201 * Test if bandwidth is available in this network to add an additional address.
202 *
203 * @param net the network type to check
204 * @param extra for how many extra addresses do we check?
205 * @return #GNUNET_YES or #GNUNET_NO
206 */
207static int
208is_bandwidth_available_in_network (struct Network *net,
209 int extra)
210{
211 unsigned int na;
212 uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
213
214 GNUNET_assert (((int) net->active_addresses) + extra >= 0);
215 na = net->active_addresses + extra;
216 if (0 == na)
217 return GNUNET_YES;
218 if (((net->total_quota_in / na) > min_bw) &&
219 ((net->total_quota_out / na) > min_bw))
220 return GNUNET_YES;
221 LOG (GNUNET_ERROR_TYPE_DEBUG,
222 "No bandwidth available in network\n");
223 return GNUNET_NO;
224}
225
226
227/**
228 * Test if all peers in this network require connectivity at level at
229 * least @a con.
230 *
231 * @param s the solver handle
232 * @param net the network type to check
233 * @param con connection return value threshold to check
234 * @return #GNUNET_YES or #GNUNET_NO
235 */
236static int
237all_require_connectivity (struct GAS_PROPORTIONAL_Handle *s,
238 struct Network *net,
239 unsigned int con)
240{
241 struct AddressWrapper *aw;
242
243 for (aw = net->head; NULL != aw; aw = aw->next)
244 if (con >
245 s->env->get_connectivity (s->env->cls,
246 &aw->addr->peer))
247 return GNUNET_NO;
248 return GNUNET_YES;
249}
250
251
252/**
253 * Update bandwidth assigned to peers in this network. The basic idea
254 * is to assign every peer in the network the minimum bandwidth, and
255 * then distribute the remaining bandwidth proportional to application
256 * preferences.
257 *
258 * @param s the solver handle
259 * @param net the network type to update
260 */
261static void
262distribute_bandwidth (struct GAS_PROPORTIONAL_Handle *s,
263 struct Network *net)
264{
265 const uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
266 struct AddressWrapper *aw;
267 unsigned long long remaining_quota_in;
268 unsigned long long quota_out_used;
269 unsigned long long remaining_quota_out;
270 unsigned long long quota_in_used;
271 unsigned int count_addresses;
272 double sum_relative_peer_prefences;
273 double peer_weight;
274 double total_weight;
275 const double *peer_relative_prefs;
276
277 LOG (GNUNET_ERROR_TYPE_INFO,
278 "Recalculate quota for network type `%s' for %u addresses (in/out): %llu/%llu \n",
279 net->desc,
280 net->active_addresses,
281 net->total_quota_in,
282 net->total_quota_in);
283
284 if (0 == net->active_addresses)
285 return; /* no addresses to update */
286
287 /* sanity checks */
288 if ((net->active_addresses * min_bw) > net->total_quota_in)
289 {
290 GNUNET_break (0);
291 return;
292 }
293 if ((net->active_addresses * min_bw) > net->total_quota_out)
294 {
295 GNUNET_break (0);
296 return;
297 }
298
299 /* Calculate sum of relative preference for active addresses in this
300 network */
301 sum_relative_peer_prefences = 0.0;
302 count_addresses = 0;
303 for (aw = net->head; NULL != aw; aw = aw->next)
304 {
305 if (GNUNET_YES != aw->addr->active)
306 continue;
307 peer_relative_prefs = s->env->get_preferences (s->env->cls,
308 &aw->addr->peer);
309 sum_relative_peer_prefences
310 += peer_relative_prefs[GNUNET_ATS_PREFERENCE_BANDWIDTH];
311 count_addresses++;
312 }
313 if (count_addresses != net->active_addresses)
314 {
315 GNUNET_break (0);
316 LOG (GNUNET_ERROR_TYPE_WARNING,
317 "%s: Counted %u active addresses, expected %u active addresses\n",
318 net->desc,
319 count_addresses,
320 net->active_addresses);
321 /* try to fix... */
322 net->active_addresses = count_addresses;
323 }
324 LOG (GNUNET_ERROR_TYPE_INFO,
325 "Total relative preference %.3f for %u addresses in network %s\n",
326 sum_relative_peer_prefences,
327 net->active_addresses,
328 net->desc);
329
330 /* check how much we have to distribute */
331 remaining_quota_in = net->total_quota_in - (net->active_addresses * min_bw);
332 remaining_quota_out = net->total_quota_out - (net->active_addresses * min_bw);
333 LOG (GNUNET_ERROR_TYPE_DEBUG,
334 "Proportionally distributable bandwidth (in/out): %llu/%llu\n",
335 remaining_quota_in,
336 remaining_quota_out);
337
338 /* distribute remaining quota; we do not do it exactly proportional,
339 but balance "even" distribution ("net->active_addresses") with
340 the preference sum using the "prop_factor". */
341 total_weight = net->active_addresses
342 + s->prop_factor * sum_relative_peer_prefences;
343 quota_out_used = 0;
344 quota_in_used = 0;
345 for (aw = net->head; NULL != aw; aw = aw->next)
346 {
347 if (GNUNET_YES != aw->addr->active)
348 {
349 /* set to 0, just to be sure */
350 aw->calculated_quota_in = 0;
351 aw->calculated_quota_out = 0;
352 continue;
353 }
354 peer_relative_prefs = s->env->get_preferences (s->env->cls,
355 &aw->addr->peer);
356 peer_weight = 1.0
357 + s->prop_factor
358 * peer_relative_prefs[GNUNET_ATS_PREFERENCE_BANDWIDTH];
359
360 aw->calculated_quota_in = min_bw
361 + (peer_weight / total_weight)
362 * remaining_quota_in;
363 aw->calculated_quota_out = min_bw
364 + (peer_weight / total_weight)
365 * remaining_quota_out;
366
367 LOG (GNUNET_ERROR_TYPE_INFO,
368 "New quotas for peer `%s' with weight (cur/total) %.3f/%.3f (in/out) are: %u/%u\n",
369 GNUNET_i2s (&aw->addr->peer),
370 peer_weight,
371 total_weight,
372 (unsigned int) aw->calculated_quota_in,
373 (unsigned int) aw->calculated_quota_out);
374 quota_in_used += aw->calculated_quota_in;
375 quota_out_used += aw->calculated_quota_out;
376 }
377 LOG (GNUNET_ERROR_TYPE_DEBUG,
378 "Total bandwidth assigned is (in/out): %llu /%llu\n",
379 quota_in_used,
380 quota_out_used);
381 /* +1 due to possible rounding errors */
382 GNUNET_break (quota_out_used <= net->total_quota_out + 1);
383 GNUNET_break (quota_in_used <= net->total_quota_in + 1);
384}
385
386
387/**
388 * Notify ATS service of bandwidth changes to addresses.
389 *
390 * @param s solver handle
391 * @param net the network to propagate changes in
392 */
393static void
394propagate_bandwidth (struct GAS_PROPORTIONAL_Handle *s,
395 struct Network *net)
396{
397 struct AddressWrapper *cur;
398
399 for (cur = net->head; NULL != cur; cur = cur->next)
400 {
401 if ((cur->addr->assigned_bw_in == cur->calculated_quota_in) &&
402 (cur->addr->assigned_bw_out == cur->calculated_quota_out))
403 continue;
404 cur->addr->assigned_bw_in = cur->calculated_quota_in;
405 cur->addr->assigned_bw_out = cur->calculated_quota_out;
406 if (GNUNET_YES == cur->addr->active)
407 s->env->bandwidth_changed_cb (s->env->cls,
408 cur->addr);
409 }
410}
411
412
413/**
414 * Distribute bandwidth. The addresses have already been selected,
415 * this is merely distributed the bandwidth among the addresses.
416 *
417 * @param s the solver handle
418 * @param n the network, can be NULL for all networks
419 */
420static void
421distribute_bandwidth_in_network (struct GAS_PROPORTIONAL_Handle *s,
422 struct Network *n)
423{
424 unsigned int i;
425
426 if (0 != s->bulk_lock)
427 {
428 s->bulk_requests++;
429 return;
430 }
431 if (NULL != n)
432 {
433 LOG (GNUNET_ERROR_TYPE_DEBUG,
434 "Redistributing bandwidth in network %s with %u active and %u total addresses\n",
435 GNUNET_NT_to_string (n->type),
436 n->active_addresses,
437 n->total_addresses);
438 s->env->info_cb (s->env->cls,
439 GAS_OP_SOLVE_START,
440 GAS_STAT_SUCCESS,
441 GAS_INFO_PROP_SINGLE);
442 distribute_bandwidth (s,
443 n);
444 s->env->info_cb (s->env->cls,
445 GAS_OP_SOLVE_STOP,
446 GAS_STAT_SUCCESS,
447 GAS_INFO_PROP_SINGLE);
448 s->env->info_cb (s->env->cls,
449 GAS_OP_SOLVE_UPDATE_NOTIFICATION_START,
450 GAS_STAT_SUCCESS,
451 GAS_INFO_PROP_SINGLE);
452 propagate_bandwidth (s,
453 n);
454
455 s->env->info_cb (s->env->cls,
456 GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP,
457 GAS_STAT_SUCCESS,
458 GAS_INFO_PROP_SINGLE);
459 }
460 else
461 {
462 LOG (GNUNET_ERROR_TYPE_DEBUG,
463 "Redistributing bandwidth in all %u networks\n",
464 s->env->network_count);
465 s->env->info_cb (s->env->cls,
466 GAS_OP_SOLVE_START,
467 GAS_STAT_SUCCESS,
468 GAS_INFO_PROP_ALL);
469 for (i = 0; i < s->env->network_count; i++)
470 distribute_bandwidth (s,
471 &s->network_entries[i]);
472 s->env->info_cb (s->env->cls,
473 GAS_OP_SOLVE_STOP,
474 GAS_STAT_SUCCESS,
475 GAS_INFO_PROP_ALL);
476 s->env->info_cb (s->env->cls,
477 GAS_OP_SOLVE_UPDATE_NOTIFICATION_START,
478 GAS_STAT_SUCCESS,
479 GAS_INFO_PROP_ALL);
480 for (i = 0; i < s->env->network_count; i++)
481 propagate_bandwidth (s,
482 &s->network_entries[i]);
483 s->env->info_cb (s->env->cls,
484 GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP,
485 GAS_STAT_SUCCESS,
486 GAS_INFO_PROP_ALL);
487 }
488}
489
490
491/**
492 * Context for finding the best address* Linked list of addresses in this network: head
493 */
494struct FindBestAddressCtx
495{
496 /**
497 * The solver handle
498 */
499 struct GAS_PROPORTIONAL_Handle *s;
500
501 /**
502 * The currently best address
503 */
504 struct ATS_Address *best;
505};
506
507
508/**
509 * Find a "good" address to use for a peer by iterating over the
510 * addresses for this peer. If we already have an existing address,
511 * we stick to it. Otherwise, we pick by lowest distance and then by
512 * lowest latency.
513 *
514 * @param cls the `struct FindBestAddressCtx *' where we store the result
515 * @param key the peer we are trying to find the best address for
516 * @param value another `struct ATS_Address*` to consider using
517 * @return #GNUNET_OK (continue to iterate)
518 */
519static int
520find_best_address_it (void *cls,
521 const struct GNUNET_PeerIdentity *key,
522 void *value)
523{
524 struct FindBestAddressCtx *ctx = cls;
525 struct ATS_Address *current = value;
526 struct AddressWrapper *asi = current->solver_information;
527 struct GNUNET_TIME_Relative active_time;
528 double best_delay;
529 double best_distance;
530 double cur_delay;
531 double cur_distance;
532 unsigned int con;
533 int bw_available;
534 int need;
535
536 /* we need +1 slot if 'current' is not yet active */
537 need = (GNUNET_YES == current->active) ? 0 : 1;
538 /* we save -1 slot if 'best' is active and belongs
539 to the same network (as we would replace it) */
540 if ((NULL != ctx->best) &&
541 (GNUNET_YES == ctx->best->active) &&
542 (((struct AddressWrapper *) ctx->best->solver_information)->network ==
543 asi->network))
544 need--;
545 /* we can gain -1 slot if this peers connectivity
546 requirement is higher than that of another peer
547 in that network scope */
548 con = ctx->s->env->get_connectivity (ctx->s->env->cls,
549 key);
550 if (GNUNET_YES !=
551 all_require_connectivity (ctx->s,
552 asi->network,
553 con))
554 need--;
555 /* test if minimum bandwidth for 'current' would be available */
556 bw_available
557 = is_bandwidth_available_in_network (asi->network,
558 need);
559 if (! bw_available)
560 {
561 /* Bandwidth for this address is unavailable, so we cannot use
562 it. */
563 return GNUNET_OK;
564 }
565 if (GNUNET_YES == current->active)
566 {
567 active_time = GNUNET_TIME_absolute_get_duration (asi->activated);
568 if (active_time.rel_value_us <=
569 ((double) GNUNET_TIME_UNIT_SECONDS.rel_value_us)
570 * ctx->s->stability_factor)
571 {
572 /* Keep active address for stability reasons */
573 ctx->best = current;
574 return GNUNET_NO;
575 }
576 }
577 if (NULL == ctx->best)
578 {
579 /* We so far have nothing else, so go with it! */
580 ctx->best = current;
581 return GNUNET_OK;
582 }
583
584 /* Now compare ATS information */
585 cur_distance = current->norm_distance.norm;
586 best_distance = ctx->best->norm_distance.norm;
587 cur_delay = current->norm_delay.norm;
588 best_delay = ctx->best->norm_delay.norm;
589
590 /* user shorter distance */
591 if (cur_distance < best_distance)
592 {
593 if (GNUNET_NO == ctx->best->active)
594 {
595 /* Activity doesn't influence the equation, use current */
596 ctx->best = current;
597 }
598 else if ((best_distance / cur_distance) > ctx->s->stability_factor)
599 {
600 /* Distance change is significant, switch active address! */
601 ctx->best = current;
602 }
603 }
604
605 /* User connection with less delay */
606 if (cur_delay < best_delay)
607 {
608 if (GNUNET_NO == ctx->best->active)
609 {
610 /* Activity doesn't influence the equation, use current */
611 ctx->best = current;
612 }
613 else if ((best_delay / cur_delay) > ctx->s->stability_factor)
614 {
615 /* Latency change is significant, switch active address! */
616 ctx->best = current;
617 }
618 }
619 return GNUNET_OK;
620}
621
622
623/**
624 * Find the currently best address for a peer from the set of
625 * addresses available or return NULL of no address is available.
626 *
627 * @param s the proportional handle
628 * @param addresses the address hashmap
629 * @param id the peer id
630 * @return the address or NULL
631 */
632struct ATS_Address *
633get_best_address (struct GAS_PROPORTIONAL_Handle *s,
634 struct GNUNET_CONTAINER_MultiPeerMap *addresses,
635 const struct GNUNET_PeerIdentity *id)
636{
637 struct FindBestAddressCtx fba_ctx;
638
639 fba_ctx.best = NULL;
640 fba_ctx.s = s;
641 GNUNET_CONTAINER_multipeermap_get_multiple (addresses,
642 id,
643 &find_best_address_it,
644 &fba_ctx);
645 return fba_ctx.best;
646}
647
648
649/**
650 * Decrease number of active addresses in network.
651 *
652 * @param s the solver handle
653 * @param net the network type
654 */
655static void
656address_decrement_active (struct GAS_PROPORTIONAL_Handle *s,
657 struct Network *net)
658{
659 GNUNET_assert (net->active_addresses > 0);
660 net->active_addresses--;
661 GNUNET_STATISTICS_update (s->env->stats,
662 net->stat_active,
663 -1,
664 GNUNET_NO);
665 GNUNET_assert (s->active_addresses > 0);
666 s->active_addresses--;
667 GNUNET_STATISTICS_update (s->env->stats,
668 "# ATS addresses total",
669 -1,
670 GNUNET_NO);
671}
672
673
674/**
675 * Address map iterator to find current active address for peer.
676 * Asserts that only one address is active per peer.
677 *
678 * @param cls last active address
679 * @param key peer's key
680 * @param value address to check
681 * @return #GNUNET_NO on double active address else #GNUNET_YES;
682 */
683static int
684get_active_address_it (void *cls,
685 const struct GNUNET_PeerIdentity *key,
686 void *value)
687{
688 struct ATS_Address **dest = cls;
689 struct ATS_Address *aa = value;
690
691 if (GNUNET_YES != aa->active)
692 return GNUNET_OK;
693 GNUNET_assert (NULL == (*dest));
694 (*dest) = aa;
695 return GNUNET_OK;
696}
697
698
699/**
700 * Find current active address for peer
701 *
702 * @param s the solver handle
703 * @param peer the peer
704 * @return active address or NULL
705 */
706static struct ATS_Address *
707get_active_address (struct GAS_PROPORTIONAL_Handle *s,
708 const struct GNUNET_PeerIdentity *peer)
709{
710 struct ATS_Address *dest;
711
712 dest = NULL;
713 GNUNET_CONTAINER_multipeermap_get_multiple (s->env->addresses,
714 peer,
715 &get_active_address_it,
716 &dest);
717 return dest;
718}
719
720
721/**
722 * Update active address for a peer. Check if active address exists
723 * and what the best address is, if addresses are different switch.
724 * Then reallocate bandwidth within the affected network scopes.
725 *
726 * @param s solver handle
727 * @param current_address the address currently active for the peer,
728 * NULL for none
729 * @param peer the peer to check
730 */
731static void
732update_active_address (struct GAS_PROPORTIONAL_Handle *s,
733 struct ATS_Address *current_address,
734 const struct GNUNET_PeerIdentity *peer)
735{
736 struct ATS_Address *best_address;
737 struct AddressWrapper *asi_cur;
738 struct AddressWrapper *asi_best;
739 struct AddressWrapper *aw;
740 struct AddressWrapper *aw_min;
741 unsigned int a_con;
742 unsigned int con_min;
743
744 best_address = get_best_address (s,
745 s->env->addresses,
746 peer);
747 if (NULL != best_address)
748 asi_best = best_address->solver_information;
749 else
750 asi_best = NULL;
751 if (current_address == best_address)
752 return; /* no changes */
753 if (NULL != current_address)
754 {
755 /* We switch to a new address (or to none);
756 mark old address as inactive. */
757 asi_cur = current_address->solver_information;
758 GNUNET_assert (GNUNET_YES == current_address->active);
759 LOG (GNUNET_ERROR_TYPE_INFO,
760 "Disabling previous active address for peer `%s'\n",
761 GNUNET_i2s (peer));
762 asi_cur->activated = GNUNET_TIME_UNIT_ZERO_ABS;
763 current_address->active = GNUNET_NO;
764 current_address->assigned_bw_in = 0;
765 current_address->assigned_bw_out = 0;
766 address_decrement_active (s,
767 asi_cur->network);
768 if ((NULL == best_address) ||
769 (asi_best->network != asi_cur->network))
770 distribute_bandwidth_in_network (s,
771 asi_cur->network);
772 if (NULL == best_address)
773 {
774 /* We previously had an active address, but now we cannot
775 * suggest one. Therefore we have to disconnect the peer.
776 * The above call to "distribute_bandwidth_in_network()
777 * does not see 'current_address' so we need to trigger
778 * the update here. */LOG (GNUNET_ERROR_TYPE_DEBUG,
779 "Disconnecting peer `%s'.\n",
780 GNUNET_i2s (peer));
781 s->env->bandwidth_changed_cb (s->env->cls,
782 current_address);
783 return;
784 }
785 }
786 if (NULL == best_address)
787 {
788 /* We do not have a new address, so we are done. */
789 LOG (GNUNET_ERROR_TYPE_DEBUG,
790 "Cannot suggest address for peer `%s'\n",
791 GNUNET_i2s (peer));
792 return;
793 }
794 /* We do have a new address, activate it */
795 LOG (GNUNET_ERROR_TYPE_DEBUG,
796 "Selecting new address %p for peer `%s'\n",
797 best_address,
798 GNUNET_i2s (peer));
799 /* Mark address as active */
800 best_address->active = GNUNET_YES;
801 asi_best->activated = GNUNET_TIME_absolute_get ();
802 asi_best->network->active_addresses++;
803 s->active_addresses++;
804 GNUNET_STATISTICS_update (s->env->stats,
805 "# ATS active addresses total",
806 1,
807 GNUNET_NO);
808 GNUNET_STATISTICS_update (s->env->stats,
809 asi_best->network->stat_active,
810 1,
811 GNUNET_NO);
812 LOG (GNUNET_ERROR_TYPE_INFO,
813 "Address %p for peer `%s' is now active\n",
814 best_address,
815 GNUNET_i2s (peer));
816
817 if (GNUNET_NO ==
818 is_bandwidth_available_in_network (asi_best->network,
819 0))
820 {
821 /* we went over the maximum number of addresses for
822 this scope; remove the address with the smallest
823 connectivity requirement */
824 con_min = UINT32_MAX;
825 aw_min = NULL;
826 for (aw = asi_best->network->head; NULL != aw; aw = aw->next)
827 {
828 if ((con_min >
829 (a_con = s->env->get_connectivity (s->env->cls,
830 &aw->addr->peer))) &&
831 (GNUNET_YES == aw->addr->active))
832 {
833 aw_min = aw;
834 con_min = a_con;
835 if (0 == con_min)
836 break;
837 }
838 }
839 update_active_address (s,
840 aw_min->addr,
841 &aw_min->addr->peer);
842 }
843 distribute_bandwidth_in_network (s,
844 asi_best->network);
845}
846
847
848/**
849 * The preferences for a peer in the problem changed.
850 *
851 * @param solver the solver handle
852 * @param peer the peer to change the preference for
853 * @param kind the kind to change the preference
854 * @param pref_rel the normalized preference value for this kind over all clients
855 */
856static void
857GAS_proportional_change_preference (void *solver,
858 const struct GNUNET_PeerIdentity *peer,
859 enum GNUNET_ATS_PreferenceKind kind,
860 double pref_rel)
861{
862 struct GAS_PROPORTIONAL_Handle *s = solver;
863
864 if (GNUNET_ATS_PREFERENCE_BANDWIDTH != kind)
865 return; /* we do not care */
866 distribute_bandwidth_in_network (s,
867 NULL);
868}
869
870
871/**
872 * Get application feedback for a peer
873 *
874 * @param solver the solver handle
875 * @param application the application
876 * @param peer the peer to change the preference for
877 * @param scope the time interval for this feedback: [now - scope .. now]
878 * @param kind the kind to change the preference
879 * @param score the score
880 */
881static void
882GAS_proportional_feedback (void *solver,
883 struct GNUNET_SERVICE_Client *application,
884 const struct GNUNET_PeerIdentity *peer,
885 const struct GNUNET_TIME_Relative scope,
886 enum GNUNET_ATS_PreferenceKind kind,
887 double score)
888{
889 /* Proportional does not care about feedback */
890}
891
892
893/**
894 * Get the preferred address for a specific peer
895 *
896 * @param solver the solver handle
897 * @param peer the identity of the peer
898 */
899static void
900GAS_proportional_start_get_address (void *solver,
901 const struct GNUNET_PeerIdentity *peer)
902{
903 struct GAS_PROPORTIONAL_Handle *s = solver;
904
905 update_active_address (s,
906 get_active_address (s,
907 peer),
908 peer);
909}
910
911
912/**
913 * Stop notifying about address and bandwidth changes for this peer
914 *
915 * @param solver the solver handle
916 * @param peer the peer
917 */
918static void
919GAS_proportional_stop_get_address (void *solver,
920 const struct GNUNET_PeerIdentity *peer)
921{
922 struct GAS_PROPORTIONAL_Handle *s = solver;
923 struct ATS_Address *cur;
924 struct AddressWrapper *asi;
925
926 cur = get_active_address (s,
927 peer);
928 if (NULL == cur)
929 return;
930 asi = cur->solver_information;
931 distribute_bandwidth_in_network (s,
932 asi->network);
933}
934
935
936/**
937 * Start a bulk operation
938 *
939 * @param solver the solver
940 */
941static void
942GAS_proportional_bulk_start (void *solver)
943{
944 struct GAS_PROPORTIONAL_Handle *s = solver;
945
946 LOG (GNUNET_ERROR_TYPE_DEBUG,
947 "Locking solver for bulk operation ...\n");
948 GNUNET_assert (NULL != solver);
949 s->bulk_lock++;
950}
951
952
953/**
954 * Bulk operation done.
955 *
956 * @param solver our `struct GAS_PROPORTIONAL_Handle *`
957 */
958static void
959GAS_proportional_bulk_stop (void *solver)
960{
961 struct GAS_PROPORTIONAL_Handle *s = solver;
962
963 LOG (GNUNET_ERROR_TYPE_DEBUG,
964 "Unlocking solver from bulk operation ...\n");
965 if (s->bulk_lock < 1)
966 {
967 GNUNET_break (0);
968 return;
969 }
970 s->bulk_lock--;
971 if ((0 == s->bulk_lock) &&
972 (0 < s->bulk_requests))
973 {
974 LOG (GNUNET_ERROR_TYPE_INFO,
975 "No lock pending, recalculating\n");
976 distribute_bandwidth_in_network (s,
977 NULL);
978 s->bulk_requests = 0;
979 }
980}
981
982
983/**
984 * Transport properties for this address have changed
985 *
986 * @param solver solver handle
987 * @param address the address
988 */
989static void
990GAS_proportional_address_property_changed (void *solver,
991 struct ATS_Address *address)
992{
993 struct GAS_PROPORTIONAL_Handle *s = solver;
994 struct AddressWrapper *asi = address->solver_information;
995
996 distribute_bandwidth_in_network (s,
997 asi->network);
998}
999
1000
1001/**
1002 * Add a new single address to a network
1003 *
1004 * @param solver the solver Handle
1005 * @param address the address to add
1006 * @param network network type of this address
1007 */
1008static void
1009GAS_proportional_address_add (void *solver,
1010 struct ATS_Address *address,
1011 uint32_t network)
1012{
1013 struct GAS_PROPORTIONAL_Handle *s = solver;
1014 struct Network *net;
1015 struct AddressWrapper *aw;
1016
1017 GNUNET_assert (network < s->env->network_count);
1018 net = &s->network_entries[network];
1019 net->total_addresses++;
1020
1021 aw = GNUNET_new (struct AddressWrapper);
1022 aw->addr = address;
1023 aw->network = net;
1024 address->solver_information = aw;
1025 GNUNET_CONTAINER_DLL_insert (net->head,
1026 net->tail,
1027 aw);
1028 GNUNET_STATISTICS_update (s->env->stats,
1029 "# ATS addresses total",
1030 1,
1031 GNUNET_NO);
1032 GNUNET_STATISTICS_update (s->env->stats,
1033 net->stat_total,
1034 1,
1035 GNUNET_NO);
1036 update_active_address (s,
1037 get_active_address (s,
1038 &address->peer),
1039 &address->peer);
1040 LOG (GNUNET_ERROR_TYPE_INFO,
1041 "Added new address for `%s', now total %u and active %u addresses in network `%s'\n",
1042 GNUNET_i2s (&address->peer),
1043 net->total_addresses,
1044 net->active_addresses,
1045 net->desc);
1046}
1047
1048
1049/**
1050 * Remove an address from the solver. To do so, we:
1051 * - Removed it from specific network
1052 * - Decrease the number of total addresses
1053 * - If active:
1054 * - decrease number of active addresses
1055 * - update quotas
1056 *
1057 * @param solver the solver handle
1058 * @param address the address to remove
1059 */
1060static void
1061GAS_proportional_address_delete (void *solver,
1062 struct ATS_Address *address)
1063{
1064 struct GAS_PROPORTIONAL_Handle *s = solver;
1065 struct AddressWrapper *aw = address->solver_information;
1066 struct Network *net = aw->network;
1067
1068 LOG (GNUNET_ERROR_TYPE_DEBUG,
1069 "Deleting %s address for peer `%s' from network `%s' (total: %u/active: %u)\n",
1070 (GNUNET_NO == address->active) ? "inactive" : "active",
1071 GNUNET_i2s (&address->peer),
1072 net->desc,
1073 net->total_addresses,
1074 net->active_addresses);
1075
1076 GNUNET_CONTAINER_DLL_remove (net->head,
1077 net->tail,
1078 aw);
1079 GNUNET_assert (net->total_addresses > 0);
1080 net->total_addresses--;
1081 GNUNET_STATISTICS_update (s->env->stats,
1082 net->stat_total,
1083 -1,
1084 GNUNET_NO);
1085 if (GNUNET_YES == address->active)
1086 {
1087 /* Address was active, remove from network and update quotas */
1088 update_active_address (s,
1089 address,
1090 &address->peer);
1091 distribute_bandwidth_in_network (s, net);
1092 }
1093 GNUNET_free (aw);
1094 address->solver_information = NULL;
1095 LOG (GNUNET_ERROR_TYPE_DEBUG,
1096 "After deleting address now total %u and active %u addresses in network `%s'\n",
1097 net->total_addresses,
1098 net->active_addresses,
1099 net->desc);
1100}
1101
1102
1103/**
1104 * Function invoked when the plugin is loaded.
1105 *
1106 * @param[in,out] cls the `struct GNUNET_ATS_PluginEnvironment *` to use;
1107 * modified to return the API functions (ugh).
1108 * @return the `struct GAS_PROPORTIONAL_Handle` to pass as a closure
1109 */
1110void *
1111libgnunet_plugin_ats_proportional_init (void *cls)
1112{
1113 static struct GNUNET_ATS_SolverFunctions sf;
1114 struct GNUNET_ATS_PluginEnvironment *env = cls;
1115 struct GAS_PROPORTIONAL_Handle *s;
1116 struct Network *cur;
1117 float f_tmp;
1118 unsigned int c;
1119
1120 s = GNUNET_new (struct GAS_PROPORTIONAL_Handle);
1121 s->env = env;
1122 sf.cls = s;
1123 sf.s_add = &GAS_proportional_address_add;
1124 sf.s_address_update_property = &GAS_proportional_address_property_changed;
1125 sf.s_get = &GAS_proportional_start_get_address;
1126 sf.s_get_stop = &GAS_proportional_stop_get_address;
1127 sf.s_pref = &GAS_proportional_change_preference;
1128 sf.s_feedback = &GAS_proportional_feedback;
1129 sf.s_del = &GAS_proportional_address_delete;
1130 sf.s_bulk_start = &GAS_proportional_bulk_start;
1131 sf.s_bulk_stop = &GAS_proportional_bulk_stop;
1132 s->stability_factor = PROP_STABILITY_FACTOR;
1133 if (GNUNET_SYSERR !=
1134 GNUNET_CONFIGURATION_get_value_float (env->cfg,
1135 "ats",
1136 "PROP_STABILITY_FACTOR",
1137 &f_tmp))
1138 {
1139 if ((f_tmp < 1.0) || (f_tmp > 2.0))
1140 {
1141 LOG (GNUNET_ERROR_TYPE_ERROR,
1142 _ ("Invalid %s configuration %f \n"),
1143 "PROP_STABILITY_FACTOR",
1144 f_tmp);
1145 }
1146 else
1147 {
1148 s->stability_factor = f_tmp;
1149 LOG (GNUNET_ERROR_TYPE_INFO,
1150 "Using %s of %.3f\n",
1151 "PROP_STABILITY_FACTOR",
1152 f_tmp);
1153 }
1154 }
1155 s->prop_factor = PROPORTIONALITY_FACTOR;
1156 if (GNUNET_SYSERR !=
1157 GNUNET_CONFIGURATION_get_value_float (env->cfg,
1158 "ats",
1159 "PROP_PROPORTIONALITY_FACTOR",
1160 &f_tmp))
1161 {
1162 if (f_tmp < 1.0)
1163 {
1164 LOG (GNUNET_ERROR_TYPE_ERROR,
1165 _ ("Invalid %s configuration %f\n"),
1166 "PROP_PROPORTIONALITY_FACTOR",
1167 f_tmp);
1168 }
1169 else
1170 {
1171 s->prop_factor = f_tmp;
1172 LOG (GNUNET_ERROR_TYPE_INFO,
1173 "Using %s of %.3f\n",
1174 "PROP_PROPORTIONALITY_FACTOR",
1175 f_tmp);
1176 }
1177 }
1178
1179 s->network_entries = GNUNET_malloc (env->network_count
1180 * sizeof(struct Network));
1181 for (c = 0; c < env->network_count; c++)
1182 {
1183 cur = &s->network_entries[c];
1184 cur->type = c;
1185 cur->total_quota_in = env->in_quota[c];
1186 cur->total_quota_out = env->out_quota[c];
1187 cur->desc = GNUNET_NT_to_string (c);
1188 GNUNET_asprintf (&cur->stat_total,
1189 "# ATS addresses %s total",
1190 cur->desc);
1191 GNUNET_asprintf (&cur->stat_active,
1192 "# ATS active addresses %s total",
1193 cur->desc);
1194 LOG (GNUNET_ERROR_TYPE_INFO,
1195 "Added network %u `%s' (%llu/%llu)\n",
1196 c,
1197 cur->desc,
1198 cur->total_quota_in,
1199 cur->total_quota_out);
1200 }
1201 return &sf;
1202}
1203
1204
1205/**
1206 * Function used to unload the plugin.
1207 *
1208 * @param cls return value from #libgnunet_plugin_ats_proportional_init()
1209 */
1210void *
1211libgnunet_plugin_ats_proportional_done (void *cls)
1212{
1213 struct GNUNET_ATS_SolverFunctions *sf = cls;
1214 struct GAS_PROPORTIONAL_Handle *s = sf->cls;
1215 struct AddressWrapper *cur;
1216 struct AddressWrapper *next;
1217 unsigned int c;
1218
1219 for (c = 0; c < s->env->network_count; c++)
1220 {
1221 GNUNET_break (0 == s->network_entries[c].total_addresses);
1222 GNUNET_break (0 == s->network_entries[c].active_addresses);
1223 next = s->network_entries[c].head;
1224 while (NULL != (cur = next))
1225 {
1226 next = cur->next;
1227 GNUNET_CONTAINER_DLL_remove (s->network_entries[c].head,
1228 s->network_entries[c].tail,
1229 cur);
1230 GNUNET_free (cur->addr->solver_information);
1231 GNUNET_free (cur);
1232 }
1233 GNUNET_free (s->network_entries[c].stat_total);
1234 GNUNET_free (s->network_entries[c].stat_active);
1235 }
1236 GNUNET_break (0 == s->active_addresses);
1237 GNUNET_free (s->network_entries);
1238 GNUNET_free (s);
1239 return NULL;
1240}
1241
1242
1243/* end of plugin_ats_proportional.c */
diff --git a/src/ats/test_ats_api.c b/src/ats/test_ats_api.c
deleted file mode 100644
index 390cafe0f..000000000
--- a/src/ats/test_ats_api.c
+++ /dev/null
@@ -1,296 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/test_ats_api.c
22 * @brief test ATS
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "test_ats_lib.h"
27
28/**
29 * Global timeout for the testcase.
30 */
31#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
32
33/**
34 * Definition of the test as a sequence of commands.
35 */
36static struct Command test_commands[] = {
37 {
38 .code = CMD_ADD_ADDRESS,
39 .label = "add-address-0-0",
40 .details.add_address = {
41 .pid = 0,
42 .addr_num = 0,
43 .addr_flags = GNUNET_HELLO_ADDRESS_INFO_NONE,
44 .session = 0,
45 .properties = {
46 .scope = GNUNET_NT_LAN
47 }
48
49
50 }
51
52
53 },
54 /* 1: adding same address again should fail */
55 {
56 .code = CMD_ADD_ADDRESS,
57 .label = "add-address-0-0:FAIL",
58 .details.add_address = {
59 .pid = 0,
60 .addr_num = 0,
61 .addr_flags = GNUNET_HELLO_ADDRESS_INFO_NONE,
62 .session = 0,
63 .properties = {
64 .scope = GNUNET_NT_LAN
65 },
66 .expect_fail = 1
67 }
68
69
70 },
71 /* 2: some solver still require explicit start */
72 {
73 .code = CMD_REQUEST_CONNECTION_START,
74 .label = "request-0",
75 .details.request_connection_start = {
76 .pid = 0
77 }
78
79
80 },
81 /* 3: check we got an address */
82 {
83 .code = CMD_AWAIT_ADDRESS_SUGGESTION,
84 .details.await_address_suggestion = {
85 .add_label = "add-address-0-0"
86 }
87
88
89 },
90 /* 4: check monitor also got the address */
91 {
92 .code = CMD_AWAIT_ADDRESS_INFORMATION,
93 .details.await_address_information = {
94 .add_label = "add-address-0-0"
95 }
96
97
98 },
99 /* 5: test session API */
100 {
101 .code = CMD_ADD_SESSION,
102 .label = "add-session-0-0-1",
103 .details.add_session = {
104 .add_label = "add-address-0-0",
105 .session = 1
106 }
107
108
109 },
110 {
111 .code = CMD_DEL_SESSION,
112 .details.del_session = {
113 .add_session_label = "add-session-0-0-1",
114 }
115
116
117 },
118 /* 7: test preference API */
119 {
120 .code = CMD_CHANGE_PREFERENCE,
121 .details.change_preference = {
122 .pid = 0
123 /* FIXME: preference details */
124 }
125
126
127 },
128 {
129 .code = CMD_PROVIDE_FEEDBACK,
130 .details.provide_feedback = {
131 .pid = 0,
132 .scope = { 50LL }
133 /* FIXME: preference details */
134 }
135
136
137 },
138 /* 9: test sanity check address listing */
139 {
140 .code = CMD_LIST_ADDRESSES,
141 .details.list_addresses = {
142 .pid = 0,
143 .all = 1,
144 .min_calls = 2, // ?
145 .max_calls = 2,
146 .min_active_calls = 1,
147 .max_active_calls = 1
148 }
149
150
151 },
152 /* 10: remove address testing */
153 {
154 .code = CMD_DEL_ADDRESS,
155 .details.del_address = {
156 .add_label = "add-address-0-0"
157 }
158
159
160 },
161 /* 11: check we got disconnected */
162 {
163 .code = CMD_AWAIT_DISCONNECT_SUGGESTION,
164 .details.await_disconnect_suggestion = {
165 .pid = 0
166 }
167
168
169 },
170 /* 12: just for symmetry, also stop asking for the connection */
171 {
172 .code = CMD_REQUEST_CONNECTION_STOP,
173 .details.request_connection_stop = {
174 .connect_label = "request-0",
175 }
176
177
178 },
179 /* 13: add address again */
180 {
181 .code = CMD_ADD_ADDRESS,
182 .label = "add-address-0-0:1",
183 .details.add_address = {
184 .pid = 0,
185 .addr_num = 0,
186 .session = 0,
187 .properties = {
188 .scope = GNUNET_NT_LAN
189 }
190
191
192 }
193
194
195 },
196 /* 14: some solver still require explicit start */
197 {
198 .code = CMD_REQUEST_CONNECTION_START,
199 .label = "request-0",
200 .details.request_connection_start = {
201 .pid = 0
202 }
203
204
205 },
206 /* 15: check we got an address */
207 {
208 .code = CMD_AWAIT_ADDRESS_SUGGESTION,
209 .details.await_address_suggestion = {
210 .add_label = "add-address-0-0:1"
211 }
212
213
214 },
215 /* 16: add alternative address */
216 {
217 .code = CMD_ADD_ADDRESS,
218 .label = "add-address-0-1",
219 .details.add_address = {
220 .pid = 0,
221 .addr_num = 1,
222 .addr_flags = GNUNET_HELLO_ADDRESS_INFO_NONE,
223 .session = 0,
224 .properties = {
225 .scope = GNUNET_NT_LAN
226 }
227
228
229 }
230
231
232 },
233 /* 17: remove original address */
234 {
235 .code = CMD_DEL_ADDRESS,
236 .details.del_address = {
237 .add_label = "add-address-0-0:1"
238 }
239
240
241 },
242 /* 18: check we switched to alternative address */
243 {
244 .code = CMD_AWAIT_ADDRESS_SUGGESTION,
245 .details.await_address_suggestion = {
246 .add_label = "add-address-0-1"
247 }
248
249
250 },
251 /* 19: remove alternative address */
252 {
253 .code = CMD_DEL_ADDRESS,
254 .details.del_address = {
255 .add_label = "add-address-0-1"
256 }
257
258
259 },
260 /* 20: check we got disconnected */
261 {
262 .code = CMD_AWAIT_DISCONNECT_SUGGESTION,
263 .details.await_disconnect_suggestion = {
264 .pid = 0
265 }
266
267
268 },
269 /* 21: just for symmetry, also stop asking for the connection */
270 {
271 .code = CMD_REQUEST_CONNECTION_STOP,
272 .details.request_connection_stop = {
273 .connect_label = "request-0",
274 }
275
276
277 },
278 /* Test ends successfully */
279 {
280 .code = CMD_END_PASS
281 }
282};
283
284
285int
286main (int argc,
287 char *argv[])
288{
289 return TEST_ATS_run (argc,
290 argv,
291 test_commands,
292 TIMEOUT);
293}
294
295
296/* end of file test_ats_api.c */
diff --git a/src/ats/test_ats_api.conf b/src/ats/test_ats_api.conf
deleted file mode 100644
index d45e84d18..000000000
--- a/src/ats/test_ats_api.conf
+++ /dev/null
@@ -1,35 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-ats-api-scheduling/
5
6[ats]
7# Enable MLP mode (default: NO)
8#MODE = ril
9MODE = mlp
10# Network specific inbound/outbound quotas
11# UNSPECIFIED
12UNSPECIFIED_QUOTA_IN = 64 KiB
13UNSPECIFIED_QUOTA_OUT = 64 KiB
14# LOOPBACK
15LOOPBACK_QUOTA_IN = unlimited
16LOOPBACK_QUOTA_OUT = unlimited
17# LAN
18LAN_QUOTA_IN = unlimited
19LAN_QUOTA_OUT = unlimited
20# WAN
21WAN_QUOTA_IN = 64 KiB
22WAN_QUOTA_OUT = 64 KiB
23# WLAN
24WLAN_QUOTA_IN = 512
25WLAN_QUOTA_OUT = 512
26
27# ATS extended options
28DUMP_MLP = NO
29DUMP_SOLUTION = NO
30DUMP_OVERWRITE = NO
31DUMP_MIN_PEERS = 0
32DUMP_MIN_ADDRS = 0
33DUMP_OVERWRITE = NO
34ATS_MIN_INTERVAL = 15000
35ATS_EXEC_INTERVAL = 30000
diff --git a/src/ats/test_ats_api_delayed.conf b/src/ats/test_ats_api_delayed.conf
deleted file mode 100644
index 3aac88cf9..000000000
--- a/src/ats/test_ats_api_delayed.conf
+++ /dev/null
@@ -1,36 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-ats-api-scheduling/
5
6[ats]
7PREFIX = ./test_delay -t 10 --
8# Enable MLP mode (default: NO)
9#MODE = ril
10MODE = mlp
11# Network specific inbound/outbound quotas
12# UNSPECIFIED
13UNSPECIFIED_QUOTA_IN = 64 KiB
14UNSPECIFIED_QUOTA_OUT = 64 KiB
15# LOOPBACK
16LOOPBACK_QUOTA_IN = unlimited
17LOOPBACK_QUOTA_OUT = unlimited
18# LAN
19LAN_QUOTA_IN = unlimited
20LAN_QUOTA_OUT = unlimited
21# WAN
22WAN_QUOTA_IN = 64 KiB
23WAN_QUOTA_OUT = 64 KiB
24# WLAN
25WLAN_QUOTA_IN = 512
26WLAN_QUOTA_OUT = 512
27
28# ATS extended options
29DUMP_MLP = NO
30DUMP_SOLUTION = NO
31DUMP_OVERWRITE = NO
32DUMP_MIN_PEERS = 0
33DUMP_MIN_ADDRS = 0
34DUMP_OVERWRITE = NO
35ATS_MIN_INTERVAL = 15000
36ATS_EXEC_INTERVAL = 30000
diff --git a/src/ats/test_ats_api_proportional.conf b/src/ats/test_ats_api_proportional.conf
deleted file mode 100644
index ee8f8f8e7..000000000
--- a/src/ats/test_ats_api_proportional.conf
+++ /dev/null
@@ -1,24 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-ats-proportional/
5
6[ats]
7# Enable PROPORTIONAL mode (default: NO)
8MODE = proportional
9# Network specific inbound/outbound quotas
10# UNSPECIFIED
11UNSPECIFIED_QUOTA_IN = unlimited
12UNSPECIFIED_QUOTA_OUT = unlimited
13# LOOPBACK
14LOOPBACK_QUOTA_IN = unlimited
15LOOPBACK_QUOTA_OUT = unlimited
16# LAN
17LAN_QUOTA_IN = unlimited
18LAN_QUOTA_OUT = unlimited
19# WAN
20WAN_QUOTA_IN = 5 MiB
21WAN_QUOTA_OUT = 5 MiB
22# WLAN
23WLAN_QUOTA_IN = 4096
24WLAN_QUOTA_OUT = 4096
diff --git a/src/ats/test_ats_lib.c b/src/ats/test_ats_lib.c
deleted file mode 100644
index d19da0106..000000000
--- a/src/ats/test_ats_lib.c
+++ /dev/null
@@ -1,1107 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/test_ats_lib.c
22 * @brief test ATS library with a generic interpreter for running ATS tests
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_ats_service.h"
28#include "gnunet_testing_lib.h"
29#include "test_ats_lib.h"
30
31/**
32 * Information about the last address suggestion we got for a peer.
33 */
34struct AddressSuggestData
35{
36 /**
37 * Which session were we given?
38 */
39 struct GNUNET_ATS_Session *session;
40
41 /**
42 * What address was assigned?
43 */
44 struct GNUNET_HELLO_Address *address;
45
46 /**
47 * Outbound bandwidth assigned.
48 */
49 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
50
51 /**
52 * Inbound bandwidth assigned.
53 */
54 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
55
56 /**
57 * Was the bandwidth assigned non-zero?
58 */
59 int active;
60};
61
62
63/**
64 * Information about the last address information we got for an address.
65 */
66struct AddressInformationData
67{
68 /**
69 * What address is this data about?
70 */
71 struct GNUNET_HELLO_Address *address;
72
73 /**
74 * Which properties were given?
75 */
76 struct GNUNET_ATS_Properties properties;
77
78 /**
79 * Outbound bandwidth reported.
80 */
81 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
82
83 /**
84 * Inbound bandwidth reported.
85 */
86 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
87
88 /**
89 * Was the address said to be 'active'?
90 */
91 int active;
92};
93
94
95/**
96 * Scheduling handle
97 */
98static struct GNUNET_ATS_SchedulingHandle *sched_ats;
99
100/**
101 * Connectivity handle
102 */
103static struct GNUNET_ATS_ConnectivityHandle *con_ats;
104
105/**
106 * Performance handle
107 */
108static struct GNUNET_ATS_PerformanceHandle *perf_ats;
109
110/**
111 * Handle for the interpreter task.
112 */
113static struct GNUNET_SCHEDULER_Task *interpreter_task;
114
115/**
116 * Map from peer identities to the last address suggestion
117 * `struct AddressSuggestData` we got for the respective peer.
118 */
119static struct GNUNET_CONTAINER_MultiPeerMap *p2asd;
120
121/**
122 * Map from peer identities to the last address information
123 * sets for all addresses of this peer. Each peer is mapped
124 * to one or more `struct AddressInformationData` entries.
125 */
126static struct GNUNET_CONTAINER_MultiPeerMap *p2aid;
127
128/**
129 * Global timeout for the test.
130 */
131static struct GNUNET_TIME_Relative TIMEOUT;
132
133/**
134 * Return value from #main().
135 */
136static int ret;
137
138/**
139 * Current global command offset into the #commands array.
140 */
141static unsigned int off;
142
143/**
144 * Commands for the current test.
145 */
146static struct Command *test_commands;
147
148
149/**
150 * Free `struct AddressSuggestData` entry.
151 *
152 * @param cls NULL
153 * @param key ignored
154 * @param value the `struct AddressSuggestData` to release
155 * @return #GNUNET_OK (continue to iterate)
156 */
157static int
158free_asd (void *cls,
159 const struct GNUNET_PeerIdentity *key,
160 void *value)
161{
162 struct AddressSuggestData *asd = value;
163
164 GNUNET_assert (GNUNET_YES ==
165 GNUNET_CONTAINER_multipeermap_remove (p2asd,
166 key,
167 asd));
168 GNUNET_free (asd->address);
169 GNUNET_free (asd);
170 return GNUNET_OK;
171}
172
173
174/**
175 * Free `struct AddressInformationData` entry.
176 *
177 * @param cls NULL
178 * @param key ignored
179 * @param value the `struct AddressSuggestData` to release
180 * @return #GNUNET_OK (continue to iterate)
181 */
182static int
183free_aid (void *cls,
184 const struct GNUNET_PeerIdentity *key,
185 void *value)
186{
187 struct AddressInformationData *aid = value;
188
189 GNUNET_assert (GNUNET_YES ==
190 GNUNET_CONTAINER_multipeermap_remove (p2aid,
191 key,
192 aid));
193 GNUNET_free (aid->address);
194 GNUNET_free (aid);
195 return GNUNET_OK;
196}
197
198
199/**
200 * Find latest address suggestion made for the given peer.
201 *
202 * @param pid peer to look up
203 * @return NULL if peer was never involved
204 */
205static struct AddressSuggestData *
206find_address_suggestion (const struct GNUNET_PeerIdentity *pid)
207{
208 return GNUNET_CONTAINER_multipeermap_get (p2asd,
209 pid);
210}
211
212
213/**
214 * Closure for #match_address()
215 */
216struct MatchAddressContext
217{
218 /**
219 * Address to find.
220 */
221 const struct GNUNET_HELLO_Address *addr;
222
223 /**
224 * Where to return address information if found.
225 */
226 struct AddressInformationData *ret;
227};
228
229
230/**
231 * Find matching address information.
232 *
233 * @param cls a `struct MatchAddressContext`
234 * @param key unused
235 * @param value a `struct AddressInformationData`
236 * @return #GNUNET_OK if not found
237 */
238static int
239match_address (void *cls,
240 const struct GNUNET_PeerIdentity *key,
241 void *value)
242{
243 struct MatchAddressContext *mac = cls;
244 struct AddressInformationData *aid = value;
245
246 if (0 == GNUNET_HELLO_address_cmp (mac->addr,
247 aid->address))
248 {
249 mac->ret = aid;
250 return GNUNET_NO;
251 }
252 return GNUNET_OK;
253}
254
255
256/**
257 * Find latest address information made for the given address.
258 *
259 * @param addr address to look up
260 * @return NULL if peer was never involved
261 */
262static struct AddressInformationData *
263find_address_information (const struct GNUNET_HELLO_Address *addr)
264{
265 struct MatchAddressContext mac;
266
267 mac.ret = NULL;
268 mac.addr = addr;
269 GNUNET_CONTAINER_multipeermap_get_multiple (p2aid,
270 &addr->peer,
271 &match_address,
272 &mac);
273 return mac.ret;
274}
275
276
277/**
278 * Task run to terminate the testcase.
279 *
280 * @param cls NULL
281 */
282static void
283end (void *cls)
284{
285 if (0 != ret)
286 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
287 "Test failed at stage %u %s\n",
288 off,
289 (NULL != test_commands[off].label)
290 ? test_commands[off].label
291 : "");
292 if (NULL != interpreter_task)
293 {
294 GNUNET_SCHEDULER_cancel (interpreter_task);
295 interpreter_task = NULL;
296 }
297 if (NULL != sched_ats)
298 {
299 GNUNET_ATS_scheduling_done (sched_ats);
300 sched_ats = NULL;
301 }
302 if (NULL != con_ats)
303 {
304 GNUNET_ATS_connectivity_done (con_ats);
305 con_ats = NULL;
306 }
307 if (NULL != perf_ats)
308 {
309 GNUNET_ATS_performance_done (perf_ats);
310 perf_ats = NULL;
311 }
312 if (NULL != p2asd)
313 {
314 GNUNET_CONTAINER_multipeermap_iterate (p2asd,
315 &free_asd,
316 NULL);
317 GNUNET_CONTAINER_multipeermap_destroy (p2asd);
318 p2asd = NULL;
319 }
320 if (NULL != p2aid)
321 {
322 GNUNET_CONTAINER_multipeermap_iterate (p2aid,
323 &free_aid,
324 NULL);
325 GNUNET_CONTAINER_multipeermap_destroy (p2aid);
326 p2aid = NULL;
327 }
328}
329
330
331/**
332 * Main interpreter loop. Runs the steps of the test.
333 *
334 * @param cls NULL
335 */
336static void
337interpreter (void *cls);
338
339
340/**
341 * Run the interpreter next.
342 */
343static void
344run_interpreter ()
345{
346 if (NULL != interpreter_task)
347 GNUNET_SCHEDULER_cancel (interpreter_task);
348 interpreter_task = GNUNET_SCHEDULER_add_now (&interpreter,
349 NULL);
350}
351
352
353/**
354 * Initialize public key of a peer based on a single number.
355 *
356 * @param pid number to use as the basis
357 * @param pk resulting fake public key
358 */
359static void
360make_peer (uint32_t pid,
361 struct GNUNET_PeerIdentity *pk)
362{
363 memset (pk,
364 (int) pid,
365 sizeof(struct GNUNET_PeerIdentity));
366 GNUNET_memcpy (pk,
367 &pid,
368 sizeof(uint32_t));
369}
370
371
372/**
373 * Generate a fake address based on the given parameters.
374 *
375 * @param pid number of the peer
376 * @param num number of the address at peer @a pid
377 * @param addr_flags flags to use for the address
378 * @return the address
379 */
380static struct GNUNET_HELLO_Address *
381make_address (uint32_t pid,
382 uint32_t num,
383 enum GNUNET_HELLO_AddressInfo addr_flags)
384{
385 struct GNUNET_PeerIdentity pk;
386 uint32_t nbo;
387
388 nbo = htonl (num);
389 make_peer (pid,
390 &pk);
391 return GNUNET_HELLO_address_allocate (&pk,
392 "test",
393 &nbo,
394 sizeof(nbo),
395 addr_flags);
396}
397
398
399/**
400 * Our dummy sessions.
401 */
402struct GNUNET_ATS_Session
403{
404 /**
405 * Field to avoid `0 == sizeof(struct GNUNET_ATS_Session)`.
406 */
407 unsigned int non_empty;
408};
409
410
411/**
412 * Create a session instance for ATS.
413 *
414 * @param i which session number to return
415 * @return NULL if @a i is 0, otherwise a pointer unique to @a i
416 */
417static struct GNUNET_ATS_Session *
418make_session (unsigned int i)
419{
420 struct GNUNET_ATS_Session *baseptr = NULL;
421
422 if (0 == i)
423 return NULL;
424 /* Yes, these are *intentionally* out-of-bounds,
425 and offset from NULL, as nobody should ever
426 use those other than to compare pointers! */
427 return baseptr + i;
428}
429
430
431/**
432 * Find a @a code command before the global #off with the
433 * specified @a label.
434 *
435 * @param code opcode to look for
436 * @param label label to look for, NULL for none
437 * @return previous command with the matching label
438 */
439static struct Command *
440find_command (enum CommandCode code,
441 const char *label)
442{
443 int i;
444
445 if (NULL == label)
446 return NULL;
447 for (i = off - 1; i >= 0; i--)
448 if ((code == test_commands[i].code) &&
449 (0 == strcmp (test_commands[i].label,
450 label)))
451 return &test_commands[i];
452 GNUNET_break (0);
453 return NULL;
454}
455
456
457/**
458 * Function called from #GNUNET_ATS_performance_list_addresses when
459 * we process a #CMD_LIST_ADDRESSES command.
460 *
461 * @param cls the `struct Command` that caused the call
462 * @param address the address, NULL if ATS service was disconnected
463 * @param address_active #GNUNET_YES if this address is actively used
464 * to maintain a connection to a peer;
465 * #GNUNET_NO if the address is not actively used;
466 * #GNUNET_SYSERR if this address is no longer available for ATS
467 * @param bandwidth_out assigned outbound bandwidth for the connection
468 * @param bandwidth_in assigned inbound bandwidth for the connection
469 * @param prop performance data for the address
470 */
471static void
472info_cb (void *cls,
473 const struct GNUNET_HELLO_Address *address,
474 int address_active,
475 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
476 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
477 const struct GNUNET_ATS_Properties *prop)
478{
479 struct Command *c = cls;
480 struct CommandListAddresses *cmd = &c->details.list_addresses;
481
482 if (NULL == address)
483 {
484 cmd->alh = NULL;
485 /* we are done with the iteration, continue to execute */
486 if ((cmd->calls < cmd->min_calls) &&
487 (cmd->active_calls < cmd->min_active_calls))
488 {
489 GNUNET_SCHEDULER_shutdown ();
490 return;
491 }
492 off++;
493 run_interpreter ();
494 return;
495 }
496 switch (address_active)
497 {
498 case GNUNET_YES:
499 cmd->active_calls++;
500 cmd->calls++;
501 break;
502
503 case GNUNET_NO:
504 cmd->calls++;
505 break;
506
507 case GNUNET_SYSERR:
508 return;
509 }
510 if ((cmd->calls > cmd->max_calls) &&
511 (cmd->active_calls < cmd->max_active_calls))
512 {
513 GNUNET_break (0);
514 GNUNET_ATS_performance_list_addresses_cancel (cmd->alh);
515 cmd->alh = NULL;
516 GNUNET_SCHEDULER_shutdown ();
517 return;
518 }
519}
520
521
522/**
523 * Function called with reservation result.
524 *
525 * @param cls closure with the reservation command (`struct Command`)
526 * @param peer identifies the peer
527 * @param amount set to the amount that was actually reserved or unreserved;
528 * either the full requested amount or zero (no partial reservations)
529 * @param res_delay if the reservation could not be satisfied (amount was 0), how
530 * long should the client wait until re-trying?
531 */
532static void
533reservation_cb (void *cls,
534 const struct GNUNET_PeerIdentity *peer,
535 int32_t amount,
536 struct GNUNET_TIME_Relative res_delay)
537{
538 struct Command *cmd = cls;
539 struct GNUNET_PeerIdentity pid;
540
541 cmd->details.reserve_bandwidth.rc = NULL;
542 make_peer (cmd->details.reserve_bandwidth.pid,
543 &pid);
544 GNUNET_assert (0 == GNUNET_memcmp (peer,
545 &pid));
546 switch (cmd->details.reserve_bandwidth.expected_result)
547 {
548 case GNUNET_OK:
549 if (amount != cmd->details.reserve_bandwidth.amount)
550 {
551 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
552 "Unexpectedly failed to reserve %d/%d bytes with delay %s!\n",
553 (int) amount,
554 (int) cmd->details.reserve_bandwidth.amount,
555 GNUNET_STRINGS_relative_time_to_string (res_delay,
556 GNUNET_YES));
557 GNUNET_break (0);
558 GNUNET_SCHEDULER_shutdown ();
559 return;
560 }
561 break;
562
563 case GNUNET_NO:
564 GNUNET_break ((0 != amount) ||
565 (0 != res_delay.rel_value_us));
566 break;
567
568 case GNUNET_SYSERR:
569 if ((amount != 0) ||
570 (0 == res_delay.rel_value_us))
571 {
572 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
573 "Unexpectedly reserved %d bytes with delay %s!\n",
574 (int) amount,
575 GNUNET_STRINGS_relative_time_to_string (res_delay,
576 GNUNET_YES));
577 GNUNET_break (0);
578 GNUNET_SCHEDULER_shutdown ();
579 return;
580 }
581 break;
582 }
583 off++;
584 run_interpreter ();
585}
586
587
588/**
589 * Main interpreter loop. Runs the steps of the test.
590 *
591 * @param cls NULL
592 */
593static void
594interpreter (void *cls)
595
596{
597 struct Command *cmd;
598
599 interpreter_task = NULL;
600 while (1)
601 {
602 cmd = &test_commands[off];
603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
604 "#%u: %d %s\n",
605 off,
606 (int) cmd->code,
607 (NULL != cmd->label) ? cmd->label : "");
608 switch (cmd->code)
609 {
610 case CMD_END_PASS:
611 ret = 0;
612 GNUNET_SCHEDULER_shutdown ();
613 return;
614
615 case CMD_ADD_ADDRESS:
616 {
617 struct GNUNET_HELLO_Address *addr;
618 struct GNUNET_ATS_Session *session;
619
620 addr = make_address (cmd->details.add_address.pid,
621 cmd->details.add_address.addr_num,
622 cmd->details.add_address.addr_flags);
623 session = make_session (cmd->details.add_address.session);
624 if (cmd->details.add_address.expect_fail)
625 GNUNET_log_skip (1, GNUNET_NO);
626 cmd->details.add_address.ar
627 = GNUNET_ATS_address_add (sched_ats,
628 addr,
629 session,
630 &cmd->details.add_address.properties);
631 GNUNET_free (addr);
632 if (cmd->details.add_address.expect_fail)
633 {
634 GNUNET_log_skip (0, GNUNET_YES);
635 }
636 else if (NULL == cmd->details.add_address.ar)
637 {
638 GNUNET_break (0);
639 GNUNET_SCHEDULER_shutdown ();
640 return;
641 }
642 off++;
643 break;
644 }
645
646 case CMD_DEL_ADDRESS:
647 {
648 struct Command *add;
649
650 add = find_command (CMD_ADD_ADDRESS,
651 cmd->details.del_address.add_label);
652 GNUNET_assert (NULL != add->details.add_address.ar);
653 GNUNET_ATS_address_destroy (add->details.add_address.ar);
654 add->details.add_address.ar = NULL;
655 off++;
656 break;
657 }
658
659 case CMD_AWAIT_ADDRESS_SUGGESTION:
660 {
661 struct GNUNET_PeerIdentity pid;
662 struct GNUNET_HELLO_Address *addr;
663 struct Command *add;
664 struct AddressSuggestData *asd;
665 int done;
666
667 make_peer (cmd->details.await_address_suggestion.pid,
668 &pid);
669 asd = find_address_suggestion (&pid);
670 if (NULL == asd)
671 return;
672 if (GNUNET_NO == asd->active)
673 return; /* last suggestion was to disconnect, wait longer */
674 done = GNUNET_YES;
675 if (NULL != cmd->details.await_address_suggestion.add_label)
676 {
677 done = GNUNET_NO;
678 add = find_command (CMD_ADD_ADDRESS,
679 cmd->details.await_address_suggestion.add_label);
680 addr = make_address (add->details.add_address.pid,
681 add->details.add_address.addr_num,
682 add->details.add_address.addr_flags);
683 if ((asd->session ==
684 make_session (add->details.add_address.session)) &&
685 (0 ==
686 GNUNET_HELLO_address_cmp (addr,
687 asd->address)))
688 done = GNUNET_YES;
689 GNUNET_free (addr);
690 }
691 if (GNUNET_NO == done)
692 return;
693 off++;
694 break;
695 }
696
697 case CMD_AWAIT_DISCONNECT_SUGGESTION:
698 {
699 struct GNUNET_PeerIdentity pid;
700 struct AddressSuggestData *asd;
701
702 make_peer (cmd->details.await_disconnect_suggestion.pid,
703 &pid);
704 asd = find_address_suggestion (&pid);
705 if (NULL == asd)
706 return; /* odd, no suggestion at all yet!? */
707 if (GNUNET_YES == asd->active)
708 return; /* last suggestion was to activate, wait longer */
709 /* last suggestion was to deactivate, condition satisfied! */
710 off++;
711 break;
712 }
713
714 case CMD_REQUEST_CONNECTION_START:
715 {
716 struct GNUNET_PeerIdentity pid;
717
718 make_peer (cmd->details.request_connection_start.pid,
719 &pid);
720 cmd->details.request_connection_start.csh
721 = GNUNET_ATS_connectivity_suggest (con_ats,
722 &pid,
723 1);
724 off++;
725 break;
726 }
727
728 case CMD_REQUEST_CONNECTION_STOP:
729 {
730 struct Command *start;
731
732 start = find_command (CMD_REQUEST_CONNECTION_START,
733 cmd->details.request_connection_stop.connect_label);
734 GNUNET_ATS_connectivity_suggest_cancel (
735 start->details.request_connection_start.csh);
736 start->details.request_connection_start.csh = NULL;
737 off++;
738 break;
739 }
740
741 case CMD_AWAIT_ADDRESS_INFORMATION:
742 {
743 struct AddressInformationData *aid;
744 struct Command *add;
745 struct Command *update;
746 struct GNUNET_HELLO_Address *addr;
747 const struct GNUNET_ATS_Properties *cmp;
748
749 add = find_command (CMD_ADD_ADDRESS,
750 cmd->details.await_address_information.add_label);
751 update = find_command (CMD_UPDATE_ADDRESS,
752 cmd->details.await_address_information.
753 update_label);
754 addr = make_address (add->details.add_address.pid,
755 add->details.add_address.addr_num,
756 add->details.add_address.addr_flags);
757 aid = find_address_information (addr);
758 GNUNET_free (addr);
759 if (NULL == update)
760 cmp = &add->details.add_address.properties;
761 else
762 cmp = &update->details.update_address.properties;
763 if ((NULL != aid) &&
764 (cmp->delay.rel_value_us == aid->properties.delay.rel_value_us) &&
765 (cmp->utilization_out == aid->properties.utilization_out) &&
766 (cmp->utilization_in == aid->properties.utilization_in) &&
767 (cmp->distance == aid->properties.distance) &&
768 (cmp->scope == aid->properties.scope))
769 {
770 off++;
771 break;
772 }
773 return;
774 }
775
776 case CMD_UPDATE_ADDRESS:
777 {
778 struct Command *add;
779
780 add = find_command (CMD_ADD_ADDRESS,
781 cmd->details.update_address.add_label);
782 GNUNET_assert (NULL != add->details.add_address.ar);
783 GNUNET_ATS_address_update (add->details.add_address.ar,
784 &cmd->details.update_address.properties);
785 off++;
786 break;
787 }
788
789 case CMD_ADD_SESSION:
790 {
791 struct Command *add;
792 struct GNUNET_ATS_Session *session;
793
794 add = find_command (CMD_ADD_ADDRESS,
795 cmd->details.add_session.add_label);
796 session = make_session (cmd->details.add_session.session);
797 GNUNET_assert (NULL != add->details.add_address.ar);
798 GNUNET_ATS_address_add_session (add->details.add_address.ar,
799 session);
800 off++;
801 break;
802 }
803
804 case CMD_DEL_SESSION:
805 {
806 struct Command *add_address;
807 struct Command *add_session;
808 struct GNUNET_ATS_Session *session;
809
810 add_session = find_command (CMD_ADD_SESSION,
811 cmd->details.del_session.add_session_label);
812 add_address = find_command (CMD_ADD_ADDRESS,
813 add_session->details.add_session.add_label);
814 GNUNET_assert (NULL != add_address->details.add_address.ar);
815 session = make_session (add_session->details.add_session.session);
816 GNUNET_ATS_address_del_session (add_address->details.add_address.ar,
817 session);
818 off++;
819 break;
820 }
821
822 case CMD_CHANGE_PREFERENCE:
823 {
824 struct GNUNET_PeerIdentity pid;
825
826 make_peer (cmd->details.change_preference.pid,
827 &pid);
828 GNUNET_ATS_performance_change_preference (perf_ats,
829 &pid,
830 GNUNET_ATS_PREFERENCE_END);
831 off++;
832 break;
833 }
834
835 case CMD_PROVIDE_FEEDBACK:
836 {
837 struct GNUNET_PeerIdentity pid;
838
839 make_peer (cmd->details.provide_feedback.pid,
840 &pid);
841 GNUNET_ATS_performance_give_feedback (perf_ats,
842 &pid,
843 cmd->details.provide_feedback.
844 scope,
845 GNUNET_ATS_PREFERENCE_END);
846 off++;
847 break;
848 }
849
850 case CMD_LIST_ADDRESSES:
851 {
852 struct GNUNET_PeerIdentity pid;
853
854 make_peer (cmd->details.list_addresses.pid,
855 &pid);
856 cmd->details.list_addresses.alh
857 = GNUNET_ATS_performance_list_addresses (perf_ats,
858 &pid,
859 cmd->details.list_addresses.
860 all,
861 &info_cb,
862 cmd);
863 return;
864 }
865
866 case CMD_RESERVE_BANDWIDTH:
867 {
868 struct GNUNET_PeerIdentity pid;
869
870 make_peer (cmd->details.reserve_bandwidth.pid,
871 &pid);
872 cmd->details.reserve_bandwidth.rc
873 = GNUNET_ATS_reserve_bandwidth (perf_ats,
874 &pid,
875 cmd->details.reserve_bandwidth.amount,
876 &reservation_cb,
877 cmd);
878 return;
879 }
880
881 case CMD_SLEEP:
882 off++;
883 interpreter_task = GNUNET_SCHEDULER_add_delayed (cmd->details.sleep.delay,
884 &interpreter,
885 NULL);
886 return;
887 } /* end switch */
888 } /* end while(1) */
889}
890
891
892/**
893 * Signature of a function called by ATS with the current bandwidth
894 * and address preferences as determined by ATS.
895 *
896 * @param cls closure, should point to "asc-closure"
897 * @param peer for which we suggest an address, NULL if ATS connection died
898 * @param address suggested address (including peer identity of the peer),
899 * may be NULL to signal disconnect from peer
900 * @param session session to use, NULL to establish a new outgoing session
901 * @param bandwidth_out assigned outbound bandwidth for the connection,
902 * 0 to signal disconnect
903 * @param bandwidth_in assigned inbound bandwidth for the connection,
904 * 0 to signal disconnect
905 */
906static void
907address_suggest_cb (void *cls,
908 const struct GNUNET_PeerIdentity *peer,
909 const struct GNUNET_HELLO_Address *address,
910 struct GNUNET_ATS_Session *session,
911 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
912 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
913{
914 const char *asc_cls = cls;
915 struct AddressSuggestData *asd;
916
917 GNUNET_break (0 == strcmp (asc_cls, "asc-closure"));
918 if (NULL == peer)
919 {
920 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
921 "Connection to ATS died, likely a crash!\n");
922 GNUNET_SCHEDULER_shutdown ();
923#if 0
924 /* This is what we should do if we wanted to continue past
925 the ATS crash. */
926 GNUNET_CONTAINER_multipeermap_iterate (p2asd,
927 &free_asd,
928 NULL);
929 GNUNET_CONTAINER_multipeermap_iterate (p2aid,
930 &free_aid,
931 NULL);
932#endif
933 return;
934 }
935
936 asd = find_address_suggestion (peer);
937 if (NULL == asd)
938 {
939 asd = GNUNET_new (struct AddressSuggestData);
940 GNUNET_assert (GNUNET_YES ==
941 GNUNET_CONTAINER_multipeermap_put (p2asd,
942 peer,
943 asd,
944 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
945 }
946 if ((0 == ntohl (bandwidth_out.value__)) &&
947 (0 == ntohl (bandwidth_in.value__)))
948 asd->active = GNUNET_NO;
949 else
950 asd->active = GNUNET_YES;
951 asd->bandwidth_out = bandwidth_out;
952 asd->bandwidth_in = bandwidth_in;
953 asd->session = session;
954 GNUNET_free (asd->address);
955 asd->address = NULL;
956 if (NULL != address)
957 asd->address = GNUNET_HELLO_address_copy (address);
958 if (NULL == interpreter_task)
959 run_interpreter ();
960}
961
962
963/**
964 * Signature of a function that is called with QoS information about an address.
965 *
966 * @param cls closure, should point to "aic-closure"
967 * @param address the address, NULL if ATS service was disconnected
968 * @param address_active #GNUNET_YES if this address is actively used
969 * to maintain a connection to a peer;
970 * #GNUNET_NO if the address is not actively used;
971 * #GNUNET_SYSERR if this address is no longer available for ATS
972 * @param bandwidth_out assigned outbound bandwidth for the connection
973 * @param bandwidth_in assigned inbound bandwidth for the connection
974 * @param prop performance data for the address
975 */
976static void
977address_information_cb (void *cls,
978 const struct GNUNET_HELLO_Address *address,
979 int address_active,
980 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
981 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
982 const struct GNUNET_ATS_Properties *prop)
983{
984 const char *aic_cls = cls;
985 struct AddressInformationData *aid;
986
987 GNUNET_break (0 == strcmp (aic_cls, "aic-closure"));
988 if (NULL == address)
989 {
990 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
991 "Connection to ATS died, likely a crash!\n");
992 GNUNET_CONTAINER_multipeermap_iterate (p2aid,
993 &free_aid,
994 NULL);
995 return;
996 }
997
998 aid = find_address_information (address);
999 if (NULL == aid)
1000 {
1001 aid = GNUNET_new (struct AddressInformationData);
1002 aid->address = GNUNET_HELLO_address_copy (address);
1003 GNUNET_assert (GNUNET_YES ==
1004 GNUNET_CONTAINER_multipeermap_put (p2aid,
1005 &address->peer,
1006 aid,
1007 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1008 }
1009 aid->active = address_active;
1010 aid->bandwidth_out = bandwidth_out;
1011 aid->bandwidth_in = bandwidth_in;
1012 aid->properties = *prop;
1013 if (NULL == interpreter_task)
1014 run_interpreter ();
1015}
1016
1017
1018/**
1019 * Function run once the ATS service has been started.
1020 *
1021 * @param cls NULL
1022 * @param cfg configuration for the testcase
1023 * @param peer handle to the peer
1024 */
1025static void
1026run (void *cls,
1027 const struct GNUNET_CONFIGURATION_Handle *cfg,
1028 struct GNUNET_TESTING_Peer *peer)
1029{
1030 p2asd = GNUNET_CONTAINER_multipeermap_create (128,
1031 GNUNET_NO);
1032 p2aid = GNUNET_CONTAINER_multipeermap_create (128,
1033 GNUNET_NO);
1034 GNUNET_SCHEDULER_add_delayed (TIMEOUT,
1035 &end,
1036 NULL);
1037
1038 sched_ats = GNUNET_ATS_scheduling_init (cfg,
1039 &address_suggest_cb,
1040 "asc-closure");
1041 if (NULL == sched_ats)
1042 {
1043 GNUNET_break (0);
1044 GNUNET_SCHEDULER_shutdown ();
1045 return;
1046 }
1047 con_ats = GNUNET_ATS_connectivity_init (cfg);
1048 if (NULL == con_ats)
1049 {
1050 GNUNET_break (0);
1051 GNUNET_SCHEDULER_shutdown ();
1052 return;
1053 }
1054 perf_ats = GNUNET_ATS_performance_init (cfg,
1055 &address_information_cb,
1056 "aic-closure");
1057 if (NULL == perf_ats)
1058 {
1059 GNUNET_break (0);
1060 GNUNET_SCHEDULER_shutdown ();
1061 return;
1062 }
1063 run_interpreter ();
1064}
1065
1066
1067/**
1068 * Run ATS test.
1069 *
1070 * @param argc length of @a argv
1071 * @param argv command line
1072 * @param cmds commands to run with the interpreter
1073 * @param timeout how long is the test allowed to take?
1074 * @return 0 on success
1075 */
1076int
1077TEST_ATS_run (int argc,
1078 char *argv[],
1079 struct Command *cmds,
1080 struct GNUNET_TIME_Relative timeout)
1081{
1082 char *test_filename = GNUNET_strdup (argv[0]);
1083 char *sep;
1084 char *config_file;
1085 char *underscore;
1086
1087 test_commands = cmds;
1088 TIMEOUT = timeout;
1089 if (NULL != (sep = strstr (test_filename, ".exe")))
1090 sep[0] = '\0';
1091 underscore = strrchr (test_filename, (int) '_');
1092 GNUNET_assert (NULL != underscore);
1093 GNUNET_asprintf (&config_file,
1094 "test_ats_api_%s.conf",
1095 underscore + 1);
1096 ret = 2;
1097 if (0 != GNUNET_TESTING_peer_run ("test-ats-api",
1098 config_file,
1099 &run, NULL))
1100 ret = 1;
1101 GNUNET_free (test_filename);
1102 GNUNET_free (config_file);
1103 return ret;
1104}
1105
1106
1107/* end of test_ats_lib.c */
diff --git a/src/ats/test_ats_lib.h b/src/ats/test_ats_lib.h
deleted file mode 100644
index 60b459f79..000000000
--- a/src/ats/test_ats_lib.h
+++ /dev/null
@@ -1,512 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/test_ats_lib.h
22 * @brief test ATS library with a generic interpreter for running ATS tests
23 * @author Christian Grothoff
24 */
25#ifndef TEST_ATS_LIB_H
26#define TEST_ATS_LIB_H
27
28#include "gnunet_util_lib.h"
29#include "gnunet_ats_service.h"
30#include "gnunet_testing_lib.h"
31
32
33/**
34 * Commands for the interpreter.
35 */
36enum CommandCode
37{
38 /**
39 * End the test (passing).
40 */
41 CMD_END_PASS = 0,
42
43 /**
44 * Call #GNUNET_ATS_address_add().
45 */
46 CMD_ADD_ADDRESS,
47
48 /**
49 * Call #GNUNET_ATS_address_del().
50 */
51 CMD_DEL_ADDRESS,
52
53 /**
54 * Wait for ATS to suggest address.
55 */
56 CMD_AWAIT_ADDRESS_SUGGESTION,
57
58 /**
59 * Wait for ATS to suggest disconnect.
60 */
61 CMD_AWAIT_DISCONNECT_SUGGESTION,
62
63 /**
64 * Ask ATS to connect to a peer, using
65 * #GNUNET_ATS_connectivity_suggest().
66 */
67 CMD_REQUEST_CONNECTION_START,
68
69 /**
70 * Tell ATS we no longer need a connection to a peer, using
71 * #GNUNET_ATS_connectivity_suggest_cancel().
72 */
73 CMD_REQUEST_CONNECTION_STOP,
74
75 /**
76 * Wait for certain address information to be provided.
77 */
78 CMD_AWAIT_ADDRESS_INFORMATION,
79
80 /**
81 * Update properties of an address, using
82 * #GNUNET_ATS_address_update().
83 */
84 CMD_UPDATE_ADDRESS,
85
86 /**
87 * Add session to an address, using
88 * #GNUNET_ATS_address_add_session().
89 */
90 CMD_ADD_SESSION,
91
92 /**
93 * Remove session from an address, using
94 * #GNUNET_ATS_address_del_session().
95 */
96 CMD_DEL_SESSION,
97
98 /**
99 * Change performance preferences for a peer, testing
100 * #GNUNET_ATS_performance_change_preference().
101 */
102 CMD_CHANGE_PREFERENCE,
103
104 /**
105 * Provide allocation quality feedback, testing
106 * #GNUNET_ATS_performance_give_feedback().
107 */
108 CMD_PROVIDE_FEEDBACK,
109
110 /**
111 * Obtain list of all addresses, testing
112 * #GNUNET_ATS_performance_list_addresses().
113 */
114 CMD_LIST_ADDRESSES,
115
116 /**
117 * Reserve bandwidth, testing
118 * #GNUNET_ATS_reserve_bandwidth().
119 */
120 CMD_RESERVE_BANDWIDTH,
121
122 /**
123 * Wait for a bit.
124 */
125 CMD_SLEEP
126};
127
128
129/**
130 * Details for the #CMD_ADD_ADDRESS command.
131 */
132struct CommandAddAddress
133{
134 /**
135 * Number of the peer (used to generate PID).
136 */
137 unsigned int pid;
138
139 /**
140 * Number of the address (used to generate binary address).
141 */
142 unsigned int addr_num;
143
144 /**
145 * Session to supply, 0 for NULL.
146 */
147 unsigned int session;
148
149 /**
150 * Flags to set for the address.
151 */
152 enum GNUNET_HELLO_AddressInfo addr_flags;
153
154 /**
155 * Performance properties to supply.
156 */
157 struct GNUNET_ATS_Properties properties;
158
159 /**
160 * Expect the operation to fail (duplicate).
161 */
162 int expect_fail;
163
164 /**
165 * Here the result of the add address operation will be stored.
166 */
167 struct GNUNET_ATS_AddressRecord *ar;
168};
169
170
171/**
172 * Details for the #CMD_DEL_ADDRESS command.
173 */
174struct CommandDelAddress
175{
176 /**
177 * Label of the corresponding #CMD_ADD_ADDRESS that
178 * we are now to remove.
179 */
180 const char *add_label;
181};
182
183
184/**
185 * Details for the #CMD_AWAIT_ADDRESS_SUGGESTION command.
186 */
187struct CommandAwaitAddressSuggestion
188{
189 /**
190 * For which peer do we expect a suggestion?
191 */
192 unsigned int pid;
193
194 /**
195 * If we expect the address suggested to match a particular
196 * addition, specify the label of the add operation here. Otherwise
197 * use NULL for "any" available address.
198 */
199 const char *add_label;
200};
201
202
203/**
204 * Details for the #CMD_AWAIT_DISCONNECT_SUGGESTION command.
205 */
206struct CommandAwaitDisconnectSuggestion
207{
208 /**
209 * For which peer do we expect the disconnect?
210 */
211 unsigned int pid;
212};
213
214
215/**
216 * Details for the #CMD_REQUEST_CONNECTION_START command.
217 */
218struct CommandRequestConnectionStart
219{
220 /**
221 * Identity of the peer we would like to connect to.
222 */
223 unsigned int pid;
224
225 /**
226 * Location where we store the handle returned from
227 * #GNUNET_ATS_connectivity_suggest().
228 */
229 struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
230};
231
232
233/**
234 * Details for the #CMD_REQUEST_CONNECTION_STOP command.
235 */
236struct CommandRequestConnectionStop
237{
238 /**
239 * Label of the corresponding #CMD_REQUEST_CONNECTION_START that
240 * we are now stopping.
241 */
242 const char *connect_label;
243};
244
245
246/**
247 * Details for the #CMD_AWAIT_ADDRESS_INFORMATION command.
248 */
249struct CommandAwaitAddressInformation
250{
251 /**
252 * For which address do we expect information?
253 * The address is identified by the respective
254 * label of the corresponding add operation.
255 */
256 const char *add_label;
257
258 /**
259 * Label of a possible update operation that may
260 * have modified the properties. NULL to use
261 * the properties from the @e add_label.
262 */
263 const char *update_label;
264};
265
266
267/**
268 * Details for the #CMD_UPDATE_ADDRESS command.
269 */
270struct CommandUpdateAddress
271{
272 /**
273 * Label of the addresses's add operation.
274 */
275 const char *add_label;
276
277 /**
278 * Performance properties to supply.
279 */
280 struct GNUNET_ATS_Properties properties;
281};
282
283
284/**
285 * Details for the #CMD_ADD_SESSION command.
286 */
287struct CommandAddSession
288{
289 /**
290 * Label of the addresses's add operation.
291 */
292 const char *add_label;
293
294 /**
295 * Session to supply.
296 */
297 unsigned int session;
298};
299
300
301/**
302 * Details for the #CMD_DEL_SESSION command.
303 */
304struct CommandDelSession
305{
306 /**
307 * Label of the addresses's add operation.
308 */
309 const char *add_session_label;
310};
311
312
313/**
314 * Details for the #CMD_CHANGE_PREFERENCE command.
315 */
316struct CommandChangePreference
317{
318 /**
319 * Identity of the peer we have a preference change towards.
320 */
321 unsigned int pid;
322
323 /* FIXME: preference details! */
324};
325
326
327/**
328 * Details for the #CMD_PROVIDE_FEEDBACK command.
329 */
330struct CommandProvideFeedback
331{
332 /**
333 * Identity of the peer we have a feedback for.
334 */
335 unsigned int pid;
336
337 /**
338 * Over which timeframe does the feedback apply?
339 */
340 struct GNUNET_TIME_Relative scope;
341
342 /* FIXME: feedback details! */
343};
344
345
346/**
347 * Details for the #CMD_LIST_ADDRESSES command.
348 */
349struct CommandListAddresses
350{
351 /**
352 * Identity of the peer we want a list for.
353 */
354 unsigned int pid;
355
356 /**
357 * All addresses or just active?
358 */
359 int all;
360
361 /**
362 * Minimum number of addresses the callback may report.
363 */
364 unsigned int min_calls;
365
366 /**
367 * Maximum number of addresses the callback may report.
368 */
369 unsigned int max_calls;
370
371 /**
372 * Minimum number of active addresses the callback may report.
373 */
374 unsigned int min_active_calls;
375
376 /**
377 * Maximum number of active addresses the callback may report.
378 */
379 unsigned int max_active_calls;
380
381 /**
382 * Number of calls the command invoked the callback with
383 * an address marked as active. (Set by command).
384 */
385 unsigned int active_calls;
386
387 /**
388 * Number of calls the command invoked the callback with
389 * any address marked as available to ATS. (Set by command).
390 */
391 unsigned int calls;
392
393 /**
394 * Location where we store the return value from
395 * #GNUNET_ATS_performance_list_addresses().
396 */
397 struct GNUNET_ATS_AddressListHandle *alh;
398};
399
400
401/**
402 * Details for the #CMD_RESERVE_BANDWIDTH command.
403 */
404struct CommandReserveBandwidth
405{
406 /**
407 * For which peer do we reserve bandwidth?
408 */
409 unsigned int pid;
410
411 /**
412 * How much should we try to reserve?
413 */
414 int32_t amount;
415
416 /**
417 * Should we expect this to work or fail?
418 * #GNUNET_YES: must work
419 * #GNUNET_NO: may work or fail
420 * #GNUNET_SYSERR: must fail
421 */
422 int expected_result;
423
424 /**
425 * Location where we store the return value from
426 * #GNUNET_ATS_reserve_bandwidth().
427 */
428 struct GNUNET_ATS_ReservationContext *rc;
429};
430
431
432/**
433 * Details for the #CMD_SLEEP command.
434 */
435struct CommandSleep
436{
437 /**
438 * How long should we wait before running the next command?
439 */
440 struct GNUNET_TIME_Relative delay;
441};
442
443
444/**
445 * A command for the test case interpreter.
446 */
447struct Command
448{
449 /**
450 * Command code to run.
451 */
452 enum CommandCode code;
453
454 /**
455 * Commands can be given a label so we can reference them later.
456 */
457 const char *label;
458
459 /**
460 * Additional arguments to commands, if any.
461 */
462 union
463 {
464 struct CommandAddAddress add_address;
465
466 struct CommandDelAddress del_address;
467
468 struct CommandAwaitAddressSuggestion await_address_suggestion;
469
470 struct CommandAwaitDisconnectSuggestion await_disconnect_suggestion;
471
472 struct CommandRequestConnectionStart request_connection_start;
473
474 struct CommandRequestConnectionStop request_connection_stop;
475
476 struct CommandAwaitAddressInformation await_address_information;
477
478 struct CommandUpdateAddress update_address;
479
480 struct CommandAddSession add_session;
481
482 struct CommandDelSession del_session;
483
484 struct CommandChangePreference change_preference;
485
486 struct CommandProvideFeedback provide_feedback;
487
488 struct CommandListAddresses list_addresses;
489
490 struct CommandReserveBandwidth reserve_bandwidth;
491
492 struct CommandSleep sleep;
493 } details;
494};
495
496
497/**
498 * Run ATS test.
499 *
500 * @param argc length of @a argv
501 * @param argv command line
502 * @param cmds commands to run with the interpreter
503 * @param timeout how long is the test allowed to take?
504 * @return 0 on success
505 */
506int
507TEST_ATS_run (int argc,
508 char *argv[],
509 struct Command *cmds,
510 struct GNUNET_TIME_Relative timeout);
511
512#endif
diff --git a/src/ats/test_ats_reservation_api.c b/src/ats/test_ats_reservation_api.c
deleted file mode 100644
index f6a964df4..000000000
--- a/src/ats/test_ats_reservation_api.c
+++ /dev/null
@@ -1,181 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file ats/test_ats_reservation_api.c
22 * @brief test ATS bandwidth reservation API
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "test_ats_lib.h"
27
28/**
29 * Global timeout for the testcase.
30 */
31#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
32
33/**
34 * Definition of the test as a sequence of commands.
35 */
36static struct Command test_commands[] = {
37 /* 0: add initial address */
38 {
39 .code = CMD_ADD_ADDRESS,
40 .label = "add-address-0-0",
41 .details.add_address = {
42 .pid = 0,
43 .addr_num = 0,
44 .session = 0,
45 .properties = {
46 /* use network with 65k quota! */
47 .scope = GNUNET_NT_WAN
48 }
49
50
51 }
52
53
54 },
55 /* 1: some solver still require explicit start */
56 {
57 .code = CMD_REQUEST_CONNECTION_START,
58 .label = "request-0",
59 .details.request_connection_start = {
60 .pid = 0
61 }
62
63
64 },
65 /* 2: check we got an address */
66 {
67 .code = CMD_AWAIT_ADDRESS_SUGGESTION,
68 .details.await_address_suggestion = {
69 .add_label = "add-address-0-0"
70 }
71
72
73 },
74 /* 3: sleep 7s, should give us 5s * 64k/s = 320k buffer;
75 Note that this depends on MAX_BANDWIDTH_CARRY_S. We
76 sleep more than 5s to show that only MAX_BANDWIDTH carries. */
77 {
78 .code = CMD_SLEEP,
79 .label = "sleep",
80 .details.sleep.delay = { 7 * 1000LL * 1000LL }
81 },
82 /* 4: reserve 128k -- should work (5s carry, so we had 320k) */
83 {
84 .code = CMD_RESERVE_BANDWIDTH,
85 .details.reserve_bandwidth = {
86 .pid = 0,
87 .amount = 128 * 1024,
88 .expected_result = GNUNET_YES
89 }
90
91
92 },
93 /* 5: reserve another 192k -- should just work (now exactly pushing the limit) */
94 {
95 .code = CMD_RESERVE_BANDWIDTH,
96 .label = "big reservation",
97 .details.reserve_bandwidth = {
98 .pid = 0,
99 .amount = 192 * 1024,
100 .expected_result = GNUNET_YES
101 }
102
103
104 },
105 /* 6: reserve another 32M -- should now fail (if MAX_BANDWIDTH_CARRY_S
106 is precisely observed) */
107 {
108 .code = CMD_RESERVE_BANDWIDTH,
109 .label = "failing reservation",
110 .details.reserve_bandwidth = {
111 .pid = 0,
112 .amount = 32 * 1024 * 1024,
113 .expected_result = GNUNET_SYSERR
114 }
115
116
117 },
118 /* 7: sleep 3s, should give us 3s * 64k/s - 32k = 160k buffer */
119 {
120 .code = CMD_SLEEP,
121 .label = "sleep",
122 .details.sleep.delay = { 6 * 1000LL * 1000LL }
123 },
124 /* 8: reserve another 160k -- should now work */
125 {
126 .code = CMD_RESERVE_BANDWIDTH,
127 .label = "successful final reservation",
128 .details.reserve_bandwidth = {
129 .pid = 0,
130 .amount = 160 * 1024,
131 .expected_result = GNUNET_YES
132 }
133
134
135 },
136 /* 9: remove address */
137 {
138 .code = CMD_DEL_ADDRESS,
139 .details.del_address = {
140 .add_label = "add-address-0-0"
141 }
142
143
144 },
145 /* 10: check we got disconnected */
146 {
147 .code = CMD_AWAIT_DISCONNECT_SUGGESTION,
148 .details.await_disconnect_suggestion = {
149 .pid = 0
150 }
151
152
153 },
154 /* 11: just for symmetry, also stop asking for the connection */
155 {
156 .code = CMD_REQUEST_CONNECTION_STOP,
157 .details.request_connection_stop = {
158 .connect_label = "request-0",
159 }
160
161
162 },
163 /* Test ends successfully */
164 {
165 .code = CMD_END_PASS
166 }
167};
168
169
170int
171main (int argc,
172 char *argv[])
173{
174 return TEST_ATS_run (argc,
175 argv,
176 test_commands,
177 TIMEOUT);
178}
179
180
181/* end of file test_ats_reservation_api.c */
diff --git a/src/ats/test_ats_solver_default.conf b/src/ats/test_ats_solver_default.conf
deleted file mode 100644
index 2d8927abd..000000000
--- a/src/ats/test_ats_solver_default.conf
+++ /dev/null
@@ -1,2 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2
diff --git a/src/ats/test_ats_solver_delayed_proportional.conf b/src/ats/test_ats_solver_delayed_proportional.conf
deleted file mode 100644
index fdfeb90b8..000000000
--- a/src/ats/test_ats_solver_delayed_proportional.conf
+++ /dev/null
@@ -1,20 +0,0 @@
1@INLINE@ test_ats_solver_default.conf
2
3[ats]
4PREFIX = ./test_delay -t 10 --
5MODE = proportional
6# UNSPECIFIED
7UNSPECIFIED_QUOTA_IN = 64 KiB
8UNSPECIFIED_QUOTA_OUT = 64 KiB
9# LOOPBACK
10LOOPBACK_QUOTA_IN = unlimited
11LOOPBACK_QUOTA_OUT = unlimited
12# LAN
13LAN_QUOTA_IN = unlimited
14LAN_QUOTA_OUT = unlimited
15# WAN
16WAN_QUOTA_IN = 64 KiB
17WAN_QUOTA_OUT = 64 KiB
18# WLAN
19WLAN_QUOTA_IN = 512
20WLAN_QUOTA_OUT = 512
diff --git a/src/ats/test_ats_solver_proportional.conf b/src/ats/test_ats_solver_proportional.conf
deleted file mode 100644
index 49815134b..000000000
--- a/src/ats/test_ats_solver_proportional.conf
+++ /dev/null
@@ -1,19 +0,0 @@
1@INLINE@ test_ats_solver_default.conf
2
3[ats]
4MODE = proportional
5# UNSPECIFIED
6UNSPECIFIED_QUOTA_IN = 64 KiB
7UNSPECIFIED_QUOTA_OUT = 64 KiB
8# LOOPBACK
9LOOPBACK_QUOTA_IN = unlimited
10LOOPBACK_QUOTA_OUT = unlimited
11# LAN
12LAN_QUOTA_IN = unlimited
13LAN_QUOTA_OUT = unlimited
14# WAN
15WAN_QUOTA_IN = 64 KiB
16WAN_QUOTA_OUT = 64 KiB
17# WLAN
18WLAN_QUOTA_IN = 512
19WLAN_QUOTA_OUT = 512
diff --git a/src/ats/test_delay b/src/ats/test_delay
deleted file mode 100755
index 31c7777c4..000000000
--- a/src/ats/test_delay
+++ /dev/null
@@ -1,18 +0,0 @@
1#!/bin/sh
2
3TEMP=$(getopt -o t: -- "$@")
4
5if [ $? != 0 ] ; then
6 exit 1
7fi
8
9eval set -- "$TEMP"
10
11while true ; do
12 case "$1" in
13 (-t) sleep "$2" ; shift 2 ;;
14 (--) shift ; break ;;
15 (*) echo "Error parsing getopt output" ; exit 1 ;;
16 esac
17done
18exec "$@"