diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2013-12-10 07:58:08 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2013-12-10 07:58:08 +0000 |
commit | efc7f31d917eca457bf2e22ebd70d06e4e21421c (patch) | |
tree | 817662ebc4c331c73353249b8cd36a7046c9586b /src/ats/plugin_ats_proportional.c | |
parent | 4c489827d1da9aea4ae763c4c16c79e02d7f37e8 (diff) | |
download | gnunet-efc7f31d917eca457bf2e22ebd70d06e4e21421c.tar.gz gnunet-efc7f31d917eca457bf2e22ebd70d06e4e21421c.zip |
renaming according to naming conventions
Diffstat (limited to 'src/ats/plugin_ats_proportional.c')
-rw-r--r-- | src/ats/plugin_ats_proportional.c | 1604 |
1 files changed, 1604 insertions, 0 deletions
diff --git a/src/ats/plugin_ats_proportional.c b/src/ats/plugin_ats_proportional.c new file mode 100644 index 000000000..79f4bc749 --- /dev/null +++ b/src/ats/plugin_ats_proportional.c | |||
@@ -0,0 +1,1604 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file ats/plugin_ats_proportional.c | ||
23 | * @brief ATS proportional solver | ||
24 | * @author Matthias Wachs | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #include "plugin_ats_proportional.h" | ||
28 | |||
29 | #define LOG(kind,...) GNUNET_log_from (kind, "ats-proportional",__VA_ARGS__) | ||
30 | |||
31 | |||
32 | /** | ||
33 | * | ||
34 | * NOTE: Do not change this documentation. This documentation is based | ||
35 | * on gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex | ||
36 | * use build_txt.sh to generate plaintext output | ||
37 | * | ||
38 | * ATS addresses : proportional solver | ||
39 | * | ||
40 | * The proportional solver ("proportional") distributes the available | ||
41 | * bandwidth fair over all the addresses influenced by the | ||
42 | * preference values. For each available network type an in- and | ||
43 | * outbound quota is configured and the bandwidth available in | ||
44 | * these networks is distributed over the addresses. The solver | ||
45 | * first assigns every addresses the minimum amount of bandwidth | ||
46 | * GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT and then distributes the | ||
47 | * remaining bandwidth available according to the preference | ||
48 | * values. For each peer only a single address gets bandwidth | ||
49 | * assigned and only one address marked as active. The most | ||
50 | * important functionality for the solver is implemented in: * | ||
51 | * find_address_it is an hashmap iterator returning the prefered | ||
52 | * address for an peer * update_quota_per_network distributes | ||
53 | * available bandwidth for a network over active addresses | ||
54 | * | ||
55 | * Changes to addresses automatically have an impact on the the | ||
56 | * bandwidth assigned to other addresses in the same network since | ||
57 | * the solver distributes the remaining bandwidth over the | ||
58 | * addresses in the network. When changes to the addresses occur, | ||
59 | * the solver first performs the changes, like adding or deleting | ||
60 | * addresses, and then updates bandwidth assignment for the | ||
61 | * affected network. Bandwidth assignment is only recalculated on | ||
62 | * demand when an address is requested by a client for a peer or | ||
63 | * when the addresses available have changed or an address changed | ||
64 | * the network it is located in. When the bandwidth assignment has | ||
65 | * changed the callback is called with the new bandwidth | ||
66 | * assignments. The bandwidth distribution for a network is | ||
67 | * recalculated due to: * address suggestion requests * address | ||
68 | * deletions * address switching networks during address update * | ||
69 | * preference changes | ||
70 | * | ||
71 | * 3.1 Data structures used | ||
72 | * | ||
73 | * For each ATS network (e.g. WAN, LAN, loopback) a struct Network | ||
74 | * is used to specify network related information as total adresses | ||
75 | * and active addresses in this network and the configured in- and | ||
76 | * outbound quota. Each network also contains a list of addresses | ||
77 | * added to the solver located in this network. The proportional | ||
78 | * solver uses the addresses' solver_information field to store the | ||
79 | * proportional network it belongs to for each address. | ||
80 | * | ||
81 | * 3.2 Initializing | ||
82 | * | ||
83 | * When the proportional solver is initialized the solver creates a | ||
84 | * new solver handle and initializes the network structures with | ||
85 | * the quotas passed from addresses and returns the handle solver. | ||
86 | * | ||
87 | * 3.3 Adding an address | ||
88 | * | ||
89 | * When a new address is added to the solver using s_add, a lookup | ||
90 | * for the network for this address is done and the address is | ||
91 | * enqueued in in the linked list of the network. | ||
92 | * | ||
93 | * 3.4 Updating an address | ||
94 | * | ||
95 | * The main purpose of address updates is to update the ATS | ||
96 | * information for addresse selection. Important for the proportional | ||
97 | * solver is when an address switches network it is located | ||
98 | * in. This is common because addresses added by transport's | ||
99 | * validation mechanism are commonly located in | ||
100 | * GNUNET_ATS_NET_UNSPECIFIED. Addresses in validation are located | ||
101 | * in this network type and only if a connection is successful on | ||
102 | * return of payload data transport switches to the real network | ||
103 | * the address is located in. When an address changes networks it | ||
104 | * is first of all removed from the old network using the solver | ||
105 | * API function GAS_proportional_address_delete and the network in | ||
106 | * the address struct is updated. A lookup for the respective new | ||
107 | * proportional network is done and stored in the addresse's | ||
108 | * solver_information field. Next the address is re-added to the | ||
109 | * solver using the solver API function | ||
110 | * GAS_proportional_address_add. If the address was marked as in | ||
111 | * active, the solver checks if bandwidth is available in the | ||
112 | * network and if yes sets the address to active and updates the | ||
113 | * bandwidth distribution in this network. If no bandwidth is | ||
114 | * available it sets the bandwidth for this address to 0 and tries | ||
115 | * to suggest an alternative address. If an alternative address was | ||
116 | * found, addresses' callback is called for this address. | ||
117 | * | ||
118 | * 3.5 Deleting an address | ||
119 | * | ||
120 | * When an address is removed from the solver, it removes the | ||
121 | * respective address from the network and if the address was | ||
122 | * marked as active, it updates the bandwidth distribution for this | ||
123 | * network. | ||
124 | * | ||
125 | * 3.6 Requesting addresses | ||
126 | * | ||
127 | * When an address is requested for a peer the solver performs a | ||
128 | * lookup for the peer entry in addresses address hashmap and | ||
129 | * selects the best address. The selection of the most suitable | ||
130 | * address is done in the find_address_it hashmap iterator | ||
131 | * described in detail in section 3.7. If no address is returned, | ||
132 | * no address can be suggested at the moment. If the address | ||
133 | * returned is marked as active, the solver can return this | ||
134 | * address. If the address is not marked as active, the solver | ||
135 | * checks if another address belongign to this peer is marked as | ||
136 | * active and marks the address as inactive, updates the bandwidth | ||
137 | * for this address to 0, call the bandwidth changed callback for | ||
138 | * this address due to the change and updates quota assignment for | ||
139 | * the addresse's network. the now in-active address is belonging | ||
140 | * to. The solver marks the new address as active and updates the | ||
141 | * bandwidth assignment for this network. | ||
142 | * | ||
143 | * 3.7 Choosing addresses | ||
144 | * | ||
145 | * Choosing the best possible address for suggestion is done by | ||
146 | * iterating over all addresses of a peer stored in addresses' | ||
147 | * hashmap and using the hashmap iterator find_address_it to select | ||
148 | * the best available address. Several checks are done when an | ||
149 | * address is selected. First if this address is currently blocked | ||
150 | * by addresses from being suggested. An address is blocked for the | ||
151 | * duration of ATS_BLOCKING_DELTA when it is suggested to | ||
152 | * transport. Next it is checked if at least | ||
153 | * GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT bytes bandwidth is available | ||
154 | * in the addresse's network, because suggesting an address without | ||
155 | * bandwidth does not make sense. This also ensures that all active | ||
156 | * addresses in this network get at least the minimum amount of | ||
157 | * bandwidth assigned. In the next step the solver ensures that for | ||
158 | * tcp connections inbound connections are prefered over outbound | ||
159 | * connections. In the next stet the solver ensures that | ||
160 | * connections are prefered in the following order: * connections | ||
161 | * are already established and have bandwidth assigned * | ||
162 | * connections with a shorter distance * connectes have a shorter | ||
163 | * latency | ||
164 | * | ||
165 | * 3.8 Changing preferences | ||
166 | * | ||
167 | * 3.9 Shutdown | ||
168 | * | ||
169 | * During shutdown all network entries and aging processes are | ||
170 | * destroyed and freed. | ||
171 | * | ||
172 | * | ||
173 | * OLD DOCUMENTATION | ||
174 | * | ||
175 | * This solver assigns in and outbound bandwidth equally for all | ||
176 | * addresses in specific network type (WAN, LAN) based on configured | ||
177 | * in and outbound quota for this network. | ||
178 | * | ||
179 | * The solver is notified by addresses about changes to the addresses | ||
180 | * and recalculates the bandwith assigned if required. The solver | ||
181 | * notifies addresses by calling the GAS_bandwidth_changed_cb | ||
182 | * callback. | ||
183 | * | ||
184 | * - Initialization | ||
185 | * | ||
186 | * | ||
187 | * | ||
188 | * | ||
189 | * For each peer only a single is selected and marked as "active" in the address | ||
190 | * struct. | ||
191 | * | ||
192 | * E.g.: | ||
193 | * | ||
194 | * You have the networks WAN and LAN and quotas | ||
195 | * WAN_TOTAL_IN, WAN_TOTAL_OUT | ||
196 | * LAN_TOTAL_IN, LAN_TOTAL_OUT | ||
197 | * | ||
198 | * If you have x addresses in the network segment LAN, the quotas are | ||
199 | * QUOTA_PER_ADDRESS = LAN_TOTAL_OUT / x | ||
200 | * | ||
201 | * Quotas are automatically recalculated and reported back when addresses are | ||
202 | * - requested | ||
203 | * | ||
204 | */ | ||
205 | |||
206 | #define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | ||
207 | #define PREF_AGING_FACTOR 0.95 | ||
208 | |||
209 | #define DEFAULT_REL_PREFERENCE 1.0 | ||
210 | #define DEFAULT_ABS_PREFERENCE 0.0 | ||
211 | #define MIN_UPDATE_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | ||
212 | |||
213 | /** | ||
214 | * A handle for the proportional solver | ||
215 | */ | ||
216 | struct GAS_PROPORTIONAL_Handle | ||
217 | { | ||
218 | struct GNUNET_ATS_PluginEnvironment *env; | ||
219 | |||
220 | /** | ||
221 | * Statistics handle | ||
222 | */ | ||
223 | struct GNUNET_STATISTICS_Handle *stats; | ||
224 | |||
225 | /** | ||
226 | * Hashmap containing all valid addresses | ||
227 | */ | ||
228 | const struct GNUNET_CONTAINER_MultiPeerMap *addresses; | ||
229 | |||
230 | /** | ||
231 | * Pending address requests | ||
232 | */ | ||
233 | struct GNUNET_CONTAINER_MultiPeerMap *requests; | ||
234 | |||
235 | /** | ||
236 | * Bandwidth changed callback | ||
237 | */ | ||
238 | GAS_bandwidth_changed_cb bw_changed; | ||
239 | |||
240 | /** | ||
241 | * Bandwidth changed callback cls | ||
242 | */ | ||
243 | void *bw_changed_cls; | ||
244 | |||
245 | /** | ||
246 | * ATS function to get preferences | ||
247 | */ | ||
248 | GAS_get_preferences get_preferences; | ||
249 | |||
250 | /** | ||
251 | * Closure for ATS function to get preferences | ||
252 | */ | ||
253 | void *get_preferences_cls; | ||
254 | |||
255 | /** | ||
256 | * ATS function to get properties | ||
257 | */ | ||
258 | GAS_get_properties get_properties; | ||
259 | |||
260 | /** | ||
261 | * Closure for ATS function to get properties | ||
262 | */ | ||
263 | void *get_properties_cls; | ||
264 | |||
265 | /** | ||
266 | * Bulk lock | ||
267 | */ | ||
268 | int bulk_lock; | ||
269 | |||
270 | /** | ||
271 | * Number of changes while solver was locked | ||
272 | */ | ||
273 | int bulk_requests; | ||
274 | |||
275 | /** | ||
276 | * Total number of addresses for solver | ||
277 | */ | ||
278 | unsigned int total_addresses; | ||
279 | |||
280 | /** | ||
281 | * Number of active addresses for solver | ||
282 | */ | ||
283 | unsigned int active_addresses; | ||
284 | |||
285 | /** | ||
286 | * Networks array | ||
287 | */ | ||
288 | struct Network *network_entries; | ||
289 | |||
290 | /** | ||
291 | * Number of networks | ||
292 | */ | ||
293 | unsigned int network_count; | ||
294 | |||
295 | }; | ||
296 | |||
297 | /** | ||
298 | * Representation of a network | ||
299 | */ | ||
300 | struct Network | ||
301 | { | ||
302 | /** | ||
303 | * ATS network type | ||
304 | */ | ||
305 | unsigned int type; | ||
306 | |||
307 | /** | ||
308 | * Network description | ||
309 | */ | ||
310 | char *desc; | ||
311 | |||
312 | /** | ||
313 | * Total inbound quota | ||
314 | * | ||
315 | */ | ||
316 | unsigned long long total_quota_in; | ||
317 | |||
318 | /** | ||
319 | * Total outbound quota | ||
320 | * | ||
321 | */ | ||
322 | unsigned long long total_quota_out; | ||
323 | |||
324 | /** | ||
325 | * Number of active addresses for this network | ||
326 | */ | ||
327 | unsigned int active_addresses; | ||
328 | |||
329 | /** | ||
330 | * Number of total addresses for this network | ||
331 | */ | ||
332 | unsigned int total_addresses; | ||
333 | |||
334 | /** | ||
335 | * String for statistics total addresses | ||
336 | */ | ||
337 | char *stat_total; | ||
338 | |||
339 | /** | ||
340 | * String for statistics active addresses | ||
341 | */ | ||
342 | char *stat_active; | ||
343 | |||
344 | struct AddressWrapper *head; | ||
345 | struct AddressWrapper *tail; | ||
346 | }; | ||
347 | |||
348 | /** | ||
349 | * Address information stored in the solver | ||
350 | */ | ||
351 | struct AddressSolverInformation | ||
352 | { | ||
353 | struct Network *network; | ||
354 | |||
355 | /** | ||
356 | * Inbound quota | ||
357 | * | ||
358 | */ | ||
359 | unsigned long long calculated_quota_in_NBO; | ||
360 | |||
361 | /** | ||
362 | * Outbound quota | ||
363 | * | ||
364 | */ | ||
365 | unsigned long long calculated_quota_out_NBO; | ||
366 | |||
367 | |||
368 | }; | ||
369 | |||
370 | /** | ||
371 | * Wrapper for addresses to store them in network's linked list | ||
372 | */ | ||
373 | struct AddressWrapper | ||
374 | { | ||
375 | /** | ||
376 | * Next in DLL | ||
377 | */ | ||
378 | struct AddressWrapper *next; | ||
379 | |||
380 | /** | ||
381 | * Previous in DLL | ||
382 | */ | ||
383 | struct AddressWrapper *prev; | ||
384 | |||
385 | /** | ||
386 | * The address | ||
387 | */ | ||
388 | struct ATS_Address *addr; | ||
389 | }; | ||
390 | |||
391 | /** | ||
392 | * Important solver functions | ||
393 | * --------------------------- | ||
394 | */ | ||
395 | |||
396 | void * | ||
397 | libgnunet_plugin_ats_proportional_init (void *cls) | ||
398 | { | ||
399 | struct GNUNET_ATS_PluginEnvironment *env = cls; | ||
400 | struct GAS_PROPORTIONAL_Handle *s; | ||
401 | struct Network * cur; | ||
402 | char * net_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; | ||
403 | int c; | ||
404 | |||
405 | GNUNET_assert (NULL != env); | ||
406 | GNUNET_assert(NULL != env->cfg); | ||
407 | GNUNET_assert(NULL != env->stats); | ||
408 | GNUNET_assert(NULL != env->bandwidth_changed_cb); | ||
409 | GNUNET_assert(NULL != env->get_preferences); | ||
410 | GNUNET_assert(NULL != env->get_property); | ||
411 | |||
412 | s = GNUNET_malloc (sizeof (struct GAS_PROPORTIONAL_Handle)); | ||
413 | s->env = env; | ||
414 | env->sf.s_add = &GAS_proportional_address_add; | ||
415 | env->sf.s_address_update_property = &GAS_proportional_address_property_changed; | ||
416 | env->sf.s_address_update_session = &GAS_proportional_address_session_changed; | ||
417 | env->sf.s_address_update_inuse = &GAS_proportional_address_inuse_changed; | ||
418 | env->sf.s_address_update_network = &GAS_proportional_address_change_network; | ||
419 | env->sf.s_get = &GAS_proportional_get_preferred_address; | ||
420 | env->sf.s_get_stop = &GAS_proportional_stop_get_preferred_address; | ||
421 | env->sf.s_pref = &GAS_proportional_address_change_preference; | ||
422 | env->sf.s_feedback = &GAS_proportional_address_preference_feedback; | ||
423 | env->sf.s_del = &GAS_proportional_address_delete; | ||
424 | env->sf.s_bulk_start = &GAS_proportional_bulk_start; | ||
425 | env->sf.s_bulk_stop = &GAS_proportional_bulk_stop; | ||
426 | |||
427 | s->stats = (struct GNUNET_STATISTICS_Handle *) env->stats; | ||
428 | s->bw_changed = env->bandwidth_changed_cb; | ||
429 | s->bw_changed_cls = env->bw_changed_cb_cls; | ||
430 | s->get_preferences = env->get_preferences; | ||
431 | s->get_preferences_cls = env->get_preference_cls; | ||
432 | s->get_properties = env->get_property; | ||
433 | s->get_properties_cls = env->get_property_cls; | ||
434 | s->network_count = env->network_count; | ||
435 | s->network_entries = GNUNET_malloc (env->network_count * sizeof (struct Network)); | ||
436 | |||
437 | /* Init */ | ||
438 | s->active_addresses = 0; | ||
439 | s->total_addresses = 0; | ||
440 | s->bulk_lock = GNUNET_NO; | ||
441 | s->addresses = env->addresses; | ||
442 | s->requests = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
443 | |||
444 | for (c = 0; c < env->network_count; c++) | ||
445 | { | ||
446 | cur = &s->network_entries[c]; | ||
447 | cur->total_addresses = 0; | ||
448 | cur->active_addresses = 0; | ||
449 | cur->type = env->networks[c]; | ||
450 | cur->total_quota_in = env->in_quota[c]; | ||
451 | cur->total_quota_out = env->out_quota[c]; | ||
452 | cur->desc = net_str[c]; | ||
453 | GNUNET_asprintf (&cur->stat_total, | ||
454 | "# ATS addresses %s total", cur->desc); | ||
455 | GNUNET_asprintf (&cur->stat_active, | ||
456 | "# ATS active addresses %s total", cur->desc); | ||
457 | LOG (GNUNET_ERROR_TYPE_INFO, "Added network %u `%s' %p\n", c, cur->desc, s); | ||
458 | } | ||
459 | return s; | ||
460 | } | ||
461 | |||
462 | void * | ||
463 | libgnunet_plugin_ats_proportional_done (void *cls) | ||
464 | { | ||
465 | struct GAS_PROPORTIONAL_Handle *s = cls; | ||
466 | struct AddressWrapper *cur; | ||
467 | struct AddressWrapper *next; | ||
468 | int c; | ||
469 | GNUNET_assert(s != NULL); | ||
470 | for (c = 0; c < s->network_count; c++) | ||
471 | { | ||
472 | if (s->network_entries[c].total_addresses > 0) | ||
473 | { | ||
474 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
475 | "Had %u addresses for network `%s' not deleted during shutdown\n", | ||
476 | s->network_entries[c].total_addresses, s->network_entries[c].desc); | ||
477 | GNUNET_break(0); | ||
478 | } | ||
479 | |||
480 | if (s->network_entries[c].active_addresses > 0) | ||
481 | { | ||
482 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
483 | "Had %u active addresses for network `%s' not deleted during shutdown\n", | ||
484 | s->network_entries[c].active_addresses, s->network_entries[c].desc); | ||
485 | GNUNET_break(0); | ||
486 | } | ||
487 | |||
488 | next = s->network_entries[c].head; | ||
489 | while (NULL != (cur = next)) | ||
490 | { | ||
491 | next = cur->next; | ||
492 | GNUNET_CONTAINER_DLL_remove(s->network_entries[c].head, | ||
493 | s->network_entries[c].tail, cur); | ||
494 | GNUNET_free_non_null (cur->addr->solver_information); | ||
495 | GNUNET_free(cur); | ||
496 | } | ||
497 | GNUNET_free(s->network_entries[c].stat_total); | ||
498 | GNUNET_free(s->network_entries[c].stat_active); | ||
499 | } | ||
500 | if (s->total_addresses > 0) | ||
501 | { | ||
502 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
503 | "Had %u addresses not deleted during shutdown\n", s->total_addresses); | ||
504 | GNUNET_break(0); | ||
505 | } | ||
506 | if (s->active_addresses > 0) | ||
507 | { | ||
508 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
509 | "Had %u active addresses not deleted during shutdown\n", | ||
510 | s->active_addresses); | ||
511 | GNUNET_break (0); | ||
512 | } | ||
513 | GNUNET_free (s->network_entries); | ||
514 | GNUNET_CONTAINER_multipeermap_destroy (s->requests); | ||
515 | GNUNET_free (s); | ||
516 | return NULL; | ||
517 | } | ||
518 | |||
519 | |||
520 | /** | ||
521 | * Test if bandwidth is available in this network to add an additional address | ||
522 | * | ||
523 | * @param net the network type to update | ||
524 | * @return GNUNET_YES or GNUNET_NO | ||
525 | */ | ||
526 | static int | ||
527 | is_bandwidth_available_in_network (struct Network *net) | ||
528 | { | ||
529 | GNUNET_assert(NULL != net); | ||
530 | unsigned int na = net->active_addresses + 1; | ||
531 | uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); | ||
532 | if (((net->total_quota_in / na) > min_bw) | ||
533 | && ((net->total_quota_out / na) > min_bw)) | ||
534 | { | ||
535 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
536 | "Enough bandwidth available for %u active addresses in network `%s'\n", | ||
537 | na, net->desc); | ||
538 | |||
539 | return GNUNET_YES; | ||
540 | } | ||
541 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
542 | "Not enough bandwidth available for %u active addresses in network `%s'\n", | ||
543 | na, net->desc); | ||
544 | return GNUNET_NO; | ||
545 | } | ||
546 | |||
547 | /** | ||
548 | * Update bandwidth assigned to peers in this network | ||
549 | * | ||
550 | * @param s the solver handle | ||
551 | * @param net the network type to update | ||
552 | * @param address_except address excluded from notification, since we suggest | ||
553 | * this address | ||
554 | */ | ||
555 | static void | ||
556 | distribute_bandwidth (struct GAS_PROPORTIONAL_Handle *s, | ||
557 | struct Network *net, struct ATS_Address *address_except) | ||
558 | { | ||
559 | struct AddressSolverInformation *asi; | ||
560 | struct AddressWrapper *cur; | ||
561 | |||
562 | unsigned long long remaining_quota_in = 0; | ||
563 | unsigned long long quota_out_used = 0; | ||
564 | unsigned long long remaining_quota_out = 0; | ||
565 | unsigned long long quota_in_used = 0; | ||
566 | uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); | ||
567 | double peer_prefs; | ||
568 | double total_prefs; /* Important: has to be double not float due to precision */ | ||
569 | double cur_pref; /* Important: has to be double not float due to precision */ | ||
570 | const double *t = NULL; /* Important: has to be double not float due to precision */ | ||
571 | int c; | ||
572 | unsigned long long assigned_quota_in = 0; | ||
573 | unsigned long long assigned_quota_out = 0; | ||
574 | |||
575 | |||
576 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
577 | "Recalculate quota for network type `%s' for %u addresses (in/out): %llu/%llu \n", | ||
578 | net->desc, net->active_addresses, net->total_quota_in, | ||
579 | net->total_quota_in); | ||
580 | |||
581 | if (net->active_addresses == 0) | ||
582 | return; /* no addresses to update */ | ||
583 | |||
584 | /* Idea | ||
585 | * Assign every peer in network minimum Bandwidth | ||
586 | * Distribute bandwidth left according to preference | ||
587 | */ | ||
588 | |||
589 | if ((net->active_addresses * min_bw) > net->total_quota_in) | ||
590 | { | ||
591 | GNUNET_break(0); | ||
592 | return; | ||
593 | } | ||
594 | if ((net->active_addresses * min_bw) > net->total_quota_out) | ||
595 | { | ||
596 | GNUNET_break(0); | ||
597 | return; | ||
598 | } | ||
599 | |||
600 | remaining_quota_in = net->total_quota_in - (net->active_addresses * min_bw); | ||
601 | remaining_quota_out = net->total_quota_out - (net->active_addresses * min_bw); | ||
602 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Remaining bandwidth : (in/out): %llu/%llu \n", | ||
603 | remaining_quota_in, remaining_quota_out); | ||
604 | total_prefs = 0.0; | ||
605 | for (cur = net->head; NULL != cur; cur = cur->next) | ||
606 | { | ||
607 | if (GNUNET_YES == cur->addr->active) | ||
608 | { | ||
609 | GNUNET_assert( | ||
610 | NULL != (t = s->get_preferences (s->get_preferences_cls, &cur->addr->peer))); | ||
611 | |||
612 | peer_prefs = 0.0; | ||
613 | for (c = 0; c < GNUNET_ATS_PreferenceCount; c++) | ||
614 | { | ||
615 | if (c != GNUNET_ATS_PREFERENCE_END) | ||
616 | { | ||
617 | //fprintf (stderr, "VALUE[%u] %s %.3f \n", c, GNUNET_i2s (&cur->addr->peer), t[c]); | ||
618 | peer_prefs += t[c]; | ||
619 | } | ||
620 | } | ||
621 | total_prefs += (peer_prefs / (GNUNET_ATS_PreferenceCount - 1)); | ||
622 | } | ||
623 | } | ||
624 | for (cur = net->head; NULL != cur; cur = cur->next) | ||
625 | { | ||
626 | if (GNUNET_YES == cur->addr->active) | ||
627 | { | ||
628 | cur_pref = 0.0; | ||
629 | GNUNET_assert( | ||
630 | NULL != (t = s->get_preferences (s->get_preferences_cls, &cur->addr->peer))); | ||
631 | |||
632 | for (c = 0; c < GNUNET_ATS_PreferenceCount; c++) | ||
633 | { | ||
634 | if (c != GNUNET_ATS_PREFERENCE_END) | ||
635 | cur_pref += t[c]; | ||
636 | } | ||
637 | cur_pref /= 2; | ||
638 | |||
639 | assigned_quota_in = min_bw | ||
640 | + ((cur_pref / total_prefs) * remaining_quota_in); | ||
641 | assigned_quota_out = min_bw | ||
642 | + ((cur_pref / total_prefs) * remaining_quota_out); | ||
643 | |||
644 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
645 | "New quota for peer `%s' with preference (cur/total) %.3f/%.3f (in/out): %llu / %llu\n", | ||
646 | GNUNET_i2s (&cur->addr->peer), cur_pref, total_prefs, | ||
647 | assigned_quota_in, assigned_quota_out); | ||
648 | } | ||
649 | else | ||
650 | { | ||
651 | assigned_quota_in = 0; | ||
652 | assigned_quota_out = 0; | ||
653 | } | ||
654 | |||
655 | quota_in_used += assigned_quota_in; | ||
656 | quota_out_used += assigned_quota_out; | ||
657 | /* Prevent overflow due to rounding errors */ | ||
658 | if (assigned_quota_in > UINT32_MAX) | ||
659 | assigned_quota_in = UINT32_MAX; | ||
660 | if (assigned_quota_out > UINT32_MAX) | ||
661 | assigned_quota_out = UINT32_MAX; | ||
662 | |||
663 | /* Compare to current bandwidth assigned */ | ||
664 | asi = cur->addr->solver_information; | ||
665 | asi->calculated_quota_in_NBO = htonl (assigned_quota_in); | ||
666 | asi->calculated_quota_out_NBO = htonl (assigned_quota_out); | ||
667 | } | ||
668 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
669 | "Total bandwidth assigned is (in/out): %llu /%llu\n", quota_in_used, | ||
670 | quota_out_used); | ||
671 | if (quota_out_used > net->total_quota_out + 1) /* +1 is required due to rounding errors */ | ||
672 | { | ||
673 | LOG(GNUNET_ERROR_TYPE_ERROR, | ||
674 | "Total outbound bandwidth assigned is larger than allowed (used/allowed) for %u active addresses: %llu / %llu\n", | ||
675 | net->active_addresses, quota_out_used, net->total_quota_out); | ||
676 | } | ||
677 | if (quota_in_used > net->total_quota_in + 1) /* +1 is required due to rounding errors */ | ||
678 | { | ||
679 | LOG(GNUNET_ERROR_TYPE_ERROR, | ||
680 | "Total inbound bandwidth assigned is larger than allowed (used/allowed) for %u active addresses: %llu / %llu\n", | ||
681 | net->active_addresses, quota_in_used, net->total_quota_in); | ||
682 | } | ||
683 | } | ||
684 | |||
685 | struct FindBestAddressCtx | ||
686 | { | ||
687 | struct GAS_PROPORTIONAL_Handle *s; | ||
688 | struct ATS_Address *best; | ||
689 | }; | ||
690 | |||
691 | static int | ||
692 | find_property_index (uint32_t type) | ||
693 | { | ||
694 | int existing_types[] = GNUNET_ATS_QualityProperties; | ||
695 | int c; | ||
696 | for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++) | ||
697 | if (existing_types[c] == type) | ||
698 | return c; | ||
699 | return GNUNET_SYSERR; | ||
700 | } | ||
701 | |||
702 | /** | ||
703 | * Find a "good" address to use for a peer by iterating over the addresses for this peer. | ||
704 | * If we already have an existing address, we stick to it. | ||
705 | * Otherwise, we pick by lowest distance and then by lowest latency. | ||
706 | * | ||
707 | * @param cls the 'struct ATS_Address**' where we store the result | ||
708 | * @param key unused | ||
709 | * @param value another 'struct ATS_Address*' to consider using | ||
710 | * @return GNUNET_OK (continue to iterate) | ||
711 | */ | ||
712 | static int | ||
713 | find_best_address_it (void *cls, | ||
714 | const struct GNUNET_PeerIdentity *key, | ||
715 | void *value) | ||
716 | { | ||
717 | struct FindBestAddressCtx *fba_ctx = (struct FindBestAddressCtx *) cls; | ||
718 | struct ATS_Address *current = (struct ATS_Address *) value; | ||
719 | struct GNUNET_TIME_Absolute now; | ||
720 | struct AddressSolverInformation *asi; | ||
721 | const double *norm_prop_cur; | ||
722 | const double *norm_prop_prev; | ||
723 | int index; | ||
724 | |||
725 | asi = current->solver_information; | ||
726 | now = GNUNET_TIME_absolute_get (); | ||
727 | |||
728 | if (current->blocked_until.abs_value_us | ||
729 | == GNUNET_TIME_absolute_max (now, current->blocked_until).abs_value_us) | ||
730 | { | ||
731 | /* This address is blocked for suggestion */ | ||
732 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Address %p blocked for suggestion for %s \n", | ||
733 | current, | ||
734 | GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_difference (now, current->blocked_until), GNUNET_YES)); | ||
735 | return GNUNET_OK; | ||
736 | } | ||
737 | if (GNUNET_NO == is_bandwidth_available_in_network (asi->network)) | ||
738 | return GNUNET_OK; /* There's no bandwidth available in this network */ | ||
739 | if (NULL != fba_ctx->best) | ||
740 | { | ||
741 | GNUNET_assert(NULL != fba_ctx->best->plugin); | ||
742 | GNUNET_assert(NULL != current->plugin); | ||
743 | if (0 == strcmp (fba_ctx->best->plugin, current->plugin)) | ||
744 | { | ||
745 | if ((0 != fba_ctx->best->addr_len) && (0 == current->addr_len)) | ||
746 | { | ||
747 | /* saved address was an outbound address, but we have an inbound address */ | ||
748 | fba_ctx->best = current; | ||
749 | return GNUNET_OK; | ||
750 | } | ||
751 | if (0 == fba_ctx->best->addr_len) | ||
752 | { | ||
753 | /* saved address was an inbound address, so do not overwrite */ | ||
754 | return GNUNET_OK; | ||
755 | } | ||
756 | } | ||
757 | } | ||
758 | if (NULL == fba_ctx->best) | ||
759 | { | ||
760 | fba_ctx->best = current; | ||
761 | return GNUNET_OK; | ||
762 | } | ||
763 | if ((ntohl (fba_ctx->best->assigned_bw_in.value__) == 0) | ||
764 | && (ntohl (current->assigned_bw_in.value__) > 0)) | ||
765 | { | ||
766 | /* stick to existing connection */ | ||
767 | fba_ctx->best = current; | ||
768 | return GNUNET_OK; | ||
769 | } | ||
770 | |||
771 | norm_prop_cur = fba_ctx->s->get_properties (fba_ctx->s->get_properties_cls, | ||
772 | (const struct ATS_Address *) current); | ||
773 | norm_prop_prev = fba_ctx->s->get_properties (fba_ctx->s->get_properties_cls, | ||
774 | (const struct ATS_Address *) fba_ctx->best); | ||
775 | /* | ||
776 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s previous %.2f current %.2f\n", | ||
777 | "DISTANCE", norm_prop_cur[1], norm_prop_cur[1]); | ||
778 | */ | ||
779 | index = find_property_index (GNUNET_ATS_QUALITY_NET_DISTANCE); | ||
780 | if (GNUNET_SYSERR == index) | ||
781 | { | ||
782 | GNUNET_break(0); | ||
783 | return GNUNET_OK; | ||
784 | } | ||
785 | if (norm_prop_cur[index] < norm_prop_prev[index]) | ||
786 | { | ||
787 | /* user shorter distance */ | ||
788 | fba_ctx->best = current; | ||
789 | return GNUNET_OK; | ||
790 | } | ||
791 | /* | ||
792 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s previous %.2f current %.2f\n", | ||
793 | "DELAY", norm_prop_cur[1], norm_prop_cur[1]); | ||
794 | */ | ||
795 | index = find_property_index (GNUNET_ATS_QUALITY_NET_DELAY); | ||
796 | if (GNUNET_SYSERR == index) | ||
797 | { | ||
798 | GNUNET_break(0); | ||
799 | return GNUNET_OK; | ||
800 | } | ||
801 | if (norm_prop_cur[index] < norm_prop_prev[index]) | ||
802 | { | ||
803 | /* user shorter delay */ | ||
804 | fba_ctx->best = current; | ||
805 | return GNUNET_OK; | ||
806 | } | ||
807 | |||
808 | /* don't care */ | ||
809 | return GNUNET_OK; | ||
810 | } | ||
811 | |||
812 | /** | ||
813 | * Helper functions | ||
814 | * --------------------------- | ||
815 | */ | ||
816 | static void | ||
817 | propagate_bandwidth (struct GAS_PROPORTIONAL_Handle *s, | ||
818 | struct Network *net, struct ATS_Address *address_except) | ||
819 | { | ||
820 | struct AddressWrapper *cur; | ||
821 | struct AddressSolverInformation *asi; | ||
822 | for (cur = net->head; NULL != cur; cur = cur->next) | ||
823 | { | ||
824 | asi = cur->addr->solver_information; | ||
825 | if ( (cur->addr->assigned_bw_in.value__ != asi->calculated_quota_in_NBO) || | ||
826 | (cur->addr->assigned_bw_out.value__ != asi->calculated_quota_out_NBO) ) | ||
827 | { | ||
828 | cur->addr->assigned_bw_in.value__ = asi->calculated_quota_in_NBO; | ||
829 | cur->addr->assigned_bw_out.value__ = asi->calculated_quota_in_NBO; | ||
830 | /* Notify on change */ | ||
831 | if ((GNUNET_YES == cur->addr->active) && (cur->addr != address_except)) | ||
832 | s->bw_changed (s->bw_changed_cls, cur->addr); | ||
833 | } | ||
834 | } | ||
835 | } | ||
836 | |||
837 | /** | ||
838 | * Distribibute bandwidth | ||
839 | * | ||
840 | * @param s the solver handle | ||
841 | * @param n the network, can be NULL for all network | ||
842 | * @param address_except do not notify for this address | ||
843 | */ | ||
844 | static void | ||
845 | distribute_bandwidth_in_network (struct GAS_PROPORTIONAL_Handle *s, | ||
846 | struct Network *n, struct ATS_Address *address_except) | ||
847 | { | ||
848 | if (GNUNET_YES == s->bulk_lock) | ||
849 | { | ||
850 | s->bulk_requests++; | ||
851 | return; | ||
852 | } | ||
853 | |||
854 | if (NULL != n) | ||
855 | { | ||
856 | if (NULL != s->env->info_cb) | ||
857 | s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_START, | ||
858 | GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE); | ||
859 | distribute_bandwidth(s, n, address_except); | ||
860 | if (NULL != s->env->info_cb) | ||
861 | s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_STOP, | ||
862 | GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE); | ||
863 | if (NULL != s->env->info_cb) | ||
864 | s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START, | ||
865 | GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE); | ||
866 | propagate_bandwidth(s, n, address_except); | ||
867 | if (NULL != s->env->info_cb) | ||
868 | s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP, | ||
869 | GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE); | ||
870 | } | ||
871 | else | ||
872 | { | ||
873 | int i; | ||
874 | if (NULL != s->env->info_cb) | ||
875 | s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_START, | ||
876 | GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL); | ||
877 | for (i = 0; i < s->network_count; i++) | ||
878 | distribute_bandwidth(s, &s->network_entries[i], NULL); | ||
879 | if (NULL != s->env->info_cb) | ||
880 | s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_STOP, | ||
881 | GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL); | ||
882 | if (NULL != s->env->info_cb) | ||
883 | s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START, | ||
884 | GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL); | ||
885 | for (i = 0; i < s->network_count; i++) | ||
886 | { | ||
887 | propagate_bandwidth(s, &s->network_entries[i], address_except); | ||
888 | } | ||
889 | if (NULL != s->env->info_cb) | ||
890 | s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP, | ||
891 | GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL); | ||
892 | } | ||
893 | } | ||
894 | |||
895 | /** | ||
896 | * Lookup network struct by type | ||
897 | * | ||
898 | * @param s the solver handle | ||
899 | * @param type the network type | ||
900 | * @return the network struct | ||
901 | */ | ||
902 | static struct Network * | ||
903 | get_network (struct GAS_PROPORTIONAL_Handle *s, uint32_t type) | ||
904 | { | ||
905 | int c; | ||
906 | for (c = 0; c < s->network_count; c++) | ||
907 | { | ||
908 | if (s->network_entries[c].type == type) | ||
909 | return &s->network_entries[c]; | ||
910 | } | ||
911 | return NULL ; | ||
912 | } | ||
913 | |||
914 | /** | ||
915 | * Hashmap Iterator to find current active address for peer | ||
916 | * | ||
917 | * @param cls last active address | ||
918 | * @param key peer's key | ||
919 | * @param value address to check | ||
920 | * @return #GNUNET_NO on double active address else #GNUNET_YES; | ||
921 | */ | ||
922 | static int | ||
923 | get_active_address_it (void *cls, | ||
924 | const struct GNUNET_PeerIdentity *key, | ||
925 | void *value) | ||
926 | { | ||
927 | struct ATS_Address **dest = cls; | ||
928 | struct ATS_Address *aa = (struct ATS_Address *) value; | ||
929 | |||
930 | if (GNUNET_YES == aa->active) | ||
931 | { | ||
932 | |||
933 | if (NULL != (*dest)) | ||
934 | { | ||
935 | /* should never happen */ | ||
936 | LOG(GNUNET_ERROR_TYPE_ERROR, "Multiple active addresses for peer `%s'\n", | ||
937 | GNUNET_i2s (&aa->peer)); | ||
938 | GNUNET_break(0); | ||
939 | return GNUNET_NO; | ||
940 | } | ||
941 | (*dest) = aa; | ||
942 | } | ||
943 | return GNUNET_OK; | ||
944 | } | ||
945 | |||
946 | /** | ||
947 | * Find current active address for peer | ||
948 | * | ||
949 | * @param solver the solver handle | ||
950 | * @param addresses the address set | ||
951 | * @param peer the peer | ||
952 | * @return active address or NULL | ||
953 | */ | ||
954 | static struct ATS_Address * | ||
955 | get_active_address (void *solver, | ||
956 | const struct GNUNET_CONTAINER_MultiPeerMap * addresses, | ||
957 | const struct GNUNET_PeerIdentity *peer) | ||
958 | { | ||
959 | struct ATS_Address * dest = NULL; | ||
960 | |||
961 | GNUNET_CONTAINER_multipeermap_get_multiple (addresses, peer, | ||
962 | &get_active_address_it, &dest); | ||
963 | return dest; | ||
964 | } | ||
965 | |||
966 | |||
967 | static void | ||
968 | addresse_increment (struct GAS_PROPORTIONAL_Handle *s, struct Network *net, | ||
969 | int total, int active) | ||
970 | { | ||
971 | if (GNUNET_YES == total) | ||
972 | { | ||
973 | s->total_addresses++; | ||
974 | net->total_addresses++; | ||
975 | GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", 1, GNUNET_NO); | ||
976 | GNUNET_STATISTICS_update (s->stats, net->stat_total, 1, GNUNET_NO); | ||
977 | } | ||
978 | if (GNUNET_YES == active) | ||
979 | { | ||
980 | net->active_addresses++; | ||
981 | s->active_addresses++; | ||
982 | GNUNET_STATISTICS_update (s->stats, "# ATS active addresses total", 1, | ||
983 | GNUNET_NO); | ||
984 | GNUNET_STATISTICS_update (s->stats, net->stat_active, 1, GNUNET_NO); | ||
985 | } | ||
986 | |||
987 | } | ||
988 | |||
989 | |||
990 | static int | ||
991 | addresse_decrement (struct GAS_PROPORTIONAL_Handle *s, struct Network *net, | ||
992 | int total, int active) | ||
993 | { | ||
994 | int res = GNUNET_OK; | ||
995 | if (GNUNET_YES == total) | ||
996 | { | ||
997 | if (s->total_addresses < 1) | ||
998 | { | ||
999 | GNUNET_break(0); | ||
1000 | res = GNUNET_SYSERR; | ||
1001 | } | ||
1002 | else | ||
1003 | { | ||
1004 | s->total_addresses--; | ||
1005 | GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", -1, | ||
1006 | GNUNET_NO); | ||
1007 | } | ||
1008 | if (net->total_addresses < 1) | ||
1009 | { | ||
1010 | GNUNET_break(0); | ||
1011 | res = GNUNET_SYSERR; | ||
1012 | } | ||
1013 | else | ||
1014 | { | ||
1015 | net->total_addresses--; | ||
1016 | GNUNET_STATISTICS_update (s->stats, net->stat_total, -1, GNUNET_NO); | ||
1017 | } | ||
1018 | } | ||
1019 | |||
1020 | if (GNUNET_YES == active) | ||
1021 | { | ||
1022 | if (net->active_addresses < 1) | ||
1023 | { | ||
1024 | GNUNET_break(0); | ||
1025 | res = GNUNET_SYSERR; | ||
1026 | } | ||
1027 | else | ||
1028 | { | ||
1029 | net->active_addresses--; | ||
1030 | GNUNET_STATISTICS_update (s->stats, net->stat_active, -1, GNUNET_NO); | ||
1031 | } | ||
1032 | if (s->active_addresses < 1) | ||
1033 | { | ||
1034 | GNUNET_break(0); | ||
1035 | res = GNUNET_SYSERR; | ||
1036 | } | ||
1037 | else | ||
1038 | { | ||
1039 | s->active_addresses--; | ||
1040 | GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", -1, | ||
1041 | GNUNET_NO); | ||
1042 | } | ||
1043 | } | ||
1044 | return res; | ||
1045 | } | ||
1046 | |||
1047 | /** | ||
1048 | * Solver API functions | ||
1049 | * --------------------------- | ||
1050 | */ | ||
1051 | |||
1052 | /** | ||
1053 | * Changes the preferences for a peer in the problem | ||
1054 | * | ||
1055 | * @param solver the solver handle | ||
1056 | * @param peer the peer to change the preference for | ||
1057 | * @param kind the kind to change the preference | ||
1058 | * @param pref_rel the normalized preference value for this kind over all clients | ||
1059 | */ | ||
1060 | void | ||
1061 | GAS_proportional_address_change_preference (void *solver, | ||
1062 | const struct GNUNET_PeerIdentity *peer, | ||
1063 | enum GNUNET_ATS_PreferenceKind kind, | ||
1064 | double pref_rel) | ||
1065 | { | ||
1066 | struct GAS_PROPORTIONAL_Handle *s = solver; | ||
1067 | GNUNET_assert(NULL != solver); | ||
1068 | GNUNET_assert(NULL != peer); | ||
1069 | |||
1070 | distribute_bandwidth_in_network (s, NULL, NULL); | ||
1071 | } | ||
1072 | |||
1073 | |||
1074 | /** | ||
1075 | * Get application feedback for a peer | ||
1076 | * | ||
1077 | * @param solver the solver handle | ||
1078 | * @param application the application | ||
1079 | * @param peer the peer to change the preference for | ||
1080 | * @param scope the time interval for this feedback: [now - scope .. now] | ||
1081 | * @param kind the kind to change the preference | ||
1082 | * @param score the score | ||
1083 | */ | ||
1084 | void | ||
1085 | GAS_proportional_address_preference_feedback (void *solver, void *application, | ||
1086 | const struct GNUNET_PeerIdentity *peer, | ||
1087 | const struct GNUNET_TIME_Relative scope, | ||
1088 | enum GNUNET_ATS_PreferenceKind kind, double score) | ||
1089 | { | ||
1090 | struct GAS_PROPORTIONAL_Handle *s = solver; | ||
1091 | GNUNET_assert(NULL != solver); | ||
1092 | GNUNET_assert(NULL != peer); | ||
1093 | |||
1094 | GNUNET_assert(NULL != s); | ||
1095 | GNUNET_break(0); | ||
1096 | } | ||
1097 | |||
1098 | /** | ||
1099 | * Get the preferred address for a specific peer | ||
1100 | * | ||
1101 | * @param solver the solver handle | ||
1102 | * @param peer the identity of the peer | ||
1103 | */ | ||
1104 | const struct ATS_Address * | ||
1105 | GAS_proportional_get_preferred_address (void *solver, | ||
1106 | const struct GNUNET_PeerIdentity *peer) | ||
1107 | { | ||
1108 | struct GAS_PROPORTIONAL_Handle *s = solver; | ||
1109 | struct Network *net_prev; | ||
1110 | struct Network *net_cur; | ||
1111 | struct ATS_Address *prev; | ||
1112 | struct FindBestAddressCtx fba_ctx; | ||
1113 | struct AddressSolverInformation *asi; | ||
1114 | struct AddressSolverInformation *asi_prev; | ||
1115 | |||
1116 | GNUNET_assert(s != NULL); | ||
1117 | GNUNET_assert(peer != NULL); | ||
1118 | |||
1119 | /* Add to list of pending requests */ | ||
1120 | if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (s->requests, | ||
1121 | peer)) | ||
1122 | { | ||
1123 | GNUNET_assert (GNUNET_OK == | ||
1124 | GNUNET_CONTAINER_multipeermap_put (s->requests, | ||
1125 | peer, NULL, | ||
1126 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1127 | } | ||
1128 | |||
1129 | /* Get address with: stick to current address, lower distance, lower latency */ | ||
1130 | fba_ctx.s = s; | ||
1131 | fba_ctx.best = NULL; | ||
1132 | |||
1133 | GNUNET_CONTAINER_multipeermap_get_multiple (s->addresses, peer, | ||
1134 | &find_best_address_it, &fba_ctx); | ||
1135 | if (NULL == fba_ctx.best) | ||
1136 | { | ||
1137 | LOG(GNUNET_ERROR_TYPE_INFO, "Cannot suggest address for peer `%s'\n", | ||
1138 | GNUNET_i2s (peer)); | ||
1139 | return NULL ; | ||
1140 | } | ||
1141 | |||
1142 | LOG(GNUNET_ERROR_TYPE_INFO, "Suggesting %s address %p for peer `%s'\n", | ||
1143 | (GNUNET_NO == fba_ctx.best->active) ? "inactive" : "active", fba_ctx.best, | ||
1144 | GNUNET_i2s (peer)); | ||
1145 | asi = fba_ctx.best->solver_information; | ||
1146 | net_cur = asi->network ; | ||
1147 | if (NULL == fba_ctx.best) | ||
1148 | { | ||
1149 | LOG(GNUNET_ERROR_TYPE_ERROR, | ||
1150 | "Trying to suggesting unknown address peer `%s'\n", GNUNET_i2s (peer)); | ||
1151 | GNUNET_break(0); | ||
1152 | return NULL ; | ||
1153 | } | ||
1154 | if (GNUNET_YES == fba_ctx.best->active) | ||
1155 | { | ||
1156 | /* This address was selected previously, so no need to update quotas */ | ||
1157 | return fba_ctx.best; | ||
1158 | } | ||
1159 | |||
1160 | /* This address was not active, so we have to: | ||
1161 | * | ||
1162 | * - mark previous active address as not active | ||
1163 | * - update quota for previous address network | ||
1164 | * - update quota for this address network | ||
1165 | */ | ||
1166 | prev = get_active_address (s, s->addresses, peer); | ||
1167 | if (NULL != prev) | ||
1168 | { | ||
1169 | asi_prev = prev->solver_information; | ||
1170 | net_prev = (struct Network *) asi_prev->network; | ||
1171 | prev->active = GNUNET_NO; /* No active any longer */ | ||
1172 | prev->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */ | ||
1173 | prev->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */ | ||
1174 | if (GNUNET_SYSERR == addresse_decrement (s, net_prev, GNUNET_NO, GNUNET_YES)) | ||
1175 | GNUNET_break(0); | ||
1176 | distribute_bandwidth_in_network (s, net_prev, NULL); | ||
1177 | } | ||
1178 | |||
1179 | if (GNUNET_NO == (is_bandwidth_available_in_network (net_cur))) | ||
1180 | { | ||
1181 | GNUNET_break(0); /* This should never happen*/ | ||
1182 | return NULL ; | ||
1183 | } | ||
1184 | |||
1185 | fba_ctx.best->active = GNUNET_YES; | ||
1186 | addresse_increment (s, net_cur, GNUNET_NO, GNUNET_YES); | ||
1187 | distribute_bandwidth_in_network (s, net_cur, fba_ctx.best); | ||
1188 | return fba_ctx.best; | ||
1189 | } | ||
1190 | |||
1191 | /** | ||
1192 | * Stop notifying about address and bandwidth changes for this peer | ||
1193 | * | ||
1194 | * @param solver the solver handle | ||
1195 | * @param peer the peer | ||
1196 | */ | ||
1197 | void | ||
1198 | GAS_proportional_stop_get_preferred_address (void *solver, | ||
1199 | const struct GNUNET_PeerIdentity *peer) | ||
1200 | { | ||
1201 | struct GAS_PROPORTIONAL_Handle *s = solver; | ||
1202 | struct ATS_Address *cur; | ||
1203 | struct AddressSolverInformation *asi; | ||
1204 | struct Network *cur_net; | ||
1205 | |||
1206 | if (GNUNET_YES | ||
1207 | == GNUNET_CONTAINER_multipeermap_contains (s->requests, | ||
1208 | peer)) | ||
1209 | GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (s->requests, peer, | ||
1210 | NULL)); | ||
1211 | |||
1212 | cur = get_active_address (s, | ||
1213 | s->addresses, peer); | ||
1214 | if (NULL != cur) | ||
1215 | { | ||
1216 | /* Disabling current address */ | ||
1217 | asi = cur->solver_information; | ||
1218 | cur_net = asi->network ; | ||
1219 | cur->active = GNUNET_NO; /* No active any longer */ | ||
1220 | cur->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */ | ||
1221 | cur->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */ | ||
1222 | if (GNUNET_SYSERR == addresse_decrement (s, cur_net, GNUNET_NO, GNUNET_YES)) | ||
1223 | GNUNET_break(0); | ||
1224 | distribute_bandwidth_in_network (s, cur_net, NULL ); | ||
1225 | } | ||
1226 | return; | ||
1227 | } | ||
1228 | |||
1229 | /** | ||
1230 | * Remove an address from the solver | ||
1231 | * | ||
1232 | * @param solver the solver handle | ||
1233 | * @param address the address to remove | ||
1234 | * @param session_only delete only session not whole address | ||
1235 | */ | ||
1236 | void | ||
1237 | GAS_proportional_address_delete (void *solver, struct ATS_Address *address, | ||
1238 | int session_only) | ||
1239 | { | ||
1240 | struct GAS_PROPORTIONAL_Handle *s = solver; | ||
1241 | struct Network *net; | ||
1242 | struct AddressWrapper *aw; | ||
1243 | struct AddressSolverInformation *asi; | ||
1244 | const struct ATS_Address *new_address; | ||
1245 | |||
1246 | |||
1247 | /* Remove an adress completely, we have to: | ||
1248 | * - Remove from specific network | ||
1249 | * - Decrease number of total addresses | ||
1250 | * - If active: | ||
1251 | * - decrease number of active addreses | ||
1252 | * - update quotas | ||
1253 | */ | ||
1254 | asi = address->solver_information; | ||
1255 | |||
1256 | if (NULL == asi) | ||
1257 | { | ||
1258 | GNUNET_break (0); | ||
1259 | return; | ||
1260 | } | ||
1261 | |||
1262 | net = asi->network; | ||
1263 | |||
1264 | if (GNUNET_NO == session_only) | ||
1265 | { | ||
1266 | LOG(GNUNET_ERROR_TYPE_INFO, | ||
1267 | "Deleting %s address %p for peer `%s' from network `%s' (total: %u/ active: %u)\n", | ||
1268 | (GNUNET_NO == address->active) ? "inactive" : "active", address, | ||
1269 | GNUNET_i2s (&address->peer), net->desc, net->total_addresses, | ||
1270 | net->active_addresses); | ||
1271 | |||
1272 | /* Remove address */ | ||
1273 | addresse_decrement (s, net, GNUNET_YES, GNUNET_NO); | ||
1274 | for (aw = net->head; NULL != aw; aw = aw->next) | ||
1275 | { | ||
1276 | if (aw->addr == address) | ||
1277 | break; | ||
1278 | } | ||
1279 | if (NULL == aw) | ||
1280 | { | ||
1281 | GNUNET_break(0); | ||
1282 | return; | ||
1283 | } | ||
1284 | GNUNET_CONTAINER_DLL_remove(net->head, net->tail, aw); | ||
1285 | GNUNET_free_non_null (aw->addr->solver_information); | ||
1286 | GNUNET_free(aw); | ||
1287 | } | ||
1288 | else | ||
1289 | { | ||
1290 | /* Remove session only: remove if active and update */ | ||
1291 | LOG(GNUNET_ERROR_TYPE_INFO, | ||
1292 | "Deleting %s session %p for peer `%s' from network `%s' (total: %u/ active: %u)\n", | ||
1293 | (GNUNET_NO == address->active) ? "inactive" : "active", address, | ||
1294 | GNUNET_i2s (&address->peer), net->desc, net->total_addresses, | ||
1295 | net->active_addresses); | ||
1296 | } | ||
1297 | |||
1298 | if (GNUNET_YES == address->active) | ||
1299 | { | ||
1300 | /* Address was active, remove from network and update quotas*/ | ||
1301 | address->active = GNUNET_NO; | ||
1302 | address->assigned_bw_in = BANDWIDTH_ZERO; | ||
1303 | address->assigned_bw_out = BANDWIDTH_ZERO; | ||
1304 | |||
1305 | if (GNUNET_SYSERR == addresse_decrement (s, net, GNUNET_NO, GNUNET_YES)) | ||
1306 | GNUNET_break(0); | ||
1307 | distribute_bandwidth_in_network (s, net, NULL); | ||
1308 | if (NULL == (new_address = GAS_proportional_get_preferred_address (s, &address->peer))) | ||
1309 | { | ||
1310 | /* No alternative address found, disconnect peer */ | ||
1311 | s->bw_changed (s->bw_changed_cls, address); | ||
1312 | } | ||
1313 | else | ||
1314 | { | ||
1315 | s->bw_changed (s->bw_changed_cls, (struct ATS_Address *) new_address); | ||
1316 | } | ||
1317 | } | ||
1318 | LOG(GNUNET_ERROR_TYPE_INFO, | ||
1319 | "After deleting address now total %u and active %u addresses in network `%s'\n", | ||
1320 | net->total_addresses, net->active_addresses, net->desc); | ||
1321 | |||
1322 | } | ||
1323 | |||
1324 | /** | ||
1325 | * Start a bulk operation | ||
1326 | * | ||
1327 | * @param solver the solver | ||
1328 | */ | ||
1329 | void | ||
1330 | GAS_proportional_bulk_start (void *solver) | ||
1331 | { | ||
1332 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Locking solver for bulk operation ...\n"); | ||
1333 | struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) solver; | ||
1334 | |||
1335 | GNUNET_assert(NULL != solver); | ||
1336 | s->bulk_lock++; | ||
1337 | } | ||
1338 | |||
1339 | |||
1340 | /** | ||
1341 | * Bulk operation done | ||
1342 | */ | ||
1343 | void | ||
1344 | GAS_proportional_bulk_stop (void *solver) | ||
1345 | { | ||
1346 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Unlocking solver from bulk operation ...\n"); | ||
1347 | |||
1348 | struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) solver; | ||
1349 | GNUNET_assert(NULL != solver); | ||
1350 | |||
1351 | if (s->bulk_lock < 1) | ||
1352 | { | ||
1353 | GNUNET_break(0); | ||
1354 | return; | ||
1355 | } | ||
1356 | s->bulk_lock--; | ||
1357 | if ((0 == s->bulk_lock) && (0 < s->bulk_requests)) | ||
1358 | { | ||
1359 | LOG(GNUNET_ERROR_TYPE_DEBUG, "No lock pending, recalculating\n"); | ||
1360 | distribute_bandwidth_in_network (s, NULL, NULL); | ||
1361 | s->bulk_requests = 0; | ||
1362 | } | ||
1363 | } | ||
1364 | |||
1365 | |||
1366 | /** | ||
1367 | * Add a new single address to a network | ||
1368 | * | ||
1369 | * @param solver the solver Handle | ||
1370 | * @param address the address to add | ||
1371 | * @param network network type of this address | ||
1372 | */ | ||
1373 | void | ||
1374 | GAS_proportional_address_add (void *solver, struct ATS_Address *address, | ||
1375 | uint32_t network); | ||
1376 | |||
1377 | /** | ||
1378 | * Transport properties for this address have changed | ||
1379 | * | ||
1380 | * @param solver solver handle | ||
1381 | * @param address the address | ||
1382 | * @param type the ATSI type in HBO | ||
1383 | * @param abs_value the absolute value of the property | ||
1384 | * @param rel_value the normalized value | ||
1385 | */ | ||
1386 | void | ||
1387 | GAS_proportional_address_property_changed (void *solver, | ||
1388 | struct ATS_Address *address, uint32_t type, uint32_t abs_value, | ||
1389 | double rel_value) | ||
1390 | { | ||
1391 | struct GAS_PROPORTIONAL_Handle *s; | ||
1392 | struct Network *n; | ||
1393 | struct AddressSolverInformation *asi; | ||
1394 | |||
1395 | GNUNET_assert(NULL != solver); | ||
1396 | GNUNET_assert(NULL != address); | ||
1397 | |||
1398 | s = (struct GAS_PROPORTIONAL_Handle *) solver; | ||
1399 | asi = address->solver_information; | ||
1400 | n = asi->network; | ||
1401 | |||
1402 | if (NULL == n) | ||
1403 | { | ||
1404 | GNUNET_break(0); | ||
1405 | return; | ||
1406 | } | ||
1407 | |||
1408 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
1409 | "Property `%s' for peer `%s' address %p changed to %.2f \n", | ||
1410 | GNUNET_ATS_print_property_type (type), GNUNET_i2s (&address->peer), | ||
1411 | address, rel_value); | ||
1412 | switch (type) | ||
1413 | { | ||
1414 | case GNUNET_ATS_UTILIZATION_OUT: | ||
1415 | case GNUNET_ATS_UTILIZATION_IN: | ||
1416 | case GNUNET_ATS_UTILIZATION_PAYLOAD_IN: | ||
1417 | case GNUNET_ATS_UTILIZATION_PAYLOAD_OUT: | ||
1418 | case GNUNET_ATS_QUALITY_NET_DELAY: | ||
1419 | case GNUNET_ATS_QUALITY_NET_DISTANCE: | ||
1420 | case GNUNET_ATS_COST_WAN: | ||
1421 | case GNUNET_ATS_COST_LAN: | ||
1422 | case GNUNET_ATS_COST_WLAN: | ||
1423 | distribute_bandwidth_in_network (s, n, NULL); | ||
1424 | break; | ||
1425 | } | ||
1426 | } | ||
1427 | |||
1428 | /** | ||
1429 | * Transport session for this address has changed | ||
1430 | * | ||
1431 | * NOTE: values in addresses are already updated | ||
1432 | * | ||
1433 | * @param solver solver handle | ||
1434 | * @param address the address | ||
1435 | * @param cur_session the current session | ||
1436 | * @param new_session the new session | ||
1437 | */ | ||
1438 | void | ||
1439 | GAS_proportional_address_session_changed (void *solver, | ||
1440 | struct ATS_Address *address, uint32_t cur_session, uint32_t new_session) | ||
1441 | { | ||
1442 | if (cur_session != new_session) | ||
1443 | { | ||
1444 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Session changed from %u to %u\n", cur_session, | ||
1445 | new_session); | ||
1446 | } | ||
1447 | } | ||
1448 | |||
1449 | /** | ||
1450 | * Usage for this address has changed | ||
1451 | * | ||
1452 | * NOTE: values in addresses are already updated | ||
1453 | * | ||
1454 | * @param solver solver handle | ||
1455 | * @param address the address | ||
1456 | * @param in_use usage state | ||
1457 | */ | ||
1458 | void | ||
1459 | GAS_proportional_address_inuse_changed (void *solver, | ||
1460 | struct ATS_Address *address, int in_use) | ||
1461 | { | ||
1462 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Usage changed to %s\n", | ||
1463 | (GNUNET_YES == in_use) ? "USED" : "UNUSED"); | ||
1464 | } | ||
1465 | |||
1466 | /** | ||
1467 | * Network scope for this address has changed | ||
1468 | * | ||
1469 | * NOTE: values in addresses are already updated | ||
1470 | * | ||
1471 | * @param solver solver handle | ||
1472 | * @param address the address | ||
1473 | * @param current_network the current network | ||
1474 | * @param new_network the new network | ||
1475 | */ | ||
1476 | void | ||
1477 | GAS_proportional_address_change_network (void *solver, | ||
1478 | struct ATS_Address *address, uint32_t current_network, uint32_t new_network) | ||
1479 | { | ||
1480 | struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) solver; | ||
1481 | struct AddressSolverInformation *asi; | ||
1482 | int save_active = GNUNET_NO; | ||
1483 | |||
1484 | struct Network *new_net = NULL; | ||
1485 | |||
1486 | if (current_network == new_network) | ||
1487 | { | ||
1488 | GNUNET_break(0); | ||
1489 | return; | ||
1490 | } | ||
1491 | |||
1492 | /* Network changed */ | ||
1493 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
1494 | "Network type changed, moving %s address from `%s' to `%s'\n", | ||
1495 | (GNUNET_YES == address->active) ? "active" : "inactive", | ||
1496 | GNUNET_ATS_print_network_type (current_network), | ||
1497 | GNUNET_ATS_print_network_type (new_network)); | ||
1498 | |||
1499 | save_active = address->active; | ||
1500 | |||
1501 | /* Disable and assign no bandwidth */ | ||
1502 | address->active = GNUNET_NO; | ||
1503 | address->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */ | ||
1504 | address->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */ | ||
1505 | |||
1506 | /* Remove from old network */ | ||
1507 | GAS_proportional_address_delete (solver, address, GNUNET_NO); | ||
1508 | |||
1509 | /* Set new network type */ | ||
1510 | if (NULL == (new_net = get_network (solver, new_network))) | ||
1511 | { | ||
1512 | /* Address changed to invalid network... */ | ||
1513 | LOG(GNUNET_ERROR_TYPE_ERROR, | ||
1514 | _("Invalid network type `%u' `%s': Disconnect!\n"), new_network, | ||
1515 | GNUNET_ATS_print_network_type (new_network)); | ||
1516 | |||
1517 | /* Find new address to suggest since no bandwidth in network*/ | ||
1518 | if (NULL == GAS_proportional_get_preferred_address (s, &address->peer)) | ||
1519 | { | ||
1520 | /* No alternative address found, disconnect peer */ | ||
1521 | s->bw_changed (s->bw_changed_cls, address); | ||
1522 | } | ||
1523 | return; | ||
1524 | } | ||
1525 | |||
1526 | /* Add to new network and update*/ | ||
1527 | asi = address->solver_information; | ||
1528 | asi->network = new_net; | ||
1529 | GAS_proportional_address_add (solver, address, new_network); | ||
1530 | if (GNUNET_YES == save_active) | ||
1531 | { | ||
1532 | /* check if bandwidth available in new network */ | ||
1533 | if (GNUNET_YES == (is_bandwidth_available_in_network (new_net))) | ||
1534 | { | ||
1535 | /* Assign bandwidth to updated address */ | ||
1536 | address->active = GNUNET_YES; | ||
1537 | addresse_increment (s, new_net, GNUNET_NO, GNUNET_YES); | ||
1538 | distribute_bandwidth_in_network (solver, new_net, NULL); | ||
1539 | } | ||
1540 | else | ||
1541 | { | ||
1542 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
1543 | "Not enough bandwidth in new network, suggesting alternative address ..\n"); | ||
1544 | /* Find new address to suggest since no bandwidth in network*/ | ||
1545 | if (NULL == GAS_proportional_get_preferred_address (s, &address->peer)) | ||
1546 | { | ||
1547 | /* No alternative address found, disconnect peer */ | ||
1548 | s->bw_changed (s->bw_changed_cls, address); | ||
1549 | } | ||
1550 | } | ||
1551 | } | ||
1552 | } | ||
1553 | |||
1554 | /** | ||
1555 | * Add a new single address to a network | ||
1556 | * | ||
1557 | * @param solver the solver Handle | ||
1558 | * @param address the address to add | ||
1559 | * @param network network type of this address | ||
1560 | */ | ||
1561 | void | ||
1562 | GAS_proportional_address_add (void *solver, struct ATS_Address *address, | ||
1563 | uint32_t network) | ||
1564 | { | ||
1565 | struct GAS_PROPORTIONAL_Handle *s = solver; | ||
1566 | struct Network *net = NULL; | ||
1567 | struct AddressWrapper *aw = NULL; | ||
1568 | struct AddressSolverInformation *asi; | ||
1569 | |||
1570 | GNUNET_assert(NULL != s); | ||
1571 | net = get_network (s, network); | ||
1572 | if (NULL == net) | ||
1573 | { | ||
1574 | GNUNET_break(0); | ||
1575 | return; | ||
1576 | } | ||
1577 | |||
1578 | aw = GNUNET_malloc (sizeof (struct AddressWrapper)); | ||
1579 | aw->addr = address; | ||
1580 | GNUNET_CONTAINER_DLL_insert(net->head, net->tail, aw); | ||
1581 | addresse_increment (s, net, GNUNET_YES, GNUNET_NO); | ||
1582 | |||
1583 | asi = GNUNET_malloc (sizeof (struct AddressSolverInformation)); | ||
1584 | asi->network = net; | ||
1585 | asi->calculated_quota_in_NBO = 0; | ||
1586 | asi->calculated_quota_out_NBO = 0; | ||
1587 | aw->addr->solver_information = asi; | ||
1588 | |||
1589 | if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (s->requests, &address->peer)) | ||
1590 | { | ||
1591 | if (NULL == get_active_address (s, s->addresses, &address->peer)) | ||
1592 | { | ||
1593 | if (NULL != GAS_proportional_get_preferred_address (s, &address->peer)) | ||
1594 | s->bw_changed (s->bw_changed_cls, (struct ATS_Address *) address); | ||
1595 | } | ||
1596 | } | ||
1597 | |||
1598 | LOG(GNUNET_ERROR_TYPE_INFO, | ||
1599 | "Adding new address %p for peer `%s', now total %u and active %u addresses in network `%s'\n", | ||
1600 | address, GNUNET_i2s(&address->peer), net->total_addresses, net->active_addresses, net->desc); | ||
1601 | } | ||
1602 | |||
1603 | |||
1604 | /* end of plugin_ats_proportional.c */ | ||