2 This file is part of GNUnet
3 Copyright (C) 2008--2013 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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, 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"
31 #include "testbed_api_topology.h"
34 * Generic loggins shorthand
36 #define LOG(kind,...) \
37 GNUNET_log_from (kind, "testbed-api-topology", __VA_ARGS__)
41 * Default number of retires
43 #define DEFAULT_RETRY_CNT 3
47 * Context information for topology operations
49 struct TopologyContext;
53 * Representation of an overlay link
59 * An operation corresponding to this link
61 struct GNUNET_TESTBED_Operation *op;
64 * The topology context this link is a part of
66 struct TopologyContext *tc;
69 * position of peer A's handle in peers array
74 * position of peer B's handle in peers array
82 * Representation of an underlay link
87 * position of peer A's handle in peers array
92 * position of peer B's handle in peers array
97 * Bandwidth of the link in bytes per second
102 * Latency of the link in milliseconds
107 * Loss in the link in percentage of message dropped
113 struct RetryListEntry
116 * the next pointer for the DLL
118 struct RetryListEntry *next;
121 * the prev pointer for the DLL
123 struct RetryListEntry *prev;
126 * The link to be retired
128 struct OverlayLink *link;
133 * Context information for overlay topologies
135 struct TopologyContextOverlay
140 struct GNUNET_TESTBED_Peer **peers;
143 * An array of links; this array is of size link_array_size
145 struct OverlayLink *link_array;
148 * The operation closure
153 * topology generation completion callback
155 GNUNET_TESTBED_TopologyCompletionCallback comp_cb;
158 * The closure for the above callback
163 * DLL head for retry list
165 struct RetryListEntry *rl_head;
168 * DLL tail for retry list
170 struct RetryListEntry *rl_tail;
173 * How many retries to do before we give up
175 unsigned int retry_cnt;
178 * Number of links to try
183 * How many links have been completed
185 unsigned int ncompleted;
188 * Total successfully established overlay connections
190 unsigned int nsuccess;
193 * Total failed overlay connections
195 unsigned int nfailures;
200 * Topology context information for underlay topologies
202 struct TopologyContextUnderlay
207 struct UnderlayLink *link_array;
212 * Context information for topology operations
214 struct TopologyContext
217 * The type of this context
222 * Type for underlay topology
224 TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0,
227 * Type for overlay topology
229 TOPOLOGYCONTEXT_TYPE_OVERLAY
236 * Topology context information for overlay topology
238 struct TopologyContextOverlay overlay;
241 * Topology context information for underlay topology
243 struct TopologyContextUnderlay underlay;
247 * The number of peers
249 unsigned int num_peers;
252 * The size of the link array
254 unsigned int link_array_size;
260 * A array of names representing topologies. Should be in sync with enum
261 * GNUNET_TESTBED_TopologyOption
263 const char *topology_strings[] = {
266 * A clique (everyone connected to everyone else). No options. If there are N
267 * peers this topology results in (N * (N -1)) connections.
272 * Small-world network (2d torus plus random links). Followed
273 * by the number of random links to add (unsigned int).
278 * Small-world network (ring plus random links). Followed
279 * by the number of random links to add (unsigned int).
284 * Ring topology. No options.
289 * 2-d torus. No options.
294 * Random graph. Followed by the number of random links to be established
297 "RANDOM", // GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI
300 * Certain percentage of peers are unable to communicate directly
301 * replicating NAT conditions. Followed by the fraction of
302 * NAT'ed peers (float).
307 * Scale free topology. Followed by the maximum number of links a node can
308 * have (unsigned int); and the number of links a new node should have when
309 * it is added to the network (unsigned int)
314 * Straight line topology. No options.
319 * Read a topology from a given file. Followed by the name of the file (const char *).
324 * All peers are disconnected. No options.
336 * Callback to be called when an overlay_link operation complete
338 * @param cls element of the link_op array which points to the corresponding operation
339 * @param op the operation that has been finished
340 * @param emsg error message in case the operation has failed; will be NULL if
341 * operation has executed successfully.
344 overlay_link_completed (void *cls, struct GNUNET_TESTBED_Operation *op,
347 struct OverlayLink *link = cls;
348 struct TopologyContext *tc;
349 struct TopologyContextOverlay *overlay;
350 struct RetryListEntry *retry_entry;
352 GNUNET_assert (op == link->op);
353 GNUNET_TESTBED_operation_done (op);
356 GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
357 overlay = &tc->u.overlay;
360 overlay->nfailures++;
361 if (0 != overlay->retry_cnt)
363 LOG (GNUNET_ERROR_TYPE_WARNING,
364 "Error while establishing a link: %s -- Retrying\n", emsg);
365 retry_entry = GNUNET_new (struct RetryListEntry);
366 retry_entry->link = link;
367 GNUNET_CONTAINER_DLL_insert_tail (overlay->rl_head, overlay->rl_tail, retry_entry);
372 overlay->ncompleted++;
373 if (overlay->ncompleted < overlay->nlinks)
375 if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head))
377 overlay->retry_cnt--;
378 overlay->ncompleted = 0;
380 while (NULL != (retry_entry = overlay->rl_head))
382 link = retry_entry->link;
384 GNUNET_TESTBED_overlay_connect (overlay->op_cls, &overlay_link_completed,
385 link, overlay->peers[link->A],
386 overlay->peers[link->B]);
388 GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, retry_entry);
389 GNUNET_free (retry_entry);
393 if (NULL != overlay->comp_cb)
395 overlay->comp_cb (overlay->comp_cb_cls, overlay->nsuccess, overlay->nfailures);
402 * Function called when a overlay connect operation is ready
404 * @param cls the Topology context
407 opstart_overlay_configure_topology (void *cls)
409 struct TopologyContext *tc = cls;
410 struct TopologyContextOverlay *overlay;
413 GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
414 overlay = &tc->u.overlay;
415 overlay->nlinks = tc->link_array_size;
416 for (p = 0; p < tc->link_array_size; p++)
418 overlay->link_array[p].op =
419 GNUNET_TESTBED_overlay_connect (overlay->op_cls, &overlay_link_completed,
420 &overlay->link_array[p],
421 overlay->peers[overlay->link_array[p].A],
422 overlay->peers[overlay->link_array[p].B]);
428 * Callback which will be called when overlay connect operation is released
430 * @param cls the Topology context
433 oprelease_overlay_configure_topology (void *cls)
435 struct TopologyContext *tc = cls;
436 struct TopologyContextOverlay *overlay;
437 struct RetryListEntry *retry_entry;
440 GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
441 overlay = &tc->u.overlay;
442 while (NULL != (retry_entry = overlay->rl_head))
444 GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, retry_entry);
445 GNUNET_free (retry_entry);
447 if (NULL != overlay->link_array)
449 for (p = 0; p < tc->link_array_size; p++)
450 if (NULL != overlay->link_array[p].op)
451 GNUNET_TESTBED_operation_done (overlay->link_array[p].op);
452 GNUNET_free (overlay->link_array);
459 * Populates the OverlayLink structure.
461 * @param offset the offset of the link array to use
462 * @param A the peer A. Should be different from B
463 * @param B the peer B. Should be different from A
464 * @param tc the TopologyContext
468 make_link (unsigned int offset, uint32_t A, uint32_t B,
469 struct TopologyContext *tc)
471 GNUNET_assert (A != B);
474 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
476 struct TopologyContextOverlay *overlay;
477 struct OverlayLink *olink;
479 overlay = &tc->u.overlay;
480 GNUNET_assert (offset < tc->link_array_size);
481 olink = &overlay->link_array[offset];
482 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A);
489 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
491 struct TopologyContextUnderlay *underlay;
492 struct UnderlayLink *ulink;
494 underlay = &tc->u.underlay;
495 GNUNET_assert (offset < tc->link_array_size);
496 ulink = &underlay->link_array[offset];
506 * Generates line topology
508 * @param tc the topology context
511 gen_topo_line (struct TopologyContext *tc)
515 tc->link_array_size = tc->num_peers - 1;
518 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
520 struct TopologyContextOverlay *overlay;
522 overlay = &tc->u.overlay;
523 overlay->link_array =
524 GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
527 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
529 struct TopologyContextUnderlay *underlay;
531 underlay = &tc->u.underlay;
532 underlay->link_array =
533 GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size);
537 for (cnt = 0; cnt < (tc->link_array_size); cnt++)
538 make_link (cnt, cnt, cnt + 1, tc);
543 * Generates ring topology
545 * @param tc the topology context
548 gen_topo_ring (struct TopologyContext *tc)
551 tc->link_array_size++;
554 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
556 struct TopologyContextOverlay *overlay;
558 overlay = &tc->u.overlay;
559 overlay->link_array =
560 GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) *
561 tc->link_array_size);
564 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
566 struct TopologyContextUnderlay *underlay;
568 underlay = &tc->u.underlay;
569 underlay->link_array =
570 GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) *
571 tc->link_array_size);
575 make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc);
580 * Returns the number of links that are required to generate a 2d torus for the
581 * given number of peers. Also returns the arrangment (number of rows and the
582 * length of each row)
584 * @param num_peers number of peers
585 * @param rows number of rows in the 2d torus. Can be NULL
586 * @param rows_len the length of each row. This array will be allocated
587 * fresh. The caller should free it. Can be NULL
588 * @return the number of links that are required to generate a 2d torus for the
589 * given number of peers
592 GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows,
593 unsigned int **rows_len)
596 unsigned int sq_floor;
598 unsigned int *_rows_len;
601 unsigned int _num_peers;
604 sq = sqrt (num_peers);
606 sq_floor = (unsigned int) sq;
607 _rows = (sq_floor + 1);
608 _rows_len = GNUNET_malloc (sizeof (unsigned int) * _rows);
609 for (y = 0; y < _rows - 1; y++)
610 _rows_len[y] = sq_floor;
611 _num_peers = sq_floor * sq_floor;
612 cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers;
615 while (_num_peers < num_peers)
618 _rows_len[_rows - 1] = ++x;
623 cnt += (x < 2) ? x : 2 * x;
624 cnt += (y < 2) ? y : 2 * y;
625 if (0 == _rows_len[_rows - 1])
629 if (NULL != rows_len)
630 *rows_len = _rows_len;
632 GNUNET_free (_rows_len);
638 * Generates ring topology
640 * @param tc the topology context
643 gen_topo_2dtorus (struct TopologyContext *tc)
646 unsigned int *rows_len;
652 tc->link_array_size =
653 GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len);
656 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
658 struct TopologyContextOverlay *overlay;
660 overlay = &tc->u.overlay;
661 overlay->link_array =
662 GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
665 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
667 struct TopologyContextUnderlay *underlay;
669 underlay = &tc->u.underlay;
670 underlay->link_array =
671 GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size);
677 for (y = 0; y < rows; y++)
679 for (x = 0; x < rows_len[y] - 1; x++)
681 make_link (cnt, offset + x, offset + x + 1, tc);
686 make_link (cnt, offset + x, offset, tc);
688 offset += rows_len[y];
690 for (x = 0; x < rows_len[0]; x++)
693 for (y = 0; y < rows - 1; y++)
695 if (x >= rows_len[y + 1])
697 GNUNET_assert (x < rows_len[y + 1]);
698 make_link (cnt, offset + x, offset + rows_len[y] + x, tc);
699 offset += rows_len[y];
704 make_link (cnt, offset + x, x, tc);
707 GNUNET_assert (cnt == tc->link_array_size);
708 GNUNET_free (rows_len);
713 * Generates ring topology
715 * @param tc the topology context
716 * @param links the number of random links to establish
717 * @param append GNUNET_YES to add links to existing link array; GNUNET_NO to
718 * create a new link array
721 gen_topo_random (struct TopologyContext *tc, unsigned int links, int append)
728 if (1 == tc->num_peers)
730 if (GNUNET_YES == append)
732 index = tc->link_array_size;
733 tc->link_array_size += links;
738 tc->link_array_size = links;
742 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
744 struct TopologyContextOverlay *overlay;
746 overlay = &tc->u.overlay;
747 if (GNUNET_YES != append)
749 GNUNET_assert (NULL == overlay->link_array);
750 overlay->link_array =
751 GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
754 GNUNET_assert ((0 < tc->link_array_size) && (NULL != overlay->link_array));
755 overlay->link_array =
756 GNUNET_realloc (overlay->link_array,
757 sizeof (struct OverlayLink) * tc->link_array_size);
760 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
762 struct TopologyContextUnderlay *underlay;
764 underlay = &tc->u.underlay;
765 if (GNUNET_YES != append)
767 GNUNET_assert (NULL == underlay->link_array);
768 underlay->link_array =
769 GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size);
772 GNUNET_assert ((0 < tc->link_array_size) && (NULL != underlay->link_array));
773 underlay->link_array =
774 GNUNET_realloc (underlay->link_array,
775 sizeof (struct UnderlayLink) * tc->link_array_size);
779 for (cnt = 0; cnt < links; cnt++)
784 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
786 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
788 while (A_rand == B_rand);
789 make_link (index+cnt, A_rand, B_rand, tc);
795 * Generates scale free network. Its construction is described in:
797 * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999.
799 * @param tc the topology context
800 * @param cap maximum allowed node degree
801 * @param m number of edges to establish for a new node when it is added to the
805 gen_topo_scale_free (struct TopologyContext *tc, uint16_t cap, uint8_t m)
810 unsigned int etaboff;
814 unsigned int random_peer;
817 unsigned int redo_threshold;
820 tc->link_array_size = tc->num_peers * m;
823 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
825 struct TopologyContextOverlay *overlay;
827 overlay = &tc->u.overlay;
828 overlay->link_array = GNUNET_malloc_large (sizeof (struct OverlayLink) *
829 tc->link_array_size);
832 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
834 struct TopologyContextUnderlay *underlay;
836 underlay = &tc->u.underlay;
837 underlay->link_array = GNUNET_malloc_large (sizeof (struct UnderlayLink) *
838 tc->link_array_size);
842 etab = GNUNET_malloc_large (sizeof (unsigned int) * 2 * tc->link_array_size);
843 deg = GNUNET_malloc (sizeof (unsigned int) * tc->num_peers);
844 used = GNUNET_malloc (sizeof (unsigned int) * m);
845 /* start by connecting peer 1 to peer 0 */
846 make_link (0, 0, 1, tc);
852 for (peer = 2; peer < tc->num_peers; peer++)
856 for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
860 off = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, etaboff);
861 random_peer = etab[off];
862 if (cap < deg[random_peer])
864 if (++redo_threshold > GNUNET_MAX (1, cap / 2))
868 for (cnt2 = 0; cnt2 < etaboff; cnt2++)
870 if (random_peer == etab[cnt2])
875 etab[cnt2 - off] = etab[cnt2];
881 for (cnt2 = 0; cnt2 < cnt; cnt2++)
882 if (random_peer == used[cnt2])
884 make_link (links + cnt, random_peer, peer, tc);
887 used[cnt] = random_peer;
889 for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
891 etab[etaboff++] = used[cnt];
892 etab[etaboff++] = peer;
894 links += GNUNET_MIN (peer, m);
899 GNUNET_assert (links <= tc->link_array_size);
900 tc->link_array_size = links;
903 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
905 struct TopologyContextOverlay *overlay;
907 overlay = &tc->u.overlay;
908 overlay->link_array =
909 GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) * tc->link_array_size);
912 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
914 struct TopologyContextUnderlay *underlay;
916 underlay = &tc->u.underlay;
917 underlay->link_array =
918 GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) * tc->link_array_size);
926 * Generates topology from the given file
928 * @param tc the topology context
929 * @param filename the filename of the file containing topology data
932 gen_topo_from_file (struct TopologyContext *tc, const char *filename)
939 unsigned long int peer_id;
940 unsigned long int other_peer_id;
945 * We read the peer index
950 * We read the other peer indices
957 status = GNUNET_SYSERR;
958 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
960 LOG (GNUNET_ERROR_TYPE_ERROR, _("Topology file %s not found\n"), filename);
964 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
966 LOG (GNUNET_ERROR_TYPE_ERROR, _("Topology file %s has no data\n"),
970 data = GNUNET_malloc (fs);
971 if (fs != GNUNET_DISK_fn_read (filename, data, fs))
973 LOG (GNUNET_ERROR_TYPE_ERROR, _("Topology file %s cannot be read\n"),
983 if (0 != isspace (data[offset]))
991 buf = strchr (&data[offset], ':');
994 LOG (GNUNET_ERROR_TYPE_ERROR,
995 _("Failed to read peer index from toology file: %s"), filename);
1000 peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1003 LOG (GNUNET_ERROR_TYPE_ERROR,
1004 _("Value in given topology file: %s out of range\n"), filename);
1007 if (&data[offset] == end)
1009 LOG (GNUNET_ERROR_TYPE_ERROR,
1010 _("Failed to read peer index from topology file: %s"), filename);
1013 if (tc->num_peers <= peer_id)
1015 LOG (GNUNET_ERROR_TYPE_ERROR,
1016 _("Topology file needs more peers than given ones\n"), filename);
1019 state = OTHER_PEER_INDEX;
1020 offset += ((unsigned int) (buf - &data[offset])) + 1;
1022 case OTHER_PEER_INDEX:
1024 other_peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1027 LOG (GNUNET_ERROR_TYPE_ERROR,
1028 _("Value in given topology file: %s out of range\n"), filename);
1031 if (&data[offset] == end)
1033 LOG (GNUNET_ERROR_TYPE_ERROR,
1034 _("Failed to read peer index from topology file: %s"), filename);
1037 if (tc->num_peers <= other_peer_id)
1039 LOG (GNUNET_ERROR_TYPE_ERROR,
1040 _("Topology file needs more peers than given ones\n"), filename);
1043 if (peer_id != other_peer_id)
1045 tc->link_array_size++;
1048 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1050 struct TopologyContextOverlay *overlay;
1052 overlay = &tc->u.overlay;
1053 overlay->link_array =
1054 GNUNET_realloc (overlay->link_array,
1055 sizeof (struct OverlayLink) * tc->link_array_size);
1058 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1060 struct TopologyContextUnderlay *underlay;
1062 underlay = &tc->u.underlay;
1063 underlay->link_array =
1064 GNUNET_realloc (underlay->link_array,
1065 sizeof (struct UnderlayLink) * tc->link_array_size);
1069 offset += end - &data[offset];
1070 make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc);
1073 LOG (GNUNET_ERROR_TYPE_WARNING,
1074 _("Ignoring to connect peer %u to peer %u\n"), peer_id,
1076 while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs))
1078 if ('\n' == data[offset])
1080 else if ('|' == data[offset])
1082 state = OTHER_PEER_INDEX;
1092 if (GNUNET_OK != status)
1094 LOG (GNUNET_ERROR_TYPE_WARNING, "Removing link data read from the file\n");
1095 tc->link_array_size = 0;
1098 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1100 struct TopologyContextOverlay *overlay;
1102 overlay = &tc->u.overlay;
1103 GNUNET_free_non_null (overlay->link_array);
1104 overlay->link_array = NULL;
1107 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1109 struct TopologyContextUnderlay *underlay;
1111 underlay = &tc->u.underlay;
1112 GNUNET_free_non_null (underlay->link_array);
1113 underlay->link_array = NULL;
1122 * Generates clique topology
1124 * @param tc the topology context
1127 gen_topo_clique (struct TopologyContext *tc)
1130 unsigned int offset;
1131 unsigned int neighbour;
1133 tc->link_array_size = tc->num_peers * (tc->num_peers - 1);
1136 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1138 struct TopologyContextOverlay *overlay;
1140 overlay = &tc->u.overlay;
1141 overlay->link_array = GNUNET_malloc (sizeof (struct OverlayLink) *
1142 tc->link_array_size);
1145 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1147 struct TopologyContextUnderlay *underlay;
1149 underlay = &tc->u.underlay;
1150 underlay->link_array = GNUNET_malloc (sizeof (struct UnderlayLink) *
1151 tc->link_array_size);
1155 for (cnt = 0; cnt < tc->num_peers; cnt++)
1157 for (neighbour = 0; neighbour < tc->num_peers; neighbour++)
1159 if (neighbour == cnt)
1161 make_link (offset, cnt, neighbour, tc);
1169 * Configure overall network topology to have a particular shape.
1171 * @param op_cls closure argument to give with the operation event
1172 * @param num_peers number of peers in 'peers'
1173 * @param peers array of 'num_peers' with the peers to configure
1174 * @param topo desired underlay topology to use
1175 * @param ap topology-specific options
1176 * @return handle to the operation, NULL if configuring the topology
1177 * is not allowed at this time
1179 struct GNUNET_TESTBED_Operation *
1180 GNUNET_TESTBED_underlay_configure_topology_va (void *op_cls,
1181 unsigned int num_peers,
1182 struct GNUNET_TESTBED_Peer
1185 GNUNET_TESTBED_TopologyOption
1194 * Configure overall network topology to have a particular shape.
1196 * @param op_cls closure argument to give with the operation event
1197 * @param num_peers number of peers in 'peers'
1198 * @param peers array of 'num_peers' with the peers to configure
1199 * @param topo desired underlay topology to use
1200 * @param ... topology-specific options
1201 * @return handle to the operation, NULL if configuring the topology
1202 * is not allowed at this time
1204 struct GNUNET_TESTBED_Operation *
1205 GNUNET_TESTBED_underlay_configure_topology (void *op_cls,
1206 unsigned int num_peers,
1207 struct GNUNET_TESTBED_Peer **peers,
1208 enum GNUNET_TESTBED_TopologyOption
1217 * All peers must have been started before calling this function.
1218 * This function then connects the given peers in the P2P overlay
1219 * using the given topology.
1221 * @param op_cls closure argument to give with the peer connect operation events
1222 * generated through this function
1223 * @param num_peers number of peers in 'peers'
1224 * @param peers array of 'num_peers' with the peers to configure
1225 * @param max_connections the maximums number of overlay connections that will
1226 * be made to achieve the given topology
1227 * @param comp_cb the completion callback to call when the topology generation
1229 * @param comp_cb_cls closure for the above completion callback
1230 * @param topo desired underlay topology to use
1231 * @param va topology-specific options
1232 * @return handle to the operation, NULL if connecting these
1233 * peers is fundamentally not possible at this time (peers
1234 * not running or underlay disallows) or if num_peers is less than 2
1236 struct GNUNET_TESTBED_Operation *
1237 GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls,
1238 unsigned int num_peers,
1239 struct GNUNET_TESTBED_Peer **peers,
1240 unsigned int *max_connections,
1241 GNUNET_TESTBED_TopologyCompletionCallback
1244 enum GNUNET_TESTBED_TopologyOption topo,
1247 struct TopologyContext *tc;
1248 struct TopologyContextOverlay *overlay;
1249 struct GNUNET_TESTBED_Operation *op;
1250 struct GNUNET_TESTBED_Controller *c;
1251 enum GNUNET_TESTBED_TopologyOption secondary_option;
1255 c = peers[0]->controller;
1256 tc = GNUNET_new (struct TopologyContext);
1257 tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY;
1258 overlay = &tc->u.overlay;
1259 overlay->peers = peers;
1260 tc->num_peers = num_peers;
1261 overlay->op_cls = op_cls;
1262 overlay->retry_cnt = DEFAULT_RETRY_CNT;
1263 overlay->comp_cb = comp_cb;
1264 overlay->comp_cb_cls = comp_cb_cls;
1267 case GNUNET_TESTBED_TOPOLOGY_LINE:
1270 case GNUNET_TESTBED_TOPOLOGY_RING:
1273 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1274 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_NO);
1276 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1278 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1280 case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
1281 gen_topo_clique (tc);
1283 case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
1284 gen_topo_2dtorus (tc);
1286 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1287 gen_topo_2dtorus (tc);
1288 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1291 case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
1296 cap = (uint16_t) va_arg (va, unsigned int);
1297 m = (uint8_t) va_arg (va, unsigned int);
1298 gen_topo_scale_free (tc, cap, m);
1301 case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1303 const char *filename;
1305 filename = va_arg (va, const char *);
1307 GNUNET_assert (NULL != filename);
1308 gen_topo_from_file (tc, filename);
1318 secondary_option = va_arg (va, enum GNUNET_TESTBED_TopologyOption);
1320 switch (secondary_option)
1322 case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT:
1323 overlay->retry_cnt = va_arg (va, unsigned int);
1325 case GNUNET_TESTBED_TOPOLOGY_OPTION_END:
1328 GNUNET_break (0); /* Should not use any other option apart from
1329 * the ones handled here */
1330 GNUNET_free_non_null (overlay->link_array);
1335 while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option);
1336 op = GNUNET_TESTBED_operation_create_ (tc,
1337 &opstart_overlay_configure_topology,
1338 &oprelease_overlay_configure_topology);
1339 GNUNET_TESTBED_operation_queue_insert_
1340 (c->opq_parallel_topology_config_operations, op);
1341 GNUNET_TESTBED_operation_begin_wait_ (op);
1342 LOG (GNUNET_ERROR_TYPE_DEBUG, "Generated %u connections\n",
1343 tc->link_array_size);
1344 if (NULL != max_connections)
1345 *max_connections = tc->link_array_size;
1351 * All peers must have been started before calling this function.
1352 * This function then connects the given peers in the P2P overlay
1353 * using the given topology.
1355 * @param op_cls closure argument to give with the peer connect operation events
1356 * generated through this function
1357 * @param num_peers number of peers in 'peers'
1358 * @param peers array of 'num_peers' with the peers to configure
1359 * @param max_connections the maximums number of overlay connections that will
1360 * be made to achieve the given topology
1361 * @param comp_cb the completion callback to call when the topology generation
1363 * @param comp_cb_cls closure for the above completion callback
1364 * @param topo desired underlay topology to use
1365 * @param ... topology-specific options
1366 * @return handle to the operation, NULL if connecting these
1367 * peers is fundamentally not possible at this time (peers
1368 * not running or underlay disallows) or if num_peers is less than 2
1370 struct GNUNET_TESTBED_Operation *
1371 GNUNET_TESTBED_overlay_configure_topology (void *op_cls,
1372 unsigned int num_peers,
1373 struct GNUNET_TESTBED_Peer **peers,
1374 unsigned int *max_connections,
1375 GNUNET_TESTBED_TopologyCompletionCallback
1378 enum GNUNET_TESTBED_TopologyOption topo,
1381 struct GNUNET_TESTBED_Operation *op;
1384 GNUNET_assert (topo < GNUNET_TESTBED_TOPOLOGY_OPTION_END);
1385 va_start (vargs, topo);
1386 op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers,
1388 comp_cb, comp_cb_cls,
1397 * Get a topology from a string input.
1399 * @param topology where to write the retrieved topology
1400 * @param topology_string The string to attempt to
1401 * get a configuration value from
1402 * @return GNUNET_YES if topology string matched a
1403 * known topology, GNUNET_NO if not
1406 GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology,
1407 const char *topology_string)
1411 for (cnt = 0; NULL != topology_strings[cnt]; cnt++)
1413 if (0 == strcasecmp (topology_string, topology_strings[cnt]))
1415 if (NULL != topology)
1416 *topology = (enum GNUNET_TESTBED_TopologyOption) cnt;
1425 * Returns the string corresponding to the given topology
1427 * @param topology the topology
1428 * @return the string (freshly allocated) of given topology; NULL if topology cannot be
1429 * expressed as a string
1432 GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology)
1434 if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology)
1436 return GNUNET_strdup (topology_strings[topology]);
1441 * Function to construct an underlay topology
1443 * @param num_peers the number of peers for which the topology should be
1445 * @param proc the underlay link processor callback. Will be called for each
1446 * underlay link generated unless a previous call to this callback
1447 * returned GNUNET_SYSERR. Cannot be NULL.
1448 * @param cls closure for proc
1449 * @param ... variable arguments denoting the topology and its parameters. They
1450 * should start with the type of topology to generate followed by their
1452 * @return GNUNET_OK if underlay link generation is successful; GNUNET_SYSERR
1453 * upon error in generating the underlay or if any calls to the
1454 * underlay link processor returned GNUNET_SYSERR
1457 GNUNET_TESTBED_underlay_construct_ (int num_peers,
1458 underlay_link_processor proc,
1462 struct TopologyContext tc;
1463 struct TopologyContextUnderlay *underlay;
1464 struct UnderlayLink *ulink;
1466 enum GNUNET_TESTBED_TopologyOption topology;
1470 GNUNET_assert (NULL != proc);
1472 memset (&tc, 0, sizeof (tc));
1473 tc.num_peers = num_peers;
1474 tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY;
1475 underlay = &tc.u.underlay;
1476 va_start (vargs, cls);
1477 topology = va_arg (vargs, enum GNUNET_TESTBED_TopologyOption);
1480 case GNUNET_TESTBED_TOPOLOGY_LINE:
1481 gen_topo_line (&tc);
1483 case GNUNET_TESTBED_TOPOLOGY_RING:
1484 gen_topo_ring (&tc);
1486 case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
1487 gen_topo_clique (&tc);
1489 case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
1490 gen_topo_2dtorus (&tc);
1492 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1493 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO);
1495 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1496 gen_topo_ring (&tc);
1497 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1499 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1500 gen_topo_2dtorus (&tc);
1501 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1503 case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1505 const char *filename;
1506 filename = va_arg (vargs, char *);
1507 GNUNET_assert (NULL != filename);
1508 gen_topo_from_file (&tc, filename);
1511 case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
1515 cap = (uint16_t) va_arg (vargs, unsigned int);
1516 m = (uint8_t) va_arg (vargs, unsigned int);
1517 gen_topo_scale_free (&tc, cap, m);
1524 for (cnt = 0; cnt < tc.link_array_size; cnt++)
1526 ulink = &underlay->link_array[cnt];
1527 if (GNUNET_SYSERR == proc (cls,
1534 ret = GNUNET_SYSERR;
1538 GNUNET_free_non_null (underlay->link_array);
1542 /* end of testbed_api_topology.c */