aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/testbed_api_topology.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testbed/testbed_api_topology.c')
-rw-r--r--src/testbed/testbed_api_topology.c1661
1 files changed, 0 insertions, 1661 deletions
diff --git a/src/testbed/testbed_api_topology.c b/src/testbed/testbed_api_topology.c
deleted file mode 100644
index 0f7c0b15c..000000000
--- a/src/testbed/testbed_api_topology.c
+++ /dev/null
@@ -1,1661 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008--2013 GNUnet e.V.
4
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.
9
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.
14
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/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testbed/testbed_api_topology.c
23 * @brief topology-generation functions
24 * @author Christian Grothoff
25 */
26#include "platform.h"
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"
32
33/**
34 * Generic loggins shorthand
35 */
36#define LOG(kind, ...) \
37 GNUNET_log_from (kind, "testbed-api-topology", __VA_ARGS__)
38
39
40/**
41 * Default number of retires
42 */
43#define DEFAULT_RETRY_CNT 3
44
45
46/**
47 * Context information for topology operations
48 */
49struct TopologyContext;
50
51
52/**
53 * Representation of an overlay link
54 */
55struct OverlayLink
56{
57 /**
58 * An operation corresponding to this link
59 */
60 struct GNUNET_TESTBED_Operation *op;
61
62 /**
63 * The topology context this link is a part of
64 */
65 struct TopologyContext *tc;
66
67 /**
68 * position of peer A's handle in peers array
69 */
70 uint32_t A;
71
72 /**
73 * position of peer B's handle in peers array
74 */
75 uint32_t B;
76};
77
78
79/**
80 * Representation of an underlay link
81 */
82struct UnderlayLink
83{
84 /**
85 * position of peer A's handle in peers array
86 */
87 uint32_t A;
88
89 /**
90 * position of peer B's handle in peers array
91 */
92 uint32_t B;
93
94 /**
95 * Bandwidth of the link in bytes per second
96 */
97 uint32_t bandwidth;
98
99 /**
100 * Latency of the link in milliseconds
101 */
102 uint32_t latency;
103
104 /**
105 * Loss in the link in percentage of message dropped
106 */
107 uint32_t loss;
108};
109
110
111struct RetryListEntry
112{
113 /**
114 * the next pointer for the DLL
115 */
116 struct RetryListEntry *next;
117
118 /**
119 * the prev pointer for the DLL
120 */
121 struct RetryListEntry *prev;
122
123 /**
124 * The link to be retired
125 */
126 struct OverlayLink *link;
127};
128
129
130/**
131 * Context information for overlay topologies
132 */
133struct TopologyContextOverlay
134{
135 /**
136 * The array of peers
137 */
138 struct GNUNET_TESTBED_Peer **peers;
139
140 /**
141 * An array of links; this array is of size link_array_size
142 */
143 struct OverlayLink *link_array;
144
145 /**
146 * The operation closure
147 */
148 void *op_cls;
149
150 /**
151 * topology generation completion callback
152 */
153 GNUNET_TESTBED_TopologyCompletionCallback comp_cb;
154
155 /**
156 * The closure for the above callback
157 */
158 void *comp_cb_cls;
159
160 /**
161 * DLL head for retry list
162 */
163 struct RetryListEntry *rl_head;
164
165 /**
166 * DLL tail for retry list
167 */
168 struct RetryListEntry *rl_tail;
169
170 /**
171 * How many retries to do before we give up
172 */
173 unsigned int retry_cnt;
174
175 /**
176 * Number of links to try
177 */
178 unsigned int nlinks;
179
180 /**
181 * How many links have been completed
182 */
183 unsigned int ncompleted;
184
185 /**
186 * Total successfully established overlay connections
187 */
188 unsigned int nsuccess;
189
190 /**
191 * Total failed overlay connections
192 */
193 unsigned int nfailures;
194};
195
196
197/**
198 * Topology context information for underlay topologies
199 */
200struct TopologyContextUnderlay
201{
202 /**
203 * The link array
204 */
205 struct UnderlayLink *link_array;
206};
207
208
209/**
210 * Context information for topology operations
211 */
212struct TopologyContext
213{
214 /**
215 * The type of this context
216 */
217 enum
218 {
219 /**
220 * Type for underlay topology
221 */
222 TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0,
223
224 /**
225 * Type for overlay topology
226 */
227 TOPOLOGYCONTEXT_TYPE_OVERLAY
228 } type;
229
230 union
231 {
232 /**
233 * Topology context information for overlay topology
234 */
235 struct TopologyContextOverlay overlay;
236
237 /**
238 * Topology context information for underlay topology
239 */
240 struct TopologyContextUnderlay underlay;
241 } u;
242
243 /**
244 * The number of peers
245 */
246 unsigned int num_peers;
247
248 /**
249 * The size of the link array
250 */
251 unsigned int link_array_size;
252};
253
254
255/**
256 * A array of names representing topologies. Should be in sync with enum
257 * GNUNET_TESTBED_TopologyOption
258 */
259static const char *topology_strings[] = {
260 /**
261 * A clique (everyone connected to everyone else). No options. If there are N
262 * peers this topology results in (N * (N -1)) connections.
263 */
264 "CLIQUE",
265
266 /*
267 * Small-world network (2d torus plus random links). Followed
268 * by the number of random links to add (unsigned int).
269 */
270 "SMALL_WORLD",
271
272 /**
273 * Small-world network (ring plus random links). Followed
274 * by the number of random links to add (unsigned int).
275 */
276 "SMALL_WORLD_RING",
277
278 /**
279 * Ring topology. No options.
280 */
281 "RING",
282
283 /**
284 * Star topology. No options.
285 */
286 "STAR",
287
288 /**
289 * 2-d torus. No options.
290 */
291 "2D_TORUS",
292
293 /**
294 * Random graph. Followed by the number of random links to be established
295 * (unsigned int)
296 */
297 "RANDOM", // GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI
298
299 /**
300 * Certain percentage of peers are unable to communicate directly
301 * replicating NAT conditions. Followed by the fraction of
302 * NAT'ed peers (float).
303 */
304 "INTERNAT",
305
306 /**
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)
310 */
311 "SCALE_FREE",
312
313 /**
314 * Straight line topology. No options.
315 */
316 "LINE",
317
318 /**
319 * Read a topology from a given file. Followed by the name of the file (const char *).
320 */
321 "FROM_FILE",
322
323 /**
324 * All peers are disconnected. No options.
325 */
326 "NONE",
327
328 /**
329 * End of strings
330 */
331 NULL
332};
333
334
335/**
336 * Callback to be called when an overlay_link operation complete
337 *
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.
342 */
343static void
344overlay_link_completed (void *cls,
345 struct GNUNET_TESTBED_Operation *op,
346 const char *emsg)
347{
348 struct OverlayLink *link = cls;
349 struct TopologyContext *tc;
350 struct TopologyContextOverlay *overlay;
351 struct RetryListEntry *retry_entry;
352
353 GNUNET_assert (op == link->op);
354 GNUNET_TESTBED_operation_done (op);
355 link->op = NULL;
356 tc = link->tc;
357 GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
358 overlay = &tc->u.overlay;
359 if (NULL != emsg)
360 {
361 overlay->nfailures++;
362 if (0 != overlay->retry_cnt)
363 {
364 LOG (GNUNET_ERROR_TYPE_WARNING,
365 "Error while establishing a link: %s -- Retrying\n",
366 emsg);
367 retry_entry = GNUNET_new (struct RetryListEntry);
368 retry_entry->link = link;
369 GNUNET_CONTAINER_DLL_insert_tail (overlay->rl_head,
370 overlay->rl_tail,
371 retry_entry);
372 }
373 }
374 else
375 overlay->nsuccess++;
376 overlay->ncompleted++;
377 if (overlay->ncompleted < overlay->nlinks)
378 return;
379 if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head))
380 {
381 overlay->retry_cnt--;
382 overlay->ncompleted = 0;
383 overlay->nlinks = 0;
384 while (NULL != (retry_entry = overlay->rl_head))
385 {
386 link = retry_entry->link;
387 link->op =
388 GNUNET_TESTBED_overlay_connect (overlay->op_cls,
389 &overlay_link_completed,
390 link,
391 overlay->peers[link->A],
392 overlay->peers[link->B]);
393 overlay->nlinks++;
394 GNUNET_CONTAINER_DLL_remove (overlay->rl_head,
395 overlay->rl_tail,
396 retry_entry);
397 GNUNET_free (retry_entry);
398 }
399 return;
400 }
401 if (NULL != overlay->comp_cb)
402 {
403 overlay->comp_cb (overlay->comp_cb_cls,
404 overlay->nsuccess,
405 overlay->nfailures);
406 }
407}
408
409
410/**
411 * Function called when a overlay connect operation is ready
412 *
413 * @param cls the Topology context
414 */
415static void
416opstart_overlay_configure_topology (void *cls)
417{
418 struct TopologyContext *tc = cls;
419 struct TopologyContextOverlay *overlay;
420 unsigned int p;
421
422 GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
423 overlay = &tc->u.overlay;
424 overlay->nlinks = tc->link_array_size;
425 for (p = 0; p < tc->link_array_size; p++)
426 {
427 overlay->link_array[p].op =
428 GNUNET_TESTBED_overlay_connect (overlay->op_cls,
429 &overlay_link_completed,
430 &overlay->link_array[p],
431 overlay->peers[overlay->link_array[p].A],
432 overlay->peers[overlay->link_array[p].B]);
433 }
434}
435
436
437/**
438 * Callback which will be called when overlay connect operation is released
439 *
440 * @param cls the Topology context
441 */
442static void
443oprelease_overlay_configure_topology (void *cls)
444{
445 struct TopologyContext *tc = cls;
446 struct TopologyContextOverlay *overlay;
447 struct RetryListEntry *retry_entry;
448 unsigned int p;
449
450 GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
451 overlay = &tc->u.overlay;
452 while (NULL != (retry_entry = overlay->rl_head))
453 {
454 GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail,
455 retry_entry);
456 GNUNET_free (retry_entry);
457 }
458 if (NULL != overlay->link_array)
459 {
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);
464 }
465 GNUNET_free (tc);
466}
467
468
469/**
470 * Populates the OverlayLink structure.
471 *
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
476 * @return
477 */
478static void
479make_link (unsigned int offset,
480 uint32_t A,
481 uint32_t B,
482 struct TopologyContext *tc)
483{
484 GNUNET_assert (A != B);
485 switch (tc->type)
486 {
487 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
488 {
489 struct TopologyContextOverlay *overlay;
490 struct OverlayLink *olink;
491
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);
496 olink->A = A;
497 olink->B = B;
498 olink->op = NULL;
499 olink->tc = tc;
500 }
501 break;
502
503 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
504 {
505 struct TopologyContextUnderlay *underlay;
506 struct UnderlayLink *ulink;
507
508 underlay = &tc->u.underlay;
509 GNUNET_assert (offset < tc->link_array_size);
510 ulink = &underlay->link_array[offset];
511 ulink->A = A;
512 ulink->B = B;
513 }
514 break;
515 }
516}
517
518
519/**
520 * Generates line topology
521 *
522 * @param tc the topology context
523 */
524static void
525gen_topo_line (struct TopologyContext *tc)
526{
527 unsigned int cnt;
528
529 tc->link_array_size = tc->num_peers - 1;
530 switch (tc->type)
531 {
532 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
533 {
534 struct TopologyContextOverlay *overlay;
535
536 overlay = &tc->u.overlay;
537 overlay->link_array =
538 GNUNET_new_array (tc->link_array_size,
539 struct OverlayLink);
540 }
541 break;
542
543 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
544 {
545 struct TopologyContextUnderlay *underlay;
546
547 underlay = &tc->u.underlay;
548 underlay->link_array =
549 GNUNET_new_array (tc->link_array_size,
550 struct UnderlayLink);
551 }
552 break;
553 }
554 for (cnt = 0; cnt < (tc->link_array_size); cnt++)
555 make_link (cnt, cnt, cnt + 1, tc);
556}
557
558
559/**
560 * Generates star topology
561 *
562 * @param tc the topology context
563 */
564static void
565gen_topo_star (struct TopologyContext *tc)
566{
567 unsigned int cnt;
568
569 tc->link_array_size = tc->num_peers - 1;
570 switch (tc->type)
571 {
572 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
573 {
574 struct TopologyContextOverlay *overlay;
575
576 overlay = &tc->u.overlay;
577 overlay->link_array =
578 GNUNET_new_array (tc->link_array_size,
579 struct OverlayLink);
580 }
581 break;
582
583 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
584 {
585 struct TopologyContextUnderlay *underlay;
586
587 underlay = &tc->u.underlay;
588 underlay->link_array =
589 GNUNET_new_array (tc->link_array_size,
590 struct UnderlayLink);
591 }
592 break;
593 }
594 for (cnt = tc->link_array_size; cnt; cnt--)
595 make_link (cnt - 1,
596 0,
597 cnt,
598 tc);
599}
600
601
602/**
603 * Generates ring topology
604 *
605 * @param tc the topology context
606 */
607static void
608gen_topo_ring (struct TopologyContext *tc)
609{
610 gen_topo_line (tc);
611 tc->link_array_size++;
612 switch (tc->type)
613 {
614 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
615 {
616 struct TopologyContextOverlay *overlay;
617
618 overlay = &tc->u.overlay;
619 overlay->link_array =
620 GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink)
621 * tc->link_array_size);
622 }
623 break;
624
625 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
626 {
627 struct TopologyContextUnderlay *underlay;
628
629 underlay = &tc->u.underlay;
630 underlay->link_array =
631 GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink)
632 * tc->link_array_size);
633 }
634 break;
635 }
636 make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc);
637}
638
639
640/**
641 * Returns the number of links that are required to generate a 2d torus for the
642 * given number of peers. Also returns the arrangement (number of rows and the
643 * length of each row)
644 *
645 * @param num_peers number of peers
646 * @param rows number of rows in the 2d torus. Can be NULL
647 * @param rows_len the length of each row. This array will be allocated
648 * fresh. The caller should free it. Can be NULL
649 * @return the number of links that are required to generate a 2d torus for the
650 * given number of peers
651 */
652unsigned int
653GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows,
654 unsigned int **rows_len)
655{
656 double sq;
657 unsigned int sq_floor;
658 unsigned int _rows;
659 unsigned int *_rows_len;
660 unsigned int x;
661 unsigned int y;
662 unsigned int _num_peers;
663 unsigned int cnt;
664
665 sq = sqrt (num_peers);
666 sq = floor (sq);
667 sq_floor = (unsigned int) sq;
668 _rows = (sq_floor + 1);
669 _rows_len = GNUNET_malloc (sizeof(unsigned int) * _rows);
670 for (y = 0; y < _rows - 1; y++)
671 _rows_len[y] = sq_floor;
672 _num_peers = sq_floor * sq_floor;
673 cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers;
674 x = 0;
675 y = 0;
676 while (_num_peers < num_peers)
677 {
678 if (x < y)
679 _rows_len[_rows - 1] = ++x;
680 else
681 _rows_len[y++]++;
682 _num_peers++;
683 }
684 cnt += (x < 2) ? x : 2 * x;
685 cnt += (y < 2) ? y : 2 * y;
686 if (0 == _rows_len[_rows - 1])
687 _rows--;
688 if (NULL != rows)
689 *rows = _rows;
690 if (NULL != rows_len)
691 *rows_len = _rows_len;
692 else
693 GNUNET_free (_rows_len);
694 return cnt;
695}
696
697
698/**
699 * Generates ring topology
700 *
701 * @param tc the topology context
702 */
703static void
704gen_topo_2dtorus (struct TopologyContext *tc)
705{
706 unsigned int rows;
707 unsigned int *rows_len;
708 unsigned int x;
709 unsigned int y;
710 unsigned int cnt;
711 unsigned int offset;
712
713 tc->link_array_size =
714 GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len);
715 switch (tc->type)
716 {
717 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
718 {
719 struct TopologyContextOverlay *overlay;
720
721 overlay = &tc->u.overlay;
722 overlay->link_array =
723 GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size);
724 }
725 break;
726
727 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
728 {
729 struct TopologyContextUnderlay *underlay;
730
731 underlay = &tc->u.underlay;
732 underlay->link_array =
733 GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size);
734 break;
735 }
736 }
737 cnt = 0;
738 offset = 0;
739 for (y = 0; y < rows; y++)
740 {
741 for (x = 0; x < rows_len[y] - 1; x++)
742 {
743 make_link (cnt, offset + x, offset + x + 1, tc);
744 cnt++;
745 }
746 if (0 == x)
747 break;
748 make_link (cnt, offset + x, offset, tc);
749 cnt++;
750 offset += rows_len[y];
751 }
752 for (x = 0; x < rows_len[0]; x++)
753 {
754 offset = 0;
755 for (y = 0; y < rows - 1; y++)
756 {
757 if (x >= rows_len[y + 1])
758 break;
759 GNUNET_assert (x < rows_len[y + 1]);
760 make_link (cnt, offset + x, offset + rows_len[y] + x, tc);
761 offset += rows_len[y];
762 cnt++;
763 }
764 if (0 == offset)
765 break;
766 make_link (cnt, offset + x, x, tc);
767 cnt++;
768 }
769 GNUNET_assert (cnt == tc->link_array_size);
770 GNUNET_free (rows_len);
771}
772
773
774/**
775 * Generates ring topology
776 *
777 * @param tc the topology context
778 * @param links the number of random links to establish
779 * @param append #GNUNET_YES to add links to existing link array; #GNUNET_NO to
780 * create a new link array
781 */
782static void
783gen_topo_random (struct TopologyContext *tc,
784 unsigned int links,
785 int append)
786{
787 unsigned int cnt;
788 unsigned int index;
789 uint32_t A_rand;
790 uint32_t B_rand;
791
792 if (1 == tc->num_peers)
793 return;
794 if (GNUNET_YES == append)
795 {
796 index = tc->link_array_size;
797 tc->link_array_size += links;
798 }
799 else
800 {
801 index = 0;
802 tc->link_array_size = links;
803 }
804 switch (tc->type)
805 {
806 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
807 {
808 struct TopologyContextOverlay *overlay;
809
810 overlay = &tc->u.overlay;
811 if (GNUNET_YES != append)
812 {
813 GNUNET_assert (NULL == overlay->link_array);
814 overlay->link_array =
815 GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size);
816 break;
817 }
818 GNUNET_assert ((0 < tc->link_array_size) && (NULL !=
819 overlay->link_array));
820 overlay->link_array =
821 GNUNET_realloc (overlay->link_array,
822 sizeof(struct OverlayLink) * tc->link_array_size);
823 break;
824 }
825
826 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
827 {
828 struct TopologyContextUnderlay *underlay;
829
830 underlay = &tc->u.underlay;
831 if (GNUNET_YES != append)
832 {
833 GNUNET_assert (NULL == underlay->link_array);
834 underlay->link_array =
835 GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size);
836 break;
837 }
838 GNUNET_assert ((0 < tc->link_array_size) && (NULL !=
839 underlay->link_array));
840 underlay->link_array =
841 GNUNET_realloc (underlay->link_array,
842 sizeof(struct UnderlayLink) * tc->link_array_size);
843 break;
844 }
845 }
846 for (cnt = 0; cnt < links; cnt++)
847 {
848 do
849 {
850 A_rand =
851 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
852 B_rand =
853 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
854 }
855 while (A_rand == B_rand);
856 make_link (index + cnt, A_rand, B_rand, tc);
857 }
858}
859
860
861/**
862 * Generates scale free network. Its construction is described in:
863 *
864 * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999.
865 *
866 * @param tc the topology context
867 * @param cap maximum allowed node degree
868 * @param m number of edges to establish for a new node when it is added to the
869 * network
870 */
871static void
872gen_topo_scale_free (struct TopologyContext *tc,
873 uint16_t cap,
874 uint8_t m)
875{
876 unsigned int *deg;
877 unsigned int *etab;
878 unsigned int *used;
879 unsigned int etaboff;
880 unsigned int cnt;
881 unsigned int cnt2;
882 unsigned int peer;
883 unsigned int random_peer;
884 unsigned int links;
885 unsigned int off;
886 unsigned int redo_threshold;
887
888 etaboff = 0;
889 tc->link_array_size = tc->num_peers * m;
890 switch (tc->type)
891 {
892 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
893 {
894 struct TopologyContextOverlay *overlay;
895
896 overlay = &tc->u.overlay;
897 overlay->link_array = GNUNET_malloc_large (sizeof(struct OverlayLink)
898 * tc->link_array_size);
899 }
900 break;
901
902 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
903 {
904 struct TopologyContextUnderlay *underlay;
905
906 underlay = &tc->u.underlay;
907 underlay->link_array = GNUNET_malloc_large (sizeof(struct UnderlayLink)
908 * tc->link_array_size);
909 }
910 break;
911 }
912 etab = GNUNET_malloc_large (sizeof(unsigned int) * 2 * tc->link_array_size);
913 deg = GNUNET_malloc (sizeof(unsigned int) * tc->num_peers);
914 used = GNUNET_malloc (sizeof(unsigned int) * m);
915 /* start by connecting peer 1 to peer 0 */
916 make_link (0, 0, 1, tc);
917 deg[0]++;
918 deg[1]++;
919 etab[etaboff++] = 0;
920 etab[etaboff++] = 1;
921 links = 1;
922 for (peer = 2; peer < tc->num_peers; peer++)
923 {
924 if (cap < deg[peer])
925 continue;
926 for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
927 {
928 redo_threshold = 0;
929redo:
930 off = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, etaboff);
931 random_peer = etab[off];
932 if (cap < deg[random_peer])
933 {
934 if (++redo_threshold > GNUNET_MAX (1, cap / 2))
935 {
936 redo_threshold = 0;
937 off = 0;
938 for (cnt2 = 0; cnt2 < etaboff; cnt2++)
939 {
940 if (random_peer == etab[cnt2])
941 {
942 off++;
943 continue;
944 }
945 etab[cnt2 - off] = etab[cnt2];
946 }
947 etaboff -= off;
948 }
949 goto redo;
950 }
951 for (cnt2 = 0; cnt2 < cnt; cnt2++)
952 if (random_peer == used[cnt2])
953 goto redo;
954 make_link (links + cnt, random_peer, peer, tc);
955 deg[random_peer]++;
956 deg[peer]++;
957 used[cnt] = random_peer;
958 }
959 for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
960 {
961 etab[etaboff++] = used[cnt];
962 etab[etaboff++] = peer;
963 }
964 links += GNUNET_MIN (peer, m);
965 }
966 GNUNET_free (etab);
967 GNUNET_free (used);
968 GNUNET_free (deg);
969 GNUNET_assert (links <= tc->link_array_size);
970 tc->link_array_size = links;
971 switch (tc->type)
972 {
973 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
974 {
975 struct TopologyContextOverlay *overlay;
976
977 overlay = &tc->u.overlay;
978 overlay->link_array =
979 GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink)
980 * tc->link_array_size);
981 }
982 break;
983
984 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
985 {
986 struct TopologyContextUnderlay *underlay;
987
988 underlay = &tc->u.underlay;
989 underlay->link_array =
990 GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink)
991 * tc->link_array_size);
992 }
993 break;
994 }
995}
996
997
998/**
999 * Generates topology from the given file
1000 *
1001 * @param tc the topology context
1002 * @param filename the filename of the file containing topology data
1003 */
1004static void
1005gen_topo_from_file (struct TopologyContext *tc,
1006 const char *filename)
1007{
1008 char *data;
1009 char *end;
1010 char *buf;
1011 uint64_t fs;
1012 uint64_t offset;
1013 unsigned long int peer_id;
1014 unsigned long int other_peer_id;
1015 enum ParseState
1016 {
1017 /**
1018 * We read the peer index
1019 */
1020 PEER_INDEX,
1021
1022 /**
1023 * We read the other peer indices
1024 */
1025 OTHER_PEER_INDEX,
1026 } state;
1027 int status;
1028
1029 status = GNUNET_SYSERR;
1030 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1031 {
1032 LOG (GNUNET_ERROR_TYPE_ERROR,
1033 _ ("Topology file %s not found\n"),
1034 filename);
1035 return;
1036 }
1037 if (GNUNET_OK !=
1038 GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
1039 {
1040 LOG (GNUNET_ERROR_TYPE_ERROR,
1041 _ ("Topology file %s has no data\n"),
1042 filename);
1043 return;
1044 }
1045 data = GNUNET_malloc (fs);
1046 if (fs != GNUNET_DISK_fn_read (filename, data, fs))
1047 {
1048 LOG (GNUNET_ERROR_TYPE_ERROR,
1049 _ ("Topology file %s cannot be read\n"),
1050 filename);
1051 goto _exit;
1052 }
1053
1054 offset = 0;
1055 peer_id = 0;
1056 state = PEER_INDEX;
1057 while (offset < fs)
1058 {
1059 if (0 != isspace ((unsigned char) data[offset]))
1060 {
1061 offset++;
1062 continue;
1063 }
1064 switch (state)
1065 {
1066 case PEER_INDEX:
1067 buf = strchr (&data[offset], ':');
1068 if (NULL == buf)
1069 {
1070 LOG (GNUNET_ERROR_TYPE_ERROR,
1071 _ ("Failed to read peer index from toology file: %s"), filename);
1072 goto _exit;
1073 }
1074 *buf = '\0';
1075 errno = 0;
1076 peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1077 if (0 != errno)
1078 {
1079 LOG (GNUNET_ERROR_TYPE_ERROR,
1080 _ ("Value in given topology file: %s out of range\n"), filename);
1081 goto _exit;
1082 }
1083 if (&data[offset] == end)
1084 {
1085 LOG (GNUNET_ERROR_TYPE_ERROR,
1086 _ ("Failed to read peer index from topology file: %s"), filename);
1087 goto _exit;
1088 }
1089 if (tc->num_peers <= peer_id)
1090 {
1091 LOG (GNUNET_ERROR_TYPE_ERROR,
1092 _ ("Topology file needs more peers than given ones\n"));
1093 goto _exit;
1094 }
1095 state = OTHER_PEER_INDEX;
1096 offset += ((unsigned int) (buf - &data[offset])) + 1;
1097 break;
1098
1099 case OTHER_PEER_INDEX:
1100 errno = 0;
1101 other_peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1102 if (0 != errno)
1103 {
1104 LOG (GNUNET_ERROR_TYPE_ERROR,
1105 _ ("Value in given topology file: %s out of range\n"), filename);
1106 goto _exit;
1107 }
1108 if (&data[offset] == end)
1109 {
1110 LOG (GNUNET_ERROR_TYPE_ERROR,
1111 _ ("Failed to read peer index from topology file: %s"), filename);
1112 goto _exit;
1113 }
1114 if (tc->num_peers <= other_peer_id)
1115 {
1116 LOG (GNUNET_ERROR_TYPE_ERROR,
1117 _ ("Topology file needs more peers than given ones\n"));
1118 goto _exit;
1119 }
1120 if (peer_id != other_peer_id)
1121 {
1122 tc->link_array_size++;
1123 switch (tc->type)
1124 {
1125 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1126 {
1127 struct TopologyContextOverlay *overlay;
1128
1129 overlay = &tc->u.overlay;
1130 overlay->link_array =
1131 GNUNET_realloc (overlay->link_array,
1132 sizeof(struct OverlayLink) * tc->link_array_size);
1133 }
1134 break;
1135
1136 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1137 {
1138 struct TopologyContextUnderlay *underlay;
1139
1140 underlay = &tc->u.underlay;
1141 underlay->link_array =
1142 GNUNET_realloc (underlay->link_array,
1143 sizeof(struct UnderlayLink)
1144 * tc->link_array_size);
1145 }
1146 break;
1147 }
1148 offset += end - &data[offset];
1149 make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc);
1150 }
1151 else
1152 LOG (GNUNET_ERROR_TYPE_WARNING,
1153 _ ("Ignoring to connect peer %lu to peer %lu\n"),
1154 peer_id,
1155 other_peer_id);
1156 while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs))
1157 offset++;
1158 if ((offset < fs) &&
1159 ('\n' == data[offset]))
1160 state = PEER_INDEX;
1161 else if ((offset < fs) &&
1162 ('|' == data[offset]))
1163 {
1164 state = OTHER_PEER_INDEX;
1165 offset++;
1166 }
1167 break;
1168 }
1169 }
1170 status = GNUNET_OK;
1171
1172_exit:
1173 GNUNET_free (data);
1174 if (GNUNET_OK != status)
1175 {
1176 LOG (GNUNET_ERROR_TYPE_WARNING,
1177 "Removing link data read from the file\n");
1178 tc->link_array_size = 0;
1179 switch (tc->type)
1180 {
1181 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1182 {
1183 struct TopologyContextOverlay *overlay;
1184
1185 overlay = &tc->u.overlay;
1186 GNUNET_free (overlay->link_array);
1187 overlay->link_array = NULL;
1188 }
1189 break;
1190
1191 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1192 {
1193 struct TopologyContextUnderlay *underlay;
1194
1195 underlay = &tc->u.underlay;
1196 GNUNET_free (underlay->link_array);
1197 underlay->link_array = NULL;
1198 }
1199 break;
1200 }
1201 }
1202}
1203
1204
1205/**
1206 * Generates clique topology
1207 *
1208 * @param tc the topology context
1209 */
1210static void
1211gen_topo_clique (struct TopologyContext *tc)
1212{
1213 unsigned int cnt;
1214 unsigned int offset;
1215 unsigned int neighbour;
1216
1217 tc->link_array_size = tc->num_peers * (tc->num_peers - 1);
1218 switch (tc->type)
1219 {
1220 case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1221 {
1222 struct TopologyContextOverlay *overlay;
1223
1224 overlay = &tc->u.overlay;
1225 overlay->link_array = GNUNET_new_array (tc->link_array_size,
1226 struct OverlayLink);
1227 }
1228 break;
1229
1230 case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1231 {
1232 struct TopologyContextUnderlay *underlay;
1233
1234 underlay = &tc->u.underlay;
1235 underlay->link_array = GNUNET_new_array (tc->link_array_size,
1236 struct UnderlayLink);
1237 }
1238 }
1239 offset = 0;
1240 for (cnt = 0; cnt < tc->num_peers; cnt++)
1241 {
1242 for (neighbour = 0; neighbour < tc->num_peers; neighbour++)
1243 {
1244 if (neighbour == cnt)
1245 continue;
1246 make_link (offset, cnt, neighbour, tc);
1247 offset++;
1248 }
1249 }
1250}
1251
1252
1253/**
1254 * Configure overall network topology to have a particular shape.
1255 *
1256 * @param op_cls closure argument to give with the operation event
1257 * @param num_peers number of peers in @a peers
1258 * @param peers array of @a num_peers with the peers to configure
1259 * @param topo desired underlay topology to use
1260 * @param ap topology-specific options
1261 * @return handle to the operation, NULL if configuring the topology
1262 * is not allowed at this time
1263 */
1264struct GNUNET_TESTBED_Operation *
1265GNUNET_TESTBED_underlay_configure_topology_va (void *op_cls,
1266 unsigned int num_peers,
1267 struct GNUNET_TESTBED_Peer
1268 **peers,
1269 enum
1270 GNUNET_TESTBED_TopologyOption
1271 topo, va_list ap)
1272{
1273 GNUNET_break (0);
1274 return NULL;
1275}
1276
1277
1278/**
1279 * Configure overall network topology to have a particular shape.
1280 *
1281 * @param op_cls closure argument to give with the operation event
1282 * @param num_peers number of peers in @a peers
1283 * @param peers array of @a num_peers with the peers to configure
1284 * @param topo desired underlay topology to use
1285 * @param ... topology-specific options
1286 * @return handle to the operation, NULL if configuring the topology
1287 * is not allowed at this time
1288 */
1289struct GNUNET_TESTBED_Operation *
1290GNUNET_TESTBED_underlay_configure_topology (void *op_cls,
1291 unsigned int num_peers,
1292 struct GNUNET_TESTBED_Peer **peers,
1293 enum GNUNET_TESTBED_TopologyOption
1294 topo, ...)
1295{
1296 GNUNET_break (0);
1297 return NULL;
1298}
1299
1300
1301/**
1302 * All peers must have been started before calling this function.
1303 * This function then connects the given peers in the P2P overlay
1304 * using the given topology.
1305 *
1306 * @param op_cls closure argument to give with the peer connect operation events
1307 * generated through this function
1308 * @param num_peers number of peers in @a peers
1309 * @param peers array of @a num_peers with the peers to configure
1310 * @param max_connections the maximums number of overlay connections that will
1311 * be made to achieve the given topology
1312 * @param comp_cb the completion callback to call when the topology generation
1313 * is completed
1314 * @param comp_cb_cls closure for the above completion callback
1315 * @param topo desired underlay topology to use
1316 * @param va topology-specific options
1317 * @return handle to the operation, NULL if connecting these
1318 * peers is fundamentally not possible at this time (peers
1319 * not running or underlay disallows) or if num_peers is less than 2
1320 */
1321struct GNUNET_TESTBED_Operation *
1322GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls,
1323 unsigned int num_peers,
1324 struct GNUNET_TESTBED_Peer **peers,
1325 unsigned int *max_connections,
1326 GNUNET_TESTBED_TopologyCompletionCallback
1327 comp_cb,
1328 void *comp_cb_cls,
1329 enum GNUNET_TESTBED_TopologyOption
1330 topo,
1331 va_list va)
1332{
1333 struct TopologyContext *tc;
1334 struct TopologyContextOverlay *overlay;
1335 struct GNUNET_TESTBED_Operation *op;
1336 struct GNUNET_TESTBED_Controller *c;
1337 enum GNUNET_TESTBED_TopologyOption secondary_option;
1338
1339 if (num_peers < 2)
1340 return NULL;
1341 c = peers[0]->controller;
1342 tc = GNUNET_new (struct TopologyContext);
1343 tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY;
1344 overlay = &tc->u.overlay;
1345 overlay->peers = peers;
1346 tc->num_peers = num_peers;
1347 overlay->op_cls = op_cls;
1348 overlay->retry_cnt = DEFAULT_RETRY_CNT;
1349 overlay->comp_cb = comp_cb;
1350 overlay->comp_cb_cls = comp_cb_cls;
1351 switch (topo)
1352 {
1353 case GNUNET_TESTBED_TOPOLOGY_LINE:
1354 gen_topo_line (tc);
1355 break;
1356
1357 case GNUNET_TESTBED_TOPOLOGY_STAR:
1358 gen_topo_star (tc);
1359 break;
1360
1361 case GNUNET_TESTBED_TOPOLOGY_RING:
1362 gen_topo_ring (tc);
1363 break;
1364
1365 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1366 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_NO);
1367 break;
1368
1369 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1370 gen_topo_ring (tc);
1371 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1372 break;
1373
1374 case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
1375 gen_topo_clique (tc);
1376 break;
1377
1378 case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
1379 gen_topo_2dtorus (tc);
1380 break;
1381
1382 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1383 gen_topo_2dtorus (tc);
1384 gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1385
1386 break;
1387
1388 case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
1389 {
1390 uint16_t cap;
1391 uint8_t m;
1392
1393 cap = (uint16_t) va_arg (va, unsigned int);
1394 m = (uint8_t) va_arg (va, unsigned int);
1395 gen_topo_scale_free (tc, cap, m);
1396 }
1397 break;
1398
1399 case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1400 {
1401 const char *filename;
1402
1403 filename = va_arg (va, const char *);
1404
1405 GNUNET_assert (NULL != filename);
1406 gen_topo_from_file (tc, filename);
1407 }
1408 break;
1409
1410 default:
1411 GNUNET_break (0);
1412 GNUNET_free (tc);
1413 return NULL;
1414 }
1415 do
1416 {
1417 secondary_option = GNUNET_VA_ARG_ENUM (va, GNUNET_TESTBED_TopologyOption);
1418
1419 switch (secondary_option)
1420 {
1421 case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT:
1422 overlay->retry_cnt = va_arg (va, unsigned int);
1423 break;
1424
1425 case GNUNET_TESTBED_TOPOLOGY_OPTION_END:
1426 break;
1427
1428 default:
1429 GNUNET_break (0); /* Should not use any other option apart from
1430 * the ones handled here */
1431 GNUNET_free (overlay->link_array);
1432 GNUNET_free (tc);
1433 return NULL;
1434 }
1435 }
1436 while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option);
1437 op = GNUNET_TESTBED_operation_create_ (tc,
1438 &opstart_overlay_configure_topology,
1439 &oprelease_overlay_configure_topology);
1440 GNUNET_TESTBED_operation_queue_insert_
1441 (c->opq_parallel_topology_config_operations, op);
1442 GNUNET_TESTBED_operation_begin_wait_ (op);
1443 LOG (GNUNET_ERROR_TYPE_DEBUG,
1444 "Generated %u connections\n",
1445 tc->link_array_size);
1446 if (NULL != max_connections)
1447 *max_connections = tc->link_array_size;
1448 return op;
1449}
1450
1451
1452/**
1453 * All peers must have been started before calling this function.
1454 * This function then connects the given peers in the P2P overlay
1455 * using the given topology.
1456 *
1457 * @param op_cls closure argument to give with the peer connect operation events
1458 * generated through this function
1459 * @param num_peers number of peers in 'peers'
1460 * @param peers array of 'num_peers' with the peers to configure
1461 * @param max_connections the maximums number of overlay connections that will
1462 * be made to achieve the given topology
1463 * @param comp_cb the completion callback to call when the topology generation
1464 * is completed
1465 * @param comp_cb_cls closure for the above completion callback
1466 * @param topo desired underlay topology to use
1467 * @param ... topology-specific options
1468 * @return handle to the operation, NULL if connecting these
1469 * peers is fundamentally not possible at this time (peers
1470 * not running or underlay disallows) or if num_peers is less than 2
1471 */
1472struct GNUNET_TESTBED_Operation *
1473GNUNET_TESTBED_overlay_configure_topology (void *op_cls,
1474 unsigned int num_peers,
1475 struct GNUNET_TESTBED_Peer **peers,
1476 unsigned int *max_connections,
1477 GNUNET_TESTBED_TopologyCompletionCallback
1478 comp_cb,
1479 void *comp_cb_cls,
1480 enum GNUNET_TESTBED_TopologyOption
1481 topo,
1482 ...)
1483{
1484 struct GNUNET_TESTBED_Operation *op;
1485 va_list vargs;
1486
1487 GNUNET_assert (topo < GNUNET_TESTBED_TOPOLOGY_OPTION_END);
1488 va_start (vargs, topo);
1489 op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers,
1490 max_connections,
1491 comp_cb, comp_cb_cls,
1492 topo,
1493 vargs);
1494 va_end (vargs);
1495 return op;
1496}
1497
1498
1499/**
1500 * Get a topology from a string input.
1501 *
1502 * @param topology where to write the retrieved topology
1503 * @param topology_string The string to attempt to
1504 * get a configuration value from
1505 * @return #GNUNET_YES if topology string matched a
1506 * known topology, #GNUNET_NO if not
1507 */
1508int
1509GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology,
1510 const char *topology_string)
1511{
1512 unsigned int cnt;
1513
1514 for (cnt = 0; NULL != topology_strings[cnt]; cnt++)
1515 {
1516 if (0 == strcasecmp (topology_string, topology_strings[cnt]))
1517 {
1518 if (NULL != topology)
1519 *topology = (enum GNUNET_TESTBED_TopologyOption) cnt;
1520 GNUNET_assert (GNUNET_TESTBED_TOPOLOGY_OPTION_END !=
1521 (enum GNUNET_TESTBED_TopologyOption) cnt);
1522 return GNUNET_YES;
1523 }
1524 }
1525 return GNUNET_NO;
1526}
1527
1528
1529/**
1530 * Returns the string corresponding to the given topology
1531 *
1532 * @param topology the topology
1533 * @return the string (freshly allocated) of given topology; NULL if topology cannot be
1534 * expressed as a string
1535 */
1536char *
1537GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology)
1538{
1539 if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology)
1540 return NULL;
1541 return GNUNET_strdup (topology_strings[topology]);
1542}
1543
1544
1545/**
1546 * Function to construct an underlay topology
1547 *
1548 * @param num_peers the number of peers for which the topology should be
1549 * generated
1550 * @param proc the underlay link processor callback. Will be called for each
1551 * underlay link generated unless a previous call to this callback
1552 * returned #GNUNET_SYSERR. Cannot be NULL.
1553 * @param cls closure for @a proc
1554 * @param ... variable arguments denoting the topology and its parameters. They
1555 * should start with the type of topology to generate followed by their
1556 * options.
1557 * @return #GNUNET_OK if underlay link generation is successful; #GNUNET_SYSERR
1558 * upon error in generating the underlay or if any calls to the
1559 * underlay link processor returned #GNUNET_SYSERR
1560 */
1561int
1562GNUNET_TESTBED_underlay_construct_ (int num_peers,
1563 underlay_link_processor proc,
1564 void *cls,
1565 ...)
1566{
1567 struct TopologyContext tc;
1568 struct TopologyContextUnderlay *underlay;
1569 struct UnderlayLink *ulink;
1570 va_list vargs;
1571 enum GNUNET_TESTBED_TopologyOption topology;
1572 unsigned int cnt;
1573 int ret;
1574
1575 GNUNET_assert (NULL != proc);
1576 ret = GNUNET_OK;
1577 memset (&tc, 0, sizeof(tc));
1578 tc.num_peers = num_peers;
1579 tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY;
1580 underlay = &tc.u.underlay;
1581 va_start (vargs, cls);
1582 topology = GNUNET_VA_ARG_ENUM (vargs, GNUNET_TESTBED_TopologyOption);
1583 switch (topology)
1584 {
1585 case GNUNET_TESTBED_TOPOLOGY_LINE:
1586 gen_topo_line (&tc);
1587 break;
1588
1589 case GNUNET_TESTBED_TOPOLOGY_STAR:
1590 gen_topo_star (&tc);
1591 break;
1592
1593 case GNUNET_TESTBED_TOPOLOGY_RING:
1594 gen_topo_ring (&tc);
1595 break;
1596
1597 case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
1598 gen_topo_clique (&tc);
1599 break;
1600
1601 case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
1602 gen_topo_2dtorus (&tc);
1603 break;
1604
1605 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1606 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO);
1607 break;
1608
1609 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1610 gen_topo_ring (&tc);
1611 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1612 break;
1613
1614 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1615 gen_topo_2dtorus (&tc);
1616 gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1617 break;
1618
1619 case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1620 {
1621 const char *filename;
1622 filename = va_arg (vargs, char *);
1623 GNUNET_assert (NULL != filename);
1624 gen_topo_from_file (&tc, filename);
1625 }
1626 break;
1627
1628 case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
1629 {
1630 uint16_t cap;
1631 uint8_t m;
1632 cap = (uint16_t) va_arg (vargs, unsigned int);
1633 m = (uint8_t) va_arg (vargs, unsigned int);
1634 gen_topo_scale_free (&tc, cap, m);
1635 }
1636 break;
1637
1638 default:
1639 GNUNET_assert (0);
1640 }
1641 va_end (vargs);
1642 for (cnt = 0; cnt < tc.link_array_size; cnt++)
1643 {
1644 ulink = &underlay->link_array[cnt];
1645 if (GNUNET_SYSERR == proc (cls,
1646 ulink->A,
1647 ulink->B,
1648 ulink->bandwidth,
1649 ulink->latency,
1650 ulink->loss))
1651 {
1652 ret = GNUNET_SYSERR;
1653 break;
1654 }
1655 }
1656 GNUNET_free (underlay->link_array);
1657 return ret;
1658}
1659
1660
1661/* end of testbed_api_topology.c */