2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file ats/gnunet-service-ats_addresses_simplistic.h
23 * @brief ats simplistic ressource assignment
24 * @author Matthias Wachs
25 * @author Christian Grothoff
28 #include "gnunet_util_lib.h"
29 #include "gnunet-service-ats_addresses.h"
30 #include "gnunet_statistics_service.h"
32 #define LOG(kind,...) GNUNET_log_from (kind, "ats-simplistic",__VA_ARGS__)
35 * A handle for the simplistic solver
37 struct GAS_SIMPLISTIC_Handle
40 unsigned int active_addresses;
42 unsigned int networks;
47 * quotas[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType;
53 * Array of inbound quotas
56 unsigned long long *total_quota_in;
59 * Array of outbound quotas
62 unsigned long long *total_quota_out;
65 * Active addresses per network type
67 unsigned int *active_addresses_per_net;
71 * Init the simplistic problem solving component
74 * network[i] contains the network type as type GNUNET_ATS_NetworkType[i]
75 * out_quota[i] contains outbound quota for network type i
76 * in_quota[i] contains inbound quota for network type i
79 * network = {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN}
80 * network[2] == GNUNET_ATS_NET_LAN
81 * out_quota[2] == 65353
82 * in_quota[2] == 65353
84 * @param cfg configuration handle
85 * @param stats the GNUNET_STATISTICS handle
86 * @param network array of GNUNET_ATS_NetworkType with length dest_length
87 * @param out_quota array of outbound quotas
88 * param in_quota array of outbound quota
89 * @return handle for the solver on success, NULL on fail
92 GAS_simplistic_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
93 const struct GNUNET_STATISTICS_Handle *stats,
95 unsigned long long *out_quota,
96 unsigned long long *in_quota,
99 struct GAS_SIMPLISTIC_Handle *solver = GNUNET_malloc (sizeof (struct GAS_SIMPLISTIC_Handle));
101 solver->networks = dest_length;
103 solver->quota_net = GNUNET_malloc (dest_length * sizeof (int));
104 memcpy (solver->quota_net, network, dest_length * sizeof (int));
106 solver->total_quota_in = GNUNET_malloc (dest_length * sizeof (unsigned long long));
107 memcpy (solver->total_quota_in, in_quota, dest_length * sizeof (int));
109 solver->total_quota_out = GNUNET_malloc (dest_length * sizeof (unsigned long long));
110 memcpy (solver->total_quota_out, out_quota, dest_length * sizeof (unsigned long long));
112 solver->active_addresses_per_net = GNUNET_malloc (dest_length * sizeof (unsigned int));
119 * Shutdown the simplistic problem solving component
121 * @param solver the respective handle to shutdown
124 GAS_simplistic_done (void *solver)
126 struct GAS_SIMPLISTIC_Handle *s = solver;
127 GNUNET_assert (s != NULL);
128 GNUNET_free (s->quota_net);
129 GNUNET_free (s->total_quota_in);
130 GNUNET_free (s->total_quota_out);
131 GNUNET_free (s->active_addresses_per_net);
136 update_quota (struct GAS_SIMPLISTIC_Handle *s, unsigned int net)
138 unsigned long long quota_in;
139 unsigned long long quota_out;
141 quota_in = s->total_quota_in[net] / s->active_addresses_per_net[net];
142 quota_out = s->total_quota_out[net] / s->active_addresses_per_net[net];
144 LOG (GNUNET_ERROR_TYPE_DEBUG,
145 "New quota for network type %u (in/out): %llu/%llu \n",
146 net, quota_in, quota_out);
150 * Add a single address to the solve
152 * @param solver the solver Handle
153 * @param addresses the address hashmap containing all addresses
154 * @param address the address to add
157 GAS_simplistic_address_add (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address)
159 struct GAS_SIMPLISTIC_Handle *s = solver;
160 GNUNET_assert (NULL != s);
162 for (c = 0; c < s->networks; c++)
164 if (address->atsp_network_type == s->quota_net[c])
166 s->active_addresses_per_net[c] ++;
167 LOG (GNUNET_ERROR_TYPE_DEBUG,
168 "Adding new address for network type %u (now %u total)\n",
169 address->atsp_network_type,
170 s->active_addresses_per_net[c]);
175 /* Update quota for this network type */
182 * Updates a single address in the solve
184 * @param solver the solver Handle
185 * @param addresses the address hashmap containing all addresses
186 * @param address the update address
189 GAS_simplistic_address_update (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address)
192 struct GAS_SIMPLISTIC_Handle *s = solver;
193 GNUNET_assert (NULL != s);
195 for (c = 0; c < s->networks; c++)
197 if (address->atsp_network_type == s->quota_net[c])
199 LOG (GNUNET_ERROR_TYPE_DEBUG,
200 "Updating address for network type %u (%u total)\n",
201 address->atsp_network_type,
202 s->active_addresses_per_net[c]);
207 /* Update quota for this network type */
214 * Remove an address from the solver
216 * @param solver the solver handle
217 * @param addresses the address hashmap containing all addresses
218 * @param address the address to remove
221 GAS_simplistic_address_delete (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address)
224 struct GAS_SIMPLISTIC_Handle *s = solver;
225 GNUNET_assert (NULL != s);
227 for (c = 0; c < s->networks; c++)
229 if (address->atsp_network_type == s->quota_net[c])
231 GNUNET_assert (s->active_addresses_per_net[c] > 0);
232 s->active_addresses_per_net[c] --;
233 LOG (GNUNET_ERROR_TYPE_DEBUG,
234 "Deleting address for network type %u (now %u total)\n",
235 address->atsp_network_type,
236 s->active_addresses_per_net[c]);
241 /* Update quota for this network type */
249 * Find a "good" address to use for a peer. If we already have an existing
250 * address, we stick to it. Otherwise, we pick by lowest distance and then
253 * @param cls the 'struct ATS_Address**' where we store the result
255 * @param value another 'struct ATS_Address*' to consider using
256 * @return GNUNET_OK (continue to iterate)
259 find_address_it (void *cls, const struct GNUNET_HashCode * key, void *value)
261 struct ATS_Address **previous_p = cls;
262 struct ATS_Address *current = (struct ATS_Address *) value;
263 struct ATS_Address *previous = *previous_p;
264 struct GNUNET_TIME_Absolute now;
266 now = GNUNET_TIME_absolute_get();
268 if (current->blocked_until.abs_value == GNUNET_TIME_absolute_max (now, current->blocked_until).abs_value)
270 /* This address is blocked for suggestion */
271 LOG (GNUNET_ERROR_TYPE_DEBUG,
272 "Address %p blocked for suggestion for %llu ms \n",
274 GNUNET_TIME_absolute_get_difference(now, current->blocked_until).rel_value);
278 if (NULL != previous)
280 if ((0 == strcmp (previous->plugin, "tcp")) &&
281 (0 == strcmp (current->plugin, "tcp")))
283 if ((0 != previous->addr_len) &&
284 (0 == current->addr_len))
286 /* saved address was an outbound address, but we have an inbound address */
287 *previous_p = current;
290 if (0 == previous->addr_len)
292 /* saved address was an inbound address, so do not overwrite */
298 if (NULL == previous)
300 *previous_p = current;
303 if ((ntohl (previous->assigned_bw_in.value__) == 0) &&
304 (ntohl (current->assigned_bw_in.value__) > 0))
306 /* stick to existing connection */
307 *previous_p = current;
310 if (previous->atsp_distance > current->atsp_distance)
312 /* user shorter distance */
313 *previous_p = current;
316 if (previous->atsp_latency.rel_value > current->atsp_latency.rel_value)
318 /* user lower latency */
319 *previous_p = current;
327 update_bw_simple_it (void *cls, const struct GNUNET_HashCode * key, void *value)
329 struct GAS_SIMPLISTIC_Handle *s = cls;
330 struct ATS_Address *aa = value;
332 if (GNUNET_YES != aa->active)
334 GNUNET_assert (s->active_addresses > 0);
339 aa->assigned_bw_in.value__ = htonl (UINT32_MAX / s->active_addresses);
340 aa->assigned_bw_out.value__ = htonl (UINT32_MAX / s->active_addresses);
346 * Some (significant) input changed, recalculate bandwidth assignment
350 recalculate_assigned_bw (void *solver,
351 struct GNUNET_CONTAINER_MultiHashMap * addresses)
353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
354 "Recalculating bandwidth for all active connections\n");
355 GNUNET_CONTAINER_multihashmap_iterate (addresses, &update_bw_simple_it, solver);
361 * Get the prefered address for a specific peer
363 * @param solver the solver handle
364 * @param addresses the address hashmap containing all addresses
365 * @param peer the identity of the peer
367 const struct ATS_Address *
368 GAS_simplistic_get_preferred_address (void *solver,
369 struct GNUNET_CONTAINER_MultiHashMap * addresses,
370 const struct GNUNET_PeerIdentity *peer)
372 struct GAS_SIMPLISTIC_Handle *s = solver;
373 struct ATS_Address *aa;
375 GNUNET_assert (s != NULL);
377 /* Get address with: stick to current address, lower distance, lower latency */
378 GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey,
379 &find_address_it, &aa);
381 LOG (GNUNET_ERROR_TYPE_DEBUG, "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer));
384 LOG (GNUNET_ERROR_TYPE_DEBUG, "Suggesting address %p for peer `%s'\n", aa, GNUNET_i2s (peer));
386 if (GNUNET_NO == aa->active)
388 aa->active = GNUNET_YES;
389 s->active_addresses++;
390 recalculate_assigned_bw (s, addresses);
399 * Changes the preferences for a peer in the problem
401 * @param solver the solver handle
402 * @param peer the peer to change the preference for
403 * @param kind the kind to change the preference
404 * @param score the score
407 GAS_simplistic_address_change_preference (void *solver,
408 const struct GNUNET_PeerIdentity *peer,
409 enum GNUNET_ATS_PreferenceKind kind,
412 /* FIXME : implement this */
415 /* end of gnunet-service-ats_addresses_simplistic.c */