GNUnet  0.10.x
plugin_ats2_simple.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2011-2015, 2018 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  */
29 #include "platform.h"
30 #include "gnunet_ats_plugin_new.h"
31 #include "gnunet_hello_lib.h"
33 
34 #define LOG(kind, ...) GNUNET_log_from (kind, "ats-simple", __VA_ARGS__)
35 
36 
44 #define SUGGEST_FREQ GNUNET_TIME_UNIT_SECONDS
45 
52 #define MIN_BANDWIDTH_PER_SESSION 1024
53 
54 
58 struct SimpleHandle;
59 
60 
65 struct Peer;
66 
67 
71 struct Hello
72 {
73 
77  struct Hello *next;
78 
82  struct Hello *prev;
83 
87  struct Peer *peer;
88 
92  const char *address;
93 
99 
104 
109 
114 
119 };
120 
121 
127 {
128 
133 
138 
143 
148 
152  struct Hello *hello;
153 
157  struct Peer *peer;
158 
162  const char *address;
163 
168  struct GNUNET_TIME_Absolute last_allocation;
169 
174 
179 
183  uint64_t target_in;
184 
188  uint64_t target_out;
189 };
190 
191 
196 struct Peer
197 {
198 
203 
208 
212  struct Hello *h_head;
213 
217  struct Hello *h_tail;
218 
222  struct SimpleHandle *h;
223 
229 
234 
239 
243  struct GNUNET_TIME_Absolute last_suggestion;
244 
249  uint64_t bw_by_pk[GNUNET_MQ_PREFERENCE_COUNT];
250 };
251 
252 
256 struct Network
257 {
258 
262  unsigned long long total_quota_in;
263 
267  unsigned long long total_quota_out;
268 
273 };
274 
275 
280 {
281 
286 
291 
296 
302  uint64_t bw_by_pk[GNUNET_MQ_PREFERENCE_COUNT];
303 
307  struct Network networks[GNUNET_NT_COUNT];
308 };
309 
310 
318 struct Peer *
320 {
321  return GNUNET_CONTAINER_multipeermap_get (h->peers, pid);
322 }
323 
324 
332 static int
334 {
336  pk++)
337  if (0 != p->bw_by_pk[pk])
338  return GNUNET_NO;
339  if (NULL != p->sh_head)
340  return GNUNET_NO;
341  return GNUNET_YES;
342 }
343 
344 
352 static void
354 {
355  struct Peer *p = hello->peer;
356  struct SimpleHandle *h = p->h;
357 
359  hello->backoff =
362  hello->expiration));
363  h->env->suggest_cb (h->env->cls, &p->pid, hello->address);
364 }
365 
366 
381 static void
382 suggest_start_cb (void *cls)
383 {
384  struct Peer *p = cls;
386  struct Hello *hello = NULL;
388  struct GNUNET_TIME_Relative xdelay;
389  struct GNUNET_TIME_Absolute xnext;
390  unsigned int num_sessions = 0;
391  uint32_t sq;
392 
393  /* count number of active sessions */
394  for (struct GNUNET_ATS_SessionHandle *sh = p->sh_head; NULL != sh;
395  sh = sh->next)
396  num_sessions++;
397  /* calculate square of number of sessions */
398  num_sessions++; /* start with 1, even if we have zero sessions */
399  if (num_sessions < UINT16_MAX)
400  sq = num_sessions * (uint32_t) num_sessions;
401  else
402  sq = UINT32_MAX;
403  xdelay =
405  sq),
407  xnext = GNUNET_TIME_relative_to_absolute (xdelay);
408 
409  p->task = NULL;
410  while (0 == delay.rel_value_us)
411  {
412  struct Hello *next;
413  struct GNUNET_TIME_Absolute xmax;
414 
415  if (NULL != hello)
416  {
417  /* We went through the loop already once and found
418  a HELLO that is due *now*, so make a suggestion! */
419  GNUNET_break (NULL == hello->sh);
420  suggest_hello (hello);
421  hello = NULL;
423  }
424  for (struct Hello *pos = p->h_head; NULL != pos; pos = next)
425  {
426  struct GNUNET_TIME_Absolute pt;
427 
428  next = pos->next;
429  if (NULL != pos->sh)
430  continue;
431  if (0 ==
433  {
434  /* expired, remove! */
436  GNUNET_free (pos);
437  continue;
438  }
439  pt = GNUNET_TIME_absolute_add (pos->last_attempt, pos->backoff);
440  if ((NULL == hello) || (pt.abs_value_us < hpt.abs_value_us))
441  {
442  hello = pos;
443  hpt = pt;
444  }
445  }
446  if (NULL == hello)
447  return; /* no HELLOs that could still be tried */
448 
449  /* hpt is now the *earliest* possible time for any HELLO
450  but we might not want to go for as early as possible for
451  this peer. So the actual time is the max of the earliest
452  HELLO and the 'xnext' */
453  xmax = GNUNET_TIME_absolute_max (hpt, xnext);
454  delay = GNUNET_TIME_absolute_get_remaining (xmax);
455  }
457 }
458 
459 
467 static void
468 watch_cb (void *cls,
469  const struct GNUNET_PEERSTORE_Record *record,
470  const char *emsg)
471 {
472  struct Peer *p = cls;
473  char *addr;
474  size_t alen;
475  enum GNUNET_NetworkType nt;
476  struct GNUNET_TIME_Absolute expiration;
477  struct Hello *hello;
478 
479  if (0 != GNUNET_memcmp (&p->pid, &record->peer))
480  {
481  GNUNET_break (0);
482  return;
483  }
484  if (0 != strcmp (record->key, GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY))
485  {
486  GNUNET_break (0);
487  return;
488  }
489  addr = GNUNET_HELLO_extract_address (record->value,
490  record->value_size,
491  &p->pid,
492  &nt,
493  &expiration);
494  if (NULL == addr)
495  return; /* invalid hello, bad signature, other problem */
496  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
497  {
498  /* expired, ignore */
499  GNUNET_free (addr);
500  return;
501  }
502  /* check if addr is already known */
503  for (struct Hello *he = p->h_head; NULL != he; he = he->next)
504  {
505  if (0 != strcmp (he->address, addr))
506  continue;
507  if (he->expiration.abs_value_us < expiration.abs_value_us)
508  {
509  he->expiration = expiration;
510  he->nt = nt;
511  }
512  GNUNET_free (addr);
513  return;
514  }
515  /* create new HELLO */
516  alen = strlen (addr) + 1;
517  hello = GNUNET_malloc (sizeof (struct Hello) + alen);
518  hello->address = (const char *) &hello[1];
519  hello->expiration = expiration;
520  hello->nt = nt;
521  hello->peer = p;
522  memcpy (&hello[1], addr, alen);
523  GNUNET_CONTAINER_DLL_insert (p->h_head, p->h_tail, hello);
524  /* check if sh for this HELLO already exists */
525  for (struct GNUNET_ATS_SessionHandle *sh = p->sh_head; NULL != sh;
526  sh = sh->next)
527  {
528  if ((NULL == sh->address) || (0 != strcmp (sh->address, addr)))
529  continue;
530  GNUNET_assert (NULL == sh->hello);
531  sh->hello = hello;
532  hello->sh = sh;
533  break;
534  }
535  GNUNET_free (addr);
536  if (NULL == p->task)
538 }
539 
540 
548 static struct Peer *
550 {
551  struct Peer *p = lookup_peer (h, pid);
552 
553  if (NULL != p)
554  return p;
555  p = GNUNET_new (struct Peer);
556  p->h = h;
557  p->pid = *pid;
558  p->wc = GNUNET_PEERSTORE_watch (h->ps,
559  "transport",
560  &p->pid,
562  &watch_cb,
563  p);
566  h->peers,
567  &p->pid,
568  p,
570 
571  return p;
572 }
573 
574 
581 static void
582 peer_free (struct Peer *p)
583 {
584  struct SimpleHandle *h = p->h;
585  struct Hello *hello;
586 
587  GNUNET_assert (NULL == p->sh_head);
588  while (NULL != (hello = p->h_head))
589  {
590  GNUNET_CONTAINER_DLL_remove (p->h_head, p->h_tail, hello);
591  GNUNET_assert (NULL == hello->sh);
592  GNUNET_free (hello);
593  }
594  if (NULL != p->task)
595  {
597  p->task = NULL;
598  }
599  if (NULL != p->wc)
600  {
602  p->wc = NULL;
603  }
606  GNUNET_free (p);
607 }
608 
609 
616 static void
618 {
619  struct Peer *peer = sh->peer;
620  struct SimpleHandle *h = peer->h;
621  enum GNUNET_NetworkType nt = sh->data->prop.nt;
622  struct GNUNET_TIME_Relative delay;
623  uint64_t sig_in;
624  uint64_t sig_out;
625  int64_t delta_in;
626  int64_t delta_out;
627 
629  /* A significant change is more than 10% of the quota,
630  which is given in bytes/second */
631  sig_in = h->networks[nt].total_quota_in * (delay.rel_value_us / 1000LL) /
632  1000LL / 10;
633  sig_out = h->networks[nt].total_quota_out * (delay.rel_value_us / 1000LL) /
634  1000LL / 10;
635  delta_in = ((int64_t) ntohl (sh->bw_in.value__)) - ((int64_t) sh->target_in);
636  delta_out = ((int64_t) ntohl (sh->bw_in.value__)) - ((int64_t) sh->target_in);
637  /* we want the absolute values */
638  if (delta_in < 0)
639  delta_in = -delta_in;
640  if (INT64_MIN == delta_in)
641  delta_in = INT64_MAX; /* Handle corner case: INT_MIN == - INT_MIN */
642  if (delta_out < 0)
643  delta_out = -delta_out;
644  if (INT64_MIN == delta_out)
645  delta_out = INT64_MAX; /* Handle corner case: INT_MIN == - INT_MIN */
646  if ((sig_in > delta_in) && (sig_out > delta_out))
647  return; /* insignificant change */
648  /* change is significant, tell transport! */
649  if (sh->target_in > UINT32_MAX)
650  sh->target_in = UINT32_MAX;
651  sh->bw_in.value__ = htonl ((uint32_t) sh->target_in);
652  if (sh->target_out > UINT32_MAX)
653  sh->target_out = UINT32_MAX;
654  sh->bw_out.value__ = htonl ((uint32_t) sh->target_out);
656  h->env->allocate_cb (h->env->cls,
657  sh->session,
658  &peer->pid,
659  sh->bw_in,
660  sh->bw_out);
661 }
662 
663 
667 struct Counters
668 {
672  struct SimpleHandle *h;
673 
680  uint64_t bw_out_by_nt[GNUNET_NT_COUNT];
681 
686  uint64_t bw_in_by_nt[GNUNET_NT_COUNT];
687 
692  double scale_out[GNUNET_NT_COUNT];
693 
698  double scale_in[GNUNET_NT_COUNT];
699 };
700 
701 
711 static int
712 update_counters (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
713 {
714  struct Counters *c = cls;
715  struct Peer *peer = value;
717 
718  (void) pid;
719  if (NULL == peer->sh_head)
720  return GNUNET_YES; /* no available session, cannot allocate bandwidth */
721  memset (best, 0, sizeof (best));
722  for (struct GNUNET_ATS_SessionHandle *sh = peer->sh_head; NULL != sh;
723  sh = sh->next)
724  {
725  enum GNUNET_NetworkType nt = sh->data->prop.nt;
726 
729  c->bw_in_by_nt[nt] +=
732  pk++)
733  {
734  /* General rule: always prefer smaller distance if possible,
735  otherwise decide by pk: */
736  switch (pk)
737  {
739  break;
741  /* For bandwidth, we compare the sum of transmitted bytes and
742  confirmed transmitted bytes, so confirmed data counts twice */
743  if ((NULL == best[pk]) ||
744  (sh->data->prop.distance < best[pk]->data->prop.distance) ||
746  best[pk]->data->prop.utilization_out +
747  best[pk]->data->prop.goodput_out))
748  best[pk] = sh;
749  /* If both are equal (i.e. usually this happens if there is a zero), use
750  latency as a yardstick */
752  best[pk]->data->prop.utilization_out +
753  best[pk]->data->prop.goodput_out) &&
754  (sh->data->prop.distance == best[pk]->data->prop.distance) &&
756  best[pk]->data->prop.delay.rel_value_us))
757  best[pk] = sh;
758  break;
760  if ((NULL == best[pk]) ||
761  (sh->data->prop.distance < best[pk]->data->prop.distance) ||
762  ((sh->data->prop.distance == best[pk]->data->prop.distance) &&
764  best[pk]->data->prop.delay.rel_value_us)))
765  best[pk] = sh;
766  break;
768  /* For reliability, we consider the ratio of goodput to utilization
769  (but use multiplicative formultations to avoid division by zero) */
770  if ((NULL == best[pk]) || (1ULL * sh->data->prop.goodput_out *
771  best[pk]->data->prop.utilization_out >
772  1ULL * sh->data->prop.utilization_out *
773  best[pk]->data->prop.goodput_out))
774  best[pk] = sh;
775  /* If both are equal (i.e. usually this happens if there is a zero), use
776  latency as a yardstick */
777  if ((1ULL * sh->data->prop.goodput_out *
778  best[pk]->data->prop.utilization_out ==
779  1ULL * sh->data->prop.utilization_out *
780  best[pk]->data->prop.goodput_out) &&
781  (sh->data->prop.distance == best[pk]->data->prop.distance) &&
783  best[pk]->data->prop.delay.rel_value_us))
784  best[pk] = sh;
785  break;
786  }
787  }
788  }
789  /* for first round, assign target bandwidth simply to sum of
790  requested bandwidth */
791  for (enum GNUNET_MQ_PreferenceKind pk =
792  1 /* skip GNUNET_MQ_PREFERENCE_NONE */;
794  pk++)
795  {
796  const struct GNUNET_ATS_SessionData *data = best[pk]->data;
797  enum GNUNET_NetworkType nt;
798 
799  GNUNET_assert (NULL != data);
800  nt = data->prop.nt;
801  best[pk]->target_out =
803  c->bw_out_by_nt[nt] +=
804  (uint64_t) (best[pk]->target_out - MIN_BANDWIDTH_PER_SESSION);
805  }
806  return GNUNET_YES;
807 }
808 
809 
819 static int
820 update_allocation (void *cls,
821  const struct GNUNET_PeerIdentity *pid,
822  void *value)
823 {
824  struct Counters *c = cls;
825  struct Peer *peer = value;
826 
827  (void) pid;
828  for (struct GNUNET_ATS_SessionHandle *sh = peer->sh_head; NULL != sh;
829  sh = sh->next)
830  {
831  enum GNUNET_NetworkType nt = sh->data->prop.nt;
832 
833  sh->target_out = (uint64_t) (c->scale_out[nt] * sh->target_out);
834  sh->target_in = (uint64_t) (c->scale_in[nt] * sh->target_in);
836  }
837  return GNUNET_YES;
838 }
839 
840 
844 static void
846 {
847  struct Counters cnt = {.h = h};
848 
850  /* calculate how badly the missmatch between requested
851  allocations and available bandwidth is per network type */
852  for (enum GNUNET_NetworkType nt = 0; nt < GNUNET_NT_COUNT; nt++)
853  {
854  cnt.scale_out[nt] =
855  1.0 * cnt.bw_out_by_nt[nt] / h->networks[nt].total_quota_out;
856  cnt.scale_in[nt] =
857  1.0 * cnt.bw_in_by_nt[nt] / h->networks[nt].total_quota_in;
858  }
859  /* recalculate allocations, considering scaling factor, and
860  update transport if the change is significant */
862 }
863 
864 
872 static struct GNUNET_ATS_PreferenceHandle *
873 simple_preference_add (void *cls, const struct GNUNET_ATS_Preference *pref)
874 {
875  struct SimpleHandle *h = cls;
876  struct Peer *p = peer_add (h, &pref->peer);
877 
879  p->bw_by_pk[pref->pk] += ntohl (pref->bw.value__);
880  h->bw_by_pk[pref->pk] += ntohl (pref->bw.value__);
881  update (h);
882  return NULL;
883 }
884 
885 
894 static void
896  struct GNUNET_ATS_PreferenceHandle *ph,
897  const struct GNUNET_ATS_Preference *pref)
898 {
899  struct SimpleHandle *h = cls;
900  struct Peer *p = lookup_peer (h, &pref->peer);
901 
902  GNUNET_assert (NULL != p);
904  p->bw_by_pk[pref->pk] -= ntohl (pref->bw.value__);
905  h->bw_by_pk[pref->pk] -= ntohl (pref->bw.value__);
906  if ((0 == p->bw_by_pk[pref->pk]) && (GNUNET_YES == peer_test_dead (p)))
907  peer_free (p);
908  update (h);
909 }
910 
911 
921 static struct GNUNET_ATS_SessionHandle *
923  const struct GNUNET_ATS_SessionData *data,
924  const char *address)
925 {
926  struct SimpleHandle *h = cls;
927  struct Peer *p = peer_add (h, &data->peer);
928  struct Hello *hello;
929  size_t alen;
931 
932  /* setup session handle */
933  GNUNET_assert (NULL != data);
934  if (NULL == address)
935  alen = 0;
936  else
937  alen = strlen (address) + 1;
938  sh = GNUNET_malloc (sizeof (struct GNUNET_ATS_SessionHandle) + alen);
939  sh->peer = p;
940  sh->session = data->session;
941  sh->data = data;
942  if (NULL == address)
943  {
944  sh->address = NULL;
945  }
946  else
947  {
948  memcpy (&sh[1], address, alen);
949  sh->address = (const char *) &sh[1];
950  }
952  if (NULL != address)
953  {
954  /* match HELLO */
955  hello = p->h_head;
956  while ((NULL != hello) && (0 != strcmp (address, hello->address)))
957  hello = hello->next;
958  if (NULL != hello)
959  {
960  hello->sh = sh;
962  sh->hello = hello;
963  }
964  }
965  update (h);
966  return sh;
967 }
968 
969 
978 static void
981  const struct GNUNET_ATS_SessionData *data)
982 {
983  struct SimpleHandle *h = cls;
984 
985  GNUNET_assert (NULL != data);
986  sh->data = data; /* this statement should not really do anything... */
987  update (h);
988 }
989 
990 
998 static void
1000  struct GNUNET_ATS_SessionHandle *sh,
1001  const struct GNUNET_ATS_SessionData *data)
1002 {
1003  struct SimpleHandle *h = cls;
1004  struct Peer *p = sh->peer;
1005  struct Hello *hello = sh->hello;
1006 
1007  /* clean up sh */
1009  if (NULL != hello)
1010  {
1011  GNUNET_assert (sh == hello->sh);
1012  hello->sh = NULL;
1013  /* session went down, if necessary restart suggesting
1014  addresses */
1015  if (NULL == p->task)
1017  }
1018  GNUNET_free (sh);
1019  /* del peer if otherwise dead */
1020  if ((NULL == p->sh_head) && (GNUNET_YES == peer_test_dead (p)))
1021  peer_free (p);
1022  update (h);
1023 }
1024 
1025 
1026 #include "plugin_ats2_common.c"
1027 
1028 
1036 void *
1038 {
1039  static struct GNUNET_ATS_SolverFunctions sf;
1041  struct SimpleHandle *s;
1042 
1043  s = GNUNET_new (struct SimpleHandle);
1044  s->env = env;
1046  s->ps = GNUNET_PEERSTORE_connect (env->cfg);
1047  sf.cls = s;
1053  for (enum GNUNET_NetworkType nt = 0; nt < GNUNET_NT_COUNT; nt++)
1054  {
1055  const char *name = GNUNET_NT_to_string (nt);
1056 
1057  if (NULL == name)
1058  {
1059  GNUNET_break (0);
1060  break;
1061  }
1062  get_quota (env->cfg, name, "IN", &s->networks[nt].total_quota_in);
1063  get_quota (env->cfg, name, "OUT", &s->networks[nt].total_quota_out);
1064  s->networks[nt].type = nt;
1065  }
1066  return &sf;
1067 }
1068 
1069 
1075 void *
1077 {
1078  struct GNUNET_ATS_SolverFunctions *sf = cls;
1079  struct SimpleHandle *s = sf->cls;
1080 
1084  GNUNET_free (s);
1085  return NULL;
1086 }
1087 
1088 
1089 /* end of plugin_ats2_simple.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
uint64_t bw_by_pk[GNUNET_MQ_PREFERENCE_COUNT]
Array where we sum up the bandwidth requests received indexed by preference kind (see enum GNUNET_MQ_...
void GNUNET_PEERSTORE_watch_cancel(struct GNUNET_PEERSTORE_WatchContext *wc)
Cancel a watch request.
enum GNUNET_NetworkType nt
Type of the network for this HELLO.
struct GNUNET_PEERSTORE_WatchContext * GNUNET_PEERSTORE_watch(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Request watching a given key User will be notified with any new values added to key.
static struct GNUNET_CRYPTO_EddsaPrivateKey * pk
Private key of this peer.
uint64_t rel_value_us
The actual value.
const char * GNUNET_NT_to_string(enum GNUNET_NetworkType net)
Convert a enum GNUNET_NetworkType to a string.
Definition: nt.c:43
struct GNUNET_ATS_Session * session
Handle to the session that has the given properties.
double scale_in[GNUNET_NT_COUNT]
By how much do we have to scale (up or down) our expectations for inbound bandwidth?
unsigned long long total_quota_out
Total outbound quota.
const struct GNUNET_ATS_SessionData * data
Current performance data for this session.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_PeerIdentity peer
Peer Identity.
void(* session_update)(void *cls, struct GNUNET_ATS_SessionHandle *sh, const struct GNUNET_ATS_SessionData *data)
data changed for a given sh, solver should consider the updated performance characteristics.
static struct GNUNET_ATS_SessionHandle * simple_session_add(void *cls, const struct GNUNET_ATS_SessionData *data, const char *address)
Transport established a new session with performance characteristics given in data.
uint32_t goodput_out
Confirmed successful payload on this connection from this peer to the other peer. ...
Definition: w32nsp.c:83
static struct GNUNET_ATS_PreferenceHandle * simple_preference_add(void *cls, const struct GNUNET_ATS_Preference *pref)
The plugin should begin to respect a new preference.
static void suggest_hello(struct Hello *hello)
Contact the transport service and suggest to it to try connecting to the address of hello...
static void update(struct SimpleHandle *h)
The world changed, recalculate our allocations.
uint64_t target_in
New BW-in allocation given to the transport service.
void * libgnunet_plugin_ats2_simple_done(void *cls)
Function used to unload the plugin.
static struct Peer * peer_add(struct SimpleHandle *h, const struct GNUNET_PeerIdentity *pid)
Find or add peer if necessary.
enum GNUNET_MQ_PreferenceKind pk
What type of performance preference does the client have?
size_t value_size
Size of value BLOB.
Internal representation of a session by the plugin.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:245
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static struct GNUNET_ATS_PerformanceHandle * ph
ATS performance handle used.
Definition: gnunet-ats.c:116
struct Hello * prev
Kept in a DLL.
struct GNUNET_TIME_Absolute last_suggestion
When did we last suggest an address to connect to for this peer?
struct GNUNET_TIME_Absolute last_attempt
When did we try it last?
static void simple_preference_del(void *cls, struct GNUNET_ATS_PreferenceHandle *ph, const struct GNUNET_ATS_Preference *pref)
The plugin should end respecting a preference.
static int update_counters(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function used to iterate over all peers and collect counter data.
No preference was expressed.
struct GNUNET_PeerIdentity peer
Peer the session is with.
static void watch_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_NO
Definition: gnunet_common.h:81
struct GNUNET_BANDWIDTH_Value32NBO bw_in
Last BW-in allocation given to the transport service.
void * libgnunet_plugin_ats2_simple_init(void *cls)
Function invoked when the plugin is loaded.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:393
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct Peer * peer
Peer this session is for.
uint64_t bw_by_pk[GNUNET_MQ_PREFERENCE_COUNT]
Array where we sum up the bandwidth requests received indexed by preference kind (see enum GNUNET_MQ_...
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
uint64_t abs_value_us
The actual value.
#define SUGGEST_FREQ
Base frequency at which we suggest addresses to transport.
static void simple_session_update(void *cls, struct GNUNET_ATS_SessionHandle *sh, const struct GNUNET_ATS_SessionData *data)
data changed for a given sh, solver should consider the updated performance characteristics.
uint64_t bw_out_by_nt[GNUNET_NT_COUNT]
Bandwidth that applications would prefer to allocate in this network type.
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:35
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:94
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
uint32_t value__
The actual value (bytes per second).
void(* session_del)(void *cls, struct GNUNET_ATS_SessionHandle *sh, const struct GNUNET_ATS_SessionData *data)
A session went away.
char * key
Record key string.
struct Hello * h_tail
Kept in a DLL.
double scale_out[GNUNET_NT_COUNT]
By how much do we have to scale (up or down) our expectations for outbound bandwidth?
struct GNUNET_ATS_PluginEnvironment * env
Our execution environment.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
struct GNUNET_PEERSTORE_Handle * ps
Handle to the peerstore service.
struct GNUNET_ATS_SessionHandle * sh_head
Kept in DLL per peer.
GNUNET_MQ_PreferenceKind
Enum defining all known preference categories.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
void * value
Record value BLOB.
static char * value
Value of the record to add/remove.
Information about ongoing sessions of the transport client.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h, int sync_first)
Disconnect from the PEERSTORE service.
struct GNUNET_ATS_PreferenceHandle *(* preference_add)(void *cls, const struct GNUNET_ATS_Preference *pref)
The plugin should begin to respect a new preference.
#define GNUNET_MQ_PREFERENCE_COUNT
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:85
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1273
struct GNUNET_TIME_Absolute expiration
When does the HELLO expire?
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:83
struct SimpleHandle * h
The handle for the proportional solver.
uint64_t bw_in_by_nt[GNUNET_NT_COUNT]
Current bandwidth utilization for this network type.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition: time.c:317
Representation of a network (to be expanded...)
struct GNUNET_TIME_Relative delay
Delay.
The preferred transmission for this envelope focuses on maximizing bandwidth.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:439
Preference being expressed by an application client.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_CONTAINER_MultiPeerMap * peers
Information we track for each peer.
Context for a watch request.
Internal representation of the hash map.
struct GNUNET_ATS_SessionHandle * sh_tail
Kept in DLL per peer.
Handle to the PEERSTORE service.
Definition: peerstore_api.c:40
struct Hello * h_head
Kept in a DLL.
static int peer_test_dead(struct Peer *p)
Check if there is any interesting information left we store about the peer in p.
struct GNUNET_BANDWIDTH_Value32NBO bw_out
Last BW-out allocation given to the transport service.
uint32_t goodput_in
Confirmed useful payload on this connection to this peer from the other peer.
struct GNUNET_ATS_SessionHandle *(* session_add)(void *cls, const struct GNUNET_ATS_SessionData *data, const char *address)
Transport established a new session with performance characteristics given in data.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
Entry in list of addresses we could try per peer.
uint64_t target_out
New BW-out allocation given to the transport service.
#define MIN_BANDWIDTH_PER_SESSION
What is the minimum bandwidth we always try to allocate for any session that is up? (May still be scaled down lower if the number of sessions is so high that the total bandwidth is insufficient to allow for this value to be granted.)
struct Peer * peer
Peer this hello belongs to.
enum GNUNET_NetworkType type
ATS network type.
ATS solver helper functions to be inlined.
static void get_quota(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *nts, const char *direction, unsigned long long *quota)
Parse cfg for quota as specified for direction of network type nts.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
unsigned long long total_quota_in
Total inbound quota.
static void peer_free(struct Peer *p)
Free the entry (and associated tasks) of peer p.
struct Hello * hello
Hello matching this session, or NULL for none.
struct GNUNET_BANDWIDTH_Value32NBO bw
How much bandwidth in bytes/second does the application expect?
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
const char * name
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
void * cls
Closure to pass to all solver functions in this struct.
Plugin-relevant information about a session.
struct GNUNET_PeerIdentity pid
Which peer is this for?
32-bit bandwidth used for network exchange by GNUnet, in bytes per second.
enum GNUNET_NetworkType nt
Which network scope does the respective address belong to?
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
struct GNUNET_SCHEDULER_Task * task
Task used to try again to suggest an address for this peer.
static void consider_notify_transport(struct GNUNET_ATS_SessionHandle *sh)
Check if the new allocation for sh is significantly different from the last one, and if so...
struct GNUNET_TIME_Absolute last_allocation
When did we last update transport about the allocation? Used to dampen the frequency of updates...
#define GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY
Key used for storing addresses in URL format in the peerstore.
void(* suggest_cb)(void *cls, const struct GNUNET_PeerIdentity *pid, const char *address)
Suggest to the transport that it should try establishing a connection using the given address...
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
struct GNUNET_ATS_SessionHandle * prev
Kept in DLL per peer.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
static void simple_session_del(void *cls, struct GNUNET_ATS_SessionHandle *sh, const struct GNUNET_ATS_SessionData *data)
A session went away.
The identity of the host (wraps the signing key of the peer).
void(* allocate_cb)(void *cls, struct GNUNET_ATS_Session *session, const struct GNUNET_PeerIdentity *peer, struct GNUNET_BANDWIDTH_Value32NBO bw_in, struct GNUNET_BANDWIDTH_Value32NBO bw_out)
Tell the transport that it should allocate the given bandwidth to the specified session.
struct GNUNET_TIME_Relative backoff
Current exponential backoff value.
static int update_allocation(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function used to iterate over all peers and collect counter data.
Information about preferences and sessions we track per peer.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:373
void(* preference_del)(void *cls, struct GNUNET_ATS_PreferenceHandle *ph, const struct GNUNET_ATS_Preference *pref)
The plugin should end respecting a preference.
struct Network networks[GNUNET_NT_COUNT]
Information we track per network type (quotas).
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
static void suggest_start_cb(void *cls)
Consider suggesting a HELLO (without a session) to transport.
struct Hello * next
Kept in a DLL.
The preferred transmission for this envelope foces on minimizing latency.
Single PEERSTORE record.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration handle to be used by the solver.
Entry in list of pending tasks.
Definition: scheduler.c:134
Closure for update_counters and update_allocation.
struct Peer * lookup_peer(struct SimpleHandle *h, const struct GNUNET_PeerIdentity *pid)
Lookup peer in the peers map.
struct GNUNET_HELLO_Message * hello
Pointer to the HELLO message of this peer; can be NULL.
const char * address
The address we could try.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
void * cls
Closure to pass to all callbacks in this struct.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
struct GNUNET_ATS_SessionHandle * sh
Is a session with this address already up? If not, set to NULL.
A handle for the proportional solver.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
struct GNUNET_PeerIdentity peer
Peer to get address suggestions for.
static struct GNUNET_ATS_SolverFunctions * sf
Solver handle.
The ATS plugin will pass a pointer to a struct of this type as to the initialization function of the ...
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
struct SimpleHandle * h
Plugin&#39;s state.
uint32_t data
The data value.
const char * address
Address used by this session (largely for debugging).
char * GNUNET_HELLO_extract_address(const void *raw, size_t raw_size, const struct GNUNET_PeerIdentity *pid, enum GNUNET_NetworkType *nt, struct GNUNET_TIME_Absolute *mono_time)
Check signature and extract address record.
Definition: hello-ng.c:108
unsigned int distance
Distance on network layer (required for distance-vector routing) in hops.
#define GNUNET_NT_COUNT
struct GNUNET_TIME_Relative GNUNET_TIME_randomized_backoff(struct GNUNET_TIME_Relative rt, struct GNUNET_TIME_Relative threshold)
Randomized exponential back-off, starting at 1 ms and going up by a factor of 2+r, where 0 <= r <= 0.5, up to a maximum of the given threshold.
Definition: time.c:759
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
uint32_t utilization_out
Actual traffic on this connection from this peer to the other peer.
struct GNUNET_PEERSTORE_WatchContext * wc
Watch context where we are currently looking for HELLOs for this peer.
struct GNUNET_ATS_Session * session
The session in the main ATS service.
struct GNUNET_ATS_Properties prop
ATS performance characteristics for a session.
struct GNUNET_ATS_SessionHandle * next
Kept in DLL per peer.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
The preferred transmission for this envelope foces on reliability.