gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r26596 - gnunet/src/dv


From: gnunet
Subject: [GNUnet-SVN] r26596 - gnunet/src/dv
Date: Mon, 25 Mar 2013 13:47:17 +0100

Author: grothoff
Date: 2013-03-25 13:47:17 +0100 (Mon, 25 Mar 2013)
New Revision: 26596

Modified:
   gnunet/src/dv/gnunet-service-dv.c
Log:
-use ATS from DV

Modified: gnunet/src/dv/gnunet-service-dv.c
===================================================================
--- gnunet/src/dv/gnunet-service-dv.c   2013-03-25 12:21:50 UTC (rev 26595)
+++ gnunet/src/dv/gnunet-service-dv.c   2013-03-25 12:47:17 UTC (rev 26596)
@@ -26,9 +26,6 @@
  *
  * @author Christian Grothoff
  * @author Nathan Evans
- *
- * TODO:
- * - distance updates are not properly communicate to US by core/transport/ats
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
@@ -38,6 +35,7 @@
 #include "gnunet_peerinfo_service.h"
 #include "gnunet_statistics_service.h"
 #include "gnunet_consensus_service.h"
+#include "gnunet_ats_service.h"
 #include "dv.h"
 #include <gcrypt.h>
 
@@ -237,6 +235,16 @@
    */
   int target_removed;
 
+  /**
+   * Our distance to this peer, 0 for unknown.
+   */
+  uint32_t distance;
+
+  /**
+   * Is this neighbor connected at the core level?
+   */
+  int connected;
+
 };
 
 
@@ -290,7 +298,9 @@
 
 
 /**
- * Hashmap of all of our direct neighbors (no DV routing).
+ * Hashmap of all of our neighbors; processing these usually requires
+ * first checking to see if the peer is core-connected and if the 
+ * distance is 1, in which case they are direct neighbors.
  */
 static struct GNUNET_CONTAINER_MultiHashMap *direct_neighbors;
 
@@ -332,30 +342,26 @@
 /**
  * Handle for the statistics service.
  */
-struct GNUNET_STATISTICS_Handle *stats;
+static struct GNUNET_STATISTICS_Handle *stats;
 
+/**
+ * Handle to ATS service.
+ */
+static struct GNUNET_ATS_PerformanceHandle *ats;
+ 
 
 /**
- * Get distance information from 'atsi'.
+ * Start creating a new consensus from scratch.
  *
- * @param atsi performance data
- * @param atsi_count number of entries in atsi
- * @return connected transport distance
- */
-static uint32_t
-get_atsi_distance (const struct GNUNET_ATS_Information *atsi,
-                   unsigned int atsi_count)
-{
-  unsigned int i;
+ * @param cls the 'struct DirectNeighbor' of the peer we're building
+ *        a routing consensus with
+ * @param tc scheduler context
+ */    
+static void
+start_consensus (void *cls,
+                const struct GNUNET_SCHEDULER_TaskContext *tc);
 
-  for (i = 0; i < atsi_count; i++)
-    if (ntohl (atsi[i].type) == GNUNET_ATS_QUALITY_NET_DISTANCE)
-      return ntohl (atsi->value);
-  /* FIXME: we do not have distance data? Assume direct neighbor. */
-  return DIRECT_NEIGHBOR_COST;
-}
 
-
 /**
  * Forward a message from another peer to the plugin.
  *
@@ -696,17 +702,31 @@
 
 
 /**
- * Start creating a new consensus from scratch.
+ * A peer is now connected to us at distance 1.  Initiate DV exchange.
  *
- * @param cls the 'struct DirectNeighbor' of the peer we're building
- *        a routing consensus with
- * @param tc scheduler context
- */    
+ * @param neighbor entry for the neighbor at distance 1
+ */
 static void
-start_consensus (void *cls,
-                const struct GNUNET_SCHEDULER_TaskContext *tc);
+handle_direct_connect (struct DirectNeighbor *neighbor)
+{
+  struct Route *route;
 
+  GNUNET_STATISTICS_update (stats,
+                           "# peers connected (1-hop)",
+                           1, GNUNET_NO);
+  route = GNUNET_CONTAINER_multihashmap_get (all_routes, 
+                                            &neighbor->peer.hashPubKey);
+  if (NULL != route)  
+  {
+    send_disconnect_to_plugin (&neighbor->peer);
+    release_route (route);
+    GNUNET_free (route);
+  }
+  neighbor->consensus_task = GNUNET_SCHEDULER_add_now (&start_consensus,
+                                                      neighbor);
+}
 
+
 /**
  * Method called whenever a peer connects.
  *
@@ -717,26 +737,22 @@
 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
 {
   struct DirectNeighbor *neighbor;
-  struct Route *route;
-  uint32_t distance;
  
   /* Check for connect to self message */
   if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
     return;
-  fprintf (stderr, "FIX ATS DATA: %s:%u!\n", __FILE__, __LINE__);
-  distance =  get_atsi_distance (NULL, 0);
+  /* check if entry exists */
   neighbor = GNUNET_CONTAINER_multihashmap_get (direct_neighbors, 
                                                &peer->hashPubKey);
   if (NULL != neighbor)
   {
-    GNUNET_break (0);
+    GNUNET_break (GNUNET_YES != neighbor->connected);
+    neighbor->connected = GNUNET_YES;
+    if (DIRECT_NEIGHBOR_COST != neighbor->distance)
+      return;
+    handle_direct_connect (neighbor);
     return;
   }
-  if (DIRECT_NEIGHBOR_COST != distance) 
-    return; /* is a DV-neighbor */
-  GNUNET_STATISTICS_update (stats,
-                           "# peers connected (1-hop)",
-                           1, GNUNET_NO);
   neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor));
   neighbor->peer = *peer;
   GNUNET_assert (GNUNET_YES ==
@@ -744,16 +760,8 @@
                                                    &peer->hashPubKey,
                                                    neighbor,
                                                    
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  route = GNUNET_CONTAINER_multihashmap_get (all_routes, 
-                                            &peer->hashPubKey);
-  if (NULL != route)  
-  {
-    send_disconnect_to_plugin (peer);
-    release_route (route);
-    GNUNET_free (route);
-  }
-  neighbor->consensus_task = GNUNET_SCHEDULER_add_now (&start_consensus,
-                                                      neighbor);
+  neighbor->connected = GNUNET_YES;
+  neighbor->distance = 0; /* unknown */
 }
 
 
@@ -834,6 +842,9 @@
 {
   struct DirectNeighbor *neighbor = value;
 
+  if ( (GNUNET_YES != neighbor->connected) ||
+       (DIRECT_NEIGHBOR_COST != neighbor->distance) )
+    return GNUNET_YES;    
   if (NULL != neighbor->neighbor_table)
     GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table,
                                           &check_possible_route,
@@ -843,6 +854,166 @@
 
 
 /**
+ * Get distance information from 'atsi'.
+ *
+ * @param atsi performance data
+ * @param atsi_count number of entries in atsi
+ * @return connected transport distance
+ */
+static uint32_t
+get_atsi_distance (const struct GNUNET_ATS_Information *atsi,
+                   uint32_t atsi_count)
+{
+  uint32_t i;
+
+  for (i = 0; i < atsi_count; i++)
+    if (ntohl (atsi[i].type) == GNUNET_ATS_QUALITY_NET_DISTANCE)
+      return ntohl (atsi->value);
+  /* If we do not have explicit distance data, assume direct neighbor. */
+  return DIRECT_NEIGHBOR_COST;
+}
+
+
+/**
+ * Multihashmap iterator for freeing routes that go via a particular
+ * neighbor that disconnected and is thus no longer available.
+ *
+ * @param cls the direct neighbor that is now unavailable
+ * @param key key value stored under
+ * @param value a 'struct Route' that may or may not go via neighbor
+ *
+ * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
+ */
+static int
+cull_routes (void *cls, const struct GNUNET_HashCode * key, void *value)
+{
+  struct DirectNeighbor *neighbor = cls;
+  struct Route *route = value;
+
+  if (route->next_hop != neighbor)
+    return GNUNET_YES; /* not affected */
+  GNUNET_assert (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_remove (all_routes, key, value));
+  release_route (route);
+  send_disconnect_to_plugin (&route->target.peer);
+  GNUNET_free (route);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handle the case that a direct connection to a peer is
+ * disrupted.  Remove all routes via that peer and
+ * stop the consensus with it.
+ *
+ * @param neighbor peer that was disconnected (or at least is no 
+ *    longer at distance 1)
+ */
+static void
+handle_direct_disconnect (struct DirectNeighbor *neighbor)
+{
+  GNUNET_CONTAINER_multihashmap_iterate (all_routes,
+                                        &cull_routes,
+                                         neighbor);
+  if (NULL != neighbor->cth)
+  {
+    GNUNET_CORE_notify_transmit_ready_cancel (neighbor->cth);
+    neighbor->cth = NULL;
+  }
+  if (NULL != neighbor->neighbor_table_consensus)
+  {
+    GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus,
+                                          &free_targets,
+                                          NULL);
+    GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table_consensus);
+    neighbor->neighbor_table_consensus = NULL;
+  }
+  if (NULL != neighbor->neighbor_table)
+  {
+    GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table,
+                                          &free_targets,
+                                          NULL);
+    GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table);
+    neighbor->neighbor_table = NULL;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != neighbor->consensus_task)
+  {
+    GNUNET_SCHEDULER_cancel (neighbor->consensus_task);
+    neighbor->consensus_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  if (NULL != neighbor->consensus)
+  {
+    GNUNET_CONSENSUS_destroy (neighbor->consensus);
+    neighbor->consensus = NULL;
+  }
+}
+
+
+/**
+ * Function that is called with QoS information about an address; used
+ * to update our current distance to another peer.
+ *
+ * @param cls closure
+ * @param address the address
+ * @param bandwidth_out assigned outbound bandwidth for the connection
+ * @param bandwidth_in assigned inbound bandwidth for the connection
+ * @param ats performance data for the address (as far as known)
+ * @param ats_count number of performance records in 'ats'
+ */
+static void
+handle_ats_update (void *cls,
+                  const struct GNUNET_HELLO_Address *address,
+                  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
+                  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
+                  const struct GNUNET_ATS_Information *ats, 
+                  uint32_t ats_count)
+{
+  struct DirectNeighbor *neighbor;
+  uint32_t distance;
+
+  /* FIXME: ignore CB if this address is not the one that is in use! */
+  distance = get_atsi_distance (ats, ats_count); 
+  /* check if entry exists */
+  neighbor = GNUNET_CONTAINER_multihashmap_get (direct_neighbors, 
+                                               &address->peer.hashPubKey);
+  if (NULL != neighbor)
+  {    
+    if ( (DIRECT_NEIGHBOR_COST == neighbor->distance) &&
+        (DIRECT_NEIGHBOR_COST == distance) )
+      return; /* no change */
+    if (DIRECT_NEIGHBOR_COST == neighbor->distance) 
+    {
+      neighbor->distance = distance;
+      GNUNET_STATISTICS_update (stats,
+                               "# peers connected (1-hop)",
+                               -1, GNUNET_NO);  
+      handle_direct_disconnect (neighbor);
+      GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors,
+                                            &refresh_routes,
+                                            NULL);
+      return;
+    }
+    neighbor->distance = distance;
+    if (DIRECT_NEIGHBOR_COST != neighbor->distance)
+      return;    
+    if (GNUNET_YES != neighbor->connected)
+      return;
+    handle_direct_connect (neighbor);
+    return;
+  }
+  neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor));
+  neighbor->peer = address->peer;
+  GNUNET_assert (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_put (direct_neighbors,
+                                                   &address->peer.hashPubKey,
+                                                   neighbor,
+                                                   
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  neighbor->connected = GNUNET_NO; /* not yet */
+  neighbor->distance = distance; 
+}
+
+
+/**
  * Check if a target was removed from the set of the other peer; if so,
  * if we also used it for our route, we need to remove it from our
  * 'all_routes' set (and later check if an alternative path now exists).
@@ -954,7 +1125,6 @@
  * The consensus has concluded, clean up and schedule the next one.
  *
  * @param cls the 'struct GNUNET_DirectNeighbor' with which we created the 
consensus
- * @param group FIXME
  */
 static void
 consensus_done_cb (void *cls)
@@ -1282,33 +1452,6 @@
 
 
 /**
- * Multihashmap iterator for freeing routes that go via a particular
- * neighbor that disconnected and is thus no longer available.
- *
- * @param cls the direct neighbor that is now unavailable
- * @param key key value stored under
- * @param value a 'struct Route' that may or may not go via neighbor
- *
- * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
- */
-static int
-cull_routes (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
-  struct DirectNeighbor *neighbor = cls;
-  struct Route *route = value;
-
-  if (route->next_hop != neighbor)
-    return GNUNET_YES; /* not affected */
-  GNUNET_assert (GNUNET_YES ==
-                GNUNET_CONTAINER_multihashmap_remove (all_routes, key, value));
-  release_route (route);
-  send_disconnect_to_plugin (&route->target.peer);
-  GNUNET_free (route);
-  return GNUNET_YES;
-}
-
-
-/**
  * Cleanup all of the data structures associated with a given neighbor.
  *
  * @param neighbor neighbor to clean up
@@ -1326,40 +1469,7 @@
                                 pending);    
     GNUNET_free (pending);
   }
-  GNUNET_CONTAINER_multihashmap_iterate (all_routes,
-                                        &cull_routes,
-                                         neighbor);
-  if (NULL != neighbor->cth)
-  {
-    GNUNET_CORE_notify_transmit_ready_cancel (neighbor->cth);
-    neighbor->cth = NULL;
-  }
-  if (NULL != neighbor->neighbor_table_consensus)
-  {
-    GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus,
-                                          &free_targets,
-                                          NULL);
-    GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table_consensus);
-    neighbor->neighbor_table_consensus = NULL;
-  }
-  if (NULL != neighbor->neighbor_table)
-  {
-    GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table,
-                                          &free_targets,
-                                          NULL);
-    GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table);
-    neighbor->neighbor_table = NULL;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != neighbor->consensus_task)
-  {
-    GNUNET_SCHEDULER_cancel (neighbor->consensus_task);
-    neighbor->consensus_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  if (NULL != neighbor->consensus)
-  {
-    GNUNET_CONSENSUS_destroy (neighbor->consensus);
-    neighbor->consensus = NULL;
-  }
+  handle_direct_disconnect (neighbor);
   GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multihashmap_remove (direct_neighbors, 
                                                       
&neighbor->peer.hashPubKey,
@@ -1389,12 +1499,17 @@
       GNUNET_CONTAINER_multihashmap_get (direct_neighbors, &peer->hashPubKey);
   if (NULL == neighbor)
   {
-    /* must have been a DV-neighbor, ignore */
+    GNUNET_break (0);
     return;
   }
-  GNUNET_STATISTICS_update (stats,
-                           "# peers connected (1-hop)",
-                           -1, GNUNET_NO);  
+  GNUNET_break (GNUNET_YES == neighbor->connected);
+  neighbor->connected = GNUNET_NO;
+  if (DIRECT_NEIGHBOR_COST == neighbor->distance)
+  {
+    GNUNET_STATISTICS_update (stats,
+                             "# peers connected (1-hop)",
+                             -1, GNUNET_NO);  
+  }
   cleanup_neighbor (neighbor);
   GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors,
                                         &refresh_routes,
@@ -1459,6 +1574,8 @@
 
   GNUNET_CORE_disconnect (core_api);
   core_api = NULL;
+  GNUNET_ATS_performance_done (ats);
+  ats = NULL;
   GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors,
                                          &free_direct_neighbors, NULL);
   GNUNET_CONTAINER_multihashmap_iterate (all_routes,
@@ -1582,6 +1699,12 @@
 
   if (NULL == core_api)
     return;
+  ats = GNUNET_ATS_performance_init (cfg, &handle_ats_update, NULL);
+  if (NULL == ats)
+  {
+    GNUNET_CORE_disconnect (core_api);
+    return;
+  }
   nc = GNUNET_SERVER_notification_context_create (server,
                                                  MAX_QUEUE_SIZE_PLUGIN);
   stats = GNUNET_STATISTICS_create ("dv", cfg);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]