diff options
Diffstat (limited to 'src/ats/plugin_ats_proportional.c')
-rw-r--r-- | src/ats/plugin_ats_proportional.c | 1243 |
1 files changed, 0 insertions, 1243 deletions
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 */ | ||