GNUnet  0.19.5
gnunet-service-ats_plugins.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2011-2014 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
27 #include "platform.h"
28 #include "gnunet_ats_plugin.h"
36 
37 
42 
46 static struct GNUNET_ATS_PluginEnvironment env;
47 
51 static char *plugin;
52 
53 
61 void
63  enum GNUNET_ATS_PreferenceKind kind,
64  double pref_rel)
65 {
66  sf->s_pref (sf->cls,
67  peer,
68  kind,
69  pref_rel);
70 }
71 
72 
73 void
75 {
77  address);
78 }
79 
80 
89 static void
94 {
95  const char *add_info;
96 
97  switch (add)
98  {
99  case GAS_INFO_NONE:
100  add_info = "GAS_INFO_NONE";
101  break;
102 
103  case GAS_INFO_FULL:
104  add_info = "GAS_INFO_MLP_FULL";
105  break;
106 
107  case GAS_INFO_UPDATED:
108  add_info = "GAS_INFO_MLP_UPDATED";
109  break;
110 
111  case GAS_INFO_PROP_ALL:
112  add_info = "GAS_INFO_PROP_ALL";
113  break;
114 
116  add_info = "GAS_INFO_PROP_SINGLE";
117  break;
118 
119  default:
120  add_info = "INVALID";
121  break;
122  }
123  switch (op)
124  {
125  case GAS_OP_SOLVE_START:
127  "Solver notifies `%s' with result `%s' `%s'\n",
128  "GAS_OP_SOLVE_START",
129  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL",
130  add_info);
131  return;
132 
133  case GAS_OP_SOLVE_STOP:
135  "Solver notifies `%s' with result `%s'\n",
136  "GAS_OP_SOLVE_STOP",
137  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
138  return;
139 
142  "Solver notifies `%s' with result `%s'\n",
143  "GAS_OP_SOLVE_SETUP_START",
144  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
145  return;
146 
149  "Solver notifies `%s' with result `%s'\n",
150  "GAS_OP_SOLVE_SETUP_STOP",
151  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
152  return;
153 
156  "Solver notifies `%s' with result `%s'\n",
157  "GAS_OP_SOLVE_LP_START",
158  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
159  return;
160 
163  "Solver notifies `%s' with result `%s'\n",
164  "GAS_OP_SOLVE_LP_STOP",
165  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
166  return;
167 
170  "Solver notifies `%s' with result `%s'\n",
171  "GAS_OP_SOLVE_MLP_START",
172  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
173  return;
174 
177  "Solver notifies `%s' with result `%s'\n",
178  "GAS_OP_SOLVE_MLP_STOP",
179  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
180  return;
181 
184  "Solver notifies `%s' with result `%s'\n",
185  "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
186  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
187  return;
188 
191  "Solver notifies `%s' with result `%s'\n",
192  "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
193  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
194  return;
195 
196  default:
197  GNUNET_break (0);
198  break;
199  }
200 }
201 
202 
209 static void
211  struct ATS_Address *address)
212 {
213  long long diff_out;
214  long long diff_in;
215 
217  "Bandwidth assignment changed for peer %s to %u/%u\n",
218  GNUNET_i2s (&address->peer),
219  (unsigned int) address->assigned_bw_in,
220  (unsigned int) address->assigned_bw_out);
223  address->assigned_bw_in));
224  /* Notify performance clients about changes to address */
226  address->plugin,
227  address->addr,
228  address->addr_len,
229  address->active,
230  &address->properties,
231  address->local_address_info,
233  address->assigned_bw_out),
235  address->assigned_bw_in));
236 
237  if ((0 == address->assigned_bw_in) &&
238  (0 == address->assigned_bw_out))
239  {
241  "Telling transport to disconnect peer `%s'\n",
242  GNUNET_i2s (&address->peer));
243 
244  /* Notify scheduling clients about suggestion */
246  address->session_id,
249  return;
250  }
251 
252  /* Do bandwidth stability check */
253  diff_out = llabs ((long long) address->assigned_bw_out
254  - (long long) address->last_notified_bw_out);
255  diff_in = llabs ((long long) address->assigned_bw_in
256  - (long long) address->last_notified_bw_in);
257  if ((diff_out < htonl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__)) &&
258  (diff_in < htonl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__)))
259  {
261  "Bandwidth change too small, not notifying client\n");
262  return;
263  }
264 
266  "Sending bandwidth update for peer `%s': %u/%u\n",
267  GNUNET_i2s (&address->peer),
268  address->assigned_bw_out,
269  address->assigned_bw_out);
270 
271  /* *Notify scheduling clients about suggestion */
273  address->session_id,
275  address->assigned_bw_out),
277  address->assigned_bw_in));
278 
279  address->last_notified_bw_out = address->assigned_bw_out;
280  address->last_notified_bw_in = address->assigned_bw_in;
281 }
282 
283 
292 static unsigned long long
293 parse_quota (const char *quota_str,
294  const char *direction,
295  enum GNUNET_NetworkType network)
296 {
297  int res;
298  unsigned long long ret;
299 
300  res = GNUNET_NO;
301  if (0 == strcmp (quota_str, GNUNET_ATS_MaxBandwidthString))
302  {
304  res = GNUNET_YES;
305  }
306  if ((GNUNET_NO == res) &&
307  (GNUNET_OK ==
309  &ret)))
310  res = GNUNET_YES;
311  if ((GNUNET_NO == res) &&
312  (1 ==
313  sscanf (quota_str,
314  "%llu",
315  &ret)))
316  res = GNUNET_YES;
317  if (GNUNET_NO == res)
318  {
320  _ (
321  "Could not load %s quota for network `%s': `%s', assigning default bandwidth %llu\n"),
322  direction,
323  GNUNET_NT_to_string (network),
324  quota_str,
325  (unsigned long long) GNUNET_ATS_DefaultBandwidth);
327  }
328  else
329  {
331  _ ("%s quota configured for network `%s' is %llu\n"),
332  direction,
333  GNUNET_NT_to_string (network),
334  ret);
335  }
336  return ret;
337 }
338 
339 
349 static unsigned long long
352  const char *direction)
353 {
354  char *entry;
355  char *quota_str;
356  unsigned long long ret;
357 
358  GNUNET_asprintf (&entry,
359  "%s_QUOTA_%s",
361  direction);
362  if (GNUNET_OK ==
364  "ats",
365  entry,
366  &quota_str))
367  {
368  ret = parse_quota (quota_str,
369  direction,
370  type);
371  GNUNET_free (quota_str);
372  }
373  else
374  {
376  _ (
377  "No %s-quota configured for network `%s', assigning default bandwidth %llu\n"),
378  direction,
380  (unsigned long long) GNUNET_ATS_DefaultBandwidth);
382  }
383  GNUNET_free (entry);
384  return ret;
385 }
386 
387 
397 static unsigned int
399  unsigned long long *out_dest,
400  unsigned long long *in_dest,
401  int dest_length)
402 {
403  unsigned int c;
404 
405  for (c = 0; (c < GNUNET_NT_COUNT) && (c < dest_length); c++)
406  {
407  in_dest[c] = load_quota (cfg,
408  c,
409  "out");
410  out_dest[c] = load_quota (cfg,
411  c,
412  "in");
414  "Loaded quota for network `%s' (in/out): %llu %llu\n",
416  in_dest[c],
417  out_dest[c]);
418  }
419  return c;
420 }
421 
422 
423 int
425 {
426  char *mode_str;
427 
428  /* Figure out configured solution method */
429  if (GNUNET_SYSERR ==
431  "ats",
432  "MODE",
433  &mode_str))
434  {
436  "No resource assignment method configured, using proportional approach\n");
437  mode_str = GNUNET_strdup ("proportional");
438  }
439  env.cls = NULL;
444  env.cfg = cfg;
445  env.stats = GSA_stats;
448  load_quotas (cfg,
449  env.out_quota,
450  env.in_quota,
453  "libgnunet_plugin_ats_%s",
454  mode_str);
456  "Initializing solver `%s'\n",
457  mode_str);
458  GNUNET_free (mode_str);
459  if (NULL == (sf = GNUNET_PLUGIN_load (plugin, &env)))
460  {
462  _ ("Failed to initialize solver `%s'!\n"),
463  plugin);
464  return GNUNET_SYSERR;
465  }
466  return GNUNET_OK;
467 }
468 
469 
473 void
475 {
477  sf);
478  sf = NULL;
480  plugin = NULL;
481 }
482 
483 
484 void
485 GAS_plugin_new_address (struct ATS_Address *new_address)
486 {
487  sf->s_add (sf->cls,
488  new_address,
489  new_address->properties.scope); /* FIXME: remove 3rd arg here! */
490 }
491 
492 
499 void
501 {
502  sf->s_del (sf->cls,
503  address);
504 }
505 
506 
517 void
519  const struct GNUNET_PeerIdentity *peer,
520  const struct GNUNET_TIME_Relative scope,
521  enum GNUNET_ATS_PreferenceKind kind,
522  float score_abs)
523 {
524  sf->s_feedback (sf->cls,
525  application,
526  peer,
527  scope,
528  kind,
529  score_abs);
530 }
531 
532 
537 void
539 {
540  sf->s_bulk_start (sf->cls);
541 }
542 
543 
547 void
549 {
550  sf->s_bulk_stop (sf->cls);
551 }
552 
553 
560 void
562 {
563  sf->s_get (sf->cls,
564  pid);
565 }
566 
567 
574 void
576 {
577  sf->s_get_stop (sf->cls,
578  pid);
579 }
580 
581 
582 /* end of gnunet-service-ats_plugins.c */
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
enum GNUNET_ABD_AlgoDirectionFlags direction
API enum, filled and passed for collect/verify.
Definition: gnunet-abd.c:172
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
struct GNUNET_STATISTICS_Handle * GSA_stats
Handle for statistics.
static int res
static char * address
GNS address for this phone.
uint16_t status
See PRISM_STATUS_*-constants.
static int add
Desired action is to add a record.
struct GNUNET_CONTAINER_MultiPeerMap * GSA_addresses
A multihashmap to store all addresses.
unsigned int GAS_connectivity_has_peer(void *cls, const struct GNUNET_PeerIdentity *peer)
Is the given peer in the list of peers for which we have an address request?
ats service, interaction with 'connecivity' API
ats service address: management of ATS properties and preferences normalization
void GAS_performance_notify_all_clients(const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, int active, const struct GNUNET_ATS_Properties *prop, enum GNUNET_HELLO_AddressInfo local_address_info, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
Transmit the given performance information to all performance clients.
ats service, interaction with 'performance' API
static unsigned long long parse_quota(const char *quota_str, const char *direction, enum GNUNET_NetworkType network)
Convert quota from text to numeric value.
static unsigned int load_quotas(const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned long long *out_dest, unsigned long long *in_dest, int dest_length)
Load quotas for networks from configuration.
static void bandwidth_changed_cb(void *cls, struct ATS_Address *address)
Callback for solver to notify about assignment changes.
void GAS_plugin_solver_unlock()
Resume instant solving, we are done with the bulk state updates.
void GAS_plugin_notify_property_changed(struct ATS_Address *address)
The relative value for a property changed.
static char * plugin
Solver plugin name as string.
void GAS_plugin_notify_feedback(struct GNUNET_SERVICE_Client *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, float score_abs)
Tell the solver that the given client has expressed its appreciation for the past performance of a gi...
int GAS_plugin_init(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize address subsystem.
void GAS_plugin_solver_lock()
Stop instant solving, there are many state updates happening in bulk right now.
void GAS_plugin_delete_address(struct ATS_Address *address)
Tell the solver that the given address is no longer valid can cannot be used any longer.
void GAS_plugin_done()
Shutdown address subsystem.
void GAS_plugin_request_connect_start(const struct GNUNET_PeerIdentity *pid)
Notify the plugin that a request to connect to a particular peer was given to us.
void GAS_plugin_request_connect_stop(const struct GNUNET_PeerIdentity *pid)
Notify the plugin that a request to connect to a particular peer was dropped.
static unsigned long long load_quota(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_NetworkType type, const char *direction)
Load quota value from the configuration cfg for the given network type and direction.
static struct GNUNET_ATS_SolverFunctions * sf
Solver handle.
static struct GNUNET_ATS_PluginEnvironment env
Solver environment.
void GAS_plugin_notify_preference_changed(const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel)
The preference changed for a peer, update solver.
void GAS_plugin_new_address(struct ATS_Address *new_address)
Tell the solver that the given address can now be used for talking to the respective peer.
static void solver_info_cb(void *cls, enum GAS_Solver_Operation op, enum GAS_Solver_Status status, enum GAS_Solver_Additional_Information add)
Solver information callback.
ats service plugin management
const double * GAS_preference_get_by_peer(void *cls, const struct GNUNET_PeerIdentity *id)
Get the normalized preference values for a specific peer or the default values if.
manage preferences expressed by clients
void GAS_reservations_set_bandwidth(const struct GNUNET_PeerIdentity *peer, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
Set the amount of bandwidth the other peer could currently transmit to us (as far as we know) to the ...
ats service, inbound bandwidth reservation management
void GAS_scheduling_transmit_address_suggestion(const struct GNUNET_PeerIdentity *peer, uint32_t session_id, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
Transmit the given address suggestion and bandwidth update to all scheduling clients.
ats service, interaction with 'scheduling' API
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
API for the ATS solvers.
#define GNUNET_NT_COUNT
GAS_Solver_Status
Status of a GAS_Solver_Operation operation.
GAS_Solver_Operation
Operation codes for solver information callback.
GAS_Solver_Additional_Information
Status of the operation.
@ GAS_STAT_SUCCESS
Success.
@ GAS_OP_SOLVE_UPDATE_NOTIFICATION_START
After the problem was finished, start notifications about changes to addresses.
@ GAS_OP_SOLVE_MLP_LP_STOP
Solving of the LP problem is done MLP solver only.
@ GAS_OP_SOLVE_START
A solution iteration has been started.
@ GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP
After the problem was finished, notifications about changes to addresses are done.
@ GAS_OP_SOLVE_MLP_LP_START
Solving of the LP problem was started MLP solver only.
@ GAS_OP_SOLVE_SETUP_STOP
The setup of the problem as a preparation to solve is finished.
@ GAS_OP_SOLVE_MLP_MLP_STOP
Solving of the MLP problem is done MLP solver only.
@ GAS_OP_SOLVE_SETUP_START
The setup of the problem as a preparation to solve it was started.
@ GAS_OP_SOLVE_MLP_MLP_START
Solving of the MLP problem was started MLP solver only.
@ GAS_OP_SOLVE_STOP
A solution iteration has been finished.
@ GAS_INFO_PROP_ALL
The proportional solver had to recalculate for all networks.
@ GAS_INFO_PROP_SINGLE
The proportional solver had to recalculate for a single network.
@ GAS_INFO_UPDATED
An existing solution was reused Quite specific to the MLP solver.
@ GAS_INFO_NONE
No more specific information.
@ GAS_INFO_FULL
A full solution process is performed Quite specific to the MLP solver.
#define GNUNET_ATS_DefaultBandwidth
Default bandwidth assigned to a network : 64 KB/s.
#define GNUNET_ATS_MaxBandwidth
Maximum bandwidth assigned to a network : 4095 MB/s.
GNUNET_ATS_PreferenceKind
Enum defining all known preference categories.
#define GNUNET_ATS_MaxBandwidthString
Textual equivalent for GNUNET_ATS_MaxBandwidth.
#define GNUNET_BANDWIDTH_ZERO
Convenience definition to use for 0-bandwidth.
struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_init(uint32_t bytes_per_second)
Create a new bandwidth value.
Definition: bandwidth.c:40
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT
Bandwidth (in/out) to assume initially (before either peer has communicated any particular preference...
#define GNUNET_log(kind,...)
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:39
const char * GNUNET_NT_to_string(enum GNUNET_NetworkType net)
Convert a enum GNUNET_NetworkType to a string.
Definition: nt.c:38
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
Definition: plugin.c:242
void * GNUNET_PLUGIN_load(const char *library_name, void *arg)
Setup plugin (runs the "init" callback and returns whatever "init" returned).
Definition: plugin.c:198
enum GNUNET_GenericReturnValue GNUNET_STRINGS_fancy_size_to_bytes(const char *fancy_size, unsigned long long *size)
Convert a given fancy human-readable size to bytes.
Definition: strings.c:236
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
static enum GNUNET_NetworkType scope
Which network scope do we belong to?
Address with additional information.
struct GNUNET_ATS_Properties properties
ATS performance information for this address.
The ATS plugin will pass a pointer to a struct of this type as to the initialization function of the ...
void * cls
Closure to pass to all callbacks in this struct.
GAS_solver_information_callback info_cb
Callback for solver to call with status information, can be NULL.
GAS_get_preferences get_preferences
ATS addresses function to obtain preference values.
unsigned long long in_quota[6]
Array of configured inbound quotas Order according to networks in network array.
struct GNUNET_CONTAINER_MultiPeerMap * addresses
Hashmap containing all addresses available.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration handle to be used by the solver.
GAS_get_connectivity get_connectivity
ATS addresses function to obtain preference values.
unsigned int network_count
Number of networks available, size of the out_quota and in_quota arrays.
GAS_bandwidth_changed_cb bandwidth_changed_cb
ATS addresses callback to be notified about bandwidth assignment changes.
struct GNUNET_STATISTICS_Handle * stats
Statistics handle to be used by the solver.
unsigned long long out_quota[6]
Array of configured outbound quotas Order according to networks in network array.
enum GNUNET_NetworkType scope
Which network scope does the respective address belong to? This property does not change.
GAS_solver_address_feedback_preference s_feedback
Give feedback about the current assignment.
GAS_solver_address_property_changed s_address_update_property
Update the properties of an address in the solver.
GAS_solver_address_add s_add
Add a new address for a peer to the solver.
void * cls
Closure to pass to all solver functions in this struct.
GAS_solver_bulk_start s_bulk_start
Start a bulk operation.
GAS_solver_get_preferred_address s_get
Tell solver to notify ATS if the address to use changes for a specific peer using the bandwidth chang...
GAS_solver_bulk_stop s_bulk_stop
Bulk operation done.
GAS_solver_address_change_preference s_pref
Change relative preference for quality in solver.
GAS_solver_stop_get_preferred_address s_get_stop
Tell solver stop notifying ATS about changes for this peers.
GAS_solver_address_delete s_del
Delete an address in the solver.
The identity of the host (wraps the signing key of the peer).
Handle to a client that is connected to a service.
Definition: service.c:252
Time for relative time used by GNUnet, in microseconds.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.