From 4a2c91ed9f94920b4c7771a618e4177dd8d91bc1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 29 Jan 2017 23:41:23 +0100 Subject: [PATCH] add path desirability calculations --- src/cadet/desirability_table.c | 35 +++++++++++ src/cadet/gnunet-service-cadet-new_paths.c | 12 +++- src/cadet/gnunet-service-cadet-new_peer.c | 69 ++++++++++++++++++++++ src/cadet/gnunet-service-cadet-new_peer.h | 14 +++++ 4 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 src/cadet/desirability_table.c diff --git a/src/cadet/desirability_table.c b/src/cadet/desirability_table.c new file mode 100644 index 000000000..21ec3e388 --- /dev/null +++ b/src/cadet/desirability_table.c @@ -0,0 +1,35 @@ +/* This file is in the public domain. */ + +/** + * @brief Program to simulate results from #GCP_get_desirability_of_path() + * for various plausible inputs. + * @author Christian Grothoff + */ +#include + +int +main () +{ + for (unsigned int num_alts=1; num_alts<10; num_alts++) + for (unsigned int off=0; off<10; off++) + for (double delta=-(int) off;delta<=5;delta += 0.25) + { + double weight_alts; + + if (delta <= - 1.0) + weight_alts = - 1.0 * num_alts / delta; /* discount alternative paths */ + else if (delta >= 1.0) + weight_alts = 1.0 * num_alts * delta; /* overcount alternative paths */ + else + weight_alts = 1.0 * num_alts; /* count alternative paths normally */ + + fprintf (stderr, + "Paths: %u Offset: %u Delta: %5.2f SCORE: %f\n", + num_alts, + off, + delta, + ((off + 1.0) / (weight_alts * weight_alts))); + } + + +} diff --git a/src/cadet/gnunet-service-cadet-new_paths.c b/src/cadet/gnunet-service-cadet-new_paths.c index 05d702717..05565c043 100644 --- a/src/cadet/gnunet-service-cadet-new_paths.c +++ b/src/cadet/gnunet-service-cadet-new_paths.c @@ -76,8 +76,16 @@ struct CadetPeerPath static void recalculate_path_desirability (struct CadetPeerPath *path) { - /* FIXME: update path desirability! */ - GNUNET_break (0); // not implemented + double result = 0.0; + + for (unsigned int i=0;ientries_length;i++) + { + struct CadetPeer *cp = path->entries[i]->peer; + + result += GCP_get_desirability_of_path (cp, + i); + } + path->desirability = (GNUNET_CONTAINER_HeapCostType) result; } diff --git a/src/cadet/gnunet-service-cadet-new_peer.c b/src/cadet/gnunet-service-cadet-new_peer.c index 9e84550ec..cc13f6da6 100644 --- a/src/cadet/gnunet-service-cadet-new_peer.c +++ b/src/cadet/gnunet-service-cadet-new_peer.c @@ -207,6 +207,12 @@ struct CadetPeer */ unsigned int num_paths; + /** + * Sum over all of the offsets of all of the paths in the @a path_heads DLLs. + * Used to speed-up @GCP_get_desirability_of_path() calculation. + */ + unsigned int off_sum; + /** * Number of message queue managers of this peer that have a message in waiting. * @@ -244,6 +250,67 @@ GCP_2s (const struct CadetPeer *cp) } +/** + * Calculate how desirable a path is for @a cp if @a cp + * is at offset @a off. + * + * The 'desirability_table.c' program can be used to compute a list of + * sample outputs for different scenarios. Basically, we score paths + * lower if there are many alternatives, and higher if they are + * shorter than average, and very high if they are much shorter than + * average and without many alternatives. + * + * @param cp a peer reachable via a path + * @param off offset of @a cp in the path + * @return score how useful a path is to reach @a cp, + * positive scores mean path is more desirable + */ +double +GCP_get_desirability_of_path (struct CadetPeer *cp, + unsigned int off) +{ + unsigned int num_alts = cp->num_paths; + unsigned int off_sum; + double avg_sum; + double path_delta; + double weight_alts; + + GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */ + GNUNET_assert (0 != cp->path_dll_length); + + /* We maintain 'off_sum' in 'peer' and thereby + avoid the SLOW recalculation each time. Kept here + just to document what is going on. */ +#if SLOW + off_sum = 0; + for (unsigned int j=0;jpath_dll_length;j++) + for (struct CadetPeerPathEntry *pe = cp->path_heads[j]; + NULL != pe; + pe = pe->next) + off_sum += j; + GNUNET_assert (off_sum == cp->off_sum); +#else + off_sum = cp->off_sum; +#endif + avg_sum = off_sum * 1.0 / cp->path_dll_length; + path_delta = off - avg_sum; + /* path_delta positiv: path off of peer above average (bad path for peer), + path_delta negativ: path off of peer below average (good path for peer) */ + if (path_delta <= - 1.0) + weight_alts = - num_alts / path_delta; /* discount alternative paths */ + else if (path_delta >= 1.0) + weight_alts = num_alts * path_delta; /* overcount alternative paths */ + else + weight_alts = num_alts; /* count alternative paths normally */ + + + /* off+1: long paths are generally harder to find and thus count + a bit more as they get longer. However, above-average paths + still need to count less, hence the squaring of that factor. */ + return (off + 1.0) / (weight_alts * weight_alts); +} + + /** * This peer is no longer be needed, clean it up now. * @@ -757,6 +824,7 @@ GCP_path_entry_add (struct CadetPeer *cp, GNUNET_CONTAINER_DLL_insert (cp->path_heads[off], cp->path_tails[off], entry); + cp->off_sum += off; cp->num_paths++; /* If we have a tunnel to this peer, tell the tunnel that there is a @@ -797,6 +865,7 @@ GCP_path_entry_remove (struct CadetPeer *cp, cp->path_tails[off], entry); GNUNET_assert (0 < cp->num_paths); + cp->off_sum -= off; cp->num_paths--; if ( (NULL == cp->core_mq) && (NULL != cp->t) && diff --git a/src/cadet/gnunet-service-cadet-new_peer.h b/src/cadet/gnunet-service-cadet-new_peer.h index aaaef15b8..e1d6fc33a 100644 --- a/src/cadet/gnunet-service-cadet-new_peer.h +++ b/src/cadet/gnunet-service-cadet-new_peer.h @@ -59,6 +59,20 @@ GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create); +/** + * Calculate how desirable a path is for @a cp if + * @a cp is at offset @a off in the path. + * + * @param cp a peer reachable via a path + * @param off offset of @a cp in a path + * @return score how useful a path is to reach @a cp, + * positive scores mean path is more desirable + */ +double +GCP_get_desirability_of_path (struct CadetPeer *cp, + unsigned int off); + + /** * Obtain the peer identity for a `struct CadetPeer`. * -- 2.25.1