- backport
authorBart Polot <bart@net.in.tum.de>
Fri, 11 Oct 2013 15:20:28 +0000 (15:20 +0000)
committerBart Polot <bart@net.in.tum.de>
Fri, 11 Oct 2013 15:20:28 +0000 (15:20 +0000)
src/mesh/gnunet-service-mesh_connection.c
src/mesh/gnunet-service-mesh_connection.h
src/mesh/gnunet-service-mesh_tunnel.c

index 910b5f1f3176cfd69b3208203e478e489ad5a35b..94813adf24efe74a88d0261ae375cee503cf54f5 100644 (file)
@@ -520,8 +520,8 @@ connection_send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-                "  last pid recv: %u, last ack sent: %u\n",
-                prev_fc->last_pid_recv, prev_fc->last_ack_sent);
+         "  last pid recv: %u, last ack sent: %u\n",
+         prev_fc->last_pid_recv, prev_fc->last_ack_sent);
     return;
   }
 
@@ -530,9 +530,9 @@ connection_send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
   ack = prev_fc->last_pid_recv + delta;
   LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-              " last pid %u, last ack %u, qmax %u, q %u\n",
-              prev_fc->last_pid_recv, prev_fc->last_ack_sent,
-              next_fc->queue_max, next_fc->queue_n);
+       " last pid %u, last ack %u, qmax %u, q %u\n",
+       prev_fc->last_pid_recv, prev_fc->last_ack_sent,
+       next_fc->queue_max, next_fc->queue_n);
   if (ack == prev_fc->last_ack_sent)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
@@ -1663,6 +1663,8 @@ GMC_send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
   LOG (GNUNET_ERROR_TYPE_DEBUG,
               "send ack %s on %p %p\n",
               fwd ? "FWD" : "BCK", c, ch);
+
+  /* Get available bufffer space */
   if (NULL == c || GMC_is_terminal (c, fwd))
   {
     struct MeshTunnel3 *t;
@@ -1677,6 +1679,7 @@ GMC_send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer available: %u\n", buffer);
 
+  /* Send available buffer space */
   if ( (NULL != ch && GMCH_is_origin (ch, fwd)) ||
        (NULL != c && GMC_is_origin (c, fwd)) )
   {
@@ -1890,6 +1893,27 @@ GMC_get_buffer (struct MeshConnection *c, int fwd)
   return (fc->queue_max - fc->queue_n);
 }
 
+/**
+ * Get how many messages have we allowed to send to us from a direction..
+ *
+ * @param c Connection.
+ * @param fwd Are we asking about traffic from FWD (BCK messages)?
+ *
+ * @return last_ack_sent - last_pid_recv
+ */
+unsigned int
+GMC_get_allowed (struct MeshConnection *c, int fwd)
+{
+  struct MeshFlowControl *fc;
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+  if (GMC_is_pid_bigger(fc->last_pid_recv, fc->last_ack_sent))
+  {
+    return 0;
+  }
+  return (fc->last_ack_sent - fc->last_pid_recv);
+}
+
 /**
  * Get messages queued in a connection.
  *
index b55d55fe6e9f5275a5fa251d1f2cc94864c58218..a617054ffa3fbfebb27bd8fb7283c6d739f4d441 100644 (file)
@@ -305,6 +305,17 @@ GMC_get_tunnel (const struct MeshConnection *c);
 unsigned int
 GMC_get_buffer (struct MeshConnection *c, int fwd);
 
+/**
+ * Get how many messages have we allowed to send to us from a direction..
+ *
+ * @param c Connection.
+ * @param fwd Are we asking about traffic from FWD (BCK messages)?
+ *
+ * @return last_ack_sent - last_pid_recv
+ */
+unsigned int
+GMC_get_allowed (struct MeshConnection *c, int fwd);
+
 /**
  * Get messages queued in a connection.
  *
index 9a25db0891ef97a6601287fa4951dbd8e783957d..105317501f0a5fa3519c449d941c42e69392bbe5 100644 (file)
@@ -1018,7 +1018,10 @@ GMT_get_buffer (struct MeshTunnel3 *t, int fwd)
     unsigned int ch_buf;
 
     if (NULL == t->channel_head)
+    {
+      /* Probably getting buffer for a channel create. */
       return 64;
+    }
 
     for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = iter_ch->next)
     {
@@ -1084,6 +1087,66 @@ GMT_get_next_chid (struct MeshTunnel3 *t)
 }
 
 
+/**
+ * Send ACK on one or more connections due to buffer space to the client.
+ *
+ * Iterates all connections of the tunnel and sends ACKs appropriately.
+ *
+ * @param ch Channel which has some free buffer space.
+ * @param fwd Is this in for FWD traffic? (ACK goes dest->root)
+ */
+static void
+GMT_send_acks (struct MeshTunnel3 *t,
+               unsigned int buffer,
+               int fwd)
+{
+  struct MeshTConnection *iter;
+  uint32_t allowed;
+  uint32_t to_allow;
+  uint32_t allow_per_connection;
+  unsigned int cs;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Tunnel send acks on %s:%X\n",
+              fwd ? "FWD" : "BCK", peer2s (ch->t->peer), ch->gid);
+
+  /* Count connections, how many messages are already allowed */
+  cs = GMT_count_connections (t);
+  for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
+  {
+    allowed += GMC_get_allowed (iter->c, fwd);
+  }
+
+  /* Make sure there is no overflow */
+  if (allowed > buffer)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  /* Authorize connections to send more data */
+  to_allow = buffer - allowed;
+
+  for (iter = t->connection_head; NULL != iter && to_allow > 0; iter = iter->next)
+  {
+    allow_per_connection = to_allow/cs;
+    to_allow -= allow_per_connection;
+    cs--;
+    if (GMC_get_allowed (iter->c, fwd) > 64 / 3)
+    {
+      continue;
+    }
+    GMC_send_ack (iter->c, NULL, fwd);
+    connection_send_ack (iter, allow_per_connection, fwd);
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Channel send connection %s ack on %s:%X\n",
+                fwd ? "FWD" : "BCK", peer2s (ch->t->peer), ch->gid);
+  GNUNET_break (to_allow == 0);
+}
+
+
 /**
  * Sends an already built message on a tunnel, GMT_encrypting it and
  * choosing the best connection.