2 This file is part of GNUnet.
3 Copyright (C) 2011-2015, 2018 GNUnet e.V.
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.
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.
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/>.
19 * @file ats/plugin_ats2_simple.c
20 * @brief ATS simple solver
21 * @author Matthias Wachs
22 * @author Christian Grothoff
25 * - subscribe to PEERSTORE when short on HELLOs (given application preferences!)
26 * - keep track of HELLOs and when we tried them last => re-suggest
27 * - sum up preferences per peer, keep totals! => PeerMap pid -> [preferences + sessions + addrs!]
28 * - sum up preferences overall, keep global sum => starting point for "proportional"
29 * - store DLL of available sessions per peer
32 #include "gnunet_ats_plugin_new.h"
33 #include "gnunet_peerstore_service.h"
35 #define LOG(kind,...) GNUNET_log_from (kind, "ats-simple",__VA_ARGS__)
39 * Entry in list of addresses we could try per peer.
55 * The address we could try.
60 * When did we try it last?
62 struct GNUNET_TIME_Absolute last_attempt;
65 * Current exponential backoff value.
67 struct GNUNET_TIME_Relative backoff;
70 * Is a session with this address already up?
71 * If not, set to NULL.
73 struct GNUNET_ATS_SessionHandle *sh;
79 * Internal representation of a session by the plugin.
80 * (If desired, plugin may just use NULL.)
82 struct GNUNET_ATS_SessionHandle
86 * Kept in DLL per peer.
88 struct GNUNET_ATS_SessionHandle *next;
91 * Kept in DLL per peer.
93 struct GNUNET_ATS_SessionHandle *prev;
96 * The session in the main ATS service.
98 struct GNUNET_ATS_Session *session;
101 * Current performance data for this @e session
103 const struct GNUNET_ATS_SessionData *data;
106 * Hello matching this session, or NULL for none.
111 * Address used by this session (largely for debugging).
116 * Last BW-in allocation given to the transport service.
118 struct GNUNET_BANDWIDTH_Value32NBO bw_in;
121 * Last BW-out allocation given to the transport service.
123 struct GNUNET_BANDWIDTH_Value32NBO bw_out;
129 * Information about preferences and sessions we track
136 * Kept in DLL per peer.
138 struct GNUNET_ATS_SessionHandle *sh_head;
141 * Kept in DLL per peer.
143 struct GNUNET_ATS_SessionHandle *sh_tail;
146 * Which peer is this for?
148 struct GNUNET_PeerIdentity pid;
151 * Array where we sum up the bandwidth requests received indexed
152 * by preference kind (see `struct GNUNET_MQ_PreferenceKind`)
154 uint64_t bw_by_pk[GNUNET_MQ_PREFERENCE_COUNT];
157 * Watch context where we are currently looking for HELLOs for
160 struct GNUNET_PEERSTORE_WatchContext *wc;
163 * Task used to try again to suggest an address for this peer.
165 struct GNUNET_SCHEDULER_TaskHandle *task;
171 * Representation of a network (to be expanded...)
177 * Total inbound quota
179 unsigned long long total_quota_in;
182 * Total outbound quota
184 unsigned long long total_quota_out;
189 enum GNUNET_NetworkType type;
195 * A handle for the proportional solver
201 * Our execution environment.
203 struct GNUNET_ATS_PluginEnvironment *env;
206 * Information we track for each peer.
208 struct GNUNET_CONTAINER_MultiPeerMap *peers;
211 * Information we track per network type (quotas).
213 struct Network networks[GNUNET_NT_COUNT];
216 * Handle to the peerstore service.
218 struct GNUNET_PEERSTORE_Handle *ps;
224 * The world changed, recalculate our allocations.
227 update (struct SimpleHandle *h)
229 // recalculate allocations
230 // notify transport if it makes sense (delta significant)
235 * The plugin should begin to respect a new preference.
237 * @param cls the closure
238 * @param pref the preference to add
239 * @return plugin's internal representation, or NULL
241 static struct GNUNET_ATS_PreferenceHandle *
242 simple_preference_add (void *cls,
243 const struct GNUNET_ATS_Preference *pref)
245 struct SimpleHandle *h = cls;
246 // Setup peer if necessary (-> including HELLO triggers!)
247 // add pref to bw_by_pk
254 * The plugin should end respecting a preference.
256 * @param cls the closure
257 * @param ph whatever @e preference_add returned
258 * @param pref the preference to delete
259 * @return plugin's internal representation, or NULL
262 simple_preference_del (void *cls,
263 struct GNUNET_ATS_PreferenceHandle *ph,
264 const struct GNUNET_ATS_Preference *pref)
266 struct SimpleHandle *h = cls;
268 // subtract pref from bw_by_pk
269 // remove peer if otherwise dead
275 * Transport established a new session with performance
276 * characteristics given in @a data.
279 * @param data performance characteristics of @a sh
280 * @param address address information (for debugging)
281 * @return handle by which the plugin will identify this session
283 static struct GNUNET_ATS_SessionHandle *
284 simple_session_add (void *cls,
285 const struct GNUNET_ATS_SessionData *data,
288 struct SimpleHandle *h = cls;
290 // find or add peer if necessary
299 * @a data changed for a given @a sh, solver should consider
300 * the updated performance characteristics.
303 * @param sh session this is about
304 * @param data performance characteristics of @a sh
307 simple_session_update (void *cls,
308 struct GNUNET_ATS_SessionHandle *sh,
309 const struct GNUNET_ATS_SessionData *data)
311 struct SimpleHandle *h = cls;
317 * A session went away. Solver should update accordingly.
320 * @param sh session this is about
321 * @param data (last) performance characteristics of @a sh
324 simple_session_del (void *cls,
325 struct GNUNET_ATS_SessionHandle *sh,
326 const struct GNUNET_ATS_SessionData *data)
328 struct SimpleHandle *h = cls;
330 // del peer if otherwise dead
335 #include "plugin_ats2_common.c"
339 * Function invoked when the plugin is loaded.
341 * @param[in,out] cls the `struct GNUNET_ATS_PluginEnvironment *` to use;
342 * modified to return the API functions (ugh).
343 * @return the `struct SimpleHandle` to pass as a closure
346 libgnunet_plugin_ats2_simple_init (void *cls)
348 static struct GNUNET_ATS_SolverFunctions sf;
349 struct GNUNET_ATS_PluginEnvironment *env = cls;
350 struct SimpleHandle *s;
352 s = GNUNET_new (struct SimpleHandle);
354 s->peers = GNUNET_CONTAINER_multipeermap_create (128,
356 s->ps = GNUNET_PEERSTORE_connect (env->cfg);
358 sf.preference_add = &simple_preference_add;
359 sf.preference_del = &simple_preference_del;
360 sf.session_add = &simple_session_add;
361 sf.session_update = &simple_session_update;
362 sf.session_del = &simple_session_del;
363 for (enum GNUNET_NetworkType nt = 0;
364 nt < GNUNET_NT_COUNT;
367 const char *name = GNUNET_NT_to_string (nt);
377 &s->networks[nt].total_quota_in);
381 &s->networks[nt].total_quota_out);
382 s->networks[nt].type = nt;
389 * Function used to unload the plugin.
391 * @param cls return value from #libgnunet_plugin_ats_proportional_init()
394 libgnunet_plugin_ats2_simple_done (void *cls)
396 struct GNUNET_ATS_SolverFunctions *sf = cls;
397 struct SimpleHandle *s = sf->cls;
399 // FIXME: iterate over peers and clean up!
400 GNUNET_CONTAINER_multipeermap_destroy (s->peers);
401 GNUNET_PEERSTORE_disconnect (s->ps,
408 /* end of plugin_ats2_simple.c */