gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r19193 - gnunet/src/vpn


From: gnunet
Subject: [GNUnet-SVN] r19193 - gnunet/src/vpn
Date: Tue, 17 Jan 2012 15:59:44 +0100

Author: grothoff
Date: 2012-01-17 15:59:44 +0100 (Tue, 17 Jan 2012)
New Revision: 19193

Modified:
   gnunet/src/vpn/gnunet-service-vpn.c
Log:
-bound #messages queued, bound #destinations and bound #tunnels

Modified: gnunet/src/vpn/gnunet-service-vpn.c
===================================================================
--- gnunet/src/vpn/gnunet-service-vpn.c 2012-01-17 14:45:05 UTC (rev 19192)
+++ gnunet/src/vpn/gnunet-service-vpn.c 2012-01-17 14:59:44 UTC (rev 19193)
@@ -29,8 +29,6 @@
  * TODO:
  * Basics:
  * - test!
- * - better message queue management (bounded state, drop oldest/RED?)
- * - actually destroy "stale" tunnels once we have too many!
  *
  * Features:
  * - add back ICMP support (especially needed for IPv6)
@@ -53,6 +51,12 @@
 
 
 /**
+ * Maximum number of messages we allow in the queue for mesh.
+ */
+#define MAX_MESSAGE_QUEUE_SIZE 4
+
+
+/**
  * State we keep for each of our tunnels.
  */
 struct TunnelState;
@@ -67,7 +71,7 @@
 
   /**
    * Key under which this entry is in the 'destination_map' (only valid
-   * if 'heap_node != NULL'.
+   * if 'heap_node != NULL').
    */
   GNUNET_HashCode key;
 
@@ -170,6 +174,7 @@
  */
 struct TunnelState
 {
+
   /**
    * Information about the tunnel to use, NULL if no tunnel
    * is available right now.
@@ -606,8 +611,6 @@
  * Add the given message to the given tunnel and trigger the
  * transmission process.
  *
- * FIXME: bound queue length!
- *
  * @param tnq message to queue
  * @param ts tunnel to queue the message for
  */
@@ -622,6 +625,23 @@
                                    ts->tmq_tail,
                                    tnq);
   ts->tmq_length++;
+  if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
+  {
+    struct TunnelMessageQueueEntry *dq;
+
+    dq = ts->tmq_head;
+    GNUNET_assert (dq != tnq);
+    GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
+                                ts->tmq_tail,
+                                dq);
+    GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
+    ts->th = NULL;
+    GNUNET_STATISTICS_update (stats,
+                             gettext_noop ("# Bytes dropped in mesh queue 
(overflow)"),
+                             dq->len, 
+                             GNUNET_NO);
+    GNUNET_free (dq);
+  }
   if (NULL == ts->th)
     ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, 
                                                GNUNET_NO /* cork */,
@@ -707,6 +727,90 @@
 
 
 /**
+ * Free resources associated with a tunnel state.
+ *
+ * @param ts state to free
+ */
+static void
+free_tunnel_state (struct TunnelState *ts)
+{
+  GNUNET_HashCode key;
+  struct TunnelMessageQueueEntry *tnq;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Cleaning up tunnel state\n");
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# Active tunnels"),
+                           -1, GNUNET_NO);
+  while (NULL != (tnq = ts->tmq_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
+                                ts->tmq_tail,
+                                tnq);
+    ts->tmq_length--;
+    GNUNET_free (tnq);
+  }
+  GNUNET_assert (0 == ts->tmq_length);
+  if (NULL != ts->client)
+  {
+    GNUNET_SERVER_client_drop (ts->client);
+    ts->client = NULL;
+  }
+  if (NULL != ts->th)
+  {
+    GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
+    ts->th = NULL;
+  }
+  GNUNET_assert (NULL == ts->destination.heap_node);
+  if (NULL != ts->tunnel)
+  {
+    GNUNET_MESH_tunnel_destroy (ts->tunnel);
+    ts->tunnel = NULL;
+  }
+  if (NULL != ts->heap_node)
+  {
+    GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
+    ts->heap_node = NULL;
+    get_tunnel_key_from_ips (ts->af,
+                            ts->protocol,
+                            &ts->source_ip,
+                            ts->source_port,
+                            &ts->destination_ip,
+                            ts->destination_port,
+                            &key);
+    GNUNET_assert (GNUNET_YES ==
+                  GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
+                                                        &key,
+                                                        ts));
+  }
+  if (NULL != ts->destination_container)
+  {
+    GNUNET_assert (ts == ts->destination_container->ts);
+    ts->destination_container->ts = NULL;
+    ts->destination_container = NULL;
+  }
+  GNUNET_free (ts);
+}
+
+
+/**
+ * We have too many active tunnels.  Clean up the oldest tunnel.
+ *
+ * @param except tunnel that must NOT be cleaned up, even if it is the oldest
+ */
+static void
+expire_tunnel (struct TunnelState *except)
+{
+  struct TunnelState *ts;
+
+  ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
+  if (except == ts)
+    return; /* can't do this */
+  free_tunnel_state (ts);
+}
+
+
+/**
  * Route a packet via mesh to the given destination.  
  *
  * @param destination description of the destination
@@ -878,7 +982,8 @@
     GNUNET_STATISTICS_update (stats,
                              gettext_noop ("# Active tunnels"),
                              1, GNUNET_NO);
-    /* FIXME: expire OLD tunnels if we have too many! */
+    while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > 
max_tunnel_mappings)
+      expire_tunnel (ts);
   }
   else
   {
@@ -1662,6 +1767,54 @@
 
 
 /**
+ * Free resources occupied by a destination entry.
+ *
+ * @param de entry to free
+ */
+static void
+free_destination_entry (struct DestinationEntry *de)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Cleaning up destination entry\n");
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# Active destinations"),
+                           -1, GNUNET_NO);
+  if (NULL != de->ts)
+  {
+    free_tunnel_state (de->ts);
+    GNUNET_assert (NULL == de->ts);
+  }
+  if (NULL != de->heap_node)
+  {
+    GNUNET_CONTAINER_heap_remove_node (de->heap_node);
+    de->heap_node = NULL;  
+    GNUNET_assert (GNUNET_YES ==
+                  GNUNET_CONTAINER_multihashmap_remove (destination_map,
+                                                        &de->key,
+                                                        de));
+  }
+  GNUNET_free (de);
+}
+
+
+/**
+ * We have too many active destinations.  Clean up the oldest destination.
+ *
+ * @param except destination that must NOT be cleaned up, even if it is the 
oldest
+ */
+static void 
+expire_destination (struct DestinationEntry *except)
+{
+  struct DestinationEntry *de;
+
+  de = GNUNET_CONTAINER_heap_peek (destination_heap);
+  if (except == de)
+    return; /* can't do this */
+  free_destination_entry (de);
+}
+
+
+/**
  * A client asks us to setup a redirection via some exit
  * node to a particular IP.  Setup the redirection and
  * give the client the allocated IP.
@@ -1807,8 +1960,9 @@
   GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# Active destinations"),
                            1, GNUNET_NO);
+  while (GNUNET_CONTAINER_multihashmap_size (destination_map) > 
max_destination_mappings)
+    expire_destination (de);
 
-  /* FIXME: expire OLD destinations if we have too many! */
   /* setup tunnel to destination */
   (void) create_tunnel_to_destination (de, 
                                       (GNUNET_NO == ntohl (msg->nac)) ? NULL : 
client,
@@ -1926,7 +2080,8 @@
   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
                                                de,
                                                GNUNET_TIME_absolute_ntoh 
(msg->expiration_time).abs_value);
-  /* FIXME: expire OLD destinations if we have too many! */
+  while (GNUNET_CONTAINER_multihashmap_size (destination_map) > 
max_destination_mappings)
+    expire_destination (de);
   (void) create_tunnel_to_destination (de,
                                       (GNUNET_NO == ntohl (msg->nac)) ? NULL : 
client,
                                       msg->request_id);
@@ -1959,104 +2114,6 @@
 
 
 /**
- * Free resources associated with a tunnel state.
- *
- * @param ts state to free
- */
-static void
-free_tunnel_state (struct TunnelState *ts)
-{
-  GNUNET_HashCode key;
-  struct TunnelMessageQueueEntry *tnq;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Cleaning up tunnel state\n");
-  GNUNET_STATISTICS_update (stats,
-                           gettext_noop ("# Active tunnels"),
-                           -1, GNUNET_NO);
-  while (NULL != (tnq = ts->tmq_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
-                                ts->tmq_tail,
-                                tnq);
-    ts->tmq_length--;
-    GNUNET_free (tnq);
-  }
-  GNUNET_assert (0 == ts->tmq_length);
-  if (NULL != ts->client)
-  {
-    GNUNET_SERVER_client_drop (ts->client);
-    ts->client = NULL;
-  }
-  if (NULL != ts->th)
-  {
-    GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
-    ts->th = NULL;
-  }
-  GNUNET_assert (NULL == ts->destination.heap_node);
-  if (NULL != ts->tunnel)
-  {
-    GNUNET_MESH_tunnel_destroy (ts->tunnel);
-    ts->tunnel = NULL;
-  }
-  if (NULL != ts->heap_node)
-  {
-    GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
-    ts->heap_node = NULL;
-    get_tunnel_key_from_ips (ts->af,
-                            ts->protocol,
-                            &ts->source_ip,
-                            ts->source_port,
-                            &ts->destination_ip,
-                            ts->destination_port,
-                            &key);
-    GNUNET_assert (GNUNET_YES ==
-                  GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
-                                                        &key,
-                                                        ts));
-  }
-  if (NULL != ts->destination_container)
-  {
-    GNUNET_assert (ts == ts->destination_container->ts);
-    ts->destination_container->ts = NULL;
-    ts->destination_container = NULL;
-  }
-  GNUNET_free (ts);
-}
-
-
-/**
- * Free resources occupied by a destination entry.
- *
- * @param de entry to free
- */
-static void
-free_destination_entry (struct DestinationEntry *de)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Cleaning up destination entry\n");
-  GNUNET_STATISTICS_update (stats,
-                           gettext_noop ("# Active destinations"),
-                           -1, GNUNET_NO);
-  if (NULL != de->ts)
-  {
-    free_tunnel_state (de->ts);
-    GNUNET_assert (NULL == de->ts);
-  }
-  if (NULL != de->heap_node)
-  {
-    GNUNET_CONTAINER_heap_remove_node (de->heap_node);
-    de->heap_node = NULL;  
-    GNUNET_assert (GNUNET_YES ==
-                  GNUNET_CONTAINER_multihashmap_remove (destination_map,
-                                                        &de->key,
-                                                        de));
-  }
-  GNUNET_free (de);
-}
-
-
-/**
  * Function called whenever an inbound tunnel is destroyed.  Should clean up
  * any associated state.
  *




reply via email to

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