2 This file is part of GNUnet
3 (C) 2008--2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testbed/testbed_api_topology.c
23 * @brief topology-generation functions
24 * @author Christian Grothoff
27 #include "gnunet_testbed_service.h"
28 #include "testbed_api.h"
29 #include "testbed_api_peers.h"
30 #include "testbed_api_operations.h"
33 * Generic loggins shorthand
35 #define LOG(kind,...) \
36 GNUNET_log_from (kind, "testbed-api-topology", __VA_ARGS__)
40 * Context information for topology operations
42 struct TopologyContext;
46 * Representation of an overlay link
52 * An operation corresponding to this link
54 struct GNUNET_TESTBED_Operation *op;
57 * The topology context this link is a part of
59 struct TopologyContext *tc;
62 * position of peer A's handle in peers array
67 * position of peer B's handle in peers array
75 * Context information for topology operations
77 struct TopologyContext
82 struct GNUNET_TESTBED_Peer **peers;
85 * An array of links; this array is of size link_array_size
87 struct OverlayLink *link_array;
90 * The operation closure
97 unsigned int num_peers;
100 * The size of the link array
102 unsigned int link_array_size;
105 * should the automatic retry be disabled
113 * Callback to be called when an overlay_link operation complete
115 * @param cls element of the link_op array which points to the corresponding operation
116 * @param op the operation that has been finished
117 * @param emsg error message in case the operation has failed; will be NULL if
118 * operation has executed successfully.
121 overlay_link_completed (void *cls,
122 struct GNUNET_TESTBED_Operation *op,
125 struct OverlayLink *link = cls;
126 struct TopologyContext *tc;
128 GNUNET_assert (op == link->op);
129 GNUNET_TESTBED_operation_done (op);
132 if ((NULL != emsg) && (GNUNET_NO == tc->disable_retry))
134 LOG (GNUNET_ERROR_TYPE_WARNING,
135 "Error while establishing a link: %s -- Retrying\n", emsg);
137 GNUNET_TESTBED_overlay_connect (tc->op_cls,
138 &overlay_link_completed,
149 * Function called when a overlay connect operation is ready
151 * @param cls the Topology context
154 opstart_overlay_configure_topology (void *cls)
156 struct TopologyContext *tc = cls;
159 for (p = 0; p < tc->link_array_size; p++)
161 tc->link_array[p].op =
162 GNUNET_TESTBED_overlay_connect (tc->op_cls, &overlay_link_completed,
164 tc->peers[tc->link_array[p].A],
165 tc->peers[tc->link_array[p].B]);
171 * Callback which will be called when overlay connect operation is released
173 * @param cls the Topology context
176 oprelease_overlay_configure_topology (void *cls)
178 struct TopologyContext *tc = cls;
181 if (NULL != tc->link_array)
183 for (p = 0; p < tc->link_array_size; p++)
184 if (NULL != tc->link_array[p].op)
185 GNUNET_TESTBED_operation_done (tc->link_array[p].op);
186 GNUNET_free (tc->link_array);
193 * Generates line topology
195 * @param tc the topology context
198 gen_topo_line (struct TopologyContext *tc)
202 tc->link_array_size = tc->num_peers - 1;
203 tc->link_array = GNUNET_malloc (sizeof (struct OverlayLink) *
204 tc->link_array_size);
205 for (cnt=0; cnt < (tc->num_peers - 1); cnt++)
207 tc->link_array[cnt].A = cnt;
208 tc->link_array[cnt].B = cnt + 1;
209 tc->link_array[cnt].tc = tc;
215 * Generates ring topology
217 * @param tc the topology context
220 gen_topo_ring (struct TopologyContext *tc)
223 tc->link_array_size++;
224 tc->link_array = GNUNET_realloc (tc->link_array,
225 sizeof (struct OverlayLink) *
226 tc->link_array_size);
227 tc->link_array[tc->link_array_size - 1].op = NULL;
228 tc->link_array[tc->link_array_size - 1].tc = tc;
229 tc->link_array[tc->link_array_size - 1].A = tc->num_peers - 1;
230 tc->link_array[tc->link_array_size - 1].B = 0;
235 * Generates ring topology
237 * @param tc the topology context
238 * @param links the number of random links to establish
239 * @param append GNUNET_YES to add links to existing link array; GNUNET_NO to
240 * create a new link array
243 gen_topo_random (struct TopologyContext *tc, unsigned int links, int append)
250 if (GNUNET_YES == append)
252 GNUNET_assert ((0 < tc->link_array_size) && (NULL != tc->link_array));
253 index = tc->link_array_size;
254 tc->link_array_size += links;
255 tc->link_array = GNUNET_realloc (tc->link_array,
256 sizeof (struct OverlayLink) *
257 tc->link_array_size);
261 GNUNET_assert ((0 == tc->link_array_size) && (NULL == tc->link_array));
263 tc->link_array_size = links;
264 tc->link_array = GNUNET_malloc (sizeof (struct OverlayLink) *
265 tc->link_array_size);
267 for (cnt = 0; cnt < links; cnt++)
270 A_rand = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
272 B_rand = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
274 } while (A_rand == B_rand);
275 tc->link_array[index + cnt].op = NULL;
276 tc->link_array[index + cnt].A = A_rand;
277 tc->link_array[index + cnt].B = B_rand;
278 tc->link_array[index + cnt].tc = tc;
284 * Configure overall network topology to have a particular shape.
286 * @param op_cls closure argument to give with the operation event
287 * @param num_peers number of peers in 'peers'
288 * @param peers array of 'num_peers' with the peers to configure
289 * @param topo desired underlay topology to use
290 * @param ap topology-specific options
291 * @return handle to the operation, NULL if configuring the topology
292 * is not allowed at this time
294 struct GNUNET_TESTBED_Operation *
295 GNUNET_TESTBED_underlay_configure_topology_va (void *op_cls,
296 unsigned int num_peers,
297 struct GNUNET_TESTBED_Peer
300 GNUNET_TESTBED_TopologyOption
309 * Configure overall network topology to have a particular shape.
311 * @param op_cls closure argument to give with the operation event
312 * @param num_peers number of peers in 'peers'
313 * @param peers array of 'num_peers' with the peers to configure
314 * @param topo desired underlay topology to use
315 * @param ... topology-specific options
316 * @return handle to the operation, NULL if configuring the topology
317 * is not allowed at this time
319 struct GNUNET_TESTBED_Operation *
320 GNUNET_TESTBED_underlay_configure_topology (void *op_cls,
321 unsigned int num_peers,
322 struct GNUNET_TESTBED_Peer **peers,
323 enum GNUNET_TESTBED_TopologyOption
332 * All peers must have been started before calling this function.
333 * This function then connects the given peers in the P2P overlay
334 * using the given topology.
336 * @param op_cls closure argument to give with the operation event
337 * @param num_peers number of peers in 'peers'
338 * @param peers array of 'num_peers' with the peers to configure
339 * @param topo desired underlay topology to use
340 * @param va topology-specific options
341 * @return handle to the operation, NULL if connecting these
342 * peers is fundamentally not possible at this time (peers
343 * not running or underlay disallows) or if num_peers is less than 2
345 struct GNUNET_TESTBED_Operation *
346 GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls,
347 unsigned int num_peers,
348 struct GNUNET_TESTBED_Peer **peers,
349 enum GNUNET_TESTBED_TopologyOption
352 struct TopologyContext *tc;
353 struct GNUNET_TESTBED_Operation *op;
354 struct GNUNET_TESTBED_Controller *c;
355 enum GNUNET_TESTBED_TopologyOption secondary_option;
360 c = peers[0]->controller;
361 tc = GNUNET_malloc (sizeof (struct TopologyContext));
363 tc->num_peers = num_peers;
367 case GNUNET_TESTBED_TOPOLOGY_LINE:
370 case GNUNET_TESTBED_TOPOLOGY_RING:
373 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
375 va_arg (va, unsigned int),
378 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
381 va_arg (va, unsigned int),
384 case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
385 tc->link_array_size = num_peers * (num_peers - 1);
386 tc->link_array = GNUNET_malloc (sizeof (struct OverlayLink) *
387 tc->link_array_size);
392 for (cnt=0; cnt < num_peers; cnt++)
394 unsigned int neighbour;
396 for (neighbour=0; neighbour < num_peers; neighbour++)
398 if (neighbour == cnt)
400 tc->link_array[offset].A = cnt;
401 tc->link_array[offset].B = neighbour;
402 tc->link_array[offset].tc = tc;
415 secondary_option = va_arg (va, enum GNUNET_TESTBED_TopologyOption);
416 switch (secondary_option)
418 case GNUNET_TESTBED_TOPOLOGY_DISABLE_AUTO_RETRY:
419 tc->disable_retry = GNUNET_YES;
421 case GNUNET_TESTBED_TOPOLOGY_OPTION_END:
424 GNUNET_break (0); /* Should not use any other option apart from
425 the ones handled here */
426 GNUNET_free_non_null (tc->link_array);
430 } while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option);
431 op = GNUNET_TESTBED_operation_create_ (tc,
432 &opstart_overlay_configure_topology,
433 &oprelease_overlay_configure_topology);
434 GNUNET_TESTBED_operation_queue_insert_
435 (c->opq_parallel_topology_config_operations, op);
436 GNUNET_TESTBED_operation_begin_wait_ (op);
442 * All peers must have been started before calling this function.
443 * This function then connects the given peers in the P2P overlay
444 * using the given topology.
446 * @param op_cls closure argument to give with the operation event
447 * @param num_peers number of peers in 'peers'
448 * @param peers array of 'num_peers' with the peers to configure
449 * @param topo desired underlay topology to use
450 * @param ... topology-specific options
451 * @return handle to the operation, NULL if connecting these
452 * peers is fundamentally not possible at this time (peers
453 * not running or underlay disallows) or if num_peers is less than 2
455 struct GNUNET_TESTBED_Operation *
456 GNUNET_TESTBED_overlay_configure_topology (void *op_cls, unsigned int num_peers,
457 struct GNUNET_TESTBED_Peer **peers,
458 enum GNUNET_TESTBED_TopologyOption
461 struct GNUNET_TESTBED_Operation *op;
464 GNUNET_assert (topo < GNUNET_TESTBED_TOPOLOGY_OPTION_END);
465 va_start (vargs, topo);
466 op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers,
472 /* end of testbed_api_topology.c */