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.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
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
58 * An operation corresponding to this link
60 struct GNUNET_TESTBED_Operation *op;
63 * The topology context this link is a part of
65 struct TopologyContext *tc;
68 * position of peer A's handle in peers array
73 * position of peer B's handle in peers array
80 * Representation of an underlay link
85 * position of peer A's handle in peers array
90 * position of peer B's handle in peers array
95 * Bandwidth of the link in bytes per second
100 * Latency of the link in milliseconds
105 * Loss in the link in percentage of message dropped
111 struct RetryListEntry
114 * the next pointer for the DLL
116 struct RetryListEntry *next;
119 * the prev pointer for the DLL
121 struct RetryListEntry *prev;
124 * The link to be retired
126 struct OverlayLink *link;
131 * Context information for overlay topologies
133 struct TopologyContextOverlay
138 struct GNUNET_TESTBED_Peer **peers;
141 * An array of links; this array is of size link_array_size
143 struct OverlayLink *link_array;
146 * The operation closure
151 * topology generation completion callback
153 GNUNET_TESTBED_TopologyCompletionCallback comp_cb;
156 * The closure for the above callback
161 * DLL head for retry list
163 struct RetryListEntry *rl_head;
166 * DLL tail for retry list
168 struct RetryListEntry *rl_tail;
171 * How many retries to do before we give up
173 unsigned int retry_cnt;
176 * Number of links to try
181 * How many links have been completed
183 unsigned int ncompleted;
186 * Total successfully established overlay connections
188 unsigned int nsuccess;
191 * Total failed overlay connections
193 unsigned int nfailures;
198 * Topology context information for underlay topologies
200 struct TopologyContextUnderlay
205 struct UnderlayLink *link_array;
210 * Context information for topology operations
212 struct TopologyContext
215 * The type of this context
220 * Type for underlay topology
222 TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0,
225 * Type for overlay topology
227 TOPOLOGYCONTEXT_TYPE_OVERLAY
233 * Topology context information for overlay topology
235 struct TopologyContextOverlay overlay;
238 * Topology context information for underlay topology
240 struct TopologyContextUnderlay underlay;
244 * The number of peers
246 unsigned int num_peers;
249 * The size of the link array
251 unsigned int link_array_size;
256 * A array of names representing topologies. Should be in sync with enum
257 * GNUNET_TESTBED_TopologyOption
259 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,
457 GNUNET_free (retry_entry);
459 if (NULL != overlay->link_array)
461 for (p = 0; p < tc->link_array_size; p++)
462 if (NULL != overlay->link_array[p].op)
463 GNUNET_TESTBED_operation_done (overlay->link_array[p].op);
464 GNUNET_free (overlay->link_array);
471 * Populates the OverlayLink structure.
473 * @param offset the offset of the link array to use
474 * @param A the peer A. Should be different from B
475 * @param B the peer B. Should be different from A
476 * @param tc the TopologyContext
480 make_link (unsigned int offset,
483 struct TopologyContext *tc)
485 GNUNET_assert (A != B);
488 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
490 struct TopologyContextOverlay *overlay;
491 struct OverlayLink *olink;
493 overlay = &tc->u.overlay;
494 GNUNET_assert (offset < tc->link_array_size);
495 olink = &overlay->link_array[offset];
496 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A);
504 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
506 struct TopologyContextUnderlay *underlay;
507 struct UnderlayLink *ulink;
509 underlay = &tc->u.underlay;
510 GNUNET_assert (offset < tc->link_array_size);
511 ulink = &underlay->link_array[offset];
521 * Generates line topology
523 * @param tc the topology context
526 gen_topo_line (struct TopologyContext *tc)
530 tc->link_array_size = tc->num_peers - 1;
533 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
535 struct TopologyContextOverlay *overlay;
537 overlay = &tc->u.overlay;
538 overlay->link_array =
539 GNUNET_new_array (tc->link_array_size,
544 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
546 struct TopologyContextUnderlay *underlay;
548 underlay = &tc->u.underlay;
549 underlay->link_array =
550 GNUNET_new_array (tc->link_array_size,
551 struct UnderlayLink);
555 for (cnt = 0; cnt < (tc->link_array_size); cnt++)
556 make_link (cnt, cnt, cnt + 1, tc);
561 * Generates star topology
563 * @param tc the topology context
566 gen_topo_star (struct TopologyContext *tc)
570 tc->link_array_size = tc->num_peers - 1;
573 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
575 struct TopologyContextOverlay *overlay;
577 overlay = &tc->u.overlay;
578 overlay->link_array =
579 GNUNET_new_array (tc->link_array_size,
584 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
586 struct TopologyContextUnderlay *underlay;
588 underlay = &tc->u.underlay;
589 underlay->link_array =
590 GNUNET_new_array (tc->link_array_size,
591 struct UnderlayLink);
595 for (cnt = tc->link_array_size; cnt; cnt--)
604 * Generates ring topology
606 * @param tc the topology context
609 gen_topo_ring (struct TopologyContext *tc)
612 tc->link_array_size++;
615 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
617 struct TopologyContextOverlay *overlay;
619 overlay = &tc->u.overlay;
620 overlay->link_array =
621 GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink)
622 * tc->link_array_size);
626 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
628 struct TopologyContextUnderlay *underlay;
630 underlay = &tc->u.underlay;
631 underlay->link_array =
632 GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink)
633 * tc->link_array_size);
637 make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc);
642 * Returns the number of links that are required to generate a 2d torus for the
643 * given number of peers. Also returns the arrangment (number of rows and the
644 * length of each row)
646 * @param num_peers number of peers
647 * @param rows number of rows in the 2d torus. Can be NULL
648 * @param rows_len the length of each row. This array will be allocated
649 * fresh. The caller should free it. Can be NULL
650 * @return the number of links that are required to generate a 2d torus for the
651 * given number of peers
654 GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows,
655 unsigned int **rows_len)
658 unsigned int sq_floor;
660 unsigned int *_rows_len;
663 unsigned int _num_peers;
666 sq = sqrt (num_peers);
668 sq_floor = (unsigned int) sq;
669 _rows = (sq_floor + 1);
670 _rows_len = GNUNET_malloc (sizeof(unsigned int) * _rows);
671 for (y = 0; y < _rows - 1; y++)
672 _rows_len[y] = sq_floor;
673 _num_peers = sq_floor * sq_floor;
674 cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers;
677 while (_num_peers < num_peers)
680 _rows_len[_rows - 1] = ++x;
685 cnt += (x < 2) ? x : 2 * x;
686 cnt += (y < 2) ? y : 2 * y;
687 if (0 == _rows_len[_rows - 1])
691 if (NULL != rows_len)
692 *rows_len = _rows_len;
694 GNUNET_free (_rows_len);
700 * Generates ring topology
702 * @param tc the topology context
705 gen_topo_2dtorus (struct TopologyContext *tc)
708 unsigned int *rows_len;
714 tc->link_array_size =
715 GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len);
718 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
720 struct TopologyContextOverlay *overlay;
722 overlay = &tc->u.overlay;
723 overlay->link_array =
724 GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size);
728 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
730 struct TopologyContextUnderlay *underlay;
732 underlay = &tc->u.underlay;
733 underlay->link_array =
734 GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size);
740 for (y = 0; y < rows; y++)
742 for (x = 0; x < rows_len[y] - 1; x++)
744 make_link (cnt, offset + x, offset + x + 1, tc);
749 make_link (cnt, offset + x, offset, tc);
751 offset += rows_len[y];
753 for (x = 0; x < rows_len[0]; x++)
756 for (y = 0; y < rows - 1; y++)
758 if (x >= rows_len[y + 1])
760 GNUNET_assert (x < rows_len[y + 1]);
761 make_link (cnt, offset + x, offset + rows_len[y] + x, tc);
762 offset += rows_len[y];
767 make_link (cnt, offset + x, x, tc);
770 GNUNET_assert (cnt == tc->link_array_size);
771 GNUNET_free (rows_len);
776 * Generates ring topology
778 * @param tc the topology context
779 * @param links the number of random links to establish
780 * @param append #GNUNET_YES to add links to existing link array; #GNUNET_NO to
781 * create a new link array
784 gen_topo_random (struct TopologyContext *tc,
793 if (1 == tc->num_peers)
795 if (GNUNET_YES == append)
797 index = tc->link_array_size;
798 tc->link_array_size += links;
803 tc->link_array_size = links;
807 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
809 struct TopologyContextOverlay *overlay;
811 overlay = &tc->u.overlay;
812 if (GNUNET_YES != append)
814 GNUNET_assert (NULL == overlay->link_array);
815 overlay->link_array =
816 GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size);
819 GNUNET_assert ((0 < tc->link_array_size) && (NULL !=
820 overlay->link_array));
821 overlay->link_array =
822 GNUNET_realloc (overlay->link_array,
823 sizeof(struct OverlayLink) * tc->link_array_size);
827 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
829 struct TopologyContextUnderlay *underlay;
831 underlay = &tc->u.underlay;
832 if (GNUNET_YES != append)
834 GNUNET_assert (NULL == underlay->link_array);
835 underlay->link_array =
836 GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size);
839 GNUNET_assert ((0 < tc->link_array_size) && (NULL !=
840 underlay->link_array));
841 underlay->link_array =
842 GNUNET_realloc (underlay->link_array,
843 sizeof(struct UnderlayLink) * tc->link_array_size);
847 for (cnt = 0; cnt < links; cnt++)
852 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
854 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
856 while (A_rand == B_rand);
857 make_link (index + cnt, A_rand, B_rand, tc);
863 * Generates scale free network. Its construction is described in:
865 * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999.
867 * @param tc the topology context
868 * @param cap maximum allowed node degree
869 * @param m number of edges to establish for a new node when it is added to the
873 gen_topo_scale_free (struct TopologyContext *tc,
880 unsigned int etaboff;
884 unsigned int random_peer;
887 unsigned int redo_threshold;
890 tc->link_array_size = tc->num_peers * m;
893 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
895 struct TopologyContextOverlay *overlay;
897 overlay = &tc->u.overlay;
898 overlay->link_array = GNUNET_malloc_large (sizeof(struct OverlayLink)
899 * tc->link_array_size);
903 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
905 struct TopologyContextUnderlay *underlay;
907 underlay = &tc->u.underlay;
908 underlay->link_array = GNUNET_malloc_large (sizeof(struct UnderlayLink)
909 * tc->link_array_size);
913 etab = GNUNET_malloc_large (sizeof(unsigned int) * 2 * tc->link_array_size);
914 deg = GNUNET_malloc (sizeof(unsigned int) * tc->num_peers);
915 used = GNUNET_malloc (sizeof(unsigned int) * m);
916 /* start by connecting peer 1 to peer 0 */
917 make_link (0, 0, 1, tc);
923 for (peer = 2; peer < tc->num_peers; peer++)
927 for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
931 off = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, etaboff);
932 random_peer = etab[off];
933 if (cap < deg[random_peer])
935 if (++redo_threshold > GNUNET_MAX (1, cap / 2))
939 for (cnt2 = 0; cnt2 < etaboff; cnt2++)
941 if (random_peer == etab[cnt2])
946 etab[cnt2 - off] = etab[cnt2];
952 for (cnt2 = 0; cnt2 < cnt; cnt2++)
953 if (random_peer == used[cnt2])
955 make_link (links + cnt, random_peer, peer, tc);
958 used[cnt] = random_peer;
960 for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
962 etab[etaboff++] = used[cnt];
963 etab[etaboff++] = peer;
965 links += GNUNET_MIN (peer, m);
970 GNUNET_assert (links <= tc->link_array_size);
971 tc->link_array_size = links;
974 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
976 struct TopologyContextOverlay *overlay;
978 overlay = &tc->u.overlay;
979 overlay->link_array =
980 GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink)
981 * tc->link_array_size);
985 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
987 struct TopologyContextUnderlay *underlay;
989 underlay = &tc->u.underlay;
990 underlay->link_array =
991 GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink)
992 * tc->link_array_size);
1000 * Generates topology from the given file
1002 * @param tc the topology context
1003 * @param filename the filename of the file containing topology data
1006 gen_topo_from_file (struct TopologyContext *tc,
1007 const char *filename)
1014 unsigned long int peer_id;
1015 unsigned long int other_peer_id;
1019 * We read the peer index
1024 * We read the other peer indices
1030 status = GNUNET_SYSERR;
1031 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1033 LOG (GNUNET_ERROR_TYPE_ERROR,
1034 _ ("Topology file %s not found\n"),
1039 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
1041 LOG (GNUNET_ERROR_TYPE_ERROR,
1042 _ ("Topology file %s has no data\n"),
1046 data = GNUNET_malloc (fs);
1047 if (fs != GNUNET_DISK_fn_read (filename, data, fs))
1049 LOG (GNUNET_ERROR_TYPE_ERROR,
1050 _ ("Topology file %s cannot be read\n"),
1060 if (0 != isspace ((unsigned char) data[offset]))
1068 buf = strchr (&data[offset], ':');
1071 LOG (GNUNET_ERROR_TYPE_ERROR,
1072 _ ("Failed to read peer index from toology file: %s"), filename);
1077 peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1080 LOG (GNUNET_ERROR_TYPE_ERROR,
1081 _ ("Value in given topology file: %s out of range\n"), filename);
1084 if (&data[offset] == end)
1086 LOG (GNUNET_ERROR_TYPE_ERROR,
1087 _ ("Failed to read peer index from topology file: %s"), filename);
1090 if (tc->num_peers <= peer_id)
1092 LOG (GNUNET_ERROR_TYPE_ERROR,
1093 _ ("Topology file needs more peers than given ones\n"), filename);
1096 state = OTHER_PEER_INDEX;
1097 offset += ((unsigned int) (buf - &data[offset])) + 1;
1100 case OTHER_PEER_INDEX:
1102 other_peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1105 LOG (GNUNET_ERROR_TYPE_ERROR,
1106 _ ("Value in given topology file: %s out of range\n"), filename);
1109 if (&data[offset] == end)
1111 LOG (GNUNET_ERROR_TYPE_ERROR,
1112 _ ("Failed to read peer index from topology file: %s"), filename);
1115 if (tc->num_peers <= other_peer_id)
1117 LOG (GNUNET_ERROR_TYPE_ERROR,
1118 _ ("Topology file needs more peers than given ones\n"), filename);
1121 if (peer_id != other_peer_id)
1123 tc->link_array_size++;
1126 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1128 struct TopologyContextOverlay *overlay;
1130 overlay = &tc->u.overlay;
1131 overlay->link_array =
1132 GNUNET_realloc (overlay->link_array,
1133 sizeof(struct OverlayLink) * tc->link_array_size);
1137 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1139 struct TopologyContextUnderlay *underlay;
1141 underlay = &tc->u.underlay;
1142 underlay->link_array =
1143 GNUNET_realloc (underlay->link_array,
1144 sizeof(struct UnderlayLink)
1145 * tc->link_array_size);
1149 offset += end - &data[offset];
1150 make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc);
1153 LOG (GNUNET_ERROR_TYPE_WARNING,
1154 _ ("Ignoring to connect peer %u to peer %u\n"),
1157 while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs))
1159 if ((offset < fs) &&
1160 ('\n' == data[offset]))
1162 else if ((offset < fs) &&
1163 ('|' == data[offset]))
1165 state = OTHER_PEER_INDEX;
1175 if (GNUNET_OK != status)
1177 LOG (GNUNET_ERROR_TYPE_WARNING,
1178 "Removing link data read from the file\n");
1179 tc->link_array_size = 0;
1182 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1184 struct TopologyContextOverlay *overlay;
1186 overlay = &tc->u.overlay;
1187 GNUNET_free_non_null (overlay->link_array);
1188 overlay->link_array = NULL;
1192 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1194 struct TopologyContextUnderlay *underlay;
1196 underlay = &tc->u.underlay;
1197 GNUNET_free_non_null (underlay->link_array);
1198 underlay->link_array = NULL;
1207 * Generates clique topology
1209 * @param tc the topology context
1212 gen_topo_clique (struct TopologyContext *tc)
1215 unsigned int offset;
1216 unsigned int neighbour;
1218 tc->link_array_size = tc->num_peers * (tc->num_peers - 1);
1221 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1223 struct TopologyContextOverlay *overlay;
1225 overlay = &tc->u.overlay;
1226 overlay->link_array = GNUNET_new_array (tc->link_array_size,
1227 struct OverlayLink);
1231 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1233 struct TopologyContextUnderlay *underlay;
1235 underlay = &tc->u.underlay;
1236 underlay->link_array = GNUNET_new_array (tc->link_array_size,
1237 struct UnderlayLink);
1241 for (cnt = 0; cnt < tc->num_peers; cnt++)
1243 for (neighbour = 0; neighbour < tc->num_peers; neighbour++)
1245 if (neighbour == cnt)
1247 make_link (offset, cnt, neighbour, tc);
1255 * Configure overall network topology to have a particular shape.
1257 * @param op_cls closure argument to give with the operation event
1258 * @param num_peers number of peers in @a peers
1259 * @param peers array of @a num_peers with the peers to configure
1260 * @param topo desired underlay topology to use
1261 * @param ap topology-specific options
1262 * @return handle to the operation, NULL if configuring the topology
1263 * is not allowed at this time
1265 struct GNUNET_TESTBED_Operation *
1266 GNUNET_TESTBED_underlay_configure_topology_va (void *op_cls,
1267 unsigned int num_peers,
1268 struct GNUNET_TESTBED_Peer
1271 GNUNET_TESTBED_TopologyOption
1280 * Configure overall network topology to have a particular shape.
1282 * @param op_cls closure argument to give with the operation event
1283 * @param num_peers number of peers in @a peers
1284 * @param peers array of @a num_peers with the peers to configure
1285 * @param topo desired underlay topology to use
1286 * @param ... topology-specific options
1287 * @return handle to the operation, NULL if configuring the topology
1288 * is not allowed at this time
1290 struct GNUNET_TESTBED_Operation *
1291 GNUNET_TESTBED_underlay_configure_topology (void *op_cls,
1292 unsigned int num_peers,
1293 struct GNUNET_TESTBED_Peer **peers,
1294 enum GNUNET_TESTBED_TopologyOption
1303 * All peers must have been started before calling this function.
1304 * This function then connects the given peers in the P2P overlay
1305 * using the given topology.
1307 * @param op_cls closure argument to give with the peer connect operation events
1308 * generated through this function
1309 * @param num_peers number of peers in @a peers
1310 * @param peers array of @a num_peers with the peers to configure
1311 * @param max_connections the maximums number of overlay connections that will
1312 * be made to achieve the given topology
1313 * @param comp_cb the completion callback to call when the topology generation
1315 * @param comp_cb_cls closure for the above completion callback
1316 * @param topo desired underlay topology to use
1317 * @param va topology-specific options
1318 * @return handle to the operation, NULL if connecting these
1319 * peers is fundamentally not possible at this time (peers
1320 * not running or underlay disallows) or if num_peers is less than 2
1322 struct GNUNET_TESTBED_Operation *
1323 GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls,
1324 unsigned int num_peers,
1325 struct GNUNET_TESTBED_Peer **peers,
1326 unsigned int *max_connections,
1327 GNUNET_TESTBED_TopologyCompletionCallback
1330 enum GNUNET_TESTBED_TopologyOption
1334 struct TopologyContext *tc;
1335 struct TopologyContextOverlay *overlay;
1336 struct GNUNET_TESTBED_Operation *op;
1337 struct GNUNET_TESTBED_Controller *c;
1338 enum GNUNET_TESTBED_TopologyOption secondary_option;
1342 c = peers[0]->controller;
1343 tc = GNUNET_new (struct TopologyContext);
1344 tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY;
1345 overlay = &tc->u.overlay;
1346 overlay->peers = peers;
1347 tc->num_peers = num_peers;
1348 overlay->op_cls = op_cls;
1349 overlay->retry_cnt = DEFAULT_RETRY_CNT;
1350 overlay->comp_cb = comp_cb;
1351 overlay->comp_cb_cls = comp_cb_cls;
1354 case GNUNET_TESTBED_TOPOLOGY_LINE:
1358 case GNUNET_TESTBED_TOPOLOGY_STAR:
1362 case GNUNET_TESTBED_TOPOLOGY_RING:
1366 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1367 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_NO);
1370 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1372 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1375 case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
1376 gen_topo_clique (tc);
1379 case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
1380 gen_topo_2dtorus (tc);
1383 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1384 gen_topo_2dtorus (tc);
1385 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1389 case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
1394 cap = (uint16_t) va_arg (va, unsigned int);
1395 m = (uint8_t) va_arg (va, unsigned int);
1396 gen_topo_scale_free (tc, cap, m);
1400 case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1402 const char *filename;
1404 filename = va_arg (va, const char *);
1406 GNUNET_assert (NULL != filename);
1407 gen_topo_from_file (tc, filename);
1418 secondary_option = GNUNET_VA_ARG_ENUM (va, GNUNET_TESTBED_TopologyOption);
1420 switch (secondary_option)
1422 case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT:
1423 overlay->retry_cnt = va_arg (va, unsigned int);
1426 case GNUNET_TESTBED_TOPOLOGY_OPTION_END:
1430 GNUNET_break (0); /* Should not use any other option apart from
1431 * the ones handled here */
1432 GNUNET_free_non_null (overlay->link_array);
1437 while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option);
1438 op = GNUNET_TESTBED_operation_create_ (tc,
1439 &opstart_overlay_configure_topology,
1440 &oprelease_overlay_configure_topology);
1441 GNUNET_TESTBED_operation_queue_insert_
1442 (c->opq_parallel_topology_config_operations, op);
1443 GNUNET_TESTBED_operation_begin_wait_ (op);
1444 LOG (GNUNET_ERROR_TYPE_DEBUG,
1445 "Generated %u connections\n",
1446 tc->link_array_size);
1447 if (NULL != max_connections)
1448 *max_connections = tc->link_array_size;
1454 * All peers must have been started before calling this function.
1455 * This function then connects the given peers in the P2P overlay
1456 * using the given topology.
1458 * @param op_cls closure argument to give with the peer connect operation events
1459 * generated through this function
1460 * @param num_peers number of peers in 'peers'
1461 * @param peers array of 'num_peers' with the peers to configure
1462 * @param max_connections the maximums number of overlay connections that will
1463 * be made to achieve the given topology
1464 * @param comp_cb the completion callback to call when the topology generation
1466 * @param comp_cb_cls closure for the above completion callback
1467 * @param topo desired underlay topology to use
1468 * @param ... topology-specific options
1469 * @return handle to the operation, NULL if connecting these
1470 * peers is fundamentally not possible at this time (peers
1471 * not running or underlay disallows) or if num_peers is less than 2
1473 struct GNUNET_TESTBED_Operation *
1474 GNUNET_TESTBED_overlay_configure_topology (void *op_cls,
1475 unsigned int num_peers,
1476 struct GNUNET_TESTBED_Peer **peers,
1477 unsigned int *max_connections,
1478 GNUNET_TESTBED_TopologyCompletionCallback
1481 enum GNUNET_TESTBED_TopologyOption
1485 struct GNUNET_TESTBED_Operation *op;
1488 GNUNET_assert (topo < GNUNET_TESTBED_TOPOLOGY_OPTION_END);
1489 va_start (vargs, topo);
1490 op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers,
1492 comp_cb, comp_cb_cls,
1501 * Get a topology from a string input.
1503 * @param topology where to write the retrieved topology
1504 * @param topology_string The string to attempt to
1505 * get a configuration value from
1506 * @return #GNUNET_YES if topology string matched a
1507 * known topology, #GNUNET_NO if not
1510 GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology,
1511 const char *topology_string)
1515 for (cnt = 0; NULL != topology_strings[cnt]; cnt++)
1517 if (0 == strcasecmp (topology_string, topology_strings[cnt]))
1519 if (NULL != topology)
1520 *topology = (enum GNUNET_TESTBED_TopologyOption) cnt;
1521 GNUNET_assert (GNUNET_TESTBED_TOPOLOGY_OPTION_END !=
1522 (enum GNUNET_TESTBED_TopologyOption) cnt);
1531 * Returns the string corresponding to the given topology
1533 * @param topology the topology
1534 * @return the string (freshly allocated) of given topology; NULL if topology cannot be
1535 * expressed as a string
1538 GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology)
1540 if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology)
1542 return GNUNET_strdup (topology_strings[topology]);
1547 * Function to construct an underlay topology
1549 * @param num_peers the number of peers for which the topology should be
1551 * @param proc the underlay link processor callback. Will be called for each
1552 * underlay link generated unless a previous call to this callback
1553 * returned #GNUNET_SYSERR. Cannot be NULL.
1554 * @param cls closure for @a proc
1555 * @param ... variable arguments denoting the topology and its parameters. They
1556 * should start with the type of topology to generate followed by their
1558 * @return #GNUNET_OK if underlay link generation is successful; #GNUNET_SYSERR
1559 * upon error in generating the underlay or if any calls to the
1560 * underlay link processor returned #GNUNET_SYSERR
1563 GNUNET_TESTBED_underlay_construct_ (int num_peers,
1564 underlay_link_processor proc,
1568 struct TopologyContext tc;
1569 struct TopologyContextUnderlay *underlay;
1570 struct UnderlayLink *ulink;
1572 enum GNUNET_TESTBED_TopologyOption topology;
1576 GNUNET_assert (NULL != proc);
1578 memset (&tc, 0, sizeof(tc));
1579 tc.num_peers = num_peers;
1580 tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY;
1581 underlay = &tc.u.underlay;
1582 va_start (vargs, cls);
1583 topology = GNUNET_VA_ARG_ENUM (vargs, GNUNET_TESTBED_TopologyOption);
1586 case GNUNET_TESTBED_TOPOLOGY_LINE:
1587 gen_topo_line (&tc);
1590 case GNUNET_TESTBED_TOPOLOGY_STAR:
1591 gen_topo_star (&tc);
1594 case GNUNET_TESTBED_TOPOLOGY_RING:
1595 gen_topo_ring (&tc);
1598 case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
1599 gen_topo_clique (&tc);
1602 case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
1603 gen_topo_2dtorus (&tc);
1606 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1607 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO);
1610 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1611 gen_topo_ring (&tc);
1612 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1615 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1616 gen_topo_2dtorus (&tc);
1617 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1620 case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1622 const char *filename;
1623 filename = va_arg (vargs, char *);
1624 GNUNET_assert (NULL != filename);
1625 gen_topo_from_file (&tc, filename);
1629 case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
1633 cap = (uint16_t) va_arg (vargs, unsigned int);
1634 m = (uint8_t) va_arg (vargs, unsigned int);
1635 gen_topo_scale_free (&tc, cap, m);
1643 for (cnt = 0; cnt < tc.link_array_size; cnt++)
1645 ulink = &underlay->link_array[cnt];
1646 if (GNUNET_SYSERR == proc (cls,
1653 ret = GNUNET_SYSERR;
1657 GNUNET_free_non_null (underlay->link_array);
1661 /* end of testbed_api_topology.c */