GNUnet  0.11.x
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 
78 void
80 {
82  address);
83 }
84 
85 
94 static void
99 {
100  const char *add_info;
101 
102  switch (add)
103  {
104  case GAS_INFO_NONE:
105  add_info = "GAS_INFO_NONE";
106  break;
107 
108  case GAS_INFO_FULL:
109  add_info = "GAS_INFO_MLP_FULL";
110  break;
111 
112  case GAS_INFO_UPDATED:
113  add_info = "GAS_INFO_MLP_UPDATED";
114  break;
115 
116  case GAS_INFO_PROP_ALL:
117  add_info = "GAS_INFO_PROP_ALL";
118  break;
119 
121  add_info = "GAS_INFO_PROP_SINGLE";
122  break;
123 
124  default:
125  add_info = "INVALID";
126  break;
127  }
128  switch (op)
129  {
130  case GAS_OP_SOLVE_START:
132  "Solver notifies `%s' with result `%s' `%s'\n",
133  "GAS_OP_SOLVE_START",
134  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL",
135  add_info);
136  return;
137 
138  case GAS_OP_SOLVE_STOP:
140  "Solver notifies `%s' with result `%s'\n",
141  "GAS_OP_SOLVE_STOP",
142  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
143  return;
144 
147  "Solver notifies `%s' with result `%s'\n",
148  "GAS_OP_SOLVE_SETUP_START",
149  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
150  return;
151 
154  "Solver notifies `%s' with result `%s'\n",
155  "GAS_OP_SOLVE_SETUP_STOP",
156  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
157  return;
158 
161  "Solver notifies `%s' with result `%s'\n",
162  "GAS_OP_SOLVE_LP_START",
163  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
164  return;
165 
168  "Solver notifies `%s' with result `%s'\n",
169  "GAS_OP_SOLVE_LP_STOP",
170  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
171  return;
172 
175  "Solver notifies `%s' with result `%s'\n",
176  "GAS_OP_SOLVE_MLP_START",
177  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
178  return;
179 
182  "Solver notifies `%s' with result `%s'\n",
183  "GAS_OP_SOLVE_MLP_STOP",
184  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
185  return;
186 
189  "Solver notifies `%s' with result `%s'\n",
190  "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
191  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
192  return;
193 
196  "Solver notifies `%s' with result `%s'\n",
197  "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
198  (GAS_STAT_SUCCESS == status) ? "SUCCESS" : "FAIL");
199  return;
200 
201  default:
202  GNUNET_break (0);
203  break;
204  }
205 }
206 
207 
214 static void
216  struct ATS_Address *address)
217 {
218  long long diff_out;
219  long long diff_in;
220 
222  "Bandwidth assignment changed for peer %s to %u/%u\n",
223  GNUNET_i2s (&address->peer),
224  (unsigned int) address->assigned_bw_in,
225  (unsigned int) address->assigned_bw_out);
228  address->assigned_bw_in));
229  /* Notify performance clients about changes to address */
231  address->plugin,
232  address->addr,
233  address->addr_len,
234  address->active,
235  &address->properties,
236  address->local_address_info,
238  address->assigned_bw_out),
240  address->assigned_bw_in));
241 
242  if ((0 == address->assigned_bw_in) &&
243  (0 == address->assigned_bw_out))
244  {
246  "Telling transport to disconnect peer `%s'\n",
247  GNUNET_i2s (&address->peer));
248 
249  /* Notify scheduling clients about suggestion */
251  address->session_id,
254  return;
255  }
256 
257  /* Do bandwidth stability check */
258  diff_out = llabs ((long long) address->assigned_bw_out
259  - (long long) address->last_notified_bw_out);
260  diff_in = llabs ((long long) address->assigned_bw_in
261  - (long long) address->last_notified_bw_in);
262  if ((diff_out < htonl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__)) &&
263  (diff_in < htonl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__)))
264  {
266  "Bandwidth change too small, not notifying client\n");
267  return;
268  }
269 
271  "Sending bandwidth update for peer `%s': %u/%u\n",
272  GNUNET_i2s (&address->peer),
273  address->assigned_bw_out,
274  address->assigned_bw_out);
275 
276  /* *Notify scheduling clients about suggestion */
278  address->session_id,
280  address->assigned_bw_out),
282  address->assigned_bw_in));
283 
284  address->last_notified_bw_out = address->assigned_bw_out;
285  address->last_notified_bw_in = address->assigned_bw_in;
286 }
287 
288 
297 static unsigned long long
298 parse_quota (const char *quota_str,
299  const char *direction,
300  enum GNUNET_NetworkType network)
301 {
302  int res;
303  unsigned long long ret;
304 
305  res = GNUNET_NO;
306  if (0 == strcmp (quota_str, GNUNET_ATS_MaxBandwidthString))
307  {
309  res = GNUNET_YES;
310  }
311  if ((GNUNET_NO == res) &&
312  (GNUNET_OK ==
314  &ret)))
315  res = GNUNET_YES;
316  if ((GNUNET_NO == res) &&
317  (1 ==
318  sscanf (quota_str,
319  "%llu",
320  &ret)))
321  res = GNUNET_YES;
322  if (GNUNET_NO == res)
323  {
325  _ (
326  "Could not load %s quota for network `%s': `%s', assigning default bandwidth %llu\n"),
327  direction,
328  GNUNET_NT_to_string (network),
329  quota_str,
330  (unsigned long long) GNUNET_ATS_DefaultBandwidth);
332  }
333  else
334  {
336  _ ("%s quota configured for network `%s' is %llu\n"),
337  direction,
338  GNUNET_NT_to_string (network),
339  ret);
340  }
341  return ret;
342 }
343 
344 
354 static unsigned long long
357  const char *direction)
358 {
359  char *entry;
360  char *quota_str;
361  unsigned long long ret;
362 
363  GNUNET_asprintf (&entry,
364  "%s_QUOTA_%s",
366  direction);
367  if (GNUNET_OK ==
369  "ats",
370  entry,
371  &quota_str))
372  {
373  ret = parse_quota (quota_str,
374  direction,
375  type);
376  GNUNET_free (quota_str);
377  }
378  else
379  {
381  _ (
382  "No %s-quota configured for network `%s', assigning default bandwidth %llu\n"),
383  direction,
385  (unsigned long long) GNUNET_ATS_DefaultBandwidth);
387  }
388  GNUNET_free (entry);
389  return ret;
390 }
391 
392 
402 static unsigned int
404  unsigned long long *out_dest,
405  unsigned long long *in_dest,
406  int dest_length)
407 {
408  unsigned int c;
409 
410  for (c = 0; (c < GNUNET_NT_COUNT) && (c < dest_length); c++)
411  {
412  in_dest[c] = load_quota (cfg,
413  c,
414  "out");
415  out_dest[c] = load_quota (cfg,
416  c,
417  "in");
419  "Loaded quota for network `%s' (in/out): %llu %llu\n",
421  in_dest[c],
422  out_dest[c]);
423  }
424  return c;
425 }
426 
427 
435 int
437 {
438  char *mode_str;
439 
440  /* Figure out configured solution method */
441  if (GNUNET_SYSERR ==
443  "ats",
444  "MODE",
445  &mode_str))
446  {
448  "No resource assignment method configured, using proportional approach\n");
449  mode_str = GNUNET_strdup ("proportional");
450  }
451  env.cls = NULL;
456  env.cfg = cfg;
457  env.stats = GSA_stats;
460  load_quotas (cfg,
461  env.out_quota,
462  env.in_quota,
465  "libgnunet_plugin_ats_%s",
466  mode_str);
468  "Initializing solver `%s'\n",
469  mode_str);
470  GNUNET_free (mode_str);
471  if (NULL == (sf = GNUNET_PLUGIN_load (plugin, &env)))
472  {
474  _ ("Failed to initialize solver `%s'!\n"),
475  plugin);
476  return GNUNET_SYSERR;
477  }
478  return GNUNET_OK;
479 }
480 
481 
485 void
487 {
489  sf);
490  sf = NULL;
492  plugin = NULL;
493 }
494 
495 
502 void
503 GAS_plugin_new_address (struct ATS_Address *new_address)
504 {
505  sf->s_add (sf->cls,
506  new_address,
507  new_address->properties.scope); /* FIXME: remove 3rd arg here! */
508 }
509 
510 
517 void
519 {
520  sf->s_del (sf->cls,
521  address);
522 }
523 
524 
535 void
537  const struct GNUNET_PeerIdentity *peer,
538  const struct GNUNET_TIME_Relative scope,
539  enum GNUNET_ATS_PreferenceKind kind,
540  float score_abs)
541 {
542  sf->s_feedback (sf->cls,
543  application,
544  peer,
545  scope,
546  kind,
547  score_abs);
548 }
549 
550 
555 void
557 {
558  sf->s_bulk_start (sf->cls);
559 }
560 
561 
565 void
567 {
568  sf->s_bulk_stop (sf->cls);
569 }
570 
571 
578 void
580 {
581  sf->s_get (sf->cls,
582  pid);
583 }
584 
585 
592 void
594 {
595  sf->s_get_stop (sf->cls,
596  pid);
597 }
598 
599 
600 /* 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 plugins 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.
#define GNUNET_log(kind,...)
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
#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:39
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...
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:36
const char * GNUNET_NT_to_string(enum GNUNET_NetworkType net)
Convert a enum GNUNET_NetworkType to a string.
Definition: nt.c:44
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
Definition: plugin.c:269
void * GNUNET_PLUGIN_load(const char *library_name, void *arg)
Setup plugin (runs the "init" callback and returns whatever "init" returned).
Definition: plugin.c:217
int 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:260
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
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:251
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.