/*
This file is part of GNUnet
(C) 2008--2012 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/testbed_api_topology.c
* @brief topology-generation functions
* @author Christian Grothoff
*/
#include "platform.h"
#include "gnunet_testbed_service.h"
#include "testbed_api.h"
#include "testbed_api_peers.h"
#include "testbed_api_operations.h"
#include "testbed_api_topology.h"
/**
* Generic loggins shorthand
*/
#define LOG(kind,...) \
GNUNET_log_from (kind, "testbed-api-topology", __VA_ARGS__)
/**
* Default number of retires
*/
#define DEFAULT_RETRY_CNT 3
/**
* Context information for topology operations
*/
struct TopologyContext;
/**
* Representation of an overlay link
*/
struct OverlayLink
{
/**
* An operation corresponding to this link
*/
struct GNUNET_TESTBED_Operation *op;
/**
* The topology context this link is a part of
*/
struct TopologyContext *tc;
/**
* position of peer A's handle in peers array
*/
uint32_t A;
/**
* position of peer B's handle in peers array
*/
uint32_t B;
};
struct RetryListEntry
{
/**
* the next pointer for the DLL
*/
struct RetryListEntry *next;
/**
* the prev pointer for the DLL
*/
struct RetryListEntry *prev;
/**
* The link to be retired
*/
struct OverlayLink *link;
};
/**
* Context information for topology operations
*/
struct TopologyContext
{
/**
* The array of peers
*/
struct GNUNET_TESTBED_Peer **peers;
/**
* An array of links; this array is of size link_array_size
*/
struct OverlayLink *link_array;
/**
* The operation closure
*/
void *op_cls;
/**
* topology generation completion callback
*/
GNUNET_TESTBED_TopologyCompletionCallback comp_cb;
/**
* The closure for the above callback
*/
void *comp_cb_cls;
/**
* DLL head for retry list
*/
struct RetryListEntry *rl_head;
/**
* DLL tail for retry list
*/
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;
/**
* Number of links to try
*/
unsigned int nlinks;
/**
* How many links have been completed
*/
unsigned int ncompleted;
/**
* Total successfully established overlay connections
*/
unsigned int nsuccess;
/**
* Total failed overlay connections
*/
unsigned int nfailures;
};
/**
* A array of names representing topologies. Should be in sync with enum
* GNUNET_TESTBED_TopologyOption
*/
const char *topology_strings[] = {
/**
* A clique (everyone connected to everyone else). No options. If there are N
* peers this topology results in (N * (N -1)) connections.
*/
"CLIQUE",
/**
* Small-world network (2d torus plus random links). Followed
* by the number of random links to add (unsigned int).
*/
"SMALL_WORLD",
/**
* Small-world network (ring plus random links). Followed
* by the number of random links to add (unsigned int).
*/
"SMALL_WORLD_RING",
/**
* Ring topology. No options.
*/
"RING",
/**
* 2-d torus. No options.
*/
"2D_TORUS",
/**
* Random graph. Followed by the number of random links to be established
* (unsigned int)
*/
"RANDOM", // GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI
/**
* Certain percentage of peers are unable to communicate directly
* replicating NAT conditions. Followed by the fraction of
* NAT'ed peers (float).
*/
"INTERNAT",
/**
* Scale free topology. No options.
*/
"SCALE_FREE",
/**
* Straight line topology. No options.
*/
"LINE",
/**
* Read a topology from a given file. Followed by the name of the file (const char *).
*/
"FROM_FILE",
/**
* All peers are disconnected. No options.
*/
"NONE",
/**
* End of strings
*/
NULL
};
/**
* Callback to be called when an overlay_link operation complete
*
* @param cls element of the link_op array which points to the corresponding operation
* @param op the operation that has been finished
* @param emsg error message in case the operation has failed; will be NULL if
* operation has executed successfully.
*/
static void
overlay_link_completed (void *cls, struct GNUNET_TESTBED_Operation *op,
const char *emsg)
{
struct OverlayLink *link = cls;
struct TopologyContext *tc;
struct RetryListEntry *retry_entry;
GNUNET_assert (op == link->op);
GNUNET_TESTBED_operation_done (op);
link->op = NULL;
tc = link->tc;
if (NULL != emsg)
{
tc->nfailures++;
if (0 != tc->retry_cnt)
{
LOG (GNUNET_ERROR_TYPE_WARNING,
"Error while establishing a link: %s -- Retrying\n", emsg);
retry_entry = GNUNET_malloc (sizeof (struct RetryListEntry));
retry_entry->link = link;
GNUNET_CONTAINER_DLL_insert_tail (tc->rl_head, tc->rl_tail, retry_entry);
}
}
else
tc->nsuccess++;
tc->ncompleted++;
if (tc->ncompleted < tc->nlinks)