- leaks
[oweals/gnunet.git] / src / mesh / test_mesh_local_traffic.c
index 2f0ce2185817ba93978c6b0e87e168662238b940..b422c64e843039702884bc179b9a2412d87506c9 100644 (file)
 
 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
 
-#define TARGET 100
+#define TARGET 1000
 
+/**
+ * DIFFERENT TESTS TO RUN
+ */
+#define FWD 0
+#define BCK 1
+#define BOTH 2
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+struct test_traffic_message
+{
+  struct GNUNET_MessageHeader header;
+  uint32_t data GNUNET_PACKED;
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+
+/** Which test to run, based on executable name */
+static int test;
+
+static int started;
+
+/** How many packets to send from root to leaf */
+static unsigned int to_send_fwd;
+
+/** How many packets to send from leaf to root */
+static unsigned int to_send_bck;
+
+static unsigned int sent_fwd = 0;
+
+static unsigned int got_fwd = 0;
+
+static unsigned int sent_bck = 0;
+
+static unsigned int got_bck = 0;
 
 static struct GNUNET_MESH_Handle *mesh_peer_1;
 
 static struct GNUNET_MESH_Handle *mesh_peer_2;
 
-static struct GNUNET_MESH_Tunnel *t;
+static struct GNUNET_MESH_Tunnel *t_fwd;
+
+static struct GNUNET_MESH_Tunnel *t_bck;
 
 static unsigned int one = 1;
 
@@ -47,10 +86,6 @@ static unsigned int two = 2;
 
 static int result = GNUNET_SYSERR;
 
-static unsigned int sent = 0;
-
-static unsigned int got = 0;
-
 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
 
 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
@@ -73,9 +108,9 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   {
     GNUNET_SCHEDULER_cancel (abort_task);
   }
-  if (NULL != t)
+  if (NULL != t_fwd)
   {
-    GNUNET_MESH_tunnel_destroy(t);
+    GNUNET_MESH_tunnel_destroy(t_fwd);
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "D1\n");
   if (NULL != mesh_peer_1)
@@ -117,6 +152,64 @@ finish(void)
 }
 
 
+/**
+ * Transmit ready callback.
+ * 
+ * @param cls Closure (peer number of peer sending the data).
+ * @param size Buffer size.
+ * @param buf Buffer.
+ */
+static size_t
+tmt_rdy (void *cls, size_t size, void *buf)
+{
+  unsigned int peer_number = *(unsigned int *) cls;
+  struct GNUNET_MessageHeader *m = buf;
+  struct GNUNET_MESH_Tunnel *t;
+  struct test_traffic_message *msg = buf;
+  size_t msize = sizeof (struct test_traffic_message);
+  unsigned int *sent;
+  unsigned int target;
+  char *s;
+
+  if (0 == size || NULL == buf)
+    return 0;
+
+  if (1 == peer_number)
+  {
+    sent = &sent_fwd;
+    target = to_send_fwd;
+    t = t_fwd;
+    s = "FWD";
+  }
+  else if (2 == peer_number)
+  {
+    sent = &sent_bck;
+    target = to_send_bck;
+    t = t_bck;
+    s = "BCK";
+  }
+  else
+    GNUNET_abort();
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %s data packet # %4u\n",
+              s, *sent);
+  GNUNET_assert (size >= msize);
+  if (GNUNET_YES == started)
+  {
+    (*sent)++;
+    if (target > *sent) {
+      GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         &peer_id, msize, &tmt_rdy, cls);
+    }
+  }
+  m->size = htons (msize);
+  m->type = htons (1);
+  msg->data = htonl (*sent - 1);
+  return msize;
+}
+
+
 /**
  * Function is called whenever a message is received.
  *
@@ -135,13 +228,63 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
                const struct GNUNET_MessageHeader *message,
                const struct GNUNET_ATS_Information *atsi)
 {
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data callback\n");
-  got++;
-  if (TARGET == got)
+  struct test_traffic_message *msg;
+  unsigned int *peer_number = cls;
+  unsigned int *got;
+  unsigned int target;
+
+  if (GNUNET_NO == started)
   {
-    end_time = GNUNET_TIME_absolute_get();
-    result = GNUNET_OK;
-    finish();
+    GNUNET_break (2 == *peer_number);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got initial data packet\n");
+    started = GNUNET_YES;
+    start_time = GNUNET_TIME_absolute_get();
+    if (FWD != test) // Send leaf -> root
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending first BCK data\n");
+      GNUNET_MESH_notify_transmit_ready (t_bck, GNUNET_NO,
+                                        GNUNET_TIME_UNIT_FOREVER_REL,
+                                        NULL,
+                                        sizeof (struct test_traffic_message),
+                                        &tmt_rdy, &two);
+    }
+    if (BCK != test) // Send root -> leaf
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending first FWD data\n");
+      GNUNET_MESH_notify_transmit_ready (t_fwd, GNUNET_NO,
+                                        GNUNET_TIME_UNIT_FOREVER_REL,
+                                        &peer_id,
+                                        sizeof (struct test_traffic_message),
+                                        &tmt_rdy, &one);
+    }
+    return GNUNET_OK;
+  }
+
+  if (*peer_number == 1)
+  {
+    got = &got_bck;
+    target = to_send_bck;
+  }
+  else if (*peer_number == 2)
+  {
+    got = &got_fwd;
+    target = to_send_fwd;
+  }
+  else
+  {
+    GNUNET_abort();
+  }
+  msg = (struct test_traffic_message *) message;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got data packet # %u [%u]\n",
+              ntohl (msg->data), *got + 1);
+  (*got)++;
+  if (target == *got)
+  {
+    if (to_send_bck == sent_bck && to_send_fwd == sent_fwd) {
+      end_time = GNUNET_TIME_absolute_get();
+      result = GNUNET_OK;
+      finish();
+    }
     return GNUNET_OK;
   }
   if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
@@ -170,11 +313,12 @@ inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
 {
   unsigned int id = *(unsigned int *) cls;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received incoming tunnel\n");
-  if (id != 1)
+  t_bck = tunnel;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received incoming tunnel %p\n", tunnel);
+  if (id != 2)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "received incoming tunnel on peer 2\n");
+                "received incoming tunnel on peer 1\n");
     result = GNUNET_SYSERR;
   }
   return NULL;
@@ -197,42 +341,15 @@ inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
   unsigned int id = *(unsigned int *) cls;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "incoming tunnel closed\n");
-  if (id != 1)
+  if (id != 2)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "received closing tunnel on peer 2\n");
+                "received closing tunnel on peer 1\n");
     result = GNUNET_SYSERR;
   }
 }
 
 
-/**
- * Transmit ready callback.
- * 
- * @param cls Closure.
- * @param size Buffer size.
- * @param buf Buffer.
- */
-static size_t
-tmt_rdy (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_MessageHeader *m = buf;
-  size_t msize = sizeof (struct GNUNET_MessageHeader);
-
-  if (0 == size || NULL == buf)
-    return 0;
-  GNUNET_assert (size >= msize);
-  sent++;
-  if (TARGET > sent)
-    GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
-                                       GNUNET_TIME_UNIT_FOREVER_REL,
-                                       &peer_id, msize, &tmt_rdy, NULL);
-  m->size = htons (msize);
-  m->type = htons (1);
-  return msize;
-}
-
-
 /**
  * Method called whenever a peer has connected to the tunnel.
  *
@@ -245,10 +362,10 @@ peer_connected (void *cls, const struct GNUNET_PeerIdentity *peer,
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer connected\n");
   peer_id = *peer;
-  start_time = GNUNET_TIME_absolute_get();
-  GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL,
-                                     peer, sizeof (struct GNUNET_MessageHeader),
-                                     &tmt_rdy, NULL);
+  /* Force an inbound tunnel notification on peer 2 */
+  GNUNET_MESH_notify_transmit_ready (t_fwd, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL,
+                                     peer, sizeof (struct test_traffic_message),
+                                     &tmt_rdy, &one);
 }
 
 
@@ -269,8 +386,8 @@ peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer)
 /**
  * Handler array for traffic received on peer1
  */
-static struct GNUNET_MESH_MessageHandler handlers1[] = {
-  {&data_callback, 1, 0},
+static struct GNUNET_MESH_MessageHandler handlers[] = {
+  {&data_callback, 1, sizeof (struct test_traffic_message)},
   {NULL, 0, 0}
 };
 
@@ -278,7 +395,7 @@ static struct GNUNET_MESH_MessageHandler handlers1[] = {
 /**
  * Handler array for traffic received on peer2 (none expected)
  */
-static struct GNUNET_MESH_MessageHandler handlers2[] = { {NULL, 0, 0} };
+static struct GNUNET_MESH_MessageHandler handlers_null[] = { {NULL, 0, 0} };
 
 
 /**
@@ -289,8 +406,8 @@ run (void *cls,
      const struct GNUNET_CONFIGURATION_Handle *cfg,
      struct GNUNET_TESTING_Peer *peer)
 {
-  static const GNUNET_MESH_ApplicationType app1[] = { 1, 0 };
-  static const GNUNET_MESH_ApplicationType app2[] = { 0 };
+  static const GNUNET_MESH_ApplicationType app1[] = { 0 };
+  static const GNUNET_MESH_ApplicationType app2[] = { 1, 0 };
 
   abort_task =
       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
@@ -298,16 +415,17 @@ run (void *cls,
                                     NULL);
   mesh_peer_1 = GNUNET_MESH_connect (cfg,       /* configuration */
                                      (void *) &one,     /* cls */
-                                     &inbound_tunnel,   /* inbound new hndlr */
-                                     &inbound_end,      /* inbound end hndlr */
-                                     handlers1, /* traffic handlers */
+                                     NULL,      /* inbound new hndlr */
+                                     NULL,      /* inbound end hndlr */
+                                     /* traffic handlers */
+                                     test == FWD ? handlers_null : handlers,
                                      app1);     /* apps offered */
 
   mesh_peer_2 = GNUNET_MESH_connect (cfg,       /* configuration */
                                      (void *) &two,     /* cls */
-                                     NULL,   /* inbound new hndlr */
-                                     NULL,      /* inbound end hndlr */
-                                     handlers2, /* traffic handlers */
+                                     &inbound_tunnel,   /* inbound new hndlr */
+                                     &inbound_end,      /* inbound end hndlr */
+                                     handlers,          /* traffic handlers */
                                      app2);     /* apps offered */
   if (NULL == mesh_peer_1 || NULL == mesh_peer_2)
   {
@@ -319,9 +437,9 @@ run (void *cls,
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to mesh\n");
   }
-  t = GNUNET_MESH_tunnel_create (mesh_peer_2, NULL, &peer_connected,
-                                 &peer_disconnected, (void *) &two);
-  GNUNET_MESH_peer_request_connect_by_type (t, 1);
+  t_fwd = GNUNET_MESH_tunnel_create (mesh_peer_1, NULL, &peer_connected,
+                                     &peer_disconnected, (void *) &two);
+  GNUNET_MESH_peer_request_connect_by_type (t_fwd, 1);
 }
 
 
@@ -331,6 +449,29 @@ run (void *cls,
 int
 main (int argc, char *argv[])
 {
+  if (strstr (argv[0], "test_mesh_local_traffic_fwd") != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FWD\n");
+    test = FWD;
+    to_send_fwd = TARGET;
+  }
+  else if (strstr (argv[0], "test_mesh_local_traffic_bck") != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BCK\n");
+    test = BCK;
+    to_send_bck = TARGET;
+  }
+  else if (strstr (argv[0], "test_mesh_local_traffic_both") != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BOTH\n");
+    test = BOTH;
+    to_send_bck = to_send_fwd = TARGET;
+  }
+  else
+  {
+    return 1;
+  }
+
   if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-traffic",
                                    "test_mesh.conf",
                                    &run, NULL))
@@ -338,22 +479,45 @@ main (int argc, char *argv[])
   if (result != GNUNET_OK)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed. Sent: %u, Got: %u\n",
-                sent, got);
+                "Failed.\nFWD expected: %u, Sent: %u, Got: %u\n",
+                to_send_fwd, sent_fwd, got_fwd);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "BCK expected: %u, Sent: %u, Got: %u\n",
+                to_send_bck, sent_bck, got_bck);
     return 1;
   }
   else
   {
     struct GNUNET_TIME_Relative total_time;
+    unsigned int total_traffic;
+    char *name;
+
+    total_traffic = BOTH == test ? 2 * TARGET : TARGET;
+    switch (test)
+    {
+      case FWD:
+        name = "Local traffic Root to Leaf";
+        break;
+      case BCK:
+        name = "Local traffic Leaf to Root";
+        break;
+      case BOTH:
+        name = "Local traffic bidirectional";
+        break;
+      default:
+        GNUNET_assert (0);
+    }
 
     total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
     FPRINTF (stderr, "\nTest time %llu ms\n",
              (unsigned long long) total_time.rel_value);
-    FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
-             4 * 1000.0 / total_time.rel_value); // 4bytes * ms
+    FPRINTF (stderr, "Test payload bandwidth: %f kb/s\n",
+             total_traffic * 4.0 / total_time.rel_value); // 4bytes * kb/ms
     FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
-             TARGET * 1000.0 / total_time.rel_value); // 1000 packets * ms
-    GAUGER ("MESH", "Tunnel 5 peers", TARGET * 1000.0 / total_time.rel_value,
+             total_traffic * 1000.0 / total_time.rel_value); // 1000 packets * ms
+    GAUGER ("MESH",
+            name,
+            total_traffic * 1000.0 / total_time.rel_value,
             "packets/s");
   }
   return 0;