2 This file is part of GNUnet
3 Copyright (C) 2008--2013 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
17 * @file testbed/testbed_api_topology.c
18 * @brief topology-generation functions
19 * @author Christian Grothoff
22 #include "gnunet_testbed_service.h"
23 #include "testbed_api.h"
24 #include "testbed_api_peers.h"
25 #include "testbed_api_operations.h"
26 #include "testbed_api_topology.h"
29 * Generic loggins shorthand
31 #define LOG(kind,...) \
32 GNUNET_log_from (kind, "testbed-api-topology", __VA_ARGS__)
36 * Default number of retires
38 #define DEFAULT_RETRY_CNT 3
42 * Context information for topology operations
44 struct TopologyContext;
48 * Representation of an overlay link
54 * An operation corresponding to this link
56 struct GNUNET_TESTBED_Operation *op;
59 * The topology context this link is a part of
61 struct TopologyContext *tc;
64 * position of peer A's handle in peers array
69 * position of peer B's handle in peers array
77 * Representation of an underlay link
82 * position of peer A's handle in peers array
87 * position of peer B's handle in peers array
92 * Bandwidth of the link in bytes per second
97 * Latency of the link in milliseconds
102 * Loss in the link in percentage of message dropped
108 struct RetryListEntry
111 * the next pointer for the DLL
113 struct RetryListEntry *next;
116 * the prev pointer for the DLL
118 struct RetryListEntry *prev;
121 * The link to be retired
123 struct OverlayLink *link;
128 * Context information for overlay topologies
130 struct TopologyContextOverlay
135 struct GNUNET_TESTBED_Peer **peers;
138 * An array of links; this array is of size link_array_size
140 struct OverlayLink *link_array;
143 * The operation closure
148 * topology generation completion callback
150 GNUNET_TESTBED_TopologyCompletionCallback comp_cb;
153 * The closure for the above callback
158 * DLL head for retry list
160 struct RetryListEntry *rl_head;
163 * DLL tail for retry list
165 struct RetryListEntry *rl_tail;
168 * How many retries to do before we give up
170 unsigned int retry_cnt;
173 * Number of links to try
178 * How many links have been completed
180 unsigned int ncompleted;
183 * Total successfully established overlay connections
185 unsigned int nsuccess;
188 * Total failed overlay connections
190 unsigned int nfailures;
195 * Topology context information for underlay topologies
197 struct TopologyContextUnderlay
202 struct UnderlayLink *link_array;
207 * Context information for topology operations
209 struct TopologyContext
212 * The type of this context
217 * Type for underlay topology
219 TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0,
222 * Type for overlay topology
224 TOPOLOGYCONTEXT_TYPE_OVERLAY
231 * Topology context information for overlay topology
233 struct TopologyContextOverlay overlay;
236 * Topology context information for underlay topology
238 struct TopologyContextUnderlay underlay;
242 * The number of peers
244 unsigned int num_peers;
247 * The size of the link array
249 unsigned int link_array_size;
255 * A array of names representing topologies. Should be in sync with enum
256 * GNUNET_TESTBED_TopologyOption
258 static const char *topology_strings[] = {
261 * A clique (everyone connected to everyone else). No options. If there are N
262 * peers this topology results in (N * (N -1)) connections.
267 * Small-world network (2d torus plus random links). Followed
268 * by the number of random links to add (unsigned int).
273 * Small-world network (ring plus random links). Followed
274 * by the number of random links to add (unsigned int).
279 * Ring topology. No options.
284 * Star 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,
345 struct GNUNET_TESTBED_Operation *op,
348 struct OverlayLink *link = cls;
349 struct TopologyContext *tc;
350 struct TopologyContextOverlay *overlay;
351 struct RetryListEntry *retry_entry;
353 GNUNET_assert (op == link->op);
354 GNUNET_TESTBED_operation_done (op);
357 GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
358 overlay = &tc->u.overlay;
361 overlay->nfailures++;
362 if (0 != overlay->retry_cnt)
364 LOG (GNUNET_ERROR_TYPE_WARNING,
365 "Error while establishing a link: %s -- Retrying\n",
367 retry_entry = GNUNET_new (struct RetryListEntry);
368 retry_entry->link = link;
369 GNUNET_CONTAINER_DLL_insert_tail (overlay->rl_head,
376 overlay->ncompleted++;
377 if (overlay->ncompleted < overlay->nlinks)
379 if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head))
381 overlay->retry_cnt--;
382 overlay->ncompleted = 0;
384 while (NULL != (retry_entry = overlay->rl_head))
386 link = retry_entry->link;
388 GNUNET_TESTBED_overlay_connect (overlay->op_cls,
389 &overlay_link_completed,
391 overlay->peers[link->A],
392 overlay->peers[link->B]);
394 GNUNET_CONTAINER_DLL_remove (overlay->rl_head,
397 GNUNET_free (retry_entry);
401 if (NULL != overlay->comp_cb)
403 overlay->comp_cb (overlay->comp_cb_cls,
412 * Function called when a overlay connect operation is ready
414 * @param cls the Topology context
417 opstart_overlay_configure_topology (void *cls)
419 struct TopologyContext *tc = cls;
420 struct TopologyContextOverlay *overlay;
423 GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
424 overlay = &tc->u.overlay;
425 overlay->nlinks = tc->link_array_size;
426 for (p = 0; p < tc->link_array_size; p++)
428 overlay->link_array[p].op =
429 GNUNET_TESTBED_overlay_connect (overlay->op_cls,
430 &overlay_link_completed,
431 &overlay->link_array[p],
432 overlay->peers[overlay->link_array[p].A],
433 overlay->peers[overlay->link_array[p].B]);
439 * Callback which will be called when overlay connect operation is released
441 * @param cls the Topology context
444 oprelease_overlay_configure_topology (void *cls)
446 struct TopologyContext *tc = cls;
447 struct TopologyContextOverlay *overlay;
448 struct RetryListEntry *retry_entry;
451 GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
452 overlay = &tc->u.overlay;
453 while (NULL != (retry_entry = overlay->rl_head))
455 GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, retry_entry);
456 GNUNET_free (retry_entry);
458 if (NULL != overlay->link_array)
460 for (p = 0; p < tc->link_array_size; p++)
461 if (NULL != overlay->link_array[p].op)
462 GNUNET_TESTBED_operation_done (overlay->link_array[p].op);
463 GNUNET_free (overlay->link_array);
470 * Populates the OverlayLink structure.
472 * @param offset the offset of the link array to use
473 * @param A the peer A. Should be different from B
474 * @param B the peer B. Should be different from A
475 * @param tc the TopologyContext
479 make_link (unsigned int offset,
482 struct TopologyContext *tc)
484 GNUNET_assert (A != B);
487 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
489 struct TopologyContextOverlay *overlay;
490 struct OverlayLink *olink;
492 overlay = &tc->u.overlay;
493 GNUNET_assert (offset < tc->link_array_size);
494 olink = &overlay->link_array[offset];
495 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A);
502 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
504 struct TopologyContextUnderlay *underlay;
505 struct UnderlayLink *ulink;
507 underlay = &tc->u.underlay;
508 GNUNET_assert (offset < tc->link_array_size);
509 ulink = &underlay->link_array[offset];
519 * Generates line topology
521 * @param tc the topology context
524 gen_topo_line (struct TopologyContext *tc)
528 tc->link_array_size = tc->num_peers - 1;
531 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
533 struct TopologyContextOverlay *overlay;
535 overlay = &tc->u.overlay;
536 overlay->link_array =
537 GNUNET_new_array (tc->link_array_size,
541 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
543 struct TopologyContextUnderlay *underlay;
545 underlay = &tc->u.underlay;
546 underlay->link_array =
547 GNUNET_new_array (tc->link_array_size,
548 struct UnderlayLink);
552 for (cnt = 0; cnt < (tc->link_array_size); cnt++)
553 make_link (cnt, cnt, cnt + 1, tc);
558 * Generates star topology
560 * @param tc the topology context
563 gen_topo_star (struct TopologyContext *tc)
567 tc->link_array_size = tc->num_peers - 1;
570 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
572 struct TopologyContextOverlay *overlay;
574 overlay = &tc->u.overlay;
575 overlay->link_array =
576 GNUNET_new_array (tc->link_array_size,
580 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
582 struct TopologyContextUnderlay *underlay;
584 underlay = &tc->u.underlay;
585 underlay->link_array =
586 GNUNET_new_array (tc->link_array_size,
587 struct UnderlayLink);
591 for (cnt = tc->link_array_size; cnt; cnt--)
600 * Generates ring topology
602 * @param tc the topology context
605 gen_topo_ring (struct TopologyContext *tc)
608 tc->link_array_size++;
611 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
613 struct TopologyContextOverlay *overlay;
615 overlay = &tc->u.overlay;
616 overlay->link_array =
617 GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) *
618 tc->link_array_size);
621 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
623 struct TopologyContextUnderlay *underlay;
625 underlay = &tc->u.underlay;
626 underlay->link_array =
627 GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) *
628 tc->link_array_size);
632 make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc);
637 * Returns the number of links that are required to generate a 2d torus for the
638 * given number of peers. Also returns the arrangment (number of rows and the
639 * length of each row)
641 * @param num_peers number of peers
642 * @param rows number of rows in the 2d torus. Can be NULL
643 * @param rows_len the length of each row. This array will be allocated
644 * fresh. The caller should free it. Can be NULL
645 * @return the number of links that are required to generate a 2d torus for the
646 * given number of peers
649 GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows,
650 unsigned int **rows_len)
653 unsigned int sq_floor;
655 unsigned int *_rows_len;
658 unsigned int _num_peers;
661 sq = sqrt (num_peers);
663 sq_floor = (unsigned int) sq;
664 _rows = (sq_floor + 1);
665 _rows_len = GNUNET_malloc (sizeof (unsigned int) * _rows);
666 for (y = 0; y < _rows - 1; y++)
667 _rows_len[y] = sq_floor;
668 _num_peers = sq_floor * sq_floor;
669 cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers;
672 while (_num_peers < num_peers)
675 _rows_len[_rows - 1] = ++x;
680 cnt += (x < 2) ? x : 2 * x;
681 cnt += (y < 2) ? y : 2 * y;
682 if (0 == _rows_len[_rows - 1])
686 if (NULL != rows_len)
687 *rows_len = _rows_len;
689 GNUNET_free (_rows_len);
695 * Generates ring topology
697 * @param tc the topology context
700 gen_topo_2dtorus (struct TopologyContext *tc)
703 unsigned int *rows_len;
709 tc->link_array_size =
710 GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len);
713 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
715 struct TopologyContextOverlay *overlay;
717 overlay = &tc->u.overlay;
718 overlay->link_array =
719 GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
722 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
724 struct TopologyContextUnderlay *underlay;
726 underlay = &tc->u.underlay;
727 underlay->link_array =
728 GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size);
734 for (y = 0; y < rows; y++)
736 for (x = 0; x < rows_len[y] - 1; x++)
738 make_link (cnt, offset + x, offset + x + 1, tc);
743 make_link (cnt, offset + x, offset, tc);
745 offset += rows_len[y];
747 for (x = 0; x < rows_len[0]; x++)
750 for (y = 0; y < rows - 1; y++)
752 if (x >= rows_len[y + 1])
754 GNUNET_assert (x < rows_len[y + 1]);
755 make_link (cnt, offset + x, offset + rows_len[y] + x, tc);
756 offset += rows_len[y];
761 make_link (cnt, offset + x, x, tc);
764 GNUNET_assert (cnt == tc->link_array_size);
765 GNUNET_free (rows_len);
770 * Generates ring topology
772 * @param tc the topology context
773 * @param links the number of random links to establish
774 * @param append #GNUNET_YES to add links to existing link array; #GNUNET_NO to
775 * create a new link array
778 gen_topo_random (struct TopologyContext *tc,
787 if (1 == tc->num_peers)
789 if (GNUNET_YES == append)
791 index = tc->link_array_size;
792 tc->link_array_size += links;
797 tc->link_array_size = links;
801 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
803 struct TopologyContextOverlay *overlay;
805 overlay = &tc->u.overlay;
806 if (GNUNET_YES != append)
808 GNUNET_assert (NULL == overlay->link_array);
809 overlay->link_array =
810 GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
813 GNUNET_assert ((0 < tc->link_array_size) && (NULL != overlay->link_array));
814 overlay->link_array =
815 GNUNET_realloc (overlay->link_array,
816 sizeof (struct OverlayLink) * tc->link_array_size);
819 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
821 struct TopologyContextUnderlay *underlay;
823 underlay = &tc->u.underlay;
824 if (GNUNET_YES != append)
826 GNUNET_assert (NULL == underlay->link_array);
827 underlay->link_array =
828 GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size);
831 GNUNET_assert ((0 < tc->link_array_size) && (NULL != underlay->link_array));
832 underlay->link_array =
833 GNUNET_realloc (underlay->link_array,
834 sizeof (struct UnderlayLink) * tc->link_array_size);
838 for (cnt = 0; cnt < links; cnt++)
843 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
845 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
847 while (A_rand == B_rand);
848 make_link (index+cnt, A_rand, B_rand, tc);
854 * Generates scale free network. Its construction is described in:
856 * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999.
858 * @param tc the topology context
859 * @param cap maximum allowed node degree
860 * @param m number of edges to establish for a new node when it is added to the
864 gen_topo_scale_free (struct TopologyContext *tc,
871 unsigned int etaboff;
875 unsigned int random_peer;
878 unsigned int redo_threshold;
881 tc->link_array_size = tc->num_peers * m;
884 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
886 struct TopologyContextOverlay *overlay;
888 overlay = &tc->u.overlay;
889 overlay->link_array = GNUNET_malloc_large (sizeof (struct OverlayLink) *
890 tc->link_array_size);
893 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
895 struct TopologyContextUnderlay *underlay;
897 underlay = &tc->u.underlay;
898 underlay->link_array = GNUNET_malloc_large (sizeof (struct UnderlayLink) *
899 tc->link_array_size);
903 etab = GNUNET_malloc_large (sizeof (unsigned int) * 2 * tc->link_array_size);
904 deg = GNUNET_malloc (sizeof (unsigned int) * tc->num_peers);
905 used = GNUNET_malloc (sizeof (unsigned int) * m);
906 /* start by connecting peer 1 to peer 0 */
907 make_link (0, 0, 1, tc);
913 for (peer = 2; peer < tc->num_peers; peer++)
917 for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
921 off = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, etaboff);
922 random_peer = etab[off];
923 if (cap < deg[random_peer])
925 if (++redo_threshold > GNUNET_MAX (1, cap / 2))
929 for (cnt2 = 0; cnt2 < etaboff; cnt2++)
931 if (random_peer == etab[cnt2])
936 etab[cnt2 - off] = etab[cnt2];
942 for (cnt2 = 0; cnt2 < cnt; cnt2++)
943 if (random_peer == used[cnt2])
945 make_link (links + cnt, random_peer, peer, tc);
948 used[cnt] = random_peer;
950 for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
952 etab[etaboff++] = used[cnt];
953 etab[etaboff++] = peer;
955 links += GNUNET_MIN (peer, m);
960 GNUNET_assert (links <= tc->link_array_size);
961 tc->link_array_size = links;
964 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
966 struct TopologyContextOverlay *overlay;
968 overlay = &tc->u.overlay;
969 overlay->link_array =
970 GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) * tc->link_array_size);
973 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
975 struct TopologyContextUnderlay *underlay;
977 underlay = &tc->u.underlay;
978 underlay->link_array =
979 GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) * tc->link_array_size);
987 * Generates topology from the given file
989 * @param tc the topology context
990 * @param filename the filename of the file containing topology data
993 gen_topo_from_file (struct TopologyContext *tc,
994 const char *filename)
1001 unsigned long int peer_id;
1002 unsigned long int other_peer_id;
1007 * We read the peer index
1012 * We read the other peer indices
1019 status = GNUNET_SYSERR;
1020 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1022 LOG (GNUNET_ERROR_TYPE_ERROR,
1023 _("Topology file %s not found\n"),
1028 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
1030 LOG (GNUNET_ERROR_TYPE_ERROR,
1031 _("Topology file %s has no data\n"),
1035 data = GNUNET_malloc (fs);
1036 if (fs != GNUNET_DISK_fn_read (filename, data, fs))
1038 LOG (GNUNET_ERROR_TYPE_ERROR,
1039 _("Topology file %s cannot be read\n"),
1049 if (0 != isspace ((unsigned char) data[offset]))
1057 buf = strchr (&data[offset], ':');
1060 LOG (GNUNET_ERROR_TYPE_ERROR,
1061 _("Failed to read peer index from toology file: %s"), filename);
1066 peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1069 LOG (GNUNET_ERROR_TYPE_ERROR,
1070 _("Value in given topology file: %s out of range\n"), filename);
1073 if (&data[offset] == end)
1075 LOG (GNUNET_ERROR_TYPE_ERROR,
1076 _("Failed to read peer index from topology file: %s"), filename);
1079 if (tc->num_peers <= peer_id)
1081 LOG (GNUNET_ERROR_TYPE_ERROR,
1082 _("Topology file needs more peers than given ones\n"), filename);
1085 state = OTHER_PEER_INDEX;
1086 offset += ((unsigned int) (buf - &data[offset])) + 1;
1088 case OTHER_PEER_INDEX:
1090 other_peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1093 LOG (GNUNET_ERROR_TYPE_ERROR,
1094 _("Value in given topology file: %s out of range\n"), filename);
1097 if (&data[offset] == end)
1099 LOG (GNUNET_ERROR_TYPE_ERROR,
1100 _("Failed to read peer index from topology file: %s"), filename);
1103 if (tc->num_peers <= other_peer_id)
1105 LOG (GNUNET_ERROR_TYPE_ERROR,
1106 _("Topology file needs more peers than given ones\n"), filename);
1109 if (peer_id != other_peer_id)
1111 tc->link_array_size++;
1114 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1116 struct TopologyContextOverlay *overlay;
1118 overlay = &tc->u.overlay;
1119 overlay->link_array =
1120 GNUNET_realloc (overlay->link_array,
1121 sizeof (struct OverlayLink) * tc->link_array_size);
1124 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1126 struct TopologyContextUnderlay *underlay;
1128 underlay = &tc->u.underlay;
1129 underlay->link_array =
1130 GNUNET_realloc (underlay->link_array,
1131 sizeof (struct UnderlayLink) * tc->link_array_size);
1135 offset += end - &data[offset];
1136 make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc);
1139 LOG (GNUNET_ERROR_TYPE_WARNING,
1140 _("Ignoring to connect peer %u to peer %u\n"),
1143 while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs))
1145 if ( (offset < fs) &&
1146 ('\n' == data[offset]) )
1148 else if ( (offset < fs) &&
1149 ('|' == data[offset]) )
1151 state = OTHER_PEER_INDEX;
1161 if (GNUNET_OK != status)
1163 LOG (GNUNET_ERROR_TYPE_WARNING,
1164 "Removing link data read from the file\n");
1165 tc->link_array_size = 0;
1168 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1170 struct TopologyContextOverlay *overlay;
1172 overlay = &tc->u.overlay;
1173 GNUNET_free_non_null (overlay->link_array);
1174 overlay->link_array = NULL;
1177 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1179 struct TopologyContextUnderlay *underlay;
1181 underlay = &tc->u.underlay;
1182 GNUNET_free_non_null (underlay->link_array);
1183 underlay->link_array = NULL;
1192 * Generates clique topology
1194 * @param tc the topology context
1197 gen_topo_clique (struct TopologyContext *tc)
1200 unsigned int offset;
1201 unsigned int neighbour;
1203 tc->link_array_size = tc->num_peers * (tc->num_peers - 1);
1206 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1208 struct TopologyContextOverlay *overlay;
1210 overlay = &tc->u.overlay;
1211 overlay->link_array = GNUNET_new_array (tc->link_array_size,
1212 struct OverlayLink);
1215 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1217 struct TopologyContextUnderlay *underlay;
1219 underlay = &tc->u.underlay;
1220 underlay->link_array = GNUNET_new_array (tc->link_array_size,
1221 struct UnderlayLink);
1225 for (cnt = 0; cnt < tc->num_peers; cnt++)
1227 for (neighbour = 0; neighbour < tc->num_peers; neighbour++)
1229 if (neighbour == cnt)
1231 make_link (offset, cnt, neighbour, tc);
1239 * Configure overall network topology to have a particular shape.
1241 * @param op_cls closure argument to give with the operation event
1242 * @param num_peers number of peers in @a peers
1243 * @param peers array of @a num_peers with the peers to configure
1244 * @param topo desired underlay topology to use
1245 * @param ap topology-specific options
1246 * @return handle to the operation, NULL if configuring the topology
1247 * is not allowed at this time
1249 struct GNUNET_TESTBED_Operation *
1250 GNUNET_TESTBED_underlay_configure_topology_va (void *op_cls,
1251 unsigned int num_peers,
1252 struct GNUNET_TESTBED_Peer
1255 GNUNET_TESTBED_TopologyOption
1264 * Configure overall network topology to have a particular shape.
1266 * @param op_cls closure argument to give with the operation event
1267 * @param num_peers number of peers in @a peers
1268 * @param peers array of @a num_peers with the peers to configure
1269 * @param topo desired underlay topology to use
1270 * @param ... topology-specific options
1271 * @return handle to the operation, NULL if configuring the topology
1272 * is not allowed at this time
1274 struct GNUNET_TESTBED_Operation *
1275 GNUNET_TESTBED_underlay_configure_topology (void *op_cls,
1276 unsigned int num_peers,
1277 struct GNUNET_TESTBED_Peer **peers,
1278 enum GNUNET_TESTBED_TopologyOption
1287 * All peers must have been started before calling this function.
1288 * This function then connects the given peers in the P2P overlay
1289 * using the given topology.
1291 * @param op_cls closure argument to give with the peer connect operation events
1292 * generated through this function
1293 * @param num_peers number of peers in @a peers
1294 * @param peers array of @a num_peers with the peers to configure
1295 * @param max_connections the maximums number of overlay connections that will
1296 * be made to achieve the given topology
1297 * @param comp_cb the completion callback to call when the topology generation
1299 * @param comp_cb_cls closure for the above completion callback
1300 * @param topo desired underlay topology to use
1301 * @param va topology-specific options
1302 * @return handle to the operation, NULL if connecting these
1303 * peers is fundamentally not possible at this time (peers
1304 * not running or underlay disallows) or if num_peers is less than 2
1306 struct GNUNET_TESTBED_Operation *
1307 GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls,
1308 unsigned int num_peers,
1309 struct GNUNET_TESTBED_Peer **peers,
1310 unsigned int *max_connections,
1311 GNUNET_TESTBED_TopologyCompletionCallback
1314 enum GNUNET_TESTBED_TopologyOption topo,
1317 struct TopologyContext *tc;
1318 struct TopologyContextOverlay *overlay;
1319 struct GNUNET_TESTBED_Operation *op;
1320 struct GNUNET_TESTBED_Controller *c;
1321 enum GNUNET_TESTBED_TopologyOption secondary_option;
1325 c = peers[0]->controller;
1326 tc = GNUNET_new (struct TopologyContext);
1327 tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY;
1328 overlay = &tc->u.overlay;
1329 overlay->peers = peers;
1330 tc->num_peers = num_peers;
1331 overlay->op_cls = op_cls;
1332 overlay->retry_cnt = DEFAULT_RETRY_CNT;
1333 overlay->comp_cb = comp_cb;
1334 overlay->comp_cb_cls = comp_cb_cls;
1337 case GNUNET_TESTBED_TOPOLOGY_LINE:
1340 case GNUNET_TESTBED_TOPOLOGY_STAR:
1343 case GNUNET_TESTBED_TOPOLOGY_RING:
1346 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1347 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_NO);
1349 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1351 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1353 case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
1354 gen_topo_clique (tc);
1356 case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
1357 gen_topo_2dtorus (tc);
1359 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1360 gen_topo_2dtorus (tc);
1361 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1364 case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
1369 cap = (uint16_t) va_arg (va, unsigned int);
1370 m = (uint8_t) va_arg (va, unsigned int);
1371 gen_topo_scale_free (tc, cap, m);
1374 case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1376 const char *filename;
1378 filename = va_arg (va, const char *);
1380 GNUNET_assert (NULL != filename);
1381 gen_topo_from_file (tc, filename);
1391 secondary_option = va_arg (va, enum GNUNET_TESTBED_TopologyOption);
1393 switch (secondary_option)
1395 case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT:
1396 overlay->retry_cnt = va_arg (va, unsigned int);
1398 case GNUNET_TESTBED_TOPOLOGY_OPTION_END:
1401 GNUNET_break (0); /* Should not use any other option apart from
1402 * the ones handled here */
1403 GNUNET_free_non_null (overlay->link_array);
1408 while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option);
1409 op = GNUNET_TESTBED_operation_create_ (tc,
1410 &opstart_overlay_configure_topology,
1411 &oprelease_overlay_configure_topology);
1412 GNUNET_TESTBED_operation_queue_insert_
1413 (c->opq_parallel_topology_config_operations, op);
1414 GNUNET_TESTBED_operation_begin_wait_ (op);
1415 LOG (GNUNET_ERROR_TYPE_DEBUG,
1416 "Generated %u connections\n",
1417 tc->link_array_size);
1418 if (NULL != max_connections)
1419 *max_connections = tc->link_array_size;
1425 * All peers must have been started before calling this function.
1426 * This function then connects the given peers in the P2P overlay
1427 * using the given topology.
1429 * @param op_cls closure argument to give with the peer connect operation events
1430 * generated through this function
1431 * @param num_peers number of peers in 'peers'
1432 * @param peers array of 'num_peers' with the peers to configure
1433 * @param max_connections the maximums number of overlay connections that will
1434 * be made to achieve the given topology
1435 * @param comp_cb the completion callback to call when the topology generation
1437 * @param comp_cb_cls closure for the above completion callback
1438 * @param topo desired underlay topology to use
1439 * @param ... topology-specific options
1440 * @return handle to the operation, NULL if connecting these
1441 * peers is fundamentally not possible at this time (peers
1442 * not running or underlay disallows) or if num_peers is less than 2
1444 struct GNUNET_TESTBED_Operation *
1445 GNUNET_TESTBED_overlay_configure_topology (void *op_cls,
1446 unsigned int num_peers,
1447 struct GNUNET_TESTBED_Peer **peers,
1448 unsigned int *max_connections,
1449 GNUNET_TESTBED_TopologyCompletionCallback
1452 enum GNUNET_TESTBED_TopologyOption topo,
1455 struct GNUNET_TESTBED_Operation *op;
1458 GNUNET_assert (topo < GNUNET_TESTBED_TOPOLOGY_OPTION_END);
1459 va_start (vargs, topo);
1460 op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers,
1462 comp_cb, comp_cb_cls,
1471 * Get a topology from a string input.
1473 * @param topology where to write the retrieved topology
1474 * @param topology_string The string to attempt to
1475 * get a configuration value from
1476 * @return #GNUNET_YES if topology string matched a
1477 * known topology, #GNUNET_NO if not
1480 GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology,
1481 const char *topology_string)
1485 for (cnt = 0; NULL != topology_strings[cnt]; cnt++)
1487 if (0 == strcasecmp (topology_string, topology_strings[cnt]))
1489 if (NULL != topology)
1490 *topology = (enum GNUNET_TESTBED_TopologyOption) cnt;
1491 GNUNET_assert (GNUNET_TESTBED_TOPOLOGY_OPTION_END != (enum GNUNET_TESTBED_TopologyOption) cnt);
1500 * Returns the string corresponding to the given topology
1502 * @param topology the topology
1503 * @return the string (freshly allocated) of given topology; NULL if topology cannot be
1504 * expressed as a string
1507 GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology)
1509 if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology)
1511 return GNUNET_strdup (topology_strings[topology]);
1516 * Function to construct an underlay topology
1518 * @param num_peers the number of peers for which the topology should be
1520 * @param proc the underlay link processor callback. Will be called for each
1521 * underlay link generated unless a previous call to this callback
1522 * returned #GNUNET_SYSERR. Cannot be NULL.
1523 * @param cls closure for @a proc
1524 * @param ... variable arguments denoting the topology and its parameters. They
1525 * should start with the type of topology to generate followed by their
1527 * @return #GNUNET_OK if underlay link generation is successful; #GNUNET_SYSERR
1528 * upon error in generating the underlay or if any calls to the
1529 * underlay link processor returned #GNUNET_SYSERR
1532 GNUNET_TESTBED_underlay_construct_ (int num_peers,
1533 underlay_link_processor proc,
1537 struct TopologyContext tc;
1538 struct TopologyContextUnderlay *underlay;
1539 struct UnderlayLink *ulink;
1541 enum GNUNET_TESTBED_TopologyOption topology;
1545 GNUNET_assert (NULL != proc);
1547 memset (&tc, 0, sizeof (tc));
1548 tc.num_peers = num_peers;
1549 tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY;
1550 underlay = &tc.u.underlay;
1551 va_start (vargs, cls);
1552 topology = va_arg (vargs, enum GNUNET_TESTBED_TopologyOption);
1555 case GNUNET_TESTBED_TOPOLOGY_LINE:
1556 gen_topo_line (&tc);
1558 case GNUNET_TESTBED_TOPOLOGY_STAR:
1559 gen_topo_star (&tc);
1561 case GNUNET_TESTBED_TOPOLOGY_RING:
1562 gen_topo_ring (&tc);
1564 case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
1565 gen_topo_clique (&tc);
1567 case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
1568 gen_topo_2dtorus (&tc);
1570 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1571 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO);
1573 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1574 gen_topo_ring (&tc);
1575 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1577 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1578 gen_topo_2dtorus (&tc);
1579 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1581 case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1583 const char *filename;
1584 filename = va_arg (vargs, char *);
1585 GNUNET_assert (NULL != filename);
1586 gen_topo_from_file (&tc, filename);
1589 case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
1593 cap = (uint16_t) va_arg (vargs, unsigned int);
1594 m = (uint8_t) va_arg (vargs, unsigned int);
1595 gen_topo_scale_free (&tc, cap, m);
1602 for (cnt = 0; cnt < tc.link_array_size; cnt++)
1604 ulink = &underlay->link_array[cnt];
1605 if (GNUNET_SYSERR == proc (cls,
1612 ret = GNUNET_SYSERR;
1616 GNUNET_free_non_null (underlay->link_array);
1620 /* end of testbed_api_topology.c */