gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r31802 - gnunet/src/testbed


From: gnunet
Subject: [GNUnet-SVN] r31802 - gnunet/src/testbed
Date: Mon, 6 Jan 2014 17:37:21 +0100

Author: harsha
Date: 2014-01-06 17:37:21 +0100 (Mon, 06 Jan 2014)
New Revision: 31802

Added:
   gnunet/src/testbed/generate-underlay-topology.c
Modified:
   gnunet/src/testbed/
   gnunet/src/testbed/Makefile.am
   gnunet/src/testbed/testbed_api_topology.c
   gnunet/src/testbed/testbed_api_topology.h
Log:
- underlay topology generation


Index: gnunet/src/testbed
===================================================================
--- gnunet/src/testbed  2014-01-06 05:50:58 UTC (rev 31801)
+++ gnunet/src/testbed  2014-01-06 16:37:21 UTC (rev 31802)

Property changes on: gnunet/src/testbed
___________________________________________________________________
Modified: svn:ignore
## -50,3 +50,4 ##
 buildvars.py
 test_testbed_api_barriers
 gnunet-daemon-testbed-underlay
+generate-underlay-topology
Modified: gnunet/src/testbed/Makefile.am
===================================================================
--- gnunet/src/testbed/Makefile.am      2014-01-06 05:50:58 UTC (rev 31801)
+++ gnunet/src/testbed/Makefile.am      2014-01-06 16:37:21 UTC (rev 31802)
@@ -18,6 +18,7 @@
 
 if HAVE_SQLITE
   underlay_daemon = gnunet-daemon-testbed-underlay
+  generate_underlay = generate-underlay-topology
 endif
 
 libexec_PROGRAMS = \
@@ -30,6 +31,9 @@
 bin_PROGRAMS = \
   gnunet-testbed-profiler
 
+noinst_PROGRAMS = \
+  $(generate_underlay)
+
 gnunet_service_testbed_SOURCES = \
   gnunet-service-testbed.c gnunet-service-testbed.h \
   gnunet-service-testbed_links.c gnunet-service-testbed_links.h \
@@ -135,6 +139,15 @@
  $(GN_LIB_LDFLAGS) \
  -version-info 0:0:0
 
+generate_underlay_topology_SOURCES = generate-underlay-topology.c
+generate_underlay_topology_LDADD = $(XLIB) \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/testbed/libgnunettestbed.la \
+ $(LTLIBINTL) -lsqlite3
+generate_underlay_topology_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ libgnunettestbed.la
+
 check_PROGRAMS = \
   test_testbed_api_hosts \
   test_testbed_logger_api \

Added: gnunet/src/testbed/generate-underlay-topology.c
===================================================================
--- gnunet/src/testbed/generate-underlay-topology.c                             
(rev 0)
+++ gnunet/src/testbed/generate-underlay-topology.c     2014-01-06 16:37:21 UTC 
(rev 31802)
@@ -0,0 +1,241 @@
+/*
+      This file is part of GNUnet
+      (C) 2008--2014 Christian Grothoff (and other contributing authors)
+
+      GNUnet is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published
+      by the Free Software Foundation; either version 3, or (at your
+      option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with GNUnet; see the file COPYING.  If not, write to the
+      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+      Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file testbed/generate-underlay-topology.c
+ * @brief Program to generate a database file containing given underlay 
topology
+ * @author Sree Harsha Totakura <address@hidden> 
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testbed_service.h"
+#include "testbed_api_topology.h"
+
+#define LOG(type, ...)                          \
+  GNUNET_log (type, __VA_ARGS__)
+
+
+#define LOG_ERROR(...)                          \
+  LOG (GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__)
+
+
+/**
+ * The topology to generate
+ */
+enum GNUNET_TESTBED_TopologyOption topology;
+
+/**
+ * The number of peers to include in the topology
+ */
+static int num_peers;
+
+/**
+ * program result
+ */
+static int exit_result;
+
+
+/**
+ * Functions of this type are called to process underlay link
+ *
+ * @param cls closure
+ * @param A offset of first peer
+ * @param B offset of second peer
+ * @param bandwidth the bandwidth of the link in bytes per second
+ * @param latency the latency of link in milliseconds
+ * @param loss the percentage of messages dropped on the link
+ * @return GNUNET_OK to continue processing; GNUNET_SYSERR to abort
+ */
+static int
+link_processor (void *cls,
+                unsigned int A,
+                unsigned int B,
+                unsigned int bandwidth,
+                unsigned int latency,
+                unsigned int loss)
+{
+  GNUNET_break (0);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Main run function.
+ *
+ * @param cls NULL
+ * @param args arguments passed to GNUNET_PROGRAM_run
+ * @param cfgfile the path to configuration file
+ * @param cfg the configuration file handle
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *config)
+{
+  const char *dbfile;
+  const char *topology_string;
+  unsigned int arg_uint1;
+  unsigned int arg_uint2;
+  const char *arg_str1;
+  const char *value;
+  unsigned int argc;
+
+  argc = 0;
+  if (NULL == args)
+  {
+    LOG_ERROR (_("Need atleast 2 arguments\n"));
+    return;
+  }
+  if (NULL == (dbfile = args[argc++]))
+  {
+    LOG_ERROR (_("Database filename missing\n"));
+    return;
+  }
+  if (NULL == (topology_string = args[argc++]))
+  {
+    LOG_ERROR (_("Topology string missing\n"));
+    return;
+  }
+  if (GNUNET_YES != GNUNET_TESTBED_topology_get_ (&topology, topology_string))
+  {
+    LOG_ERROR (_("Invalid topology: %s\n"), topology_string);
+    return;
+  }
+  /* parse for first TOPOOPT.  This can either be arg_uint1 or arg_str1 */
+  switch (topology)
+  {
+  case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
+  case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
+  case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
+  case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
+    if (NULL == (value = args[argc++]))
+    {
+      LOG_ERROR (_("An argument is missing for given topology `%s'\n"),
+                 topology_string);
+      return;
+    }
+    if (-1 == SSCANF (value, "%u", &arg_uint1))
+    {
+      LOG_ERROR (_("Invalid argument `%s' given as topology argument\n"),
+                 value);
+      return;
+    }
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
+    if (NULL == (arg_str1 = args[argc++]))
+    {
+      LOG_ERROR (_("Filename argument missing for topology `%s'\n"),
+                 topology_string);
+      return;
+    }
+    break;
+  default:
+    GNUNET_assert (0);
+  }
+  /* parse for second TOPOOPT.  Only required for SCALE_FREE topology */
+  switch (topology)
+  {
+  case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
+    if (NULL == (value = args[argc++]))
+    {
+      LOG_ERROR (_("Second argument for topology `%s' is missing\n"),
+                 topology_string);
+      return;
+    }
+    if (-1 == SSCANF (value, "%u", &arg_uint2))
+    {
+      LOG_ERROR (_("Invalid argument `%s'; expecting unsigned int\n"), value);
+      return;
+    }
+    break;
+  default:
+    GNUNET_assert (0);
+  }
+  /* contruct topologies */
+  switch (topology)
+  {
+  case GNUNET_TESTBED_TOPOLOGY_LINE:
+  case GNUNET_TESTBED_TOPOLOGY_RING:
+  case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
+  case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
+    GNUNET_TESTBED_underlay_construct_ (num_peers, link_processor, NULL,
+                                        topology);
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
+  case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
+  case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
+    GNUNET_TESTBED_underlay_construct_ (num_peers, link_processor, NULL,
+                                        topology,
+                                        arg_uint1);
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
+    GNUNET_TESTBED_underlay_construct_ (num_peers, link_processor, NULL,
+                                        topology,
+                                        arg_str1);
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
+    GNUNET_TESTBED_underlay_construct_ (num_peers, link_processor, NULL,
+                                        topology,
+                                        arg_uint1,
+                                        arg_uint2);
+    break;
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+/**
+ * Main
+ */
+int
+main (int argc, char *const argv[])
+{
+  struct GNUNET_GETOPT_CommandLineOption option[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  int ret;
+  
+  exit_result = GNUNET_SYSERR;
+  ret =
+      GNUNET_PROGRAM_run (argc, argv, "gnunet-underlay-topology",
+                          _("Generates SQLite3 database representing a given 
underlay topology.\n"
+                            "Usage: gnunet-underlay-topology [OPTIONS] 
db-filename TOPO [TOPOOPTS]\n"
+                            "The following options are available for TOPO 
followed by TOPOOPTS if applicable:\n"
+                            "\t LINE\n"
+                            "\t RING\n"
+                            "\t RANDOM <num_rnd_links>\n"
+                            "\t SMALL_WORLD <num_rnd_links>\n"
+                            "\t SMALL_WORLD_RING <num_rnd_links>\n"
+                            "\t CLIQUE\n"
+                            "\t 2D_TORUS\n"
+                            "\t SCALE_FREE <cap> <m>\n"
+                            "\t FROM_FILE <filename>\n"
+                            "TOPOOPTS:\n"
+                            "\t num_rnd_links: The number of random links\n"
+                            "\t cap: the maximum number of links a node can 
have\n"
+                            "\t m: the number of links a node should have 
while joining the network\n"
+                            "\t filename: the path of the file which contains 
topology information\n"
+                            "NOTE: the format of the above file is descibed 
here: https://www.gnunet.org/content/topology-file-format\n";),
+                          option, &run, NULL);
+  if ((GNUNET_OK != ret) || (GNUNET_OK != exit_result))
+    return 1;
+  return 0;
+}

Modified: gnunet/src/testbed/testbed_api_topology.c
===================================================================
--- gnunet/src/testbed/testbed_api_topology.c   2014-01-06 05:50:58 UTC (rev 
31801)
+++ gnunet/src/testbed/testbed_api_topology.c   2014-01-06 16:37:21 UTC (rev 
31802)
@@ -78,6 +78,38 @@
 };
 
 
+/**
+ * Representation of an underlay link
+ */
+struct UnderlayLink
+{
+  /**
+   * position of peer A's handle in peers array
+   */
+  uint32_t A;
+
+  /**
+   * position of peer B's handle in peers array
+   */
+  uint32_t B;
+
+  /**
+   * Bandwidth of the link in bytes per second
+   */
+  uint32_t bandwidth;
+
+  /**
+   * Latency of the link in milliseconds
+   */
+  uint32_t latency;
+
+  /**
+   * Loss in the link in percentage of message dropped
+   */
+  uint32_t loss;
+};
+
+
 struct RetryListEntry
 {
   /**
@@ -98,9 +130,9 @@
 
 
 /**
- * Context information for topology operations
+ * Context information for overlay topologies
  */
-struct TopologyContext
+struct TopologyContextOverlay
 {
   /**
    * The array of peers
@@ -138,16 +170,6 @@
   struct RetryListEntry *rl_tail;
 
   /**
-   * The number of peers
-   */
-  unsigned int num_peers;
-
-  /**
-   * The size of the link array
-   */
-  unsigned int link_array_size;
-
-  /**
    * How many retries to do before we give up
    */
   unsigned int retry_cnt;
@@ -175,6 +197,66 @@
 
 
 /**
+ * Topology context information for underlay topologies
+ */
+struct TopologyContextUnderlay
+{
+  /**
+   * The link array
+   */
+  struct UnderlayLink *link_array;
+};
+
+
+/**
+ * Context information for topology operations
+ */
+struct TopologyContext
+{
+  /**
+   * The type of this context
+   */
+  enum {
+    
+    /**
+     * Type for underlay topology
+     */
+    TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0,
+    
+    /**
+     * Type for overlay topology
+     */
+    TOPOLOGYCONTEXT_TYPE_OVERLAY
+
+  } type;
+
+  union {
+
+    /**
+     * Topology context information for overlay topology
+     */
+    struct TopologyContextOverlay overlay;
+
+    /**
+     * Topology context information for underlay topology
+     */
+    struct TopologyContextUnderlay underlay;
+  } u;
+
+  /**
+   * The number of peers
+   */
+  unsigned int num_peers;
+
+  /**
+   * The size of the link array
+   */
+  unsigned int link_array_size;
+
+};
+
+
+/**
  * A array of names representing topologies. Should be in sync with enum
  * GNUNET_TESTBED_TopologyOption
  */
@@ -222,7 +304,9 @@
   "INTERNAT",
 
     /**
-     * Scale free topology. No options.
+     * Scale free topology. Followed by the maximum number of links a node can
+     * have (unsigned int); and the number of links a new node should have when
+     * it is added to the network (unsigned int)
      */
   "SCALE_FREE",
 
@@ -262,50 +346,53 @@
 {
   struct OverlayLink *link = cls;
   struct TopologyContext *tc;
+  struct TopologyContextOverlay *overlay;
   struct RetryListEntry *retry_entry;
 
   GNUNET_assert (op == link->op);
   GNUNET_TESTBED_operation_done (op);
   link->op = NULL;
   tc = link->tc;
+  GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
+  overlay = &tc->u.overlay;
   if (NULL != emsg)
   {
-    tc->nfailures++;
-    if (0 != tc->retry_cnt)
+    overlay->nfailures++;
+    if (0 != overlay->retry_cnt)
     {
       LOG (GNUNET_ERROR_TYPE_WARNING,
            "Error while establishing a link: %s -- Retrying\n", emsg);
       retry_entry = GNUNET_new (struct RetryListEntry);
       retry_entry->link = link;
-      GNUNET_CONTAINER_DLL_insert_tail (tc->rl_head, tc->rl_tail, retry_entry);
+      GNUNET_CONTAINER_DLL_insert_tail (overlay->rl_head, overlay->rl_tail, 
retry_entry);
     }
   }
   else
-    tc->nsuccess++;
-  tc->ncompleted++;
-  if (tc->ncompleted < tc->nlinks)
+    overlay->nsuccess++;
+  overlay->ncompleted++;
+  if (overlay->ncompleted < overlay->nlinks)
     return;
-  if ((0 != tc->retry_cnt) && (NULL != tc->rl_head))
+  if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head))
   {
-    tc->retry_cnt--;
-    tc->ncompleted = 0;
-    tc->nlinks = 0;
-    while (NULL != (retry_entry = tc->rl_head))
+    overlay->retry_cnt--;
+    overlay->ncompleted = 0;
+    overlay->nlinks = 0;
+    while (NULL != (retry_entry = overlay->rl_head))
     {
       link = retry_entry->link;
       link->op =
-          GNUNET_TESTBED_overlay_connect (tc->op_cls, &overlay_link_completed,
-                                          link, tc->peers[link->A],
-                                          tc->peers[link->B]);
-      tc->nlinks++;
-      GNUNET_CONTAINER_DLL_remove (tc->rl_head, tc->rl_tail, retry_entry);
+          GNUNET_TESTBED_overlay_connect (overlay->op_cls, 
&overlay_link_completed,
+                                          link, overlay->peers[link->A],
+                                          overlay->peers[link->B]);
+      overlay->nlinks++;
+      GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, 
retry_entry);
       GNUNET_free (retry_entry);
     }
     return;
   }
-  if (NULL != tc->comp_cb)
+  if (NULL != overlay->comp_cb)
   {
-    tc->comp_cb (tc->comp_cb_cls, tc->nsuccess, tc->nfailures);
+    overlay->comp_cb (overlay->comp_cb_cls, overlay->nsuccess, 
overlay->nfailures);
   }
 }
 
@@ -320,16 +407,19 @@
 opstart_overlay_configure_topology (void *cls)
 {
   struct TopologyContext *tc = cls;
+  struct TopologyContextOverlay *overlay;
   unsigned int p;
 
-  tc->nlinks = tc->link_array_size;
+  GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
+  overlay = &tc->u.overlay;
+  overlay->nlinks = tc->link_array_size;
   for (p = 0; p < tc->link_array_size; p++)
   {
-    tc->link_array[p].op =
-        GNUNET_TESTBED_overlay_connect (tc->op_cls, &overlay_link_completed,
-                                        &tc->link_array[p],
-                                        tc->peers[tc->link_array[p].A],
-                                        tc->peers[tc->link_array[p].B]);
+    overlay->link_array[p].op =
+        GNUNET_TESTBED_overlay_connect (overlay->op_cls, 
&overlay_link_completed,
+                                        &overlay->link_array[p],
+                                        
overlay->peers[overlay->link_array[p].A],
+                                        
overlay->peers[overlay->link_array[p].B]);
   }
 }
 
@@ -343,20 +433,23 @@
 oprelease_overlay_configure_topology (void *cls)
 {
   struct TopologyContext *tc = cls;
+  struct TopologyContextOverlay *overlay;
   struct RetryListEntry *retry_entry;
   unsigned int p;
 
-  while (NULL != (retry_entry = tc->rl_head))
+  GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
+  overlay = &tc->u.overlay;
+  while (NULL != (retry_entry = overlay->rl_head))
   {
-    GNUNET_CONTAINER_DLL_remove (tc->rl_head, tc->rl_tail, retry_entry);
+    GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, 
retry_entry);
     GNUNET_free (retry_entry);
   }
-  if (NULL != tc->link_array)
+  if (NULL != overlay->link_array)
   {
     for (p = 0; p < tc->link_array_size; p++)
-      if (NULL != tc->link_array[p].op)
-        GNUNET_TESTBED_operation_done (tc->link_array[p].op);
-    GNUNET_free (tc->link_array);
+      if (NULL != overlay->link_array[p].op)
+        GNUNET_TESTBED_operation_done (overlay->link_array[p].op);
+    GNUNET_free (overlay->link_array);
   }
   GNUNET_free (tc);
 }
@@ -365,22 +458,47 @@
 /**
  * Populates the OverlayLink structure.
  *
- * @param link the OverlayLink
+ * @param offset the offset of the link array to use
  * @param A the peer A. Should be different from B
  * @param B the peer B. Should be different from A
  * @param tc the TopologyContext
  * @return
  */
 static void
-make_link (struct OverlayLink *link, uint32_t A, uint32_t B,
+make_link (unsigned int offset, uint32_t A, uint32_t B,
            struct TopologyContext *tc)
 {
   GNUNET_assert (A != B);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A);
-  link->A = A;
-  link->B = B;
-  link->op = NULL;
-  link->tc = tc;
+  switch (tc->type)
+  {
+  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
+    {
+      struct TopologyContextOverlay *overlay;
+      struct OverlayLink *olink;
+      
+      overlay = &tc->u.overlay;
+      GNUNET_assert (offset < tc->link_array_size);
+      olink = &overlay->link_array[offset];
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A);
+      olink->A = A;
+      olink->B = B;
+      olink->op = NULL;
+      olink->tc = tc;
+    }
+    break;
+  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
+    {
+      struct TopologyContextUnderlay *underlay;
+      struct UnderlayLink *ulink;
+      
+      underlay = &tc->u.underlay;
+      GNUNET_assert (offset < tc->link_array_size);
+      ulink = &underlay->link_array[offset];
+      ulink->A = A;
+      ulink->B = B;
+    }
+    break;
+  }
 }
 
 
@@ -395,10 +513,29 @@
   unsigned int cnt;
 
   tc->link_array_size = tc->num_peers - 1;
-  tc->link_array =
-      GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
-  for (cnt = 0; cnt < (tc->num_peers - 1); cnt++)
-    make_link (&tc->link_array[cnt], cnt, cnt + 1, tc);
+  switch (tc->type)
+  {
+  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
+    {
+      struct TopologyContextOverlay *overlay;
+      
+      overlay = &tc->u.overlay;
+      overlay->link_array =
+          GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
+    }
+    break;
+  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
+    {
+      struct TopologyContextUnderlay *underlay;
+      
+      underlay = &tc->u.underlay;
+      underlay->link_array =
+          GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size);
+    }
+    break;
+  }
+  for (cnt = 0; cnt < (tc->link_array_size); cnt++)
+    make_link (cnt, cnt, cnt + 1, tc);
 }
 
 
@@ -412,11 +549,30 @@
 {
   gen_topo_line (tc);
   tc->link_array_size++;
-  tc->link_array =
-      GNUNET_realloc (tc->link_array,
-                      sizeof (struct OverlayLink) * tc->link_array_size);
-  make_link (&tc->link_array[tc->link_array_size - 1], tc->num_peers - 1, 0,
-             tc);
+  switch (tc->type)
+  {
+  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
+    {
+      struct TopologyContextOverlay *overlay;
+
+      overlay = &tc->u.overlay;
+      overlay->link_array =
+          GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) *
+                          tc->link_array_size);
+    }
+    break;
+  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
+    {
+      struct TopologyContextUnderlay *underlay;
+      
+      underlay = &tc->u.underlay;
+      underlay->link_array =
+          GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) *
+      tc->link_array_size);
+    }
+    break;
+  }
+  make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc);
 }
 
 
@@ -495,20 +651,39 @@
 
   tc->link_array_size =
       GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len);
-  tc->link_array =
-      GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
+  switch (tc->type)
+  {
+  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
+    {
+      struct TopologyContextOverlay *overlay;
+      
+      overlay = &tc->u.overlay;
+      overlay->link_array =
+          GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
+    }
+    break;
+  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
+    {
+      struct TopologyContextUnderlay *underlay;
+
+      underlay = &tc->u.underlay;
+      underlay->link_array =
+          GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size);
+      break;
+    }
+  }
   cnt = 0;
   offset = 0;
   for (y = 0; y < rows; y++)
   {
     for (x = 0; x < rows_len[y] - 1; x++)
     {
-      make_link (&tc->link_array[cnt], offset + x, offset + x + 1, tc);
+      make_link (cnt, offset + x, offset + x + 1, tc);
       cnt++;
     }
     if (0 == x)
       break;
-    make_link (&tc->link_array[cnt], offset + x, offset, tc);
+    make_link (cnt, offset + x, offset, tc);
     cnt++;
     offset += rows_len[y];
   }
@@ -520,14 +695,13 @@
       if (x >= rows_len[y + 1])
         break;
       GNUNET_assert (x < rows_len[y + 1]);
-      make_link (&tc->link_array[cnt], offset + x, offset + rows_len[y] + x,
-                 tc);
+      make_link (cnt, offset + x, offset + rows_len[y] + x, tc);
       offset += rows_len[y];
       cnt++;
     }
     if (0 == offset)
       break;
-    make_link (&tc->link_array[cnt], offset + x, x, tc);
+    make_link (cnt, offset + x, x, tc);
     cnt++;
   }
   GNUNET_assert (cnt == tc->link_array_size);
@@ -553,21 +727,53 @@
 
   if (GNUNET_YES == append)
   {
-    GNUNET_assert ((0 < tc->link_array_size) && (NULL != tc->link_array));
     index = tc->link_array_size;
     tc->link_array_size += links;
-    tc->link_array =
-        GNUNET_realloc (tc->link_array,
-                        sizeof (struct OverlayLink) * tc->link_array_size);
   }
   else
   {
-    GNUNET_assert ((0 == tc->link_array_size) && (NULL == tc->link_array));
     index = 0;
     tc->link_array_size = links;
-    tc->link_array =
-        GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
   }
+  switch (tc->type)
+  {
+  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
+    {
+      struct TopologyContextOverlay *overlay;
+
+      overlay = &tc->u.overlay;
+      if (GNUNET_YES != append)
+      {
+        GNUNET_assert (NULL == overlay->link_array);
+        overlay->link_array =
+            GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
+        break;
+      }
+      GNUNET_assert ((0 < tc->link_array_size) && (NULL != 
overlay->link_array));
+      overlay->link_array =
+          GNUNET_realloc (overlay->link_array,
+                          sizeof (struct OverlayLink) * tc->link_array_size);
+      break;
+    }
+  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
+    {
+      struct TopologyContextUnderlay *underlay;
+
+      underlay = &tc->u.underlay;
+      if (GNUNET_YES != append)
+      {
+        GNUNET_assert (NULL == underlay->link_array);
+        underlay->link_array =
+            GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size);
+        break;
+      }
+      GNUNET_assert ((0 < tc->link_array_size) && (NULL != 
underlay->link_array));
+      underlay->link_array =
+          GNUNET_realloc (underlay->link_array,
+                          sizeof (struct UnderlayLink) * tc->link_array_size);
+      break;
+    }
+  }
   for (cnt = 0; cnt < links; cnt++)
   {
     do
@@ -578,7 +784,7 @@
           GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
     }
     while (A_rand == B_rand);
-    make_link (&tc->link_array[index + cnt], A_rand, B_rand, tc);
+    make_link (index+cnt, A_rand, B_rand, tc);
   }
 }
 
@@ -594,7 +800,7 @@
  *   network
  */
 static void
-gen_scale_free (struct TopologyContext *tc, uint16_t cap, uint8_t m)
+gen_topo_scale_free (struct TopologyContext *tc, uint16_t cap, uint8_t m)
 {
   unsigned int *deg;
   unsigned int *etab;
@@ -610,13 +816,32 @@
 
   etaboff = 0;
   tc->link_array_size = tc->num_peers * m;
-  tc->link_array = GNUNET_malloc_large (sizeof (struct OverlayLink) *
-                                        tc->link_array_size);
+  switch (tc->type)
+  {
+  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
+    {
+      struct TopologyContextOverlay *overlay;
+
+      overlay = &tc->u.overlay;
+      overlay->link_array = GNUNET_malloc_large (sizeof (struct OverlayLink) *
+                                                 tc->link_array_size);
+    }
+    break;
+  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
+    {
+      struct TopologyContextUnderlay *underlay;
+
+      underlay = &tc->u.underlay;
+      underlay->link_array = GNUNET_malloc_large (sizeof (struct UnderlayLink) 
*
+                                                  tc->link_array_size);
+    }
+    break;
+  }
   etab = GNUNET_malloc_large (sizeof (unsigned int) * 2 * tc->link_array_size);
   deg = GNUNET_malloc (sizeof (unsigned int) * tc->num_peers);
   used = GNUNET_malloc (sizeof (unsigned int) * m);
   /* start by connecting peer 1 to peer 0 */
-  make_link (&tc->link_array[0], 0, 1, tc);
+  make_link (0, 0, 1, tc);
   deg[0]++;
   deg[1]++;
   etab[etaboff++] = 0;
@@ -654,7 +879,7 @@
       for (cnt2 = 0; cnt2 < cnt; cnt2++)
         if (random_peer == used[cnt2])
           goto redo;
-      make_link (&tc->link_array[links + cnt], random_peer, peer, tc);
+      make_link (links + cnt, random_peer, peer, tc);
       deg[random_peer]++;
       deg[peer]++;
       used[cnt] = random_peer;
@@ -671,9 +896,27 @@
   GNUNET_free (deg);
   GNUNET_assert (links <= tc->link_array_size);
   tc->link_array_size = links;
-  tc->link_array =
-      GNUNET_realloc (tc->link_array,
-                      sizeof (struct OverlayLink) * tc->link_array_size);
+  switch (tc->type)
+  {
+  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
+    {
+      struct TopologyContextOverlay *overlay;
+      
+      overlay = &tc->u.overlay;
+      overlay->link_array = 
+          GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) * 
tc->link_array_size);
+    }
+    break;
+  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
+    {
+      struct TopologyContextUnderlay *underlay;
+
+      underlay = &tc->u.underlay;
+      underlay->link_array =
+          GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) * 
tc->link_array_size);
+    }
+    break;
+  }
 }
 
 
@@ -798,12 +1041,31 @@
       if (peer_id != other_peer_id)
       {
         tc->link_array_size++;
-        tc->link_array =
-            GNUNET_realloc (tc->link_array,
-                            sizeof (struct OverlayLink) * tc->link_array_size);
+        switch (tc->type)
+        {
+        case TOPOLOGYCONTEXT_TYPE_OVERLAY:
+          {
+            struct TopologyContextOverlay *overlay;
+            
+            overlay = &tc->u.overlay;
+            overlay->link_array = 
+                GNUNET_realloc (overlay->link_array,
+                                sizeof (struct OverlayLink) * 
tc->link_array_size);
+          }
+          break;
+        case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
+          {
+            struct TopologyContextUnderlay *underlay;
+            
+            underlay = &tc->u.underlay;
+            underlay->link_array =
+                GNUNET_realloc (underlay->link_array,
+                                sizeof (struct UnderlayLink) * 
tc->link_array_size);
+          }
+          break;
+        }
         offset += end - &data[offset];
-        make_link (&tc->link_array[tc->link_array_size - 1], peer_id,
-                   other_peer_id, tc);
+        make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc);
       }
       else
         LOG (GNUNET_ERROR_TYPE_WARNING,
@@ -829,13 +1091,79 @@
   {
     LOG (GNUNET_ERROR_TYPE_WARNING, "Removing link data read from the file\n");
     tc->link_array_size = 0;
-    GNUNET_free_non_null (tc->link_array);
-    tc->link_array = NULL;
+    switch (tc->type)
+    {
+    case TOPOLOGYCONTEXT_TYPE_OVERLAY:
+      {
+        struct TopologyContextOverlay *overlay;
+        
+        overlay = &tc->u.overlay;
+        GNUNET_free_non_null (overlay->link_array);
+        overlay->link_array = NULL;
+      }
+      break;
+    case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
+      {
+        struct TopologyContextUnderlay *underlay;
+        
+        underlay = &tc->u.underlay;
+        GNUNET_free_non_null (underlay->link_array);
+        underlay->link_array = NULL;
+      }
+      break;
+    }
   }
 }
 
 
 /**
+ * Generates clique topology
+ *
+ * @param tc the topology context
+ */
+static void
+gen_topo_clique (struct TopologyContext *tc)
+{
+  unsigned int cnt;
+  unsigned int offset;
+  unsigned int neighbour;
+  
+  tc->link_array_size = tc->num_peers * (tc->num_peers - 1);
+  switch (tc->type)
+  {
+  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
+    {
+      struct TopologyContextOverlay *overlay;
+
+      overlay = &tc->u.overlay;
+      overlay->link_array = GNUNET_malloc (sizeof (struct OverlayLink) *
+                                           tc->link_array_size);
+    }
+    break;
+  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
+    {
+      struct TopologyContextUnderlay *underlay;
+
+      underlay = &tc->u.underlay;
+      underlay->link_array = GNUNET_malloc (sizeof (struct UnderlayLink) *
+                                            tc->link_array_size);
+    }
+  }
+  offset = 0;
+  for (cnt = 0; cnt < tc->num_peers; cnt++)
+  {
+    for (neighbour = 0; neighbour < tc->num_peers; neighbour++)
+    {
+      if (neighbour == cnt)
+        continue;
+      make_link (offset, cnt, neighbour, tc);
+      offset++;
+    }
+  }
+}
+
+
+/**
  * Configure overall network topology to have a particular shape.
  *
  * @param op_cls closure argument to give with the operation event
@@ -915,21 +1243,23 @@
                                               va_list va)
 {
   struct TopologyContext *tc;
+  struct TopologyContextOverlay *overlay;
   struct GNUNET_TESTBED_Operation *op;
   struct GNUNET_TESTBED_Controller *c;
   enum GNUNET_TESTBED_TopologyOption secondary_option;
-  unsigned int cnt;
 
   if (num_peers < 2)
     return NULL;
   c = peers[0]->controller;
   tc = GNUNET_new (struct TopologyContext);
-  tc->peers = peers;
+  tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY;
+  overlay = &tc->u.overlay;
+  overlay->peers = peers;
   tc->num_peers = num_peers;
-  tc->op_cls = op_cls;
-  tc->retry_cnt = DEFAULT_RETRY_CNT;
-  tc->comp_cb = comp_cb;
-  tc->comp_cb_cls = comp_cb_cls;
+  overlay->op_cls = op_cls;
+  overlay->retry_cnt = DEFAULT_RETRY_CNT;
+  overlay->comp_cb = comp_cb;
+  overlay->comp_cb_cls = comp_cb_cls;
   switch (topo)
   {
   case GNUNET_TESTBED_TOPOLOGY_LINE:
@@ -946,28 +1276,7 @@
     gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
     break;
   case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
-    tc->link_array_size = num_peers * (num_peers - 1);
-    tc->link_array =
-        GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
-    {
-      unsigned int offset;
-
-      offset = 0;
-      for (cnt = 0; cnt < num_peers; cnt++)
-      {
-        unsigned int neighbour;
-
-        for (neighbour = 0; neighbour < num_peers; neighbour++)
-        {
-          if (neighbour == cnt)
-            continue;
-          tc->link_array[offset].A = cnt;
-          tc->link_array[offset].B = neighbour;
-          tc->link_array[offset].tc = tc;
-          offset++;
-        }
-      }
-    }
+    gen_topo_clique (tc);
     break;
   case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
     gen_topo_2dtorus (tc);
@@ -984,7 +1293,7 @@
 
       cap = (uint16_t) va_arg (va, unsigned int);
       m = (uint8_t) va_arg (va, unsigned int);
-      gen_scale_free (tc, cap, m);
+      gen_topo_scale_free (tc, cap, m);
     }
     break;
   case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
@@ -1009,14 +1318,14 @@
     switch (secondary_option)
     {
     case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT:
-      tc->retry_cnt =  va_arg (va, unsigned int);
+      overlay->retry_cnt =  va_arg (va, unsigned int);
       break;
     case GNUNET_TESTBED_TOPOLOGY_OPTION_END:
       break;
     default:
       GNUNET_break (0);         /* Should not use any other option apart from
                                  * the ones handled here */
-      GNUNET_free_non_null (tc->link_array);
+      GNUNET_free_non_null (overlay->link_array);
       GNUNET_free (tc);
       return NULL;
     }
@@ -1125,4 +1434,106 @@
   return GNUNET_strdup (topology_strings[topology]);
 }
 
+
+/**
+ * Function to construct an underlay topology
+ *
+ * @param num_peers the number of peers for which the topology should be
+ *          generated
+ * @param proc the underlay link processor callback.  Will be called for each
+ *          underlay link generated unless a previous call to this callback
+ *          returned GNUNET_SYSERR.  Cannot be NULL.
+ * @param cls closure for proc
+ * @param ... variable arguments denoting the topology and its parameters.  
They
+ *          should start with the type of topology to generate followed by 
their
+ *          options.
+ * @return GNUNET_OK if underlay link generation is successful; GNUNET_SYSERR
+ *          upon error in generating the underlay or if any calls to the
+ *          underlay link processor returned GNUNET_SYSERR
+ */
+int
+GNUNET_TESTBED_underlay_construct_ (int num_peers,
+                                    underlay_link_processor proc,
+                                    void *cls,
+                                    ...)
+{
+  struct TopologyContext tc;
+  struct TopologyContextUnderlay *underlay;
+  struct UnderlayLink *ulink;
+  va_list vargs;
+  enum GNUNET_TESTBED_TopologyOption topology;
+  unsigned int cnt;
+  int ret;
+  
+  GNUNET_assert (NULL != proc);
+  ret = GNUNET_OK;
+  memset (&tc, 0, sizeof (tc));
+  tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY;
+  underlay = &tc.u.underlay;
+  va_start (vargs, cls);
+  topology = va_arg (vargs, enum GNUNET_TESTBED_TopologyOption);
+  switch (topology)
+  {
+  case GNUNET_TESTBED_TOPOLOGY_LINE:
+    gen_topo_line (&tc);
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_RING:
+    gen_topo_ring (&tc);
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
+    gen_topo_clique (&tc);
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
+    gen_topo_2dtorus (&tc);
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
+    gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO);
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
+    gen_topo_ring (&tc);
+    gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
+    gen_topo_2dtorus (&tc);
+    gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
+    {
+      const char *filename;
+      filename = va_arg (vargs, char *);
+      GNUNET_assert (NULL != filename);
+      gen_topo_from_file (&tc, filename);
+    }
+    break;
+  case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
+    {
+      uint16_t cap;
+      uint8_t m;
+      cap = (uint16_t) va_arg (vargs, unsigned int);
+      m = (uint8_t) va_arg (vargs, unsigned int);
+      gen_topo_scale_free (&tc, cap, m);
+    }
+    break;
+  default:
+    GNUNET_assert (0);
+  }
+  va_end (vargs);
+  for (cnt = 0; cnt < tc.link_array_size; cnt++)
+  {
+    ulink = &underlay->link_array[cnt];
+    if (GNUNET_SYSERR == proc (cls,
+                               ulink->A,
+                               ulink->B,
+                               ulink->bandwidth,
+                               ulink->latency,
+                               ulink->loss))
+    {
+      ret = GNUNET_SYSERR;
+      break;
+    }
+  }
+  GNUNET_free_non_null (underlay->link_array);
+  return ret;
+}
+
 /* end of testbed_api_topology.c */

Modified: gnunet/src/testbed/testbed_api_topology.h
===================================================================
--- gnunet/src/testbed/testbed_api_topology.h   2014-01-06 05:50:58 UTC (rev 
31801)
+++ gnunet/src/testbed/testbed_api_topology.h   2014-01-06 16:37:21 UTC (rev 
31802)
@@ -66,5 +66,48 @@
 char *
 GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology);
 
+
+/**
+ * Functions of this type are called to process underlay link
+ *
+ * @param cls closure
+ * @param A offset of first peer
+ * @param B offset of second peer
+ * @param bandwidth the bandwidth of the link in bytes per second
+ * @param latency the latency of link in milliseconds
+ * @param loss the percentage of messages dropped on the link
+ * @return GNUNET_OK to continue processing; GNUNET_SYSERR to abort
+ */
+typedef int (*underlay_link_processor) (void *cls,
+                                        unsigned int A,
+                                        unsigned int B,
+                                        unsigned int bandwidth,
+                                        unsigned int latency,
+                                        unsigned int loss);
+
+
+/**
+ * Function to construct an underlay topology
+ *
+ * @param num_peers the number of peers for which the topology should be
+ *          generated
+ * @param proc the underlay link processor callback.  Will be called for each
+ *          underlay link generated unless a previous call to this callback
+ *          returned GNUNET_SYSERR.  Cannot be NULL.
+ * @param cls closure for proc
+ * @param ... variable arguments denoting the topology and its parameters.  
They
+ *          should start with the type of topology to generate followed by 
their
+ *          options.  These arguments should *always* end with
+ *          GNUNET_TESTBED_TOPOLOGY_OPTION_END option
+ * @return GNUNET_OK if underlay link generation is successful; GNUNET_SYSERR
+ *          upon error in generating the underlay or if any calls to the
+ *          underlay link processor returned GNUNET_SYSERR
+ */
+int
+GNUNET_TESTBED_underlay_construct_ (int num_peers,
+                                    underlay_link_processor proc,
+                                    void *cls,
+                                    ...);
+
 #endif
 /* end of  testbed_api_topology.h */




reply via email to

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