diff options
Diffstat (limited to 'src/ats')
48 files changed, 0 insertions, 16984 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 @@ | |||
1 | gnunet-service-ats | ||
2 | test_ats_api_proportional | ||
3 | test_ats_reservation_api_proportional | ||
4 | test_ats_api_mlp | ||
5 | test_ats_api_ril | ||
6 | gnunet-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 | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | plugindir = $(libdir)/gnunet | ||
5 | |||
6 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
7 | |||
8 | libexecdir= $(pkglibdir)/libexec/ | ||
9 | |||
10 | pkgcfg_DATA = \ | ||
11 | ats.conf | ||
12 | |||
13 | if USE_COVERAGE | ||
14 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | ||
15 | endif | ||
16 | |||
17 | lib_LTLIBRARIES = \ | ||
18 | libgnunetats.la | ||
19 | |||
20 | plugin_LTLIBRARIES = \ | ||
21 | libgnunet_plugin_ats_proportional.la | ||
22 | |||
23 | libgnunetats_la_SOURCES = \ | ||
24 | ats_api_connectivity.c \ | ||
25 | ats_api_scheduling.c \ | ||
26 | ats_api_scanner.c \ | ||
27 | ats_api_performance.c | ||
28 | libgnunetats_la_LIBADD = \ | ||
29 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
30 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
31 | $(LTLIBINTL) | ||
32 | libgnunetats_la_LDFLAGS = \ | ||
33 | $(GN_LIB_LDFLAGS) \ | ||
34 | -version-info 4:0:0 | ||
35 | |||
36 | libgnunet_plugin_ats_proportional_la_SOURCES = \ | ||
37 | plugin_ats_proportional.c | ||
38 | libgnunet_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) | ||
44 | libgnunet_plugin_ats_proportional_la_LDFLAGS = \ | ||
45 | $(GN_PLUGIN_LDFLAGS) | ||
46 | |||
47 | |||
48 | libexec_PROGRAMS = \ | ||
49 | gnunet-service-ats | ||
50 | |||
51 | gnunet_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 | ||
61 | gnunet_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 | |||
68 | TESTING_TESTS = \ | ||
69 | test_ats_api_proportional \ | ||
70 | test_ats_reservation_api_proportional | ||
71 | |||
72 | check_PROGRAMS = \ | ||
73 | $(TESTING_TESTS) | ||
74 | |||
75 | if ENABLE_TEST_RUN | ||
76 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
77 | TESTS = $(check_PROGRAMS) | ||
78 | endif | ||
79 | |||
80 | test_ats_api_proportional_SOURCES = \ | ||
81 | test_ats_api.c \ | ||
82 | test_ats_lib.c test_ats_lib.h | ||
83 | test_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 | |||
89 | test_ats_reservation_api_proportional_SOURCES = \ | ||
90 | test_ats_reservation_api.c \ | ||
91 | test_ats_lib.c test_ats_lib.h | ||
92 | test_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 | |||
98 | EXTRA_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] | ||
2 | START_ON_DEMAND = @START_ON_DEMAND@ | ||
3 | @UNIXONLY@ PORT = 2098 | ||
4 | HOSTNAME = localhost | ||
5 | BINARY = gnunet-service-ats | ||
6 | ACCEPT_FROM = 127.0.0.1; | ||
7 | ACCEPT_FROM6 = ::1; | ||
8 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-ats.sock | ||
9 | UNIX_MATCH_UID = NO | ||
10 | UNIX_MATCH_GID = YES | ||
11 | # PREFIX = valgrind | ||
12 | # Designated assignment mode: PROPORTIONAL / MLP / RIL | ||
13 | MODE = 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 | ||
18 | UNSPECIFIED_QUOTA_IN = unlimited | ||
19 | UNSPECIFIED_QUOTA_OUT = unlimited | ||
20 | # LOOPBACK | ||
21 | LOOPBACK_QUOTA_IN = unlimited | ||
22 | LOOPBACK_QUOTA_OUT = unlimited | ||
23 | # LAN | ||
24 | LAN_QUOTA_IN = unlimited | ||
25 | LAN_QUOTA_OUT = unlimited | ||
26 | # WAN | ||
27 | WAN_QUOTA_IN = 10 MiB | ||
28 | WAN_QUOTA_OUT = 10 MiB | ||
29 | # WLAN | ||
30 | WLAN_QUOTA_IN = unlimited | ||
31 | WLAN_QUOTA_OUT = unlimited | ||
32 | # BLUETOOTH | ||
33 | BLUETOOTH_QUOTA_IN = 10 MiB | ||
34 | BLUETOOTH_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 | ||
41 | PROP_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 | ||
44 | PROP_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 | */ | ||
37 | enum 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 | |||
63 | GNUNET_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 | */ | ||
69 | struct 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 | */ | ||
87 | struct 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 | */ | ||
111 | struct 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 | */ | ||
161 | struct 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 | */ | ||
192 | struct 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 | */ | ||
217 | struct 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 | */ | ||
243 | struct 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 | */ | ||
278 | struct 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 | */ | ||
341 | struct 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 | */ | ||
369 | struct 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 | */ | ||
391 | struct 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 | */ | ||
419 | struct 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 | */ | ||
437 | struct 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 | */ | ||
463 | struct 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 | |||
489 | GNUNET_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 f62d89772..000000000 --- a/src/ats/ats_api_connectivity.c +++ /dev/null | |||
@@ -1,362 +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 | */ | ||
38 | struct 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 | */ | ||
60 | struct 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 | */ | ||
96 | static void | ||
97 | reconnect (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 | */ | ||
105 | static void | ||
106 | reconnect_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 | */ | ||
120 | static void | ||
121 | force_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 | */ | ||
142 | static void | ||
143 | error_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 | */ | ||
164 | static int | ||
165 | transmit_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 | */ | ||
189 | static void | ||
190 | reconnect (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 | */ | ||
226 | struct GNUNET_ATS_ConnectivityHandle * | ||
227 | GNUNET_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 | */ | ||
249 | static int | ||
250 | free_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 | */ | ||
266 | void | ||
267 | GNUNET_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 | */ | ||
298 | struct GNUNET_ATS_ConnectivitySuggestHandle * | ||
299 | GNUNET_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 | void | ||
334 | GNUNET_ATS_connectivity_suggest_cancel (struct | ||
335 | GNUNET_ATS_ConnectivitySuggestHandle *sh) | ||
336 | { | ||
337 | struct GNUNET_ATS_ConnectivityHandle *ch = sh->ch; | ||
338 | struct GNUNET_MQ_Envelope *ev; | ||
339 | struct RequestAddressMessage *m; | ||
340 | |||
341 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
342 | "Telling ATS we no longer care for an address for `%s'\n", | ||
343 | GNUNET_i2s (&sh->id)); | ||
344 | GNUNET_assert (GNUNET_OK == | ||
345 | GNUNET_CONTAINER_multipeermap_remove (ch->sug_requests, | ||
346 | &sh->id, | ||
347 | sh)); | ||
348 | if (NULL == ch->mq) | ||
349 | { | ||
350 | GNUNET_free (sh); | ||
351 | return; | ||
352 | } | ||
353 | ev = GNUNET_MQ_msg (m, | ||
354 | GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL); | ||
355 | m->strength = htonl (0); | ||
356 | m->peer = sh->id; | ||
357 | GNUNET_MQ_send (ch->mq, ev); | ||
358 | GNUNET_free (sh); | ||
359 | } | ||
360 | |||
361 | |||
362 | /* 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 242589851..000000000 --- a/src/ats/ats_api_performance.c +++ /dev/null | |||
@@ -1,946 +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 | */ | ||
38 | struct 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 | */ | ||
85 | struct 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 | */ | ||
137 | struct 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 | */ | ||
215 | static void | ||
216 | reconnect (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 | */ | ||
224 | static void | ||
225 | reconnect_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 | */ | ||
239 | static void | ||
240 | do_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 | */ | ||
302 | static int | ||
303 | check_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 | */ | ||
333 | static void | ||
334 | handle_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 | */ | ||
375 | static void | ||
376 | handle_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 | */ | ||
428 | static int | ||
429 | check_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 | */ | ||
459 | static void | ||
460 | handle_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 | */ | ||
549 | static void | ||
550 | mq_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 | */ | ||
564 | static void | ||
565 | reconnect (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 | */ | ||
612 | struct GNUNET_ATS_PerformanceHandle * | ||
613 | GNUNET_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 | */ | ||
638 | void | ||
639 | GNUNET_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 | struct GNUNET_ATS_ReservationContext * | ||
674 | GNUNET_ATS_reserve_bandwidth (struct GNUNET_ATS_PerformanceHandle *ph, | ||
675 | const struct GNUNET_PeerIdentity *peer, | ||
676 | int32_t amount, | ||
677 | GNUNET_ATS_ReservationCallback rcb, | ||
678 | void *rcb_cls) | ||
679 | { | ||
680 | struct GNUNET_ATS_ReservationContext *rc; | ||
681 | struct GNUNET_MQ_Envelope *env; | ||
682 | struct ReservationRequestMessage *m; | ||
683 | |||
684 | if (NULL == ph->mq) | ||
685 | return NULL; | ||
686 | rc = GNUNET_new (struct GNUNET_ATS_ReservationContext); | ||
687 | rc->size = amount; | ||
688 | rc->peer = *peer; | ||
689 | rc->rcb = rcb; | ||
690 | rc->rcb_cls = rcb_cls; | ||
691 | if ((NULL != rcb) && | ||
692 | (amount > 0)) | ||
693 | rc->undo = GNUNET_YES; | ||
694 | GNUNET_CONTAINER_DLL_insert_tail (ph->reservation_head, | ||
695 | ph->reservation_tail, | ||
696 | rc); | ||
697 | env = GNUNET_MQ_msg (m, | ||
698 | GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST); | ||
699 | m->amount = htonl (amount); | ||
700 | m->peer = *peer; | ||
701 | GNUNET_MQ_send (ph->mq, | ||
702 | env); | ||
703 | return rc; | ||
704 | } | ||
705 | |||
706 | |||
707 | void | ||
708 | GNUNET_ATS_reserve_bandwidth_cancel (struct GNUNET_ATS_ReservationContext *rc) | ||
709 | { | ||
710 | rc->rcb = NULL; | ||
711 | } | ||
712 | |||
713 | |||
714 | struct GNUNET_ATS_AddressListHandle* | ||
715 | GNUNET_ATS_performance_list_addresses (struct GNUNET_ATS_PerformanceHandle *ph, | ||
716 | const struct GNUNET_PeerIdentity *peer, | ||
717 | int all, | ||
718 | GNUNET_ATS_AddressInformationCallback | ||
719 | infocb, | ||
720 | void *infocb_cls) | ||
721 | { | ||
722 | struct GNUNET_ATS_AddressListHandle *alh; | ||
723 | struct GNUNET_MQ_Envelope *env; | ||
724 | struct AddressListRequestMessage *m; | ||
725 | |||
726 | if (NULL == ph->mq) | ||
727 | return NULL; | ||
728 | if (NULL == infocb) | ||
729 | { | ||
730 | GNUNET_break (0); | ||
731 | return NULL; | ||
732 | } | ||
733 | alh = GNUNET_new (struct GNUNET_ATS_AddressListHandle); | ||
734 | alh->id = ph->id++; | ||
735 | alh->cb = infocb; | ||
736 | alh->cb_cls = infocb_cls; | ||
737 | alh->ph = ph; | ||
738 | alh->all_addresses = all; | ||
739 | if (NULL == peer) | ||
740 | { | ||
741 | alh->all_peers = GNUNET_YES; | ||
742 | } | ||
743 | else | ||
744 | { | ||
745 | alh->all_peers = GNUNET_NO; | ||
746 | alh->peer = *peer; | ||
747 | } | ||
748 | GNUNET_CONTAINER_DLL_insert (ph->addresslist_head, | ||
749 | ph->addresslist_tail, | ||
750 | alh); | ||
751 | env = GNUNET_MQ_msg (m, | ||
752 | GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST); | ||
753 | m->all = htonl (all); | ||
754 | m->id = htonl (alh->id); | ||
755 | if (NULL != peer) | ||
756 | m->peer = *peer; | ||
757 | GNUNET_MQ_send (ph->mq, | ||
758 | env); | ||
759 | return alh; | ||
760 | } | ||
761 | |||
762 | |||
763 | void | ||
764 | GNUNET_ATS_performance_list_addresses_cancel (struct | ||
765 | GNUNET_ATS_AddressListHandle *alh) | ||
766 | { | ||
767 | struct GNUNET_ATS_PerformanceHandle *ph = alh->ph; | ||
768 | |||
769 | GNUNET_CONTAINER_DLL_remove (ph->addresslist_head, | ||
770 | ph->addresslist_tail, | ||
771 | alh); | ||
772 | GNUNET_free (alh); | ||
773 | } | ||
774 | |||
775 | |||
776 | const char * | ||
777 | GNUNET_ATS_print_preference_type (enum GNUNET_ATS_PreferenceKind type) | ||
778 | { | ||
779 | const char *prefs[] = GNUNET_ATS_PreferenceTypeString; | ||
780 | |||
781 | if (type < GNUNET_ATS_PREFERENCE_END) | ||
782 | return prefs[type]; | ||
783 | return NULL; | ||
784 | } | ||
785 | |||
786 | |||
787 | void | ||
788 | GNUNET_ATS_performance_change_preference (struct | ||
789 | GNUNET_ATS_PerformanceHandle *ph, | ||
790 | const struct | ||
791 | GNUNET_PeerIdentity *peer, | ||
792 | ...) | ||
793 | { | ||
794 | struct GNUNET_MQ_Envelope *env; | ||
795 | struct ChangePreferenceMessage *m; | ||
796 | uint32_t count; | ||
797 | struct PreferenceInformation *pi; | ||
798 | va_list ap; | ||
799 | enum GNUNET_ATS_PreferenceKind kind; | ||
800 | |||
801 | if (NULL == ph->mq) | ||
802 | return; | ||
803 | count = 0; | ||
804 | va_start (ap, peer); | ||
805 | while (GNUNET_ATS_PREFERENCE_END != | ||
806 | (kind = GNUNET_VA_ARG_ENUM (ap, GNUNET_ATS_PreferenceKind))) | ||
807 | { | ||
808 | switch (kind) | ||
809 | { | ||
810 | case GNUNET_ATS_PREFERENCE_BANDWIDTH: | ||
811 | count++; | ||
812 | (void) va_arg (ap, double); | ||
813 | break; | ||
814 | |||
815 | case GNUNET_ATS_PREFERENCE_LATENCY: | ||
816 | count++; | ||
817 | (void) va_arg (ap, double); | ||
818 | break; | ||
819 | |||
820 | default: | ||
821 | GNUNET_assert (0); | ||
822 | } | ||
823 | } | ||
824 | va_end (ap); | ||
825 | env = GNUNET_MQ_msg_extra (m, | ||
826 | count * sizeof(struct PreferenceInformation), | ||
827 | GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE); | ||
828 | m->num_preferences = htonl (count); | ||
829 | m->peer = *peer; | ||
830 | pi = (struct PreferenceInformation *) &m[1]; | ||
831 | count = 0; | ||
832 | va_start (ap, peer); | ||
833 | while (GNUNET_ATS_PREFERENCE_END != (kind = | ||
834 | GNUNET_VA_ARG_ENUM (ap, | ||
835 | GNUNET_ATS_PreferenceKind))) | ||
836 | { | ||
837 | pi[count].preference_kind = htonl (kind); | ||
838 | switch (kind) | ||
839 | { | ||
840 | case GNUNET_ATS_PREFERENCE_BANDWIDTH: | ||
841 | pi[count].preference_value = (float) va_arg (ap, double); | ||
842 | |||
843 | count++; | ||
844 | break; | ||
845 | |||
846 | case GNUNET_ATS_PREFERENCE_LATENCY: | ||
847 | pi[count].preference_value = (float) va_arg (ap, double); | ||
848 | |||
849 | count++; | ||
850 | break; | ||
851 | |||
852 | default: | ||
853 | GNUNET_assert (0); | ||
854 | } | ||
855 | } | ||
856 | va_end (ap); | ||
857 | GNUNET_MQ_send (ph->mq, | ||
858 | env); | ||
859 | } | ||
860 | |||
861 | |||
862 | /** | ||
863 | * Send feedback to ATS on how good a the requirements for a peer and a | ||
864 | * preference is satisfied by ATS | ||
865 | * | ||
866 | * @param ph performance handle | ||
867 | * @param scope the time interval this valid for: [now - scope .. now] | ||
868 | * @param peer identifies the peer | ||
869 | * @param ... #GNUNET_ATS_PREFERENCE_END-terminated specification of the desired changes | ||
870 | */ | ||
871 | void | ||
872 | GNUNET_ATS_performance_give_feedback (struct GNUNET_ATS_PerformanceHandle *ph, | ||
873 | const struct GNUNET_PeerIdentity *peer, | ||
874 | const struct GNUNET_TIME_Relative scope, | ||
875 | ...) | ||
876 | { | ||
877 | struct GNUNET_MQ_Envelope *env; | ||
878 | struct FeedbackPreferenceMessage *m; | ||
879 | uint32_t count; | ||
880 | struct PreferenceInformation *pi; | ||
881 | va_list ap; | ||
882 | enum GNUNET_ATS_PreferenceKind kind; | ||
883 | |||
884 | if (NULL == ph->mq) | ||
885 | return; | ||
886 | count = 0; | ||
887 | va_start (ap, scope); | ||
888 | while (GNUNET_ATS_PREFERENCE_END != | ||
889 | (kind = GNUNET_VA_ARG_ENUM (ap, GNUNET_ATS_PreferenceKind))) | ||
890 | { | ||
891 | switch (kind) | ||
892 | { | ||
893 | case GNUNET_ATS_PREFERENCE_BANDWIDTH: | ||
894 | count++; | ||
895 | (void) va_arg (ap, double); | ||
896 | break; | ||
897 | |||
898 | case GNUNET_ATS_PREFERENCE_LATENCY: | ||
899 | count++; | ||
900 | (void) va_arg (ap, double); | ||
901 | break; | ||
902 | |||
903 | default: | ||
904 | GNUNET_assert (0); | ||
905 | } | ||
906 | } | ||
907 | va_end (ap); | ||
908 | env = GNUNET_MQ_msg_extra (m, | ||
909 | count * sizeof(struct PreferenceInformation), | ||
910 | GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_FEEDBACK); | ||
911 | m->scope = GNUNET_TIME_relative_hton (scope); | ||
912 | m->num_feedback = htonl (count); | ||
913 | m->peer = *peer; | ||
914 | pi = (struct PreferenceInformation *) &m[1]; | ||
915 | count = 0; | ||
916 | va_start (ap, scope); | ||
917 | while (GNUNET_ATS_PREFERENCE_END != (kind = | ||
918 | GNUNET_VA_ARG_ENUM (ap, | ||
919 | GNUNET_ATS_PreferenceKind))) | ||
920 | { | ||
921 | pi[count].preference_kind = htonl (kind); | ||
922 | switch (kind) | ||
923 | { | ||
924 | case GNUNET_ATS_PREFERENCE_BANDWIDTH: | ||
925 | pi[count].preference_value = (float) va_arg (ap, double); | ||
926 | |||
927 | count++; | ||
928 | break; | ||
929 | |||
930 | case GNUNET_ATS_PREFERENCE_LATENCY: | ||
931 | pi[count].preference_value = (float) va_arg (ap, double); | ||
932 | |||
933 | count++; | ||
934 | break; | ||
935 | |||
936 | default: | ||
937 | GNUNET_assert (0); | ||
938 | } | ||
939 | } | ||
940 | va_end (ap); | ||
941 | GNUNET_MQ_send (ph->mq, | ||
942 | env); | ||
943 | } | ||
944 | |||
945 | |||
946 | /* 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 | */ | ||
35 | void | ||
36 | GNUNET_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 | */ | ||
53 | void | ||
54 | GNUNET_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 6fb61b2e8..000000000 --- a/src/ats/ats_api_scheduling.c +++ /dev/null | |||
@@ -1,781 +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 | */ | ||
57 | struct 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 | */ | ||
102 | struct 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 | */ | ||
154 | static void | ||
155 | reconnect (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 | */ | ||
163 | static void | ||
164 | reconnect_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 | */ | ||
178 | static void | ||
179 | force_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 | */ | ||
205 | static struct GNUNET_ATS_AddressRecord * | ||
206 | find_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 | */ | ||
247 | static uint32_t | ||
248 | find_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 | */ | ||
281 | static uint32_t | ||
282 | find_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 | */ | ||
314 | static void | ||
315 | release_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 | */ | ||
349 | static void | ||
350 | handle_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 | */ | ||
369 | static void | ||
370 | handle_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 | */ | ||
445 | static void | ||
446 | error_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 | */ | ||
465 | static void | ||
466 | send_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 | */ | ||
511 | static void | ||
512 | reconnect (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 | struct GNUNET_ATS_SchedulingHandle * | ||
561 | GNUNET_ATS_scheduling_init (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
562 | GNUNET_ATS_AddressSuggestionCallback suggest_cb, | ||
563 | void *suggest_cb_cls) | ||
564 | { | ||
565 | struct GNUNET_ATS_SchedulingHandle *sh; | ||
566 | |||
567 | sh = GNUNET_new (struct GNUNET_ATS_SchedulingHandle); | ||
568 | sh->cfg = cfg; | ||
569 | sh->suggest_cb = suggest_cb; | ||
570 | sh->suggest_cb_cls = suggest_cb_cls; | ||
571 | GNUNET_array_grow (sh->session_array, | ||
572 | sh->session_array_size, | ||
573 | 4); | ||
574 | reconnect (sh); | ||
575 | return sh; | ||
576 | } | ||
577 | |||
578 | |||
579 | /** | ||
580 | * Client is done with ATS scheduling, release resources. | ||
581 | * | ||
582 | * @param sh handle to release | ||
583 | */ | ||
584 | void | ||
585 | GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh) | ||
586 | { | ||
587 | struct GNUNET_ATS_AddressRecord *ar; | ||
588 | unsigned int i; | ||
589 | |||
590 | if (NULL != sh->mq) | ||
591 | { | ||
592 | GNUNET_MQ_destroy (sh->mq); | ||
593 | sh->mq = NULL; | ||
594 | } | ||
595 | if (NULL != sh->task) | ||
596 | { | ||
597 | GNUNET_SCHEDULER_cancel (sh->task); | ||
598 | sh->task = NULL; | ||
599 | } | ||
600 | for (i = 0; i < sh->session_array_size; i++) | ||
601 | { | ||
602 | if (NULL != (ar = sh->session_array[i])) | ||
603 | { | ||
604 | GNUNET_HELLO_address_free (ar->address); | ||
605 | GNUNET_free (ar); | ||
606 | sh->session_array[i] = NULL; | ||
607 | } | ||
608 | } | ||
609 | GNUNET_array_grow (sh->session_array, | ||
610 | sh->session_array_size, | ||
611 | 0); | ||
612 | GNUNET_free (sh); | ||
613 | } | ||
614 | |||
615 | |||
616 | /** | ||
617 | * We have a new address ATS should know. Addresses have to be added | ||
618 | * with this function before they can be: updated, set in use and | ||
619 | * destroyed. | ||
620 | * | ||
621 | * @param sh handle | ||
622 | * @param address the address | ||
623 | * @param session session handle, can be NULL | ||
624 | * @param prop performance data for the address | ||
625 | * @return handle to the address representation inside ATS, NULL | ||
626 | * on error (i.e. ATS knows this exact address already) | ||
627 | */ | ||
628 | struct GNUNET_ATS_AddressRecord * | ||
629 | GNUNET_ATS_address_add (struct GNUNET_ATS_SchedulingHandle *sh, | ||
630 | const struct GNUNET_HELLO_Address *address, | ||
631 | struct GNUNET_ATS_Session *session, | ||
632 | const struct GNUNET_ATS_Properties *prop) | ||
633 | { | ||
634 | struct GNUNET_ATS_AddressRecord *ar; | ||
635 | size_t namelen; | ||
636 | size_t msize; | ||
637 | uint32_t s; | ||
638 | |||
639 | if (NULL == address) | ||
640 | { | ||
641 | /* we need a valid address */ | ||
642 | GNUNET_break (0); | ||
643 | return NULL; | ||
644 | } | ||
645 | GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope); | ||
646 | namelen = strlen (address->transport_name) + 1; | ||
647 | msize = address->address_length + namelen; | ||
648 | if ((msize + sizeof(struct AddressUpdateMessage) >= | ||
649 | GNUNET_MAX_MESSAGE_SIZE) || | ||
650 | (address->address_length >= GNUNET_MAX_MESSAGE_SIZE) || | ||
651 | (namelen >= GNUNET_MAX_MESSAGE_SIZE)) | ||
652 | { | ||
653 | /* address too large for us, this should not happen */ | ||
654 | GNUNET_break (0); | ||
655 | return NULL; | ||
656 | } | ||
657 | |||
658 | if (NOT_FOUND != | ||
659 | find_session_id (sh, | ||
660 | session, | ||
661 | address)) | ||
662 | { | ||
663 | /* Already existing, nothing todo, but this should not happen */ | ||
664 | GNUNET_break (0); | ||
665 | return NULL; | ||
666 | } | ||
667 | s = find_empty_session_slot (sh); | ||
668 | ar = GNUNET_new (struct GNUNET_ATS_AddressRecord); | ||
669 | ar->sh = sh; | ||
670 | ar->slot = s; | ||
671 | ar->session = session; | ||
672 | ar->address = GNUNET_HELLO_address_copy (address); | ||
673 | GNUNET_ATS_properties_hton (&ar->properties, | ||
674 | prop); | ||
675 | sh->session_array[s] = ar; | ||
676 | send_add_address_message (sh, ar); | ||
677 | return ar; | ||
678 | } | ||
679 | |||
680 | |||
681 | /** | ||
682 | * An address was used to initiate a session. | ||
683 | * | ||
684 | * @param ar address record to update information for | ||
685 | * @param session session handle | ||
686 | */ | ||
687 | void | ||
688 | GNUNET_ATS_address_add_session (struct GNUNET_ATS_AddressRecord *ar, | ||
689 | struct GNUNET_ATS_Session *session) | ||
690 | { | ||
691 | GNUNET_break (NULL == ar->session); | ||
692 | ar->session = session; | ||
693 | } | ||
694 | |||
695 | |||
696 | int | ||
697 | GNUNET_ATS_address_del_session (struct GNUNET_ATS_AddressRecord *ar, | ||
698 | struct GNUNET_ATS_Session *session) | ||
699 | { | ||
700 | GNUNET_assert (session == ar->session); | ||
701 | ar->session = NULL; | ||
702 | if (GNUNET_HELLO_address_check_option (ar->address, | ||
703 | GNUNET_HELLO_ADDRESS_INFO_INBOUND)) | ||
704 | { | ||
705 | GNUNET_ATS_address_destroy (ar); | ||
706 | return GNUNET_YES; | ||
707 | } | ||
708 | return GNUNET_NO; | ||
709 | } | ||
710 | |||
711 | |||
712 | /** | ||
713 | * We have updated performance statistics for a given address. Note | ||
714 | * that this function can be called for addresses that are currently | ||
715 | * in use as well as addresses that are valid but not actively in use. | ||
716 | * Furthermore, the peer may not even be connected to us right now (in | ||
717 | * which case the call may be ignored or the information may be stored | ||
718 | * for later use). Update bandwidth assignments. | ||
719 | * | ||
720 | * @param ar address record to update information for | ||
721 | * @param prop performance data for the address | ||
722 | */ | ||
723 | void | ||
724 | GNUNET_ATS_address_update (struct GNUNET_ATS_AddressRecord *ar, | ||
725 | const struct GNUNET_ATS_Properties *prop) | ||
726 | { | ||
727 | struct GNUNET_ATS_SchedulingHandle *sh = ar->sh; | ||
728 | struct GNUNET_MQ_Envelope *ev; | ||
729 | struct AddressUpdateMessage *m; | ||
730 | |||
731 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
732 | "Updating address for peer `%s', plugin `%s', session %p slot %u\n", | ||
733 | GNUNET_i2s (&ar->address->peer), | ||
734 | ar->address->transport_name, | ||
735 | ar->session, | ||
736 | ar->slot); | ||
737 | GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope); | ||
738 | GNUNET_ATS_properties_hton (&ar->properties, | ||
739 | prop); | ||
740 | if (NULL == sh->mq) | ||
741 | return; /* disconnected, skip for now */ | ||
742 | ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE); | ||
743 | m->session_id = htonl (ar->slot); | ||
744 | m->peer = ar->address->peer; | ||
745 | m->properties = ar->properties; | ||
746 | GNUNET_MQ_send (sh->mq, | ||
747 | ev); | ||
748 | } | ||
749 | |||
750 | |||
751 | /** | ||
752 | * An address got destroyed, stop using it as a valid address. | ||
753 | * | ||
754 | * @param ar address to destroy | ||
755 | */ | ||
756 | void | ||
757 | GNUNET_ATS_address_destroy (struct GNUNET_ATS_AddressRecord *ar) | ||
758 | { | ||
759 | struct GNUNET_ATS_SchedulingHandle *sh = ar->sh; | ||
760 | struct GNUNET_MQ_Envelope *ev; | ||
761 | struct AddressDestroyedMessage *m; | ||
762 | |||
763 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
764 | "Deleting address for peer `%s', plugin `%s', slot %u session %p\n", | ||
765 | GNUNET_i2s (&ar->address->peer), | ||
766 | ar->address->transport_name, | ||
767 | ar->slot, | ||
768 | ar->session); | ||
769 | GNUNET_break (NULL == ar->session); | ||
770 | ar->session = NULL; | ||
771 | ar->in_destroy = GNUNET_YES; | ||
772 | if (NULL == sh->mq) | ||
773 | return; | ||
774 | ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED); | ||
775 | m->session_id = htonl (ar->slot); | ||
776 | m->peer = ar->address->peer; | ||
777 | GNUNET_MQ_send (sh->mq, ev); | ||
778 | } | ||
779 | |||
780 | |||
781 | /* 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] | ||
2 | name = test | ||
3 | max_duration = 15 s | ||
4 | log_freq = 1000 ms | ||
5 | cfg_file = experiments/gnunet_ats_sim_default.conf | ||
6 | log_output_dir = data/ | ||
7 | log_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 | ||
14 | duration = 0 | ||
15 | op-0-operation = address_add | ||
16 | op-0-address-id = 0 | ||
17 | op-0-peer-id = 0 | ||
18 | op-0-address-session = 0 | ||
19 | op-0-address-network = 0 | ||
20 | op-0-address = 0_0_test | ||
21 | op-0-plugin = test | ||
22 | |||
23 | op-1-operation = address_add | ||
24 | op-1-address-id = 1 | ||
25 | op-1-peer-id = 1 | ||
26 | op-1-address-session = 0 | ||
27 | op-1-address-network = 0 | ||
28 | op-1-address = 1_1_test | ||
29 | op-1-plugin = test | ||
30 | |||
31 | op-2-operation = start_request | ||
32 | op-2-peer-id = 0 | ||
33 | |||
34 | op-3-operation = start_request | ||
35 | op-3-peer-id = 1 | ||
36 | |||
37 | [episode-1] | ||
38 | # Set delay | ||
39 | duration = 5 s | ||
40 | |||
41 | op-0-operation = start_set_property | ||
42 | op-0-address-id = 0 | ||
43 | op-0-peer-id = 0 | ||
44 | # constant, linear, sinus, random | ||
45 | op-0-gen-type = random | ||
46 | op-0-base-rate= 10000 | ||
47 | op-0-max-rate = 20000 | ||
48 | op-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" | ||
51 | op-0-property = DELAY | ||
52 | |||
53 | op-1-operation = start_set_property | ||
54 | op-1-address-id = 1 | ||
55 | op-1-peer-id = 1 | ||
56 | # constant, linear, sinus, random | ||
57 | op-1-gen-type = constant | ||
58 | op-1-base-rate= 1 | ||
59 | op-1-max-rate = 1 | ||
60 | op-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" | ||
63 | op-1-property = DELAY | ||
64 | |||
65 | |||
66 | [episode-2] | ||
67 | # Shutdown | ||
68 | duration = 2 s | ||
69 | op-0-operation = stop_set_property | ||
70 | op-0-address-id = 0 | ||
71 | op-0-peer-id = 0 | ||
72 | op-0-property = DELAY | ||
73 | |||
74 | op-1-operation = stop_set_property | ||
75 | op-1-address-id = 1 | ||
76 | op-1-peer-id = 1 | ||
77 | op-1-property = DELAY | ||
78 | |||
79 | [episode-3] | ||
80 | # Shutdown | ||
81 | duration = 2 s | ||
82 | |||
83 | op-0-operation = stop_request | ||
84 | op-0-peer-id = 0 | ||
85 | |||
86 | op-1-operation = stop_request | ||
87 | op-1-peer-id = 1 | ||
88 | |||
89 | op-2-operation = address_del | ||
90 | op-2-address-id = 0 | ||
91 | op-2-peer-id = 0 | ||
92 | op-2-address-session = 0 | ||
93 | op-2-address-network = 0 | ||
94 | op-2-address = 0_0_test | ||
95 | op-2-plugin = test | ||
96 | |||
97 | op-2-operation = address_del | ||
98 | op-2-address-id = 1 | ||
99 | op-2-peer-id = 1 | ||
100 | op-2-address-session = 0 | ||
101 | op-2-address-network = 0 | ||
102 | op-2-address = 1_1_test | ||
103 | op-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] | ||
2 | UNSPECIFIED_QUOTA_IN = 64 KiB | ||
3 | UNSPECIFIED_QUOTA_OUT = 64 KiB | ||
4 | # LOOPBACK | ||
5 | LOOPBACK_QUOTA_IN = 64 KiB | ||
6 | LOOPBACK_QUOTA_OUT = 64 KiB | ||
7 | # LAN | ||
8 | LAN_QUOTA_IN = 64 KiB | ||
9 | LAN_QUOTA_OUT = 64 KiB | ||
10 | # WAN | ||
11 | WAN_QUOTA_IN = 64 KiB | ||
12 | WAN_QUOTA_OUT = 64 KiB | ||
13 | # WLAN | ||
14 | WLAN_QUOTA_IN = 64 KiB | ||
15 | WLAN_QUOTA_OUT = 64 KiB | ||
16 | # BLUETOOTH | ||
17 | BLUETOOTH_QUOTA_IN = 64 KiB | ||
18 | BLUETOOTH_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] | ||
4 | name = test | ||
5 | max_duration = 15 s | ||
6 | log_freq = 1000 ms | ||
7 | log_prefix = set_preference | ||
8 | cfg_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 | ||
15 | duration = 1 s | ||
16 | |||
17 | op-0-operation = address_add | ||
18 | op-0-address-id = 0 | ||
19 | op-0-peer-id = 0 | ||
20 | op-0-address-session = 0 | ||
21 | op-0-address-network = lan | ||
22 | op-0-address = 0_0_test | ||
23 | op-0-plugin = test | ||
24 | |||
25 | op-1-operation = address_add | ||
26 | op-1-address-id = 1 | ||
27 | op-1-peer-id = 1 | ||
28 | op-1-address-session = 0 | ||
29 | op-1-address-network = lan | ||
30 | op-1-address = 1_1_test | ||
31 | op-1-plugin = test | ||
32 | |||
33 | op-2-operation = start_request | ||
34 | op-2-peer-id = 0 | ||
35 | |||
36 | op-3-operation = start_request | ||
37 | op-3-peer-id = 1 | ||
38 | |||
39 | [episode-1] | ||
40 | # Set delay | ||
41 | duration = 20 s | ||
42 | |||
43 | op-0-operation = start_set_preference | ||
44 | op-0-address-id = 0 | ||
45 | op-0-peer-id = 0 | ||
46 | op-0-client-id = 1 | ||
47 | # constant, linear, sinus, random | ||
48 | op-0-gen-type = linear | ||
49 | op-0-base-rate= 1000 | ||
50 | op-0-max-rate = 10000 | ||
51 | op-0-period = 10 s | ||
52 | op-0-frequency = 500 ms | ||
53 | op-0-feedback_delay = 500 ms | ||
54 | # BANDWIDTH, LATENCY | ||
55 | op-0-pref = BANDWIDTH | ||
56 | |||
57 | |||
58 | op-1-operation = start_set_preference | ||
59 | op-1-address-id = 1 | ||
60 | op-1-peer-id = 1 | ||
61 | op-1-client-id = 1 | ||
62 | # constant, linear, sinus, random | ||
63 | op-1-gen-type = constant | ||
64 | op-1-base-rate= 1000 | ||
65 | op-1-max-rate = 1000 | ||
66 | op-1-period = 10 s | ||
67 | op-1-frequency = 500 ms | ||
68 | # BANDWIDTH, LATENCY | ||
69 | op-1-pref = BANDWIDTH | ||
70 | |||
71 | [episode-2] | ||
72 | # Shutdown | ||
73 | duration = 2 s | ||
74 | |||
75 | op-0-operation = stop_request | ||
76 | op-0-peer-id = 0 | ||
77 | |||
78 | op-1-operation = stop_request | ||
79 | op-1-peer-id = 1 | ||
80 | |||
81 | op-2-operation = address_del | ||
82 | op-2-address-id = 0 | ||
83 | op-2-peer-id = 0 | ||
84 | op-2-address-session = 0 | ||
85 | op-2-address-network = 0 | ||
86 | op-2-address = 0_0_test | ||
87 | op-2-plugin = test | ||
88 | |||
89 | op-3-operation = address_del | ||
90 | op-3-address-id = 1 | ||
91 | op-3-peer-id = 1 | ||
92 | op-3-address-session = 0 | ||
93 | op-3-address-network = 0 | ||
94 | op-3-address = 1_1_test | ||
95 | op-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 | */ | ||
37 | struct GNUNET_STATISTICS_Handle *GSA_stats; | ||
38 | |||
39 | |||
40 | static struct Experiment *e; | ||
41 | |||
42 | static struct LoggingHandle *l; | ||
43 | |||
44 | static struct SolverHandle *sh; | ||
45 | |||
46 | static struct TestPeer *peer_head; | ||
47 | |||
48 | static struct TestPeer *peer_tail; | ||
49 | |||
50 | static double default_properties[GNUNET_ATS_PropertyCount]; | ||
51 | static double default_preferences[GNUNET_ATS_PreferenceCount]; | ||
52 | |||
53 | /** | ||
54 | * cmd option -e: experiment file | ||
55 | */ | ||
56 | static char *opt_exp_file; | ||
57 | |||
58 | static char *opt_solver; | ||
59 | |||
60 | /** | ||
61 | * cmd option -l: enable logging | ||
62 | */ | ||
63 | static int opt_log; | ||
64 | |||
65 | /** | ||
66 | * cmd option -p: enable plots | ||
67 | */ | ||
68 | static int opt_save; | ||
69 | |||
70 | /** | ||
71 | * cmd option -v: verbose logs | ||
72 | */ | ||
73 | static int opt_verbose; | ||
74 | |||
75 | /** | ||
76 | * cmd option -p: print logs | ||
77 | */ | ||
78 | static int opt_print; | ||
79 | |||
80 | /** | ||
81 | * cmd option -d: disable normalization | ||
82 | */ | ||
83 | static int opt_disable_normalization; | ||
84 | |||
85 | static int res; | ||
86 | |||
87 | static void | ||
88 | end_now (); | ||
89 | |||
90 | |||
91 | static char * | ||
92 | print_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 | |||
115 | static struct TestPeer * | ||
116 | find_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 | |||
127 | static struct TestPeer * | ||
128 | find_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 | |||
139 | static struct TestAddress * | ||
140 | find_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 | */ | ||
154 | void | ||
155 | GNUNET_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 | |||
231 | static void | ||
232 | logging_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 | |||
244 | struct LoggingHandle * | ||
245 | GNUNET_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 | |||
259 | void | ||
260 | GNUNET_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 | |||
271 | static struct LoggingFileHandle * | ||
272 | find_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 | |||
285 | void | ||
286 | GNUNET_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 | |||
458 | void | ||
459 | GNUNET_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 | |||
503 | void | ||
504 | GNUNET_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 | */ | ||
552 | static struct PropertyGenerator *prop_gen_head; | ||
553 | static struct PropertyGenerator *prop_gen_tail; | ||
554 | |||
555 | |||
556 | static double | ||
557 | get_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 | |||
623 | static void | ||
624 | set_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 | */ | ||
697 | static struct PropertyGenerator * | ||
698 | find_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 | |||
713 | void | ||
714 | GNUNET_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 | */ | ||
748 | struct PropertyGenerator * | ||
749 | GNUNET_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 | */ | ||
827 | void | ||
828 | GNUNET_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 | */ | ||
845 | static struct PreferenceGenerator *pref_gen_head; | ||
846 | static struct PreferenceGenerator *pref_gen_tail; | ||
847 | |||
848 | |||
849 | static double | ||
850 | get_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 | |||
916 | static void | ||
917 | set_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 | |||
997 | static void | ||
998 | set_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 | |||
1054 | static struct PreferenceGenerator * | ||
1055 | find_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 | |||
1069 | void | ||
1070 | GNUNET_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 | |||
1093 | static struct TestAddress* | ||
1094 | find_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 | */ | ||
1121 | struct PreferenceGenerator * | ||
1122 | GNUNET_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 | */ | ||
1226 | void | ||
1227 | GNUNET_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 | */ | ||
1244 | static const char * | ||
1245 | print_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 | |||
1280 | static struct Experiment * | ||
1281 | create_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 | |||
1293 | static void | ||
1294 | free_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 | |||
1325 | static int | ||
1326 | load_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 | |||
1464 | static int | ||
1465 | load_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 | |||
1553 | static enum GNUNET_ATS_Property | ||
1554 | parse_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 | |||
1566 | static int | ||
1567 | load_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 | |||
1746 | static int | ||
1747 | load_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 | |||
1815 | static enum GNUNET_ATS_Property | ||
1816 | parse_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 | |||
1828 | static int | ||
1829 | load_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 | |||
1996 | static int | ||
1997 | load_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 | |||
2067 | static int | ||
2068 | load_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 | |||
2092 | static int | ||
2093 | load_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 | |||
2117 | static int | ||
2118 | load_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 | |||
2220 | static int | ||
2221 | load_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 | |||
2277 | static void | ||
2278 | timeout_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 | |||
2296 | struct ATS_Address * | ||
2297 | create_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 | |||
2325 | static void | ||
2326 | enforce_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 | |||
2378 | static void | ||
2379 | enforce_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 | |||
2429 | static void | ||
2430 | enforce_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 | |||
2471 | static void | ||
2472 | enforce_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 | |||
2495 | static void | ||
2496 | enforce_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 | |||
2528 | static void | ||
2529 | enforce_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 | |||
2552 | static void | ||
2553 | enforce_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 | |||
2573 | static void | ||
2574 | enforce_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 | |||
2601 | static void | ||
2602 | enforce_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 | |||
2669 | static void | ||
2670 | timeout_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 | |||
2704 | void | ||
2705 | GNUNET_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 | |||
2741 | void | ||
2742 | GNUNET_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 | |||
2763 | struct Experiment * | ||
2764 | GNUNET_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 | |||
2898 | static int | ||
2899 | free_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 | |||
2914 | void | ||
2915 | GNUNET_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 | */ | ||
2941 | unsigned int | ||
2942 | GNUNET_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 | "a_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 | "a_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 | */ | ||
3089 | static void | ||
3090 | solver_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 | |||
3201 | static void | ||
3202 | solver_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 | |||
3253 | const double * | ||
3254 | get_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 | |||
3270 | struct SolverHandle * | ||
3271 | GNUNET_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 | |||
3342 | static void | ||
3343 | done () | ||
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 | |||
3410 | static void | ||
3411 | experiment_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 | |||
3424 | static void | ||
3425 | episode_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 | */ | ||
3434 | static void | ||
3435 | end_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 | |||
3450 | static void | ||
3451 | run (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 | */ | ||
3540 | int | ||
3541 | main (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 | |||
37 | enum 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 | |||
46 | enum 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 | |||
58 | struct 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 | |||
81 | enum GNUNET_ATS_Solvers | ||
82 | { | ||
83 | GNUNET_ATS_SOLVER_PROPORTIONAL, | ||
84 | GNUNET_ATS_SOLVER_MLP, | ||
85 | GNUNET_ATS_SOLVER_RIL, | ||
86 | }; | ||
87 | |||
88 | struct 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 | |||
103 | struct 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 | |||
115 | struct 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 | |||
130 | struct 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 | |||
146 | struct 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 | |||
167 | struct 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 | |||
180 | struct Episode; | ||
181 | |||
182 | struct Experiment; | ||
183 | |||
184 | typedef void (*GNUNET_ATS_TESTING_EpisodeDoneCallback) ( | ||
185 | struct Episode *e); | ||
186 | |||
187 | typedef 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 | */ | ||
196 | struct 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 | |||
223 | struct 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 | |||
233 | struct 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 | |||
243 | struct 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 | |||
268 | struct 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 | |||
310 | struct 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 | */ | ||
42 | struct 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 | */ | ||
52 | static void | ||
53 | handle_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 | */ | ||
103 | static void | ||
104 | handle_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 | */ | ||
122 | static int | ||
123 | check_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 | */ | ||
150 | static void | ||
151 | handle_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 | */ | ||
197 | static void | ||
198 | handle_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 | */ | ||
215 | static void | ||
216 | handle_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 | */ | ||
233 | static void | ||
234 | handle_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 | */ | ||
251 | static int | ||
252 | check_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 | */ | ||
288 | static void | ||
289 | handle_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 | */ | ||
305 | static void | ||
306 | handle_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 | */ | ||
322 | static void | ||
323 | handle_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 | */ | ||
340 | static int | ||
341 | check_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 | */ | ||
367 | static void | ||
368 | handle_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 | */ | ||
388 | static void * | ||
389 | client_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 | */ | ||
405 | static void | ||
406 | client_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 | */ | ||
423 | static void | ||
424 | cleanup_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 | */ | ||
450 | static void | ||
451 | run (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 | */ | ||
488 | GNUNET_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 | */ | ||
39 | extern 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 9c9856094..000000000 --- a/src/ats/gnunet-service-ats_addresses.c +++ /dev/null | |||
@@ -1,686 +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 | */ | ||
37 | struct GNUNET_CONTAINER_MultiPeerMap *GSA_addresses; | ||
38 | |||
39 | |||
40 | /** | ||
41 | * Update statistic on number of addresses. | ||
42 | */ | ||
43 | static void | ||
44 | update_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 | */ | ||
58 | static void | ||
59 | free_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 | */ | ||
86 | static void | ||
87 | init_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 | */ | ||
107 | static struct ATS_Address * | ||
108 | create_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 | */ | ||
138 | struct 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 | */ | ||
160 | static int | ||
161 | find_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 | */ | ||
184 | static struct ATS_Address * | ||
185 | find_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 | void | ||
200 | GAS_addresses_add (const struct GNUNET_PeerIdentity *peer, | ||
201 | const char *plugin_name, | ||
202 | const void *plugin_addr, | ||
203 | size_t plugin_addr_len, | ||
204 | uint32_t local_address_info, | ||
205 | uint32_t session_id, | ||
206 | const struct GNUNET_ATS_Properties *prop) | ||
207 | { | ||
208 | struct ATS_Address *new_address; | ||
209 | |||
210 | if (NULL != find_exact_address (peer, | ||
211 | session_id)) | ||
212 | { | ||
213 | GNUNET_break (0); | ||
214 | return; | ||
215 | } | ||
216 | GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope); | ||
217 | new_address = create_address (peer, | ||
218 | plugin_name, | ||
219 | plugin_addr, | ||
220 | plugin_addr_len, | ||
221 | local_address_info, | ||
222 | session_id); | ||
223 | /* Add a new address */ | ||
224 | new_address->properties = *prop; | ||
225 | new_address->t_added = GNUNET_TIME_absolute_get (); | ||
226 | new_address->t_last_activity = GNUNET_TIME_absolute_get (); | ||
227 | GNUNET_assert (GNUNET_OK == | ||
228 | GNUNET_CONTAINER_multipeermap_put (GSA_addresses, | ||
229 | peer, | ||
230 | new_address, | ||
231 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
232 | update_addresses_stat (); | ||
233 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
234 | "Adding new address for peer `%s' slot %u\n", | ||
235 | GNUNET_i2s (peer), | ||
236 | session_id); | ||
237 | /* Tell solver about new address */ | ||
238 | GAS_plugin_solver_lock (); | ||
239 | GAS_plugin_new_address (new_address); | ||
240 | GAS_normalization_update_property (new_address); // FIXME: needed? | ||
241 | GAS_plugin_solver_unlock (); | ||
242 | /* Notify performance clients about new address */ | ||
243 | GAS_performance_notify_all_clients (&new_address->peer, | ||
244 | new_address->plugin, | ||
245 | new_address->addr, | ||
246 | new_address->addr_len, | ||
247 | new_address->active, | ||
248 | &new_address->properties, | ||
249 | new_address->local_address_info, | ||
250 | GNUNET_BANDWIDTH_value_init ( | ||
251 | new_address->assigned_bw_out), | ||
252 | GNUNET_BANDWIDTH_value_init ( | ||
253 | new_address->assigned_bw_in)); | ||
254 | } | ||
255 | |||
256 | |||
257 | void | ||
258 | GAS_addresses_update (const struct GNUNET_PeerIdentity *peer, | ||
259 | uint32_t session_id, | ||
260 | const struct GNUNET_ATS_Properties *prop) | ||
261 | { | ||
262 | struct ATS_Address *aa; | ||
263 | |||
264 | /* Get existing address */ | ||
265 | aa = find_exact_address (peer, | ||
266 | session_id); | ||
267 | if (NULL == aa) | ||
268 | { | ||
269 | GNUNET_break (0); | ||
270 | return; | ||
271 | } | ||
272 | if (NULL == aa->solver_information) | ||
273 | { | ||
274 | GNUNET_break (0); | ||
275 | return; | ||
276 | } | ||
277 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
278 | "Received ADDRESS_UPDATE for peer `%s' slot %u\n", | ||
279 | GNUNET_i2s (peer), | ||
280 | (unsigned int) session_id); | ||
281 | GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope); | ||
282 | /* Update address */ | ||
283 | aa->t_last_activity = GNUNET_TIME_absolute_get (); | ||
284 | aa->properties = *prop; | ||
285 | /* Notify performance clients about updated address */ | ||
286 | GAS_performance_notify_all_clients (&aa->peer, | ||
287 | aa->plugin, | ||
288 | aa->addr, | ||
289 | aa->addr_len, | ||
290 | aa->active, | ||
291 | prop, | ||
292 | aa->local_address_info, | ||
293 | GNUNET_BANDWIDTH_value_init ( | ||
294 | aa->assigned_bw_out), | ||
295 | GNUNET_BANDWIDTH_value_init ( | ||
296 | aa->assigned_bw_in)); | ||
297 | |||
298 | GAS_normalization_update_property (aa); | ||
299 | } | ||
300 | |||
301 | |||
302 | /** | ||
303 | * Remove an address for a peer. | ||
304 | * | ||
305 | * @param peer peer | ||
306 | * @param session_id session id, can never be 0 | ||
307 | */ | ||
308 | void | ||
309 | GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer, | ||
310 | uint32_t session_id) | ||
311 | { | ||
312 | struct ATS_Address *ea; | ||
313 | |||
314 | /* Get existing address */ | ||
315 | ea = find_exact_address (peer, | ||
316 | session_id); | ||
317 | if (NULL == ea) | ||
318 | { | ||
319 | GNUNET_break (0); | ||
320 | return; | ||
321 | } | ||
322 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
323 | "Received ADDRESS_DESTROYED for peer `%s' session %u\n", | ||
324 | GNUNET_i2s (peer), | ||
325 | session_id); | ||
326 | free_address (ea); | ||
327 | } | ||
328 | |||
329 | |||
330 | /** | ||
331 | * Initialize address subsystem. The addresses subsystem manages the addresses | ||
332 | * known and current performance information. It has a solver component | ||
333 | * responsible for the resource allocation. It tells the solver about changes | ||
334 | * and receives updates when the solver changes the resource allocation. | ||
335 | */ | ||
336 | void | ||
337 | GAS_addresses_init () | ||
338 | { | ||
339 | GSA_addresses | ||
340 | = GNUNET_CONTAINER_multipeermap_create (128, | ||
341 | GNUNET_NO); | ||
342 | update_addresses_stat (); | ||
343 | } | ||
344 | |||
345 | |||
346 | /** | ||
347 | * Destroy all addresses iterator | ||
348 | * | ||
349 | * @param cls NULL | ||
350 | * @param key peer identity (unused) | ||
351 | * @param value the 'struct ATS_Address' to free | ||
352 | * @return #GNUNET_OK (continue to iterate) | ||
353 | */ | ||
354 | static int | ||
355 | destroy_all_address_it (void *cls, | ||
356 | const struct GNUNET_PeerIdentity *key, | ||
357 | void *value) | ||
358 | { | ||
359 | struct ATS_Address *aa = value; | ||
360 | |||
361 | free_address (aa); | ||
362 | return GNUNET_OK; | ||
363 | } | ||
364 | |||
365 | |||
366 | /** | ||
367 | * Remove all addresses | ||
368 | */ | ||
369 | void | ||
370 | GAS_addresses_destroy_all () | ||
371 | { | ||
372 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
373 | "Destroying all addresses\n"); | ||
374 | if (NULL == GSA_addresses) | ||
375 | return; | ||
376 | if (0 == | ||
377 | GNUNET_CONTAINER_multipeermap_size (GSA_addresses)) | ||
378 | return; | ||
379 | GAS_plugin_solver_lock (); | ||
380 | GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses, | ||
381 | &destroy_all_address_it, | ||
382 | NULL); | ||
383 | GAS_plugin_solver_unlock (); | ||
384 | } | ||
385 | |||
386 | |||
387 | /** | ||
388 | * Shutdown address subsystem. | ||
389 | */ | ||
390 | void | ||
391 | GAS_addresses_done () | ||
392 | { | ||
393 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
394 | "Shutting down addresses\n"); | ||
395 | GAS_plugin_solver_lock (); | ||
396 | GAS_addresses_destroy_all (); | ||
397 | GAS_plugin_solver_unlock (); | ||
398 | GNUNET_CONTAINER_multipeermap_destroy (GSA_addresses); | ||
399 | GSA_addresses = NULL; | ||
400 | } | ||
401 | |||
402 | |||
403 | /** | ||
404 | * Closure for #peerinfo_it(). | ||
405 | */ | ||
406 | struct PeerInfoIteratorContext | ||
407 | { | ||
408 | /** | ||
409 | * Function to call for each address. | ||
410 | */ | ||
411 | GNUNET_ATS_PeerInfo_Iterator it; | ||
412 | |||
413 | /** | ||
414 | * Closure for @e it. | ||
415 | */ | ||
416 | void *it_cls; | ||
417 | }; | ||
418 | |||
419 | |||
420 | /** | ||
421 | * Iterator to iterate over a peer's addresses | ||
422 | * | ||
423 | * @param cls a `struct PeerInfoIteratorContext` | ||
424 | * @param key the peer id | ||
425 | * @param value the `struct ATS_address` | ||
426 | * @return #GNUNET_OK to continue | ||
427 | */ | ||
428 | static int | ||
429 | peerinfo_it (void *cls, | ||
430 | const struct GNUNET_PeerIdentity *key, | ||
431 | void *value) | ||
432 | { | ||
433 | struct PeerInfoIteratorContext *pi_ctx = cls; | ||
434 | struct ATS_Address *addr = value; | ||
435 | |||
436 | pi_ctx->it (pi_ctx->it_cls, | ||
437 | &addr->peer, | ||
438 | addr->plugin, | ||
439 | addr->addr, | ||
440 | addr->addr_len, | ||
441 | addr->active, | ||
442 | &addr->properties, | ||
443 | addr->local_address_info, | ||
444 | GNUNET_BANDWIDTH_value_init (addr->assigned_bw_out), | ||
445 | GNUNET_BANDWIDTH_value_init (addr->assigned_bw_in)); | ||
446 | return GNUNET_OK; | ||
447 | } | ||
448 | |||
449 | |||
450 | void | ||
451 | GAS_addresses_get_peer_info (const struct GNUNET_PeerIdentity *peer, | ||
452 | GNUNET_ATS_PeerInfo_Iterator pi_it, | ||
453 | void *pi_it_cls) | ||
454 | { | ||
455 | struct PeerInfoIteratorContext pi_ctx; | ||
456 | |||
457 | if (NULL == pi_it) | ||
458 | { | ||
459 | /* does not make sense without callback */ | ||
460 | GNUNET_break (0); | ||
461 | return; | ||
462 | } | ||
463 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
464 | "Returning information for %s from a total of %u known addresses\n", | ||
465 | (NULL == peer) | ||
466 | ? "all peers" | ||
467 | : GNUNET_i2s (peer), | ||
468 | (unsigned int) GNUNET_CONTAINER_multipeermap_size ( | ||
469 | GSA_addresses)); | ||
470 | pi_ctx.it = pi_it; | ||
471 | pi_ctx.it_cls = pi_it_cls; | ||
472 | if (NULL == peer) | ||
473 | GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses, | ||
474 | &peerinfo_it, | ||
475 | &pi_ctx); | ||
476 | else | ||
477 | GNUNET_CONTAINER_multipeermap_get_multiple (GSA_addresses, | ||
478 | peer, | ||
479 | &peerinfo_it, &pi_ctx); | ||
480 | pi_it (pi_it_cls, | ||
481 | NULL, NULL, NULL, 0, | ||
482 | GNUNET_NO, | ||
483 | NULL, | ||
484 | GNUNET_HELLO_ADDRESS_INFO_NONE, | ||
485 | GNUNET_BANDWIDTH_ZERO, | ||
486 | GNUNET_BANDWIDTH_ZERO); | ||
487 | } | ||
488 | |||
489 | |||
490 | /** | ||
491 | * Information we need for the callbacks to return a list of addresses | ||
492 | * back to the client. | ||
493 | */ | ||
494 | struct AddressIteration | ||
495 | { | ||
496 | /** | ||
497 | * Actual handle to the client. | ||
498 | */ | ||
499 | struct GNUNET_SERVICE_Client *client; | ||
500 | |||
501 | /** | ||
502 | * Are we sending all addresses, or only those that are active? | ||
503 | */ | ||
504 | int all; | ||
505 | |||
506 | /** | ||
507 | * Which ID should be included in the response? | ||
508 | */ | ||
509 | uint32_t id; | ||
510 | }; | ||
511 | |||
512 | |||
513 | /** | ||
514 | * Send a #GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE with the | ||
515 | * given address details to the client identified in @a ai. | ||
516 | * | ||
517 | * @param ai our address information context (identifies the client) | ||
518 | * @param id the peer id this address is for | ||
519 | * @param plugin_name name of the plugin that supports this address | ||
520 | * @param plugin_addr address | ||
521 | * @param plugin_addr_len length of @a plugin_addr | ||
522 | * @param active #GNUNET_YES if this address is actively used | ||
523 | * @param prop performance information | ||
524 | * @param local_address_info flags for the address | ||
525 | * @param bandwidth_out current outbound bandwidth assigned to address | ||
526 | * @param bandwidth_in current inbound bandwidth assigned to address | ||
527 | */ | ||
528 | static void | ||
529 | transmit_req_addr (struct AddressIteration *ai, | ||
530 | const struct GNUNET_PeerIdentity *id, | ||
531 | const char *plugin_name, | ||
532 | const void *plugin_addr, | ||
533 | size_t plugin_addr_len, | ||
534 | int active, | ||
535 | const struct GNUNET_ATS_Properties *prop, | ||
536 | enum GNUNET_HELLO_AddressInfo local_address_info, | ||
537 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, | ||
538 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) | ||
539 | |||
540 | { | ||
541 | struct GNUNET_MQ_Envelope *env; | ||
542 | struct PeerInformationMessage *msg; | ||
543 | char *addrp; | ||
544 | size_t plugin_name_length; | ||
545 | size_t msize; | ||
546 | |||
547 | if (NULL != plugin_name) | ||
548 | plugin_name_length = strlen (plugin_name) + 1; | ||
549 | else | ||
550 | plugin_name_length = 0; | ||
551 | msize = plugin_addr_len + plugin_name_length; | ||
552 | |||
553 | GNUNET_assert (sizeof(struct PeerInformationMessage) + msize | ||
554 | < GNUNET_MAX_MESSAGE_SIZE); | ||
555 | env = GNUNET_MQ_msg_extra (msg, | ||
556 | msize, | ||
557 | GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE); | ||
558 | msg->id = htonl (ai->id); | ||
559 | if (NULL != id) | ||
560 | msg->peer = *id; | ||
561 | msg->address_length = htons (plugin_addr_len); | ||
562 | msg->address_active = ntohl (active); | ||
563 | msg->plugin_name_length = htons (plugin_name_length); | ||
564 | msg->bandwidth_out = bandwidth_out; | ||
565 | msg->bandwidth_in = bandwidth_in; | ||
566 | if (NULL != prop) | ||
567 | GNUNET_ATS_properties_hton (&msg->properties, | ||
568 | prop); | ||
569 | msg->address_local_info = htonl ((uint32_t) local_address_info); | ||
570 | addrp = (char *) &msg[1]; | ||
571 | GNUNET_memcpy (addrp, | ||
572 | plugin_addr, | ||
573 | plugin_addr_len); | ||
574 | if (NULL != plugin_name) | ||
575 | strcpy (&addrp[plugin_addr_len], | ||
576 | plugin_name); | ||
577 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (ai->client), | ||
578 | env); | ||
579 | } | ||
580 | |||
581 | |||
582 | /** | ||
583 | * Iterator for #GAS_addresses_get_peer_info(), called with peer-specific | ||
584 | * information to be passed back to the client. | ||
585 | * | ||
586 | * @param cls closure with our `struct AddressIteration *` | ||
587 | * @param id the peer id | ||
588 | * @param plugin_name plugin name | ||
589 | * @param plugin_addr address | ||
590 | * @param plugin_addr_len length of @a plugin_addr | ||
591 | * @param active is address actively used | ||
592 | * @param prop performance information | ||
593 | * @param local_address_info additional local info for the address | ||
594 | * @param bandwidth_out current outbound bandwidth assigned to address | ||
595 | * @param bandwidth_in current inbound bandwidth assigned to address | ||
596 | */ | ||
597 | static void | ||
598 | req_addr_peerinfo_it (void *cls, | ||
599 | const struct GNUNET_PeerIdentity *id, | ||
600 | const char *plugin_name, | ||
601 | const void *plugin_addr, | ||
602 | size_t plugin_addr_len, | ||
603 | int active, | ||
604 | const struct GNUNET_ATS_Properties *prop, | ||
605 | enum GNUNET_HELLO_AddressInfo local_address_info, | ||
606 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, | ||
607 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) | ||
608 | { | ||
609 | struct AddressIteration *ai = cls; | ||
610 | |||
611 | if ((NULL == id) && | ||
612 | (NULL == plugin_name) && | ||
613 | (NULL == plugin_addr)) | ||
614 | { | ||
615 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
616 | "Address iteration done for one peer\n"); | ||
617 | return; | ||
618 | } | ||
619 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
620 | "Callback for %s peer `%s' plugin `%s' BW out %u, BW in %u\n", | ||
621 | (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE", | ||
622 | GNUNET_i2s (id), | ||
623 | plugin_name, | ||
624 | (unsigned int) ntohl (bandwidth_out.value__), | ||
625 | (unsigned int) ntohl (bandwidth_in.value__)); | ||
626 | /* Transmit result (either if address is active, or if | ||
627 | client wanted all addresses) */ | ||
628 | if ((GNUNET_YES != ai->all) && | ||
629 | (GNUNET_YES != active)) | ||
630 | return; | ||
631 | transmit_req_addr (ai, | ||
632 | id, | ||
633 | plugin_name, | ||
634 | plugin_addr, plugin_addr_len, | ||
635 | active, | ||
636 | prop, | ||
637 | local_address_info, | ||
638 | bandwidth_out, | ||
639 | bandwidth_in); | ||
640 | } | ||
641 | |||
642 | |||
643 | void | ||
644 | GAS_handle_request_address_list (struct GNUNET_SERVICE_Client *client, | ||
645 | const struct AddressListRequestMessage *alrm) | ||
646 | { | ||
647 | struct AddressIteration ai; | ||
648 | struct GNUNET_PeerIdentity allzeros; | ||
649 | |||
650 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
651 | "Received ADDRESSLIST_REQUEST message\n"); | ||
652 | ai.all = ntohl (alrm->all); | ||
653 | ai.id = ntohl (alrm->id); | ||
654 | ai.client = client; | ||
655 | |||
656 | memset (&allzeros, | ||
657 | '\0', | ||
658 | sizeof(struct GNUNET_PeerIdentity)); | ||
659 | if (GNUNET_YES == GNUNET_is_zero (&alrm->peer)) | ||
660 | { | ||
661 | /* Return addresses for all peers */ | ||
662 | GAS_addresses_get_peer_info (NULL, | ||
663 | &req_addr_peerinfo_it, | ||
664 | &ai); | ||
665 | } | ||
666 | else | ||
667 | { | ||
668 | /* Return addresses for a specific peer */ | ||
669 | GAS_addresses_get_peer_info (&alrm->peer, | ||
670 | &req_addr_peerinfo_it, | ||
671 | &ai); | ||
672 | } | ||
673 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
674 | "Finished handling `%s' message\n", | ||
675 | "ADDRESSLIST_REQUEST"); | ||
676 | transmit_req_addr (&ai, | ||
677 | NULL, NULL, NULL, | ||
678 | 0, GNUNET_NO, | ||
679 | NULL, | ||
680 | GNUNET_HELLO_ADDRESS_INFO_NONE, | ||
681 | GNUNET_BANDWIDTH_ZERO, | ||
682 | GNUNET_BANDWIDTH_ZERO); | ||
683 | } | ||
684 | |||
685 | |||
686 | /* 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 8e6f40f38..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 | */ | ||
230 | struct 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 | */ | ||
257 | struct 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 | */ | ||
364 | extern 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 | */ | ||
371 | void | ||
372 | GAS_addresses_init (void); | ||
373 | |||
374 | |||
375 | /** | ||
376 | * Shutdown address subsystem. | ||
377 | */ | ||
378 | void | ||
379 | GAS_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 | */ | ||
393 | void | ||
394 | GAS_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 | */ | ||
410 | void | ||
411 | GAS_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 | */ | ||
422 | void | ||
423 | GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer, | ||
424 | uint32_t session_id); | ||
425 | |||
426 | |||
427 | /** | ||
428 | * Remove all addresses. | ||
429 | */ | ||
430 | void | ||
431 | GAS_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 | */ | ||
448 | typedef 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, NULL for 'all' peers | ||
468 | * @param pi_it the iterator to call for every peer | ||
469 | * @param pi_it_cls the closure for @a pi_it | ||
470 | */ | ||
471 | void | ||
472 | GAS_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 | */ | ||
483 | void | ||
484 | GAS_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 702c5ba87..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 | */ | ||
38 | struct 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 | */ | ||
52 | static 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 | */ | ||
63 | unsigned int | ||
64 | GAS_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 msg the request message | ||
80 | */ | ||
81 | void | ||
82 | GAS_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 | */ | ||
110 | static int | ||
111 | free_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 | */ | ||
141 | void | ||
142 | GAS_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 | */ | ||
162 | void | ||
163 | GAS_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 | */ | ||
175 | void | ||
176 | GAS_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 | */ | ||
192 | static int | ||
193 | free_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 | */ | ||
209 | void | ||
210 | GAS_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 | */ | ||
40 | unsigned int | ||
41 | GAS_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 | */ | ||
51 | void | ||
52 | GAS_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 | */ | ||
62 | void | ||
63 | GAS_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 | */ | ||
73 | void | ||
74 | GAS_connectivity_remove_client (struct GNUNET_SERVICE_Client *client); | ||
75 | |||
76 | |||
77 | /** | ||
78 | * Initialize connectivity subsystem. | ||
79 | */ | ||
80 | void | ||
81 | GAS_connectivity_init (void); | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Shutdown connectivity subsystem. | ||
86 | */ | ||
87 | void | ||
88 | GAS_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 | */ | ||
40 | struct 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 | */ | ||
57 | static 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 | */ | ||
67 | static void | ||
68 | update_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 | */ | ||
105 | static int | ||
106 | find_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 | */ | ||
141 | static void | ||
142 | update_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 | */ | ||
165 | static int | ||
166 | normalize_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 | */ | ||
196 | static int | ||
197 | notify_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 | */ | ||
214 | static void | ||
215 | init_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 | */ | ||
230 | void | ||
231 | GAS_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 | ¬ify_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 | */ | ||
282 | void | ||
283 | GAS_normalization_start () | ||
284 | { | ||
285 | init_range (&property_range); | ||
286 | } | ||
287 | |||
288 | |||
289 | /** | ||
290 | * Stop the normalization component and free all items | ||
291 | */ | ||
292 | void | ||
293 | GAS_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 | */ | ||
42 | void | ||
43 | GAS_normalization_update_property (struct ATS_Address *address); | ||
44 | |||
45 | |||
46 | /** | ||
47 | * Start the normalization component | ||
48 | */ | ||
49 | void | ||
50 | GAS_normalization_start (void); | ||
51 | |||
52 | |||
53 | /** | ||
54 | * Stop the normalization component and free all items | ||
55 | */ | ||
56 | void | ||
57 | GAS_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 | */ | ||
39 | static struct GNUNET_NotificationContext *nc_no_pic; | ||
40 | |||
41 | /** | ||
42 | * Context for sending messages to performance clients with PIC. | ||
43 | */ | ||
44 | static 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 | */ | ||
65 | static void | ||
66 | notify_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 | */ | ||
144 | void | ||
145 | GAS_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 | */ | ||
191 | static void | ||
192 | peerinfo_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 | */ | ||
233 | void | ||
234 | GAS_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 | */ | ||
261 | void | ||
262 | GAS_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 | */ | ||
272 | void | ||
273 | GAS_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 | */ | ||
52 | void | ||
53 | GAS_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 | */ | ||
73 | void | ||
74 | GAS_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 | */ | ||
84 | void | ||
85 | GAS_performance_init (void); | ||
86 | |||
87 | |||
88 | /** | ||
89 | * Shutdown performance subsystem. | ||
90 | */ | ||
91 | void | ||
92 | GAS_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 d3db69caa..000000000 --- a/src/ats/gnunet-service-ats_plugins.c +++ /dev/null | |||
@@ -1,582 +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 | */ | ||
41 | static struct GNUNET_ATS_SolverFunctions *sf; | ||
42 | |||
43 | /** | ||
44 | * Solver environment. | ||
45 | */ | ||
46 | static struct GNUNET_ATS_PluginEnvironment env; | ||
47 | |||
48 | /** | ||
49 | * Solver plugin name as string | ||
50 | */ | ||
51 | static 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 | */ | ||
61 | void | ||
62 | GAS_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 | void | ||
74 | GAS_plugin_notify_property_changed (struct ATS_Address *address) | ||
75 | { | ||
76 | sf->s_address_update_property (sf->cls, | ||
77 | address); | ||
78 | } | ||
79 | |||
80 | |||
81 | /** | ||
82 | * Solver information callback | ||
83 | * | ||
84 | * @param cls the closure | ||
85 | * @param op the operation | ||
86 | * @param status operation status | ||
87 | * @param add additional information | ||
88 | */ | ||
89 | static void | ||
90 | solver_info_cb (void *cls, | ||
91 | enum GAS_Solver_Operation op, | ||
92 | enum GAS_Solver_Status status, | ||
93 | enum GAS_Solver_Additional_Information add) | ||
94 | { | ||
95 | const char *add_info; | ||
96 | |||
97 | switch (add) | ||
98 | { | ||
99 | case GAS_INFO_NONE: | ||
100 | add_info = "GAS_INFO_NONE"; | ||
101 | break; | ||
102 | |||
103 | case GAS_INFO_FULL: | ||
104 | add_info = "GAS_INFO_MLP_FULL"; | ||
105 | break; | ||
106 | |||
107 | case GAS_INFO_UPDATED: | ||
108 | add_info = "GAS_INFO_MLP_UPDATED"; | ||
109 | break; | ||
110 | |||
111 | case GAS_INFO_PROP_ALL: | ||
112 | add_info = "GAS_INFO_PROP_ALL"; | ||
113 | break; | ||
114 | |||
115 | case GAS_INFO_PROP_SINGLE: | ||
116 | add_info = "GAS_INFO_PROP_SINGLE"; | ||
117 | break; | ||
118 | |||
119 | default: | ||
120 | add_info = "INVALID"; | ||
121 | break; | ||
122 | } | ||
123 | switch (op) | ||
124 | { | ||
125 | case GAS_OP_SOLVE_START: | ||
126 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
127 | "Solver notifies `%s' with result `%s' `%s'\n", | ||
128 | "GAS_OP_SOLVE_START", | ||
129 | (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL", | ||
130 | add_info); | ||
131 | return; | ||
132 | |||
133 | case GAS_OP_SOLVE_STOP: | ||
134 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
135 | "Solver notifies `%s' with result `%s'\n", | ||
136 | "GAS_OP_SOLVE_STOP", | ||
137 | (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL"); | ||
138 | return; | ||
139 | |||
140 | case GAS_OP_SOLVE_SETUP_START: | ||
141 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
142 | "Solver notifies `%s' with result `%s'\n", | ||
143 | "GAS_OP_SOLVE_SETUP_START", | ||
144 | (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL"); | ||
145 | return; | ||
146 | |||
147 | case GAS_OP_SOLVE_SETUP_STOP: | ||
148 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
149 | "Solver notifies `%s' with result `%s'\n", | ||
150 | "GAS_OP_SOLVE_SETUP_STOP", | ||
151 | (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL"); | ||
152 | return; | ||
153 | |||
154 | case GAS_OP_SOLVE_MLP_LP_START: | ||
155 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
156 | "Solver notifies `%s' with result `%s'\n", | ||
157 | "GAS_OP_SOLVE_LP_START", | ||
158 | (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL"); | ||
159 | return; | ||
160 | |||
161 | case GAS_OP_SOLVE_MLP_LP_STOP: | ||
162 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
163 | "Solver notifies `%s' with result `%s'\n", | ||
164 | "GAS_OP_SOLVE_LP_STOP", | ||
165 | (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL"); | ||
166 | return; | ||
167 | |||
168 | case GAS_OP_SOLVE_MLP_MLP_START: | ||
169 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
170 | "Solver notifies `%s' with result `%s'\n", | ||
171 | "GAS_OP_SOLVE_MLP_START", | ||
172 | (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL"); | ||
173 | return; | ||
174 | |||
175 | case GAS_OP_SOLVE_MLP_MLP_STOP: | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
177 | "Solver notifies `%s' with result `%s'\n", | ||
178 | "GAS_OP_SOLVE_MLP_STOP", | ||
179 | (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL"); | ||
180 | return; | ||
181 | |||
182 | case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START: | ||
183 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
184 | "Solver notifies `%s' with result `%s'\n", | ||
185 | "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START", | ||
186 | (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL"); | ||
187 | return; | ||
188 | |||
189 | case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP: | ||
190 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
191 | "Solver notifies `%s' with result `%s'\n", | ||
192 | "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP", | ||
193 | (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL"); | ||
194 | return; | ||
195 | |||
196 | default: | ||
197 | GNUNET_break (0); | ||
198 | break; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | |||
203 | /** | ||
204 | * Callback for solver to notify about assignment changes | ||
205 | * | ||
206 | * @param cls NULL | ||
207 | * @param address the address with changes | ||
208 | */ | ||
209 | static void | ||
210 | bandwidth_changed_cb (void *cls, | ||
211 | struct ATS_Address *address) | ||
212 | { | ||
213 | long long diff_out; | ||
214 | long long diff_in; | ||
215 | |||
216 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
217 | "Bandwidth assignment changed for peer %s to %u/%u\n", | ||
218 | GNUNET_i2s (&address->peer), | ||
219 | (unsigned int) address->assigned_bw_in, | ||
220 | (unsigned int) address->assigned_bw_out); | ||
221 | GAS_reservations_set_bandwidth (&address->peer, | ||
222 | GNUNET_BANDWIDTH_value_init ( | ||
223 | address->assigned_bw_in)); | ||
224 | /* Notify performance clients about changes to address */ | ||
225 | GAS_performance_notify_all_clients (&address->peer, | ||
226 | address->plugin, | ||
227 | address->addr, | ||
228 | address->addr_len, | ||
229 | address->active, | ||
230 | &address->properties, | ||
231 | address->local_address_info, | ||
232 | GNUNET_BANDWIDTH_value_init ( | ||
233 | address->assigned_bw_out), | ||
234 | GNUNET_BANDWIDTH_value_init ( | ||
235 | address->assigned_bw_in)); | ||
236 | |||
237 | if ((0 == address->assigned_bw_in) && | ||
238 | (0 == address->assigned_bw_out)) | ||
239 | { | ||
240 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
241 | "Telling transport to disconnect peer `%s'\n", | ||
242 | GNUNET_i2s (&address->peer)); | ||
243 | |||
244 | /* Notify scheduling clients about suggestion */ | ||
245 | GAS_scheduling_transmit_address_suggestion (&address->peer, | ||
246 | address->session_id, | ||
247 | GNUNET_BANDWIDTH_ZERO, | ||
248 | GNUNET_BANDWIDTH_ZERO); | ||
249 | return; | ||
250 | } | ||
251 | |||
252 | /* Do bandwidth stability check */ | ||
253 | diff_out = llabs ((long long) address->assigned_bw_out | ||
254 | - (long long) address->last_notified_bw_out); | ||
255 | diff_in = llabs ((long long) address->assigned_bw_in | ||
256 | - (long long) address->last_notified_bw_in); | ||
257 | if ((diff_out < htonl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__)) && | ||
258 | (diff_in < htonl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__))) | ||
259 | { | ||
260 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
261 | "Bandwidth change too small, not notifying client\n"); | ||
262 | return; | ||
263 | } | ||
264 | |||
265 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
266 | "Sending bandwidth update for peer `%s': %u/%u\n", | ||
267 | GNUNET_i2s (&address->peer), | ||
268 | address->assigned_bw_out, | ||
269 | address->assigned_bw_out); | ||
270 | |||
271 | /* *Notify scheduling clients about suggestion */ | ||
272 | GAS_scheduling_transmit_address_suggestion (&address->peer, | ||
273 | address->session_id, | ||
274 | GNUNET_BANDWIDTH_value_init ( | ||
275 | address->assigned_bw_out), | ||
276 | GNUNET_BANDWIDTH_value_init ( | ||
277 | address->assigned_bw_in)); | ||
278 | |||
279 | address->last_notified_bw_out = address->assigned_bw_out; | ||
280 | address->last_notified_bw_in = address->assigned_bw_in; | ||
281 | } | ||
282 | |||
283 | |||
284 | /** | ||
285 | * Convert quota from text to numeric value. | ||
286 | * | ||
287 | * @param quota_str the value found in the configuration | ||
288 | * @param direction direction of the quota | ||
289 | * @param network network the quota applies to | ||
290 | * @return numeric quota value to use | ||
291 | */ | ||
292 | static unsigned long long | ||
293 | parse_quota (const char *quota_str, | ||
294 | const char *direction, | ||
295 | enum GNUNET_NetworkType network) | ||
296 | { | ||
297 | int res; | ||
298 | unsigned long long ret; | ||
299 | |||
300 | res = GNUNET_NO; | ||
301 | if (0 == strcmp (quota_str, GNUNET_ATS_MaxBandwidthString)) | ||
302 | { | ||
303 | ret = GNUNET_ATS_MaxBandwidth; | ||
304 | res = GNUNET_YES; | ||
305 | } | ||
306 | if ((GNUNET_NO == res) && | ||
307 | (GNUNET_OK == | ||
308 | GNUNET_STRINGS_fancy_size_to_bytes (quota_str, | ||
309 | &ret))) | ||
310 | res = GNUNET_YES; | ||
311 | if ((GNUNET_NO == res) && | ||
312 | (1 == | ||
313 | sscanf (quota_str, | ||
314 | "%llu", | ||
315 | &ret))) | ||
316 | res = GNUNET_YES; | ||
317 | if (GNUNET_NO == res) | ||
318 | { | ||
319 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
320 | _ ( | ||
321 | "Could not load %s quota for network `%s': `%s', assigning default bandwidth %llu\n"), | ||
322 | direction, | ||
323 | GNUNET_NT_to_string (network), | ||
324 | quota_str, | ||
325 | (unsigned long long) GNUNET_ATS_DefaultBandwidth); | ||
326 | ret = GNUNET_ATS_DefaultBandwidth; | ||
327 | } | ||
328 | else | ||
329 | { | ||
330 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
331 | _ ("%s quota configured for network `%s' is %llu\n"), | ||
332 | direction, | ||
333 | GNUNET_NT_to_string (network), | ||
334 | ret); | ||
335 | } | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | |||
340 | /** | ||
341 | * Load quota value from the configuration @a cfg for the | ||
342 | * given network @a type and @a direction. | ||
343 | * | ||
344 | * @param cfg configuration to parse | ||
345 | * @param type network type to parse for | ||
346 | * @param direction traffic direction to parse for | ||
347 | * @return quota to apply | ||
348 | */ | ||
349 | static unsigned long long | ||
350 | load_quota (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
351 | enum GNUNET_NetworkType type, | ||
352 | const char *direction) | ||
353 | { | ||
354 | char *entry; | ||
355 | char *quota_str; | ||
356 | unsigned long long ret; | ||
357 | |||
358 | GNUNET_asprintf (&entry, | ||
359 | "%s_QUOTA_%s", | ||
360 | GNUNET_NT_to_string (type), | ||
361 | direction); | ||
362 | if (GNUNET_OK == | ||
363 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
364 | "ats", | ||
365 | entry, | ||
366 | "a_str)) | ||
367 | { | ||
368 | ret = parse_quota (quota_str, | ||
369 | direction, | ||
370 | type); | ||
371 | GNUNET_free (quota_str); | ||
372 | } | ||
373 | else | ||
374 | { | ||
375 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
376 | _ ( | ||
377 | "No %s-quota configured for network `%s', assigning default bandwidth %llu\n"), | ||
378 | direction, | ||
379 | GNUNET_NT_to_string (type), | ||
380 | (unsigned long long) GNUNET_ATS_DefaultBandwidth); | ||
381 | ret = GNUNET_ATS_DefaultBandwidth; | ||
382 | } | ||
383 | GNUNET_free (entry); | ||
384 | return ret; | ||
385 | } | ||
386 | |||
387 | |||
388 | /** | ||
389 | * Load quotas for networks from configuration | ||
390 | * | ||
391 | * @param cfg configuration handle | ||
392 | * @param out_dest where to write outbound quotas | ||
393 | * @param in_dest where to write inbound quotas | ||
394 | * @param dest_length length of inbound and outbound arrays | ||
395 | * @return number of networks loaded | ||
396 | */ | ||
397 | static unsigned int | ||
398 | load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
399 | unsigned long long *out_dest, | ||
400 | unsigned long long *in_dest, | ||
401 | int dest_length) | ||
402 | { | ||
403 | unsigned int c; | ||
404 | |||
405 | for (c = 0; (c < GNUNET_NT_COUNT) && (c < dest_length); c++) | ||
406 | { | ||
407 | in_dest[c] = load_quota (cfg, | ||
408 | c, | ||
409 | "out"); | ||
410 | out_dest[c] = load_quota (cfg, | ||
411 | c, | ||
412 | "in"); | ||
413 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
414 | "Loaded quota for network `%s' (in/out): %llu %llu\n", | ||
415 | GNUNET_NT_to_string (c), | ||
416 | in_dest[c], | ||
417 | out_dest[c]); | ||
418 | } | ||
419 | return c; | ||
420 | } | ||
421 | |||
422 | |||
423 | int | ||
424 | GAS_plugin_init (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
425 | { | ||
426 | char *mode_str; | ||
427 | |||
428 | /* Figure out configured solution method */ | ||
429 | if (GNUNET_SYSERR == | ||
430 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
431 | "ats", | ||
432 | "MODE", | ||
433 | &mode_str)) | ||
434 | { | ||
435 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
436 | "No resource assignment method configured, using proportional approach\n"); | ||
437 | mode_str = GNUNET_strdup ("proportional"); | ||
438 | } | ||
439 | env.cls = NULL; | ||
440 | env.info_cb = &solver_info_cb; | ||
441 | env.bandwidth_changed_cb = &bandwidth_changed_cb; | ||
442 | env.get_preferences = &GAS_preference_get_by_peer; | ||
443 | env.get_connectivity = &GAS_connectivity_has_peer; | ||
444 | env.cfg = cfg; | ||
445 | env.stats = GSA_stats; | ||
446 | env.addresses = GSA_addresses; | ||
447 | env.network_count = GNUNET_NT_COUNT; | ||
448 | load_quotas (cfg, | ||
449 | env.out_quota, | ||
450 | env.in_quota, | ||
451 | GNUNET_NT_COUNT); | ||
452 | GNUNET_asprintf (&plugin, | ||
453 | "libgnunet_plugin_ats_%s", | ||
454 | mode_str); | ||
455 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
456 | "Initializing solver `%s'\n", | ||
457 | mode_str); | ||
458 | GNUNET_free (mode_str); | ||
459 | if (NULL == (sf = GNUNET_PLUGIN_load (plugin, &env))) | ||
460 | { | ||
461 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
462 | _ ("Failed to initialize solver `%s'!\n"), | ||
463 | plugin); | ||
464 | return GNUNET_SYSERR; | ||
465 | } | ||
466 | return GNUNET_OK; | ||
467 | } | ||
468 | |||
469 | |||
470 | /** | ||
471 | * Shutdown address subsystem. | ||
472 | */ | ||
473 | void | ||
474 | GAS_plugin_done () | ||
475 | { | ||
476 | GNUNET_PLUGIN_unload (plugin, | ||
477 | sf); | ||
478 | sf = NULL; | ||
479 | GNUNET_free (plugin); | ||
480 | plugin = NULL; | ||
481 | } | ||
482 | |||
483 | |||
484 | void | ||
485 | GAS_plugin_new_address (struct ATS_Address *new_address) | ||
486 | { | ||
487 | sf->s_add (sf->cls, | ||
488 | new_address, | ||
489 | new_address->properties.scope); /* FIXME: remove 3rd arg here! */ | ||
490 | } | ||
491 | |||
492 | |||
493 | /** | ||
494 | * Tell the solver that the given address is no longer valid | ||
495 | * can cannot be used any longer. | ||
496 | * | ||
497 | * @param address address that was deleted | ||
498 | */ | ||
499 | void | ||
500 | GAS_plugin_delete_address (struct ATS_Address *address) | ||
501 | { | ||
502 | sf->s_del (sf->cls, | ||
503 | address); | ||
504 | } | ||
505 | |||
506 | |||
507 | /** | ||
508 | * Tell the solver that the given client has expressed its | ||
509 | * appreciation for the past performance of a given connection. | ||
510 | * | ||
511 | * @param application client providing the feedback | ||
512 | * @param peer peer the feedback is about | ||
513 | * @param scope timeframe the feedback applies to | ||
514 | * @param kind performance property the feedback relates to | ||
515 | * @param score_abs degree of the appreciation | ||
516 | */ | ||
517 | void | ||
518 | GAS_plugin_notify_feedback (struct GNUNET_SERVICE_Client *application, | ||
519 | const struct GNUNET_PeerIdentity *peer, | ||
520 | const struct GNUNET_TIME_Relative scope, | ||
521 | enum GNUNET_ATS_PreferenceKind kind, | ||
522 | float score_abs) | ||
523 | { | ||
524 | sf->s_feedback (sf->cls, | ||
525 | application, | ||
526 | peer, | ||
527 | scope, | ||
528 | kind, | ||
529 | score_abs); | ||
530 | } | ||
531 | |||
532 | |||
533 | /** | ||
534 | * Stop instant solving, there are many state updates | ||
535 | * happening in bulk right now. | ||
536 | */ | ||
537 | void | ||
538 | GAS_plugin_solver_lock () | ||
539 | { | ||
540 | sf->s_bulk_start (sf->cls); | ||
541 | } | ||
542 | |||
543 | |||
544 | /** | ||
545 | * Resume instant solving, we are done with the bulk state updates. | ||
546 | */ | ||
547 | void | ||
548 | GAS_plugin_solver_unlock () | ||
549 | { | ||
550 | sf->s_bulk_stop (sf->cls); | ||
551 | } | ||
552 | |||
553 | |||
554 | /** | ||
555 | * Notify the plugin that a request to connect to | ||
556 | * a particular peer was given to us. | ||
557 | * | ||
558 | * @param pid identity of peer we now care about | ||
559 | */ | ||
560 | void | ||
561 | GAS_plugin_request_connect_start (const struct GNUNET_PeerIdentity *pid) | ||
562 | { | ||
563 | sf->s_get (sf->cls, | ||
564 | pid); | ||
565 | } | ||
566 | |||
567 | |||
568 | /** | ||
569 | * Notify the plugin that a request to connect to | ||
570 | * a particular peer was dropped. | ||
571 | * | ||
572 | * @param pid identity of peer we care now less about | ||
573 | */ | ||
574 | void | ||
575 | GAS_plugin_request_connect_stop (const struct GNUNET_PeerIdentity *pid) | ||
576 | { | ||
577 | sf->s_get_stop (sf->cls, | ||
578 | pid); | ||
579 | } | ||
580 | |||
581 | |||
582 | /* 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 1abdbbd80..000000000 --- a/src/ats/gnunet-service-ats_plugins.h +++ /dev/null | |||
@@ -1,149 +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 | */ | ||
43 | int | ||
44 | GAS_plugin_init (const struct GNUNET_CONFIGURATION_Handle *cfg); | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Shutdown address subsystem. | ||
49 | */ | ||
50 | void | ||
51 | GAS_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 | */ | ||
61 | void | ||
62 | GAS_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 for which a property changed. | ||
71 | */ | ||
72 | void | ||
73 | GAS_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 | */ | ||
82 | void | ||
83 | GAS_plugin_new_address (struct ATS_Address *new_address); | ||
84 | |||
85 | |||
86 | /** | ||
87 | * Tell the solver that the given address is no longer valid | ||
88 | * can cannot be used any longer. | ||
89 | * | ||
90 | * @param address address that was deleted | ||
91 | */ | ||
92 | void | ||
93 | GAS_plugin_delete_address (struct ATS_Address *address); | ||
94 | |||
95 | |||
96 | /** | ||
97 | * Tell the solver that the given client has expressed its | ||
98 | * appreciation for the past performance of a given connection. | ||
99 | * | ||
100 | * @param application client providing the feedback | ||
101 | * @param peer peer the feedback is about | ||
102 | * @param scope timeframe the feedback applies to | ||
103 | * @param kind performance property the feedback relates to | ||
104 | * @param score_abs degree of the appreciation | ||
105 | */ | ||
106 | void | ||
107 | GAS_plugin_notify_feedback (struct GNUNET_SERVICE_Client *application, | ||
108 | const struct GNUNET_PeerIdentity *peer, | ||
109 | const struct GNUNET_TIME_Relative scope, | ||
110 | enum GNUNET_ATS_PreferenceKind kind, | ||
111 | float score_abs); | ||
112 | |||
113 | |||
114 | /** | ||
115 | * Stop instant solving, there are many state updates | ||
116 | * happening in bulk right now. | ||
117 | */ | ||
118 | void | ||
119 | GAS_plugin_solver_lock (void); | ||
120 | |||
121 | |||
122 | /** | ||
123 | * Resume instant solving, we are done with the bulk state updates. | ||
124 | */ | ||
125 | void | ||
126 | GAS_plugin_solver_unlock (void); | ||
127 | |||
128 | |||
129 | /** | ||
130 | * Notify the plugin that a request to connect to | ||
131 | * a particular peer was given to us. | ||
132 | * | ||
133 | * @param pid identity of peer we now care about | ||
134 | */ | ||
135 | void | ||
136 | GAS_plugin_request_connect_start (const struct GNUNET_PeerIdentity *pid); | ||
137 | |||
138 | |||
139 | /** | ||
140 | * Notify the plugin that a request to connect to | ||
141 | * a particular peer was dropped. | ||
142 | * | ||
143 | * @param pid identity of peer we care now less about | ||
144 | */ | ||
145 | void | ||
146 | GAS_plugin_request_connect_stop (const struct GNUNET_PeerIdentity *pid); | ||
147 | |||
148 | |||
149 | #endif | ||
diff --git a/src/ats/gnunet-service-ats_preferences.c b/src/ats/gnunet-service-ats_preferences.c deleted file mode 100644 index c2b2dc4c1..000000000 --- a/src/ats/gnunet-service-ats_preferences.c +++ /dev/null | |||
@@ -1,771 +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 | */ | ||
60 | struct 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 | */ | ||
81 | static struct PeerRelative defvalues; | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Preference information per peer and client. | ||
86 | */ | ||
87 | struct 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 | */ | ||
119 | struct 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 | */ | ||
155 | static struct GNUNET_CONTAINER_MultiPeerMap *preference_peers; | ||
156 | |||
157 | /** | ||
158 | * Clients in DLL: head | ||
159 | */ | ||
160 | static struct PreferenceClient *pc_head; | ||
161 | |||
162 | /** | ||
163 | * Clients in DLL: tail | ||
164 | */ | ||
165 | static struct PreferenceClient *pc_tail; | ||
166 | |||
167 | /** | ||
168 | * Handle for task we run periodically to age preferences over time. | ||
169 | */ | ||
170 | static struct GNUNET_SCHEDULER_Task *aging_task; | ||
171 | |||
172 | |||
173 | /** | ||
174 | * Closure for #sum_relative_preferences(). | ||
175 | */ | ||
176 | struct 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 | */ | ||
200 | static int | ||
201 | sum_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 | */ | ||
221 | static void | ||
222 | update_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 | */ | ||
262 | static int | ||
263 | free_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 | */ | ||
286 | static int | ||
287 | free_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 | */ | ||
318 | struct 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 | */ | ||
341 | static int | ||
342 | age_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 | */ | ||
388 | static void | ||
389 | preference_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 | */ | ||
423 | struct 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 | */ | ||
446 | static int | ||
447 | update_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 | */ | ||
468 | static int | ||
469 | update_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 | */ | ||
493 | static void | ||
494 | recalculate_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 | */ | ||
530 | static int | ||
531 | update_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 | */ | ||
552 | static void | ||
553 | update_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 | */ | ||
649 | void | ||
650 | GAS_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 | */ | ||
679 | void | ||
680 | GAS_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 | */ | ||
694 | void | ||
695 | GAS_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 | */ | ||
734 | const double * | ||
735 | GAS_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 | void | ||
751 | GAS_preference_client_disconnect (struct GNUNET_SERVICE_Client *client) | ||
752 | { | ||
753 | struct PreferenceClient *c_cur; | ||
754 | |||
755 | for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next) | ||
756 | if (client == c_cur->client) | ||
757 | break; | ||
758 | if (NULL == c_cur) | ||
759 | return; | ||
760 | GNUNET_CONTAINER_DLL_remove (pc_head, | ||
761 | pc_tail, | ||
762 | c_cur); | ||
763 | GNUNET_CONTAINER_multipeermap_iterate (c_cur->peer2pref, | ||
764 | &free_preference, | ||
765 | c_cur); | ||
766 | GNUNET_CONTAINER_multipeermap_destroy (c_cur->peer2pref); | ||
767 | GNUNET_free (c_cur); | ||
768 | } | ||
769 | |||
770 | |||
771 | /* 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 | */ | ||
52 | void | ||
53 | GAS_handle_preference_change (struct GNUNET_SERVICE_Client *client, | ||
54 | const struct ChangePreferenceMessage *msg); | ||
55 | |||
56 | |||
57 | /** | ||
58 | * Initialize preferences subsystem. | ||
59 | */ | ||
60 | void | ||
61 | GAS_preference_init (void); | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Shutdown preferences subsystem. | ||
66 | */ | ||
67 | void | ||
68 | GAS_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 | */ | ||
79 | const double * | ||
80 | GAS_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 | */ | ||
89 | void | ||
90 | GAS_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 471a19859..000000000 --- a/src/ats/gnunet-service-ats_reservations.c +++ /dev/null | |||
@@ -1,211 +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 | */ | ||
41 | static 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 | */ | ||
55 | static struct GNUNET_TIME_Relative | ||
56 | reservations_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 | */ | ||
100 | void | ||
101 | GAS_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 | void | ||
139 | GAS_handle_reservation_request (struct GNUNET_SERVICE_Client *client, | ||
140 | const struct ReservationRequestMessage *msg) | ||
141 | { | ||
142 | struct GNUNET_MQ_Envelope *env; | ||
143 | struct ReservationResultMessage *result; | ||
144 | int32_t amount; | ||
145 | struct GNUNET_TIME_Relative res_delay; | ||
146 | |||
147 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
148 | "Received RESERVATION_REQUEST message\n"); | ||
149 | amount = (int32_t) ntohl (msg->amount); | ||
150 | res_delay = reservations_reserve (&msg->peer, amount); | ||
151 | if (res_delay.rel_value_us > 0) | ||
152 | amount = 0; | ||
153 | env = GNUNET_MQ_msg (result, | ||
154 | GNUNET_MESSAGE_TYPE_ATS_RESERVATION_RESULT); | ||
155 | result->amount = htonl (amount); | ||
156 | result->peer = msg->peer; | ||
157 | result->res_delay = GNUNET_TIME_relative_hton (res_delay); | ||
158 | GNUNET_STATISTICS_update (GSA_stats, | ||
159 | "# reservation requests processed", | ||
160 | 1, | ||
161 | GNUNET_NO); | ||
162 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
163 | env); | ||
164 | } | ||
165 | |||
166 | |||
167 | /** | ||
168 | * Initialize reservations subsystem. | ||
169 | */ | ||
170 | void | ||
171 | GAS_reservations_init () | ||
172 | { | ||
173 | trackers = GNUNET_CONTAINER_multipeermap_create (128, | ||
174 | GNUNET_NO); | ||
175 | } | ||
176 | |||
177 | |||
178 | /** | ||
179 | * Free memory of bandwidth tracker. | ||
180 | * | ||
181 | * @param cls NULL | ||
182 | * @param key peer identity (unused) | ||
183 | * @param value the `struct GNUNET_BANDWIDTH_Tracker` to free | ||
184 | * @return #GNUNET_OK (continue to iterate) | ||
185 | */ | ||
186 | static int | ||
187 | free_tracker (void *cls, | ||
188 | const struct GNUNET_PeerIdentity *key, | ||
189 | void *value) | ||
190 | { | ||
191 | struct GNUNET_BANDWIDTH_Tracker *tracker = value; | ||
192 | |||
193 | GNUNET_free (tracker); | ||
194 | return GNUNET_OK; | ||
195 | } | ||
196 | |||
197 | |||
198 | /** | ||
199 | * Shutdown reservations subsystem. | ||
200 | */ | ||
201 | void | ||
202 | GAS_reservations_done () | ||
203 | { | ||
204 | GNUNET_CONTAINER_multipeermap_iterate (trackers, | ||
205 | &free_tracker, | ||
206 | NULL); | ||
207 | GNUNET_CONTAINER_multipeermap_destroy (trackers); | ||
208 | } | ||
209 | |||
210 | |||
211 | /* 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 07edd69e0..000000000 --- a/src/ats/gnunet-service-ats_reservations.h +++ /dev/null | |||
@@ -1,72 +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 | */ | ||
41 | void | ||
42 | GAS_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 | */ | ||
53 | void | ||
54 | GAS_handle_reservation_request (struct GNUNET_SERVICE_Client *client, | ||
55 | const struct | ||
56 | ReservationRequestMessage *message); | ||
57 | |||
58 | |||
59 | /** | ||
60 | * Initialize reservations subsystem. | ||
61 | */ | ||
62 | void | ||
63 | GAS_reservations_init (void); | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Shutdown reservations subsystem. | ||
68 | */ | ||
69 | void | ||
70 | GAS_reservations_done (void); | ||
71 | |||
72 | #endif | ||
diff --git a/src/ats/gnunet-service-ats_scheduling.c b/src/ats/gnunet-service-ats_scheduling.c deleted file mode 100644 index 2dfb70343..000000000 --- a/src/ats/gnunet-service-ats_scheduling.c +++ /dev/null | |||
@@ -1,195 +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 | */ | ||
35 | static 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 | */ | ||
44 | int | ||
45 | GAS_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 | */ | ||
64 | void | ||
65 | GAS_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 | void | ||
75 | GAS_scheduling_transmit_address_suggestion (const struct | ||
76 | GNUNET_PeerIdentity *peer, | ||
77 | uint32_t session_id, | ||
78 | struct GNUNET_BANDWIDTH_Value32NBO | ||
79 | bandwidth_out, | ||
80 | struct GNUNET_BANDWIDTH_Value32NBO | ||
81 | bandwidth_in) | ||
82 | { | ||
83 | struct GNUNET_MQ_Envelope *env; | ||
84 | struct AddressSuggestionMessage *msg; | ||
85 | |||
86 | if (NULL == my_client) | ||
87 | return; | ||
88 | GNUNET_STATISTICS_update (GSA_stats, | ||
89 | "# address suggestions made", | ||
90 | 1, | ||
91 | GNUNET_NO); | ||
92 | env = GNUNET_MQ_msg (msg, | ||
93 | GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION); | ||
94 | msg->peer = *peer; | ||
95 | msg->session_id = htonl (session_id); | ||
96 | msg->bandwidth_out = bandwidth_out; | ||
97 | msg->bandwidth_in = bandwidth_in; | ||
98 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
99 | "ATS sends quota for peer `%s': (in/out) %u/%u\n", | ||
100 | GNUNET_i2s (peer), | ||
101 | (unsigned int) ntohl (bandwidth_in.value__), | ||
102 | (unsigned int) ntohl (bandwidth_out.value__)); | ||
103 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (my_client), | ||
104 | env); | ||
105 | } | ||
106 | |||
107 | |||
108 | void | ||
109 | GAS_handle_address_add (const struct AddressAddMessage *m) | ||
110 | { | ||
111 | const char *address; | ||
112 | const char *plugin_name; | ||
113 | uint16_t address_length; | ||
114 | uint16_t plugin_name_length; | ||
115 | struct GNUNET_ATS_Properties prop; | ||
116 | |||
117 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
118 | "Received `%s' message\n", | ||
119 | "ADDRESS_ADD"); | ||
120 | address_length = ntohs (m->address_length); | ||
121 | plugin_name_length = ntohs (m->plugin_name_length); | ||
122 | address = (const char *) &m[1]; | ||
123 | if (plugin_name_length != 0) | ||
124 | plugin_name = &address[address_length]; | ||
125 | else | ||
126 | plugin_name = ""; | ||
127 | GNUNET_STATISTICS_update (GSA_stats, | ||
128 | "# addresses created", | ||
129 | 1, | ||
130 | GNUNET_NO); | ||
131 | GNUNET_ATS_properties_ntoh (&prop, | ||
132 | &m->properties); | ||
133 | GNUNET_break (GNUNET_NT_UNSPECIFIED != prop.scope); | ||
134 | GAS_addresses_add (&m->peer, | ||
135 | plugin_name, | ||
136 | address, | ||
137 | address_length, | ||
138 | ntohl (m->address_local_info), | ||
139 | ntohl (m->session_id), | ||
140 | &prop); | ||
141 | } | ||
142 | |||
143 | |||
144 | /** | ||
145 | * Handle 'address update' messages from clients. | ||
146 | * | ||
147 | * @param m the request message | ||
148 | */ | ||
149 | void | ||
150 | GAS_handle_address_update (const struct AddressUpdateMessage *m) | ||
151 | { | ||
152 | struct GNUNET_ATS_Properties prop; | ||
153 | |||
154 | GNUNET_STATISTICS_update (GSA_stats, | ||
155 | "# address updates received", | ||
156 | 1, | ||
157 | GNUNET_NO); | ||
158 | GNUNET_ATS_properties_ntoh (&prop, | ||
159 | &m->properties); | ||
160 | GAS_addresses_update (&m->peer, | ||
161 | ntohl (m->session_id), | ||
162 | &prop); | ||
163 | } | ||
164 | |||
165 | |||
166 | /** | ||
167 | * Handle 'address destroyed' messages from clients. | ||
168 | * | ||
169 | * @param m the request message | ||
170 | */ | ||
171 | void | ||
172 | GAS_handle_address_destroyed (const struct AddressDestroyedMessage *m) | ||
173 | { | ||
174 | struct GNUNET_MQ_Envelope *env; | ||
175 | struct GNUNET_ATS_SessionReleaseMessage *srm; | ||
176 | |||
177 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
178 | "Received `%s' message\n", | ||
179 | "ADDRESS_DESTROYED"); | ||
180 | GNUNET_STATISTICS_update (GSA_stats, | ||
181 | "# addresses destroyed", | ||
182 | 1, | ||
183 | GNUNET_NO); | ||
184 | GAS_addresses_destroy (&m->peer, | ||
185 | ntohl (m->session_id)); | ||
186 | env = GNUNET_MQ_msg (srm, | ||
187 | GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE); | ||
188 | srm->session_id = m->session_id; | ||
189 | srm->peer = m->peer; | ||
190 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (my_client), | ||
191 | env); | ||
192 | } | ||
193 | |||
194 | |||
195 | /* 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 ca6c1bd57..000000000 --- a/src/ats/gnunet-service-ats_scheduling.h +++ /dev/null | |||
@@ -1,100 +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 | */ | ||
39 | int | ||
40 | GAS_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 | */ | ||
49 | void | ||
50 | GAS_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 for the given client | ||
59 | * @param bandwidth_out assigned outbound bandwidth | ||
60 | * @param bandwidth_in assigned inbound bandwidth | ||
61 | */ | ||
62 | void | ||
63 | GAS_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 m the request message | ||
76 | */ | ||
77 | void | ||
78 | GAS_handle_address_add (const struct AddressAddMessage *m); | ||
79 | |||
80 | |||
81 | /** | ||
82 | * Handle 'address update' messages from clients. | ||
83 | * | ||
84 | * @param m the request message | ||
85 | */ | ||
86 | void | ||
87 | GAS_handle_address_update (const struct AddressUpdateMessage *m); | ||
88 | |||
89 | |||
90 | /** | ||
91 | * Handle 'address destroyed' messages from clients. | ||
92 | * | ||
93 | * @param m the request message | ||
94 | */ | ||
95 | void | ||
96 | GAS_handle_address_destroyed (const struct AddressDestroyedMessage *m); | ||
97 | |||
98 | |||
99 | #endif | ||
100 | /* 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] | ||
2 | SERVERS = | ||
3 | |||
4 | [transport-udp] | ||
5 | BROADCAST = NO | ||
6 | |||
7 | [peerinfo] | ||
8 | USE_INCLUDED_HELLOS = NO | ||
9 | |||
10 | # Network specific inbound/outbound quotas | ||
11 | UNSPECIFIED_QUOTA_IN = 128 KiB | ||
12 | UNSPECIFIED_QUOTA_OUT = 128 KiB | ||
13 | # LOOPBACK | ||
14 | LOOPBACK_QUOTA_IN = 128 KiB | ||
15 | LOOPBACK_QUOTA_OUT = 128 KiB | ||
16 | # LAN | ||
17 | LAN_QUOTA_IN = 128 KiB | ||
18 | LAN_QUOTA_OUT = 128 KiB | ||
19 | # WAN | ||
20 | WAN_QUOTA_IN = 128 KiB | ||
21 | WAN_QUOTA_OUT = 128 KiB | ||
22 | # WLAN | ||
23 | WLAN_QUOTA_IN = 128 KiB | ||
24 | WLAN_QUOTA_OUT = 128 KiB | ||
25 | # BLUETOOTH | ||
26 | BLUETOOTH_QUOTA_IN = 128 KiB | ||
27 | BLUETOOTH_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] | ||
2 | SERVERS = | ||
3 | |||
4 | [transport-udp] | ||
5 | BROADCAST = NO | ||
6 | |||
7 | [peerinfo] | ||
8 | USE_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 | */ | ||
47 | struct GNUNET_STATISTICS_Handle *GSA_stats; | ||
48 | |||
49 | /** | ||
50 | * Handle for ATS address component | ||
51 | */ | ||
52 | struct 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 | */ | ||
168 | struct 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 | */ | ||
179 | struct 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 | */ | ||
286 | struct 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 | */ | ||
308 | static struct PerfHandle ph; | ||
309 | |||
310 | /** | ||
311 | * Return value | ||
312 | */ | ||
313 | static int ret; | ||
314 | |||
315 | |||
316 | /** | ||
317 | * Do shutdown | ||
318 | */ | ||
319 | static void | ||
320 | end_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 | */ | ||
342 | static void | ||
343 | perf_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 | */ | ||
358 | static void | ||
359 | perf_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 | |||
401 | static void | ||
402 | bandwidth_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 | |||
420 | static const double * | ||
421 | get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id) | ||
422 | { | ||
423 | return GAS_preference_get_by_peer (NULL, id); | ||
424 | } | ||
425 | |||
426 | |||
427 | static void | ||
428 | perf_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 | |||
454 | struct DUA_Ctx | ||
455 | { | ||
456 | int r; | ||
457 | int c_cur_a; | ||
458 | }; | ||
459 | |||
460 | |||
461 | static int | ||
462 | do_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 | */ | ||
483 | static void | ||
484 | perf_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 | */ | ||
541 | static struct ATS_Address * | ||
542 | perf_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 | */ | ||
561 | static void | ||
562 | solver_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 | */ | ||
828 | static void | ||
829 | evaluate (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 | |||
903 | static unsigned int | ||
904 | get_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 | */ | ||
915 | static void | ||
916 | write_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 | |||
1103 | static int | ||
1104 | do_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 | */ | ||
1127 | static void | ||
1128 | perf_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 | |||
1254 | static void | ||
1255 | run (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 | */ | ||
1451 | int | ||
1452 | main (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 | ||
3 | UNSPECIFIED_QUOTA_IN = 1000000 | ||
4 | UNSPECIFIED_QUOTA_OUT = 1000000 | ||
5 | # LOOPBACK | ||
6 | LOOPBACK_QUOTA_IN = 10000000 | ||
7 | LOOPBACK_QUOTA_OUT = 10000000 | ||
8 | # LAN | ||
9 | LAN_QUOTA_IN = 10000000 | ||
10 | LAN_QUOTA_OUT = 10000000 | ||
11 | # WAN | ||
12 | WAN_QUOTA_IN = 10000000 | ||
13 | WAN_QUOTA_OUT = 10000000 | ||
14 | # WLAN | ||
15 | WLAN_QUOTA_IN = 10000000 | ||
16 | WLAN_QUOTA_OUT = 10000000 | ||
17 | # BLUETOOTH | ||
18 | BLUETOOTH_QUOTA_IN = 10000000 | ||
19 | BLUETOOTH_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 | ||
25 | PROP_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 | ||
28 | PROP_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 | */ | ||
61 | struct 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 | */ | ||
103 | struct 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 | */ | ||
160 | struct 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 | */ | ||
207 | static int | ||
208 | is_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 | */ | ||
236 | static int | ||
237 | all_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 | */ | ||
261 | static void | ||
262 | distribute_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 | */ | ||
393 | static void | ||
394 | propagate_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 | */ | ||
420 | static void | ||
421 | distribute_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 | */ | ||
494 | struct 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 | */ | ||
519 | static int | ||
520 | find_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 | */ | ||
632 | struct ATS_Address * | ||
633 | get_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 | */ | ||
655 | static void | ||
656 | address_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 | */ | ||
683 | static int | ||
684 | get_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 | */ | ||
706 | static struct ATS_Address * | ||
707 | get_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 | */ | ||
731 | static void | ||
732 | update_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 | */ | ||
856 | static void | ||
857 | GAS_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 | */ | ||
881 | static void | ||
882 | GAS_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 | */ | ||
899 | static void | ||
900 | GAS_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 | */ | ||
918 | static void | ||
919 | GAS_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 | */ | ||
941 | static void | ||
942 | GAS_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 | */ | ||
958 | static void | ||
959 | GAS_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 | */ | ||
989 | static void | ||
990 | GAS_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 | */ | ||
1008 | static void | ||
1009 | GAS_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 | */ | ||
1060 | static void | ||
1061 | GAS_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 | */ | ||
1110 | void * | ||
1111 | libgnunet_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 | */ | ||
1210 | void * | ||
1211 | libgnunet_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 | */ | ||
36 | static 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 | |||
285 | int | ||
286 | main (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] | ||
4 | GNUNET_TEST_HOME = $GNUNET_TMP/test-ats-api-scheduling/ | ||
5 | |||
6 | [ats] | ||
7 | # Enable MLP mode (default: NO) | ||
8 | #MODE = ril | ||
9 | MODE = mlp | ||
10 | # Network specific inbound/outbound quotas | ||
11 | # UNSPECIFIED | ||
12 | UNSPECIFIED_QUOTA_IN = 64 KiB | ||
13 | UNSPECIFIED_QUOTA_OUT = 64 KiB | ||
14 | # LOOPBACK | ||
15 | LOOPBACK_QUOTA_IN = unlimited | ||
16 | LOOPBACK_QUOTA_OUT = unlimited | ||
17 | # LAN | ||
18 | LAN_QUOTA_IN = unlimited | ||
19 | LAN_QUOTA_OUT = unlimited | ||
20 | # WAN | ||
21 | WAN_QUOTA_IN = 64 KiB | ||
22 | WAN_QUOTA_OUT = 64 KiB | ||
23 | # WLAN | ||
24 | WLAN_QUOTA_IN = 512 | ||
25 | WLAN_QUOTA_OUT = 512 | ||
26 | |||
27 | # ATS extended options | ||
28 | DUMP_MLP = NO | ||
29 | DUMP_SOLUTION = NO | ||
30 | DUMP_OVERWRITE = NO | ||
31 | DUMP_MIN_PEERS = 0 | ||
32 | DUMP_MIN_ADDRS = 0 | ||
33 | DUMP_OVERWRITE = NO | ||
34 | ATS_MIN_INTERVAL = 15000 | ||
35 | ATS_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] | ||
4 | GNUNET_TEST_HOME = $GNUNET_TMP/test-ats-api-scheduling/ | ||
5 | |||
6 | [ats] | ||
7 | PREFIX = ./test_delay -t 10 -- | ||
8 | # Enable MLP mode (default: NO) | ||
9 | #MODE = ril | ||
10 | MODE = mlp | ||
11 | # Network specific inbound/outbound quotas | ||
12 | # UNSPECIFIED | ||
13 | UNSPECIFIED_QUOTA_IN = 64 KiB | ||
14 | UNSPECIFIED_QUOTA_OUT = 64 KiB | ||
15 | # LOOPBACK | ||
16 | LOOPBACK_QUOTA_IN = unlimited | ||
17 | LOOPBACK_QUOTA_OUT = unlimited | ||
18 | # LAN | ||
19 | LAN_QUOTA_IN = unlimited | ||
20 | LAN_QUOTA_OUT = unlimited | ||
21 | # WAN | ||
22 | WAN_QUOTA_IN = 64 KiB | ||
23 | WAN_QUOTA_OUT = 64 KiB | ||
24 | # WLAN | ||
25 | WLAN_QUOTA_IN = 512 | ||
26 | WLAN_QUOTA_OUT = 512 | ||
27 | |||
28 | # ATS extended options | ||
29 | DUMP_MLP = NO | ||
30 | DUMP_SOLUTION = NO | ||
31 | DUMP_OVERWRITE = NO | ||
32 | DUMP_MIN_PEERS = 0 | ||
33 | DUMP_MIN_ADDRS = 0 | ||
34 | DUMP_OVERWRITE = NO | ||
35 | ATS_MIN_INTERVAL = 15000 | ||
36 | ATS_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] | ||
4 | GNUNET_TEST_HOME = $GNUNET_TMP/test-ats-proportional/ | ||
5 | |||
6 | [ats] | ||
7 | # Enable PROPORTIONAL mode (default: NO) | ||
8 | MODE = proportional | ||
9 | # Network specific inbound/outbound quotas | ||
10 | # UNSPECIFIED | ||
11 | UNSPECIFIED_QUOTA_IN = unlimited | ||
12 | UNSPECIFIED_QUOTA_OUT = unlimited | ||
13 | # LOOPBACK | ||
14 | LOOPBACK_QUOTA_IN = unlimited | ||
15 | LOOPBACK_QUOTA_OUT = unlimited | ||
16 | # LAN | ||
17 | LAN_QUOTA_IN = unlimited | ||
18 | LAN_QUOTA_OUT = unlimited | ||
19 | # WAN | ||
20 | WAN_QUOTA_IN = 5 MiB | ||
21 | WAN_QUOTA_OUT = 5 MiB | ||
22 | # WLAN | ||
23 | WLAN_QUOTA_IN = 4096 | ||
24 | WLAN_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 | */ | ||
34 | struct 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 | */ | ||
66 | struct 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 | */ | ||
98 | static struct GNUNET_ATS_SchedulingHandle *sched_ats; | ||
99 | |||
100 | /** | ||
101 | * Connectivity handle | ||
102 | */ | ||
103 | static struct GNUNET_ATS_ConnectivityHandle *con_ats; | ||
104 | |||
105 | /** | ||
106 | * Performance handle | ||
107 | */ | ||
108 | static struct GNUNET_ATS_PerformanceHandle *perf_ats; | ||
109 | |||
110 | /** | ||
111 | * Handle for the interpreter task. | ||
112 | */ | ||
113 | static 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 | */ | ||
119 | static 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 | */ | ||
126 | static struct GNUNET_CONTAINER_MultiPeerMap *p2aid; | ||
127 | |||
128 | /** | ||
129 | * Global timeout for the test. | ||
130 | */ | ||
131 | static struct GNUNET_TIME_Relative TIMEOUT; | ||
132 | |||
133 | /** | ||
134 | * Return value from #main(). | ||
135 | */ | ||
136 | static int ret; | ||
137 | |||
138 | /** | ||
139 | * Current global command offset into the #commands array. | ||
140 | */ | ||
141 | static unsigned int off; | ||
142 | |||
143 | /** | ||
144 | * Commands for the current test. | ||
145 | */ | ||
146 | static 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 | */ | ||
157 | static int | ||
158 | free_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 | */ | ||
182 | static int | ||
183 | free_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 | */ | ||
205 | static struct AddressSuggestData * | ||
206 | find_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 | */ | ||
216 | struct 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 | */ | ||
238 | static int | ||
239 | match_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 | */ | ||
262 | static struct AddressInformationData * | ||
263 | find_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 | */ | ||
282 | static void | ||
283 | end (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 | */ | ||
336 | static void | ||
337 | interpreter (void *cls); | ||
338 | |||
339 | |||
340 | /** | ||
341 | * Run the interpreter next. | ||
342 | */ | ||
343 | static void | ||
344 | run_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 | */ | ||
359 | static void | ||
360 | make_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 | */ | ||
380 | static struct GNUNET_HELLO_Address * | ||
381 | make_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 | */ | ||
402 | struct 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 | */ | ||
417 | static struct GNUNET_ATS_Session * | ||
418 | make_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 | */ | ||
439 | static struct Command * | ||
440 | find_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 | */ | ||
471 | static void | ||
472 | info_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 | */ | ||
532 | static void | ||
533 | reservation_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 | */ | ||
593 | static void | ||
594 | interpreter (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 | */ | ||
906 | static void | ||
907 | address_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 | */ | ||
976 | static void | ||
977 | address_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 | */ | ||
1025 | static void | ||
1026 | run (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 | */ | ||
1076 | int | ||
1077 | TEST_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 | */ | ||
36 | enum 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 | */ | ||
132 | struct 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 | */ | ||
174 | struct 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 | */ | ||
187 | struct 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 | */ | ||
206 | struct 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 | */ | ||
218 | struct 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 | */ | ||
236 | struct 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 | */ | ||
249 | struct 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 | */ | ||
270 | struct 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 | */ | ||
287 | struct 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 | */ | ||
304 | struct 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 | */ | ||
316 | struct 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 | */ | ||
330 | struct 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 | */ | ||
349 | struct 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 | */ | ||
404 | struct 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 | */ | ||
435 | struct 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 | */ | ||
447 | struct 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 | */ | ||
506 | int | ||
507 | TEST_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 | */ | ||
36 | static 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 | |||
170 | int | ||
171 | main (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] | ||
4 | PREFIX = ./test_delay -t 10 -- | ||
5 | MODE = proportional | ||
6 | # UNSPECIFIED | ||
7 | UNSPECIFIED_QUOTA_IN = 64 KiB | ||
8 | UNSPECIFIED_QUOTA_OUT = 64 KiB | ||
9 | # LOOPBACK | ||
10 | LOOPBACK_QUOTA_IN = unlimited | ||
11 | LOOPBACK_QUOTA_OUT = unlimited | ||
12 | # LAN | ||
13 | LAN_QUOTA_IN = unlimited | ||
14 | LAN_QUOTA_OUT = unlimited | ||
15 | # WAN | ||
16 | WAN_QUOTA_IN = 64 KiB | ||
17 | WAN_QUOTA_OUT = 64 KiB | ||
18 | # WLAN | ||
19 | WLAN_QUOTA_IN = 512 | ||
20 | WLAN_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] | ||
4 | MODE = proportional | ||
5 | # UNSPECIFIED | ||
6 | UNSPECIFIED_QUOTA_IN = 64 KiB | ||
7 | UNSPECIFIED_QUOTA_OUT = 64 KiB | ||
8 | # LOOPBACK | ||
9 | LOOPBACK_QUOTA_IN = unlimited | ||
10 | LOOPBACK_QUOTA_OUT = unlimited | ||
11 | # LAN | ||
12 | LAN_QUOTA_IN = unlimited | ||
13 | LAN_QUOTA_OUT = unlimited | ||
14 | # WAN | ||
15 | WAN_QUOTA_IN = 64 KiB | ||
16 | WAN_QUOTA_OUT = 64 KiB | ||
17 | # WLAN | ||
18 | WLAN_QUOTA_IN = 512 | ||
19 | WLAN_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 | |||
3 | TEMP=$(getopt -o t: -- "$@") | ||
4 | |||
5 | if [ $? != 0 ] ; then | ||
6 | exit 1 | ||
7 | fi | ||
8 | |||
9 | eval set -- "$TEMP" | ||
10 | |||
11 | while 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 | ||
17 | done | ||
18 | exec "$@" | ||