diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2014-01-06 16:37:21 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2014-01-06 16:37:21 +0000 |
commit | 57cba940bf568f0337bfc1a8cffb8542a78e8b1e (patch) | |
tree | b49ba4518fffd16997d7163aa578cf04e41fdaae /src/testbed/testbed_api_topology.c | |
parent | f15d774da10fa73be8c43982b438f55e576a6936 (diff) | |
download | gnunet-57cba940bf568f0337bfc1a8cffb8542a78e8b1e.tar.gz gnunet-57cba940bf568f0337bfc1a8cffb8542a78e8b1e.zip |
- underlay topology generation
Diffstat (limited to 'src/testbed/testbed_api_topology.c')
-rw-r--r-- | src/testbed/testbed_api_topology.c | 651 |
1 files changed, 531 insertions, 120 deletions
diff --git a/src/testbed/testbed_api_topology.c b/src/testbed/testbed_api_topology.c index d4eaec0c5..99ab76f8b 100644 --- a/src/testbed/testbed_api_topology.c +++ b/src/testbed/testbed_api_topology.c | |||
@@ -78,6 +78,38 @@ struct OverlayLink | |||
78 | }; | 78 | }; |
79 | 79 | ||
80 | 80 | ||
81 | /** | ||
82 | * Representation of an underlay link | ||
83 | */ | ||
84 | struct UnderlayLink | ||
85 | { | ||
86 | /** | ||
87 | * position of peer A's handle in peers array | ||
88 | */ | ||
89 | uint32_t A; | ||
90 | |||
91 | /** | ||
92 | * position of peer B's handle in peers array | ||
93 | */ | ||
94 | uint32_t B; | ||
95 | |||
96 | /** | ||
97 | * Bandwidth of the link in bytes per second | ||
98 | */ | ||
99 | uint32_t bandwidth; | ||
100 | |||
101 | /** | ||
102 | * Latency of the link in milliseconds | ||
103 | */ | ||
104 | uint32_t latency; | ||
105 | |||
106 | /** | ||
107 | * Loss in the link in percentage of message dropped | ||
108 | */ | ||
109 | uint32_t loss; | ||
110 | }; | ||
111 | |||
112 | |||
81 | struct RetryListEntry | 113 | struct RetryListEntry |
82 | { | 114 | { |
83 | /** | 115 | /** |
@@ -98,9 +130,9 @@ struct RetryListEntry | |||
98 | 130 | ||
99 | 131 | ||
100 | /** | 132 | /** |
101 | * Context information for topology operations | 133 | * Context information for overlay topologies |
102 | */ | 134 | */ |
103 | struct TopologyContext | 135 | struct TopologyContextOverlay |
104 | { | 136 | { |
105 | /** | 137 | /** |
106 | * The array of peers | 138 | * The array of peers |
@@ -138,16 +170,6 @@ struct TopologyContext | |||
138 | struct RetryListEntry *rl_tail; | 170 | struct RetryListEntry *rl_tail; |
139 | 171 | ||
140 | /** | 172 | /** |
141 | * The number of peers | ||
142 | */ | ||
143 | unsigned int num_peers; | ||
144 | |||
145 | /** | ||
146 | * The size of the link array | ||
147 | */ | ||
148 | unsigned int link_array_size; | ||
149 | |||
150 | /** | ||
151 | * How many retries to do before we give up | 173 | * How many retries to do before we give up |
152 | */ | 174 | */ |
153 | unsigned int retry_cnt; | 175 | unsigned int retry_cnt; |
@@ -175,6 +197,66 @@ struct TopologyContext | |||
175 | 197 | ||
176 | 198 | ||
177 | /** | 199 | /** |
200 | * Topology context information for underlay topologies | ||
201 | */ | ||
202 | struct TopologyContextUnderlay | ||
203 | { | ||
204 | /** | ||
205 | * The link array | ||
206 | */ | ||
207 | struct UnderlayLink *link_array; | ||
208 | }; | ||
209 | |||
210 | |||
211 | /** | ||
212 | * Context information for topology operations | ||
213 | */ | ||
214 | struct TopologyContext | ||
215 | { | ||
216 | /** | ||
217 | * The type of this context | ||
218 | */ | ||
219 | enum { | ||
220 | |||
221 | /** | ||
222 | * Type for underlay topology | ||
223 | */ | ||
224 | TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0, | ||
225 | |||
226 | /** | ||
227 | * Type for overlay topology | ||
228 | */ | ||
229 | TOPOLOGYCONTEXT_TYPE_OVERLAY | ||
230 | |||
231 | } type; | ||
232 | |||
233 | union { | ||
234 | |||
235 | /** | ||
236 | * Topology context information for overlay topology | ||
237 | */ | ||
238 | struct TopologyContextOverlay overlay; | ||
239 | |||
240 | /** | ||
241 | * Topology context information for underlay topology | ||
242 | */ | ||
243 | struct TopologyContextUnderlay underlay; | ||
244 | } u; | ||
245 | |||
246 | /** | ||
247 | * The number of peers | ||
248 | */ | ||
249 | unsigned int num_peers; | ||
250 | |||
251 | /** | ||
252 | * The size of the link array | ||
253 | */ | ||
254 | unsigned int link_array_size; | ||
255 | |||
256 | }; | ||
257 | |||
258 | |||
259 | /** | ||
178 | * A array of names representing topologies. Should be in sync with enum | 260 | * A array of names representing topologies. Should be in sync with enum |
179 | * GNUNET_TESTBED_TopologyOption | 261 | * GNUNET_TESTBED_TopologyOption |
180 | */ | 262 | */ |
@@ -222,7 +304,9 @@ const char *topology_strings[] = { | |||
222 | "INTERNAT", | 304 | "INTERNAT", |
223 | 305 | ||
224 | /** | 306 | /** |
225 | * Scale free topology. No options. | 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) | ||
226 | */ | 310 | */ |
227 | "SCALE_FREE", | 311 | "SCALE_FREE", |
228 | 312 | ||
@@ -262,50 +346,53 @@ overlay_link_completed (void *cls, struct GNUNET_TESTBED_Operation *op, | |||
262 | { | 346 | { |
263 | struct OverlayLink *link = cls; | 347 | struct OverlayLink *link = cls; |
264 | struct TopologyContext *tc; | 348 | struct TopologyContext *tc; |
349 | struct TopologyContextOverlay *overlay; | ||
265 | struct RetryListEntry *retry_entry; | 350 | struct RetryListEntry *retry_entry; |
266 | 351 | ||
267 | GNUNET_assert (op == link->op); | 352 | GNUNET_assert (op == link->op); |
268 | GNUNET_TESTBED_operation_done (op); | 353 | GNUNET_TESTBED_operation_done (op); |
269 | link->op = NULL; | 354 | link->op = NULL; |
270 | tc = link->tc; | 355 | tc = link->tc; |
356 | GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); | ||
357 | overlay = &tc->u.overlay; | ||
271 | if (NULL != emsg) | 358 | if (NULL != emsg) |
272 | { | 359 | { |
273 | tc->nfailures++; | 360 | overlay->nfailures++; |
274 | if (0 != tc->retry_cnt) | 361 | if (0 != overlay->retry_cnt) |
275 | { | 362 | { |
276 | LOG (GNUNET_ERROR_TYPE_WARNING, | 363 | LOG (GNUNET_ERROR_TYPE_WARNING, |
277 | "Error while establishing a link: %s -- Retrying\n", emsg); | 364 | "Error while establishing a link: %s -- Retrying\n", emsg); |
278 | retry_entry = GNUNET_new (struct RetryListEntry); | 365 | retry_entry = GNUNET_new (struct RetryListEntry); |
279 | retry_entry->link = link; | 366 | retry_entry->link = link; |
280 | GNUNET_CONTAINER_DLL_insert_tail (tc->rl_head, tc->rl_tail, retry_entry); | 367 | GNUNET_CONTAINER_DLL_insert_tail (overlay->rl_head, overlay->rl_tail, retry_entry); |
281 | } | 368 | } |
282 | } | 369 | } |
283 | else | 370 | else |
284 | tc->nsuccess++; | 371 | overlay->nsuccess++; |
285 | tc->ncompleted++; | 372 | overlay->ncompleted++; |
286 | if (tc->ncompleted < tc->nlinks) | 373 | if (overlay->ncompleted < overlay->nlinks) |
287 | return; | 374 | return; |
288 | if ((0 != tc->retry_cnt) && (NULL != tc->rl_head)) | 375 | if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head)) |
289 | { | 376 | { |
290 | tc->retry_cnt--; | 377 | overlay->retry_cnt--; |
291 | tc->ncompleted = 0; | 378 | overlay->ncompleted = 0; |
292 | tc->nlinks = 0; | 379 | overlay->nlinks = 0; |
293 | while (NULL != (retry_entry = tc->rl_head)) | 380 | while (NULL != (retry_entry = overlay->rl_head)) |
294 | { | 381 | { |
295 | link = retry_entry->link; | 382 | link = retry_entry->link; |
296 | link->op = | 383 | link->op = |
297 | GNUNET_TESTBED_overlay_connect (tc->op_cls, &overlay_link_completed, | 384 | GNUNET_TESTBED_overlay_connect (overlay->op_cls, &overlay_link_completed, |
298 | link, tc->peers[link->A], | 385 | link, overlay->peers[link->A], |
299 | tc->peers[link->B]); | 386 | overlay->peers[link->B]); |
300 | tc->nlinks++; | 387 | overlay->nlinks++; |
301 | GNUNET_CONTAINER_DLL_remove (tc->rl_head, tc->rl_tail, retry_entry); | 388 | GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, retry_entry); |
302 | GNUNET_free (retry_entry); | 389 | GNUNET_free (retry_entry); |
303 | } | 390 | } |
304 | return; | 391 | return; |
305 | } | 392 | } |
306 | if (NULL != tc->comp_cb) | 393 | if (NULL != overlay->comp_cb) |
307 | { | 394 | { |
308 | tc->comp_cb (tc->comp_cb_cls, tc->nsuccess, tc->nfailures); | 395 | overlay->comp_cb (overlay->comp_cb_cls, overlay->nsuccess, overlay->nfailures); |
309 | } | 396 | } |
310 | } | 397 | } |
311 | 398 | ||
@@ -320,16 +407,19 @@ static void | |||
320 | opstart_overlay_configure_topology (void *cls) | 407 | opstart_overlay_configure_topology (void *cls) |
321 | { | 408 | { |
322 | struct TopologyContext *tc = cls; | 409 | struct TopologyContext *tc = cls; |
410 | struct TopologyContextOverlay *overlay; | ||
323 | unsigned int p; | 411 | unsigned int p; |
324 | 412 | ||
325 | tc->nlinks = tc->link_array_size; | 413 | GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); |
414 | overlay = &tc->u.overlay; | ||
415 | overlay->nlinks = tc->link_array_size; | ||
326 | for (p = 0; p < tc->link_array_size; p++) | 416 | for (p = 0; p < tc->link_array_size; p++) |
327 | { | 417 | { |
328 | tc->link_array[p].op = | 418 | overlay->link_array[p].op = |
329 | GNUNET_TESTBED_overlay_connect (tc->op_cls, &overlay_link_completed, | 419 | GNUNET_TESTBED_overlay_connect (overlay->op_cls, &overlay_link_completed, |
330 | &tc->link_array[p], | 420 | &overlay->link_array[p], |
331 | tc->peers[tc->link_array[p].A], | 421 | overlay->peers[overlay->link_array[p].A], |
332 | tc->peers[tc->link_array[p].B]); | 422 | overlay->peers[overlay->link_array[p].B]); |
333 | } | 423 | } |
334 | } | 424 | } |
335 | 425 | ||
@@ -343,20 +433,23 @@ static void | |||
343 | oprelease_overlay_configure_topology (void *cls) | 433 | oprelease_overlay_configure_topology (void *cls) |
344 | { | 434 | { |
345 | struct TopologyContext *tc = cls; | 435 | struct TopologyContext *tc = cls; |
436 | struct TopologyContextOverlay *overlay; | ||
346 | struct RetryListEntry *retry_entry; | 437 | struct RetryListEntry *retry_entry; |
347 | unsigned int p; | 438 | unsigned int p; |
348 | 439 | ||
349 | while (NULL != (retry_entry = tc->rl_head)) | 440 | GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); |
441 | overlay = &tc->u.overlay; | ||
442 | while (NULL != (retry_entry = overlay->rl_head)) | ||
350 | { | 443 | { |
351 | GNUNET_CONTAINER_DLL_remove (tc->rl_head, tc->rl_tail, retry_entry); | 444 | GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, retry_entry); |
352 | GNUNET_free (retry_entry); | 445 | GNUNET_free (retry_entry); |
353 | } | 446 | } |
354 | if (NULL != tc->link_array) | 447 | if (NULL != overlay->link_array) |
355 | { | 448 | { |
356 | for (p = 0; p < tc->link_array_size; p++) | 449 | for (p = 0; p < tc->link_array_size; p++) |
357 | if (NULL != tc->link_array[p].op) | 450 | if (NULL != overlay->link_array[p].op) |
358 | GNUNET_TESTBED_operation_done (tc->link_array[p].op); | 451 | GNUNET_TESTBED_operation_done (overlay->link_array[p].op); |
359 | GNUNET_free (tc->link_array); | 452 | GNUNET_free (overlay->link_array); |
360 | } | 453 | } |
361 | GNUNET_free (tc); | 454 | GNUNET_free (tc); |
362 | } | 455 | } |
@@ -365,22 +458,47 @@ oprelease_overlay_configure_topology (void *cls) | |||
365 | /** | 458 | /** |
366 | * Populates the OverlayLink structure. | 459 | * Populates the OverlayLink structure. |
367 | * | 460 | * |
368 | * @param link the OverlayLink | 461 | * @param offset the offset of the link array to use |
369 | * @param A the peer A. Should be different from B | 462 | * @param A the peer A. Should be different from B |
370 | * @param B the peer B. Should be different from A | 463 | * @param B the peer B. Should be different from A |
371 | * @param tc the TopologyContext | 464 | * @param tc the TopologyContext |
372 | * @return | 465 | * @return |
373 | */ | 466 | */ |
374 | static void | 467 | static void |
375 | make_link (struct OverlayLink *link, uint32_t A, uint32_t B, | 468 | make_link (unsigned int offset, uint32_t A, uint32_t B, |
376 | struct TopologyContext *tc) | 469 | struct TopologyContext *tc) |
377 | { | 470 | { |
378 | GNUNET_assert (A != B); | 471 | GNUNET_assert (A != B); |
379 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A); | 472 | switch (tc->type) |
380 | link->A = A; | 473 | { |
381 | link->B = B; | 474 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: |
382 | link->op = NULL; | 475 | { |
383 | link->tc = tc; | 476 | struct TopologyContextOverlay *overlay; |
477 | struct OverlayLink *olink; | ||
478 | |||
479 | overlay = &tc->u.overlay; | ||
480 | GNUNET_assert (offset < tc->link_array_size); | ||
481 | olink = &overlay->link_array[offset]; | ||
482 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A); | ||
483 | olink->A = A; | ||
484 | olink->B = B; | ||
485 | olink->op = NULL; | ||
486 | olink->tc = tc; | ||
487 | } | ||
488 | break; | ||
489 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
490 | { | ||
491 | struct TopologyContextUnderlay *underlay; | ||
492 | struct UnderlayLink *ulink; | ||
493 | |||
494 | underlay = &tc->u.underlay; | ||
495 | GNUNET_assert (offset < tc->link_array_size); | ||
496 | ulink = &underlay->link_array[offset]; | ||
497 | ulink->A = A; | ||
498 | ulink->B = B; | ||
499 | } | ||
500 | break; | ||
501 | } | ||
384 | } | 502 | } |
385 | 503 | ||
386 | 504 | ||
@@ -395,10 +513,29 @@ gen_topo_line (struct TopologyContext *tc) | |||
395 | unsigned int cnt; | 513 | unsigned int cnt; |
396 | 514 | ||
397 | tc->link_array_size = tc->num_peers - 1; | 515 | tc->link_array_size = tc->num_peers - 1; |
398 | tc->link_array = | 516 | switch (tc->type) |
399 | GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); | 517 | { |
400 | for (cnt = 0; cnt < (tc->num_peers - 1); cnt++) | 518 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: |
401 | make_link (&tc->link_array[cnt], cnt, cnt + 1, tc); | 519 | { |
520 | struct TopologyContextOverlay *overlay; | ||
521 | |||
522 | overlay = &tc->u.overlay; | ||
523 | overlay->link_array = | ||
524 | GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); | ||
525 | } | ||
526 | break; | ||
527 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
528 | { | ||
529 | struct TopologyContextUnderlay *underlay; | ||
530 | |||
531 | underlay = &tc->u.underlay; | ||
532 | underlay->link_array = | ||
533 | GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size); | ||
534 | } | ||
535 | break; | ||
536 | } | ||
537 | for (cnt = 0; cnt < (tc->link_array_size); cnt++) | ||
538 | make_link (cnt, cnt, cnt + 1, tc); | ||
402 | } | 539 | } |
403 | 540 | ||
404 | 541 | ||
@@ -412,11 +549,30 @@ gen_topo_ring (struct TopologyContext *tc) | |||
412 | { | 549 | { |
413 | gen_topo_line (tc); | 550 | gen_topo_line (tc); |
414 | tc->link_array_size++; | 551 | tc->link_array_size++; |
415 | tc->link_array = | 552 | switch (tc->type) |
416 | GNUNET_realloc (tc->link_array, | 553 | { |
417 | sizeof (struct OverlayLink) * tc->link_array_size); | 554 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: |
418 | make_link (&tc->link_array[tc->link_array_size - 1], tc->num_peers - 1, 0, | 555 | { |
419 | tc); | 556 | struct TopologyContextOverlay *overlay; |
557 | |||
558 | overlay = &tc->u.overlay; | ||
559 | overlay->link_array = | ||
560 | GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) * | ||
561 | tc->link_array_size); | ||
562 | } | ||
563 | break; | ||
564 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
565 | { | ||
566 | struct TopologyContextUnderlay *underlay; | ||
567 | |||
568 | underlay = &tc->u.underlay; | ||
569 | underlay->link_array = | ||
570 | GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) * | ||
571 | tc->link_array_size); | ||
572 | } | ||
573 | break; | ||
574 | } | ||
575 | make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc); | ||
420 | } | 576 | } |
421 | 577 | ||
422 | 578 | ||
@@ -495,20 +651,39 @@ gen_topo_2dtorus (struct TopologyContext *tc) | |||
495 | 651 | ||
496 | tc->link_array_size = | 652 | tc->link_array_size = |
497 | GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len); | 653 | GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len); |
498 | tc->link_array = | 654 | switch (tc->type) |
499 | GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); | 655 | { |
656 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
657 | { | ||
658 | struct TopologyContextOverlay *overlay; | ||
659 | |||
660 | overlay = &tc->u.overlay; | ||
661 | overlay->link_array = | ||
662 | GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); | ||
663 | } | ||
664 | break; | ||
665 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
666 | { | ||
667 | struct TopologyContextUnderlay *underlay; | ||
668 | |||
669 | underlay = &tc->u.underlay; | ||
670 | underlay->link_array = | ||
671 | GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size); | ||
672 | break; | ||
673 | } | ||
674 | } | ||
500 | cnt = 0; | 675 | cnt = 0; |
501 | offset = 0; | 676 | offset = 0; |
502 | for (y = 0; y < rows; y++) | 677 | for (y = 0; y < rows; y++) |
503 | { | 678 | { |
504 | for (x = 0; x < rows_len[y] - 1; x++) | 679 | for (x = 0; x < rows_len[y] - 1; x++) |
505 | { | 680 | { |
506 | make_link (&tc->link_array[cnt], offset + x, offset + x + 1, tc); | 681 | make_link (cnt, offset + x, offset + x + 1, tc); |
507 | cnt++; | 682 | cnt++; |
508 | } | 683 | } |
509 | if (0 == x) | 684 | if (0 == x) |
510 | break; | 685 | break; |
511 | make_link (&tc->link_array[cnt], offset + x, offset, tc); | 686 | make_link (cnt, offset + x, offset, tc); |
512 | cnt++; | 687 | cnt++; |
513 | offset += rows_len[y]; | 688 | offset += rows_len[y]; |
514 | } | 689 | } |
@@ -520,14 +695,13 @@ gen_topo_2dtorus (struct TopologyContext *tc) | |||
520 | if (x >= rows_len[y + 1]) | 695 | if (x >= rows_len[y + 1]) |
521 | break; | 696 | break; |
522 | GNUNET_assert (x < rows_len[y + 1]); | 697 | GNUNET_assert (x < rows_len[y + 1]); |
523 | make_link (&tc->link_array[cnt], offset + x, offset + rows_len[y] + x, | 698 | make_link (cnt, offset + x, offset + rows_len[y] + x, tc); |
524 | tc); | ||
525 | offset += rows_len[y]; | 699 | offset += rows_len[y]; |
526 | cnt++; | 700 | cnt++; |
527 | } | 701 | } |
528 | if (0 == offset) | 702 | if (0 == offset) |
529 | break; | 703 | break; |
530 | make_link (&tc->link_array[cnt], offset + x, x, tc); | 704 | make_link (cnt, offset + x, x, tc); |
531 | cnt++; | 705 | cnt++; |
532 | } | 706 | } |
533 | GNUNET_assert (cnt == tc->link_array_size); | 707 | GNUNET_assert (cnt == tc->link_array_size); |
@@ -553,20 +727,52 @@ gen_topo_random (struct TopologyContext *tc, unsigned int links, int append) | |||
553 | 727 | ||
554 | if (GNUNET_YES == append) | 728 | if (GNUNET_YES == append) |
555 | { | 729 | { |
556 | GNUNET_assert ((0 < tc->link_array_size) && (NULL != tc->link_array)); | ||
557 | index = tc->link_array_size; | 730 | index = tc->link_array_size; |
558 | tc->link_array_size += links; | 731 | tc->link_array_size += links; |
559 | tc->link_array = | ||
560 | GNUNET_realloc (tc->link_array, | ||
561 | sizeof (struct OverlayLink) * tc->link_array_size); | ||
562 | } | 732 | } |
563 | else | 733 | else |
564 | { | 734 | { |
565 | GNUNET_assert ((0 == tc->link_array_size) && (NULL == tc->link_array)); | ||
566 | index = 0; | 735 | index = 0; |
567 | tc->link_array_size = links; | 736 | tc->link_array_size = links; |
568 | tc->link_array = | 737 | } |
569 | GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); | 738 | switch (tc->type) |
739 | { | ||
740 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
741 | { | ||
742 | struct TopologyContextOverlay *overlay; | ||
743 | |||
744 | overlay = &tc->u.overlay; | ||
745 | if (GNUNET_YES != append) | ||
746 | { | ||
747 | GNUNET_assert (NULL == overlay->link_array); | ||
748 | overlay->link_array = | ||
749 | GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); | ||
750 | break; | ||
751 | } | ||
752 | GNUNET_assert ((0 < tc->link_array_size) && (NULL != overlay->link_array)); | ||
753 | overlay->link_array = | ||
754 | GNUNET_realloc (overlay->link_array, | ||
755 | sizeof (struct OverlayLink) * tc->link_array_size); | ||
756 | break; | ||
757 | } | ||
758 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
759 | { | ||
760 | struct TopologyContextUnderlay *underlay; | ||
761 | |||
762 | underlay = &tc->u.underlay; | ||
763 | if (GNUNET_YES != append) | ||
764 | { | ||
765 | GNUNET_assert (NULL == underlay->link_array); | ||
766 | underlay->link_array = | ||
767 | GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size); | ||
768 | break; | ||
769 | } | ||
770 | GNUNET_assert ((0 < tc->link_array_size) && (NULL != underlay->link_array)); | ||
771 | underlay->link_array = | ||
772 | GNUNET_realloc (underlay->link_array, | ||
773 | sizeof (struct UnderlayLink) * tc->link_array_size); | ||
774 | break; | ||
775 | } | ||
570 | } | 776 | } |
571 | for (cnt = 0; cnt < links; cnt++) | 777 | for (cnt = 0; cnt < links; cnt++) |
572 | { | 778 | { |
@@ -578,7 +784,7 @@ gen_topo_random (struct TopologyContext *tc, unsigned int links, int append) | |||
578 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers); | 784 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers); |
579 | } | 785 | } |
580 | while (A_rand == B_rand); | 786 | while (A_rand == B_rand); |
581 | make_link (&tc->link_array[index + cnt], A_rand, B_rand, tc); | 787 | make_link (index+cnt, A_rand, B_rand, tc); |
582 | } | 788 | } |
583 | } | 789 | } |
584 | 790 | ||
@@ -594,7 +800,7 @@ gen_topo_random (struct TopologyContext *tc, unsigned int links, int append) | |||
594 | * network | 800 | * network |
595 | */ | 801 | */ |
596 | static void | 802 | static void |
597 | gen_scale_free (struct TopologyContext *tc, uint16_t cap, uint8_t m) | 803 | gen_topo_scale_free (struct TopologyContext *tc, uint16_t cap, uint8_t m) |
598 | { | 804 | { |
599 | unsigned int *deg; | 805 | unsigned int *deg; |
600 | unsigned int *etab; | 806 | unsigned int *etab; |
@@ -610,13 +816,32 @@ gen_scale_free (struct TopologyContext *tc, uint16_t cap, uint8_t m) | |||
610 | 816 | ||
611 | etaboff = 0; | 817 | etaboff = 0; |
612 | tc->link_array_size = tc->num_peers * m; | 818 | tc->link_array_size = tc->num_peers * m; |
613 | tc->link_array = GNUNET_malloc_large (sizeof (struct OverlayLink) * | 819 | switch (tc->type) |
614 | tc->link_array_size); | 820 | { |
821 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
822 | { | ||
823 | struct TopologyContextOverlay *overlay; | ||
824 | |||
825 | overlay = &tc->u.overlay; | ||
826 | overlay->link_array = GNUNET_malloc_large (sizeof (struct OverlayLink) * | ||
827 | tc->link_array_size); | ||
828 | } | ||
829 | break; | ||
830 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
831 | { | ||
832 | struct TopologyContextUnderlay *underlay; | ||
833 | |||
834 | underlay = &tc->u.underlay; | ||
835 | underlay->link_array = GNUNET_malloc_large (sizeof (struct UnderlayLink) * | ||
836 | tc->link_array_size); | ||
837 | } | ||
838 | break; | ||
839 | } | ||
615 | etab = GNUNET_malloc_large (sizeof (unsigned int) * 2 * tc->link_array_size); | 840 | etab = GNUNET_malloc_large (sizeof (unsigned int) * 2 * tc->link_array_size); |
616 | deg = GNUNET_malloc (sizeof (unsigned int) * tc->num_peers); | 841 | deg = GNUNET_malloc (sizeof (unsigned int) * tc->num_peers); |
617 | used = GNUNET_malloc (sizeof (unsigned int) * m); | 842 | used = GNUNET_malloc (sizeof (unsigned int) * m); |
618 | /* start by connecting peer 1 to peer 0 */ | 843 | /* start by connecting peer 1 to peer 0 */ |
619 | make_link (&tc->link_array[0], 0, 1, tc); | 844 | make_link (0, 0, 1, tc); |
620 | deg[0]++; | 845 | deg[0]++; |
621 | deg[1]++; | 846 | deg[1]++; |
622 | etab[etaboff++] = 0; | 847 | etab[etaboff++] = 0; |
@@ -654,7 +879,7 @@ gen_scale_free (struct TopologyContext *tc, uint16_t cap, uint8_t m) | |||
654 | for (cnt2 = 0; cnt2 < cnt; cnt2++) | 879 | for (cnt2 = 0; cnt2 < cnt; cnt2++) |
655 | if (random_peer == used[cnt2]) | 880 | if (random_peer == used[cnt2]) |
656 | goto redo; | 881 | goto redo; |
657 | make_link (&tc->link_array[links + cnt], random_peer, peer, tc); | 882 | make_link (links + cnt, random_peer, peer, tc); |
658 | deg[random_peer]++; | 883 | deg[random_peer]++; |
659 | deg[peer]++; | 884 | deg[peer]++; |
660 | used[cnt] = random_peer; | 885 | used[cnt] = random_peer; |
@@ -671,9 +896,27 @@ gen_scale_free (struct TopologyContext *tc, uint16_t cap, uint8_t m) | |||
671 | GNUNET_free (deg); | 896 | GNUNET_free (deg); |
672 | GNUNET_assert (links <= tc->link_array_size); | 897 | GNUNET_assert (links <= tc->link_array_size); |
673 | tc->link_array_size = links; | 898 | tc->link_array_size = links; |
674 | tc->link_array = | 899 | switch (tc->type) |
675 | GNUNET_realloc (tc->link_array, | 900 | { |
676 | sizeof (struct OverlayLink) * tc->link_array_size); | 901 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: |
902 | { | ||
903 | struct TopologyContextOverlay *overlay; | ||
904 | |||
905 | overlay = &tc->u.overlay; | ||
906 | overlay->link_array = | ||
907 | GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) * tc->link_array_size); | ||
908 | } | ||
909 | break; | ||
910 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
911 | { | ||
912 | struct TopologyContextUnderlay *underlay; | ||
913 | |||
914 | underlay = &tc->u.underlay; | ||
915 | underlay->link_array = | ||
916 | GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) * tc->link_array_size); | ||
917 | } | ||
918 | break; | ||
919 | } | ||
677 | } | 920 | } |
678 | 921 | ||
679 | 922 | ||
@@ -798,12 +1041,31 @@ gen_topo_from_file (struct TopologyContext *tc, const char *filename) | |||
798 | if (peer_id != other_peer_id) | 1041 | if (peer_id != other_peer_id) |
799 | { | 1042 | { |
800 | tc->link_array_size++; | 1043 | tc->link_array_size++; |
801 | tc->link_array = | 1044 | switch (tc->type) |
802 | GNUNET_realloc (tc->link_array, | 1045 | { |
803 | sizeof (struct OverlayLink) * tc->link_array_size); | 1046 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: |
1047 | { | ||
1048 | struct TopologyContextOverlay *overlay; | ||
1049 | |||
1050 | overlay = &tc->u.overlay; | ||
1051 | overlay->link_array = | ||
1052 | GNUNET_realloc (overlay->link_array, | ||
1053 | sizeof (struct OverlayLink) * tc->link_array_size); | ||
1054 | } | ||
1055 | break; | ||
1056 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
1057 | { | ||
1058 | struct TopologyContextUnderlay *underlay; | ||
1059 | |||
1060 | underlay = &tc->u.underlay; | ||
1061 | underlay->link_array = | ||
1062 | GNUNET_realloc (underlay->link_array, | ||
1063 | sizeof (struct UnderlayLink) * tc->link_array_size); | ||
1064 | } | ||
1065 | break; | ||
1066 | } | ||
804 | offset += end - &data[offset]; | 1067 | offset += end - &data[offset]; |
805 | make_link (&tc->link_array[tc->link_array_size - 1], peer_id, | 1068 | make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc); |
806 | other_peer_id, tc); | ||
807 | } | 1069 | } |
808 | else | 1070 | else |
809 | LOG (GNUNET_ERROR_TYPE_WARNING, | 1071 | LOG (GNUNET_ERROR_TYPE_WARNING, |
@@ -829,8 +1091,74 @@ _exit: | |||
829 | { | 1091 | { |
830 | LOG (GNUNET_ERROR_TYPE_WARNING, "Removing link data read from the file\n"); | 1092 | LOG (GNUNET_ERROR_TYPE_WARNING, "Removing link data read from the file\n"); |
831 | tc->link_array_size = 0; | 1093 | tc->link_array_size = 0; |
832 | GNUNET_free_non_null (tc->link_array); | 1094 | switch (tc->type) |
833 | tc->link_array = NULL; | 1095 | { |
1096 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
1097 | { | ||
1098 | struct TopologyContextOverlay *overlay; | ||
1099 | |||
1100 | overlay = &tc->u.overlay; | ||
1101 | GNUNET_free_non_null (overlay->link_array); | ||
1102 | overlay->link_array = NULL; | ||
1103 | } | ||
1104 | break; | ||
1105 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
1106 | { | ||
1107 | struct TopologyContextUnderlay *underlay; | ||
1108 | |||
1109 | underlay = &tc->u.underlay; | ||
1110 | GNUNET_free_non_null (underlay->link_array); | ||
1111 | underlay->link_array = NULL; | ||
1112 | } | ||
1113 | break; | ||
1114 | } | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1118 | |||
1119 | /** | ||
1120 | * Generates clique topology | ||
1121 | * | ||
1122 | * @param tc the topology context | ||
1123 | */ | ||
1124 | static void | ||
1125 | gen_topo_clique (struct TopologyContext *tc) | ||
1126 | { | ||
1127 | unsigned int cnt; | ||
1128 | unsigned int offset; | ||
1129 | unsigned int neighbour; | ||
1130 | |||
1131 | tc->link_array_size = tc->num_peers * (tc->num_peers - 1); | ||
1132 | switch (tc->type) | ||
1133 | { | ||
1134 | case TOPOLOGYCONTEXT_TYPE_OVERLAY: | ||
1135 | { | ||
1136 | struct TopologyContextOverlay *overlay; | ||
1137 | |||
1138 | overlay = &tc->u.overlay; | ||
1139 | overlay->link_array = GNUNET_malloc (sizeof (struct OverlayLink) * | ||
1140 | tc->link_array_size); | ||
1141 | } | ||
1142 | break; | ||
1143 | case TOPOLOGYCONTEXT_TYPE_UNDERLAY: | ||
1144 | { | ||
1145 | struct TopologyContextUnderlay *underlay; | ||
1146 | |||
1147 | underlay = &tc->u.underlay; | ||
1148 | underlay->link_array = GNUNET_malloc (sizeof (struct UnderlayLink) * | ||
1149 | tc->link_array_size); | ||
1150 | } | ||
1151 | } | ||
1152 | offset = 0; | ||
1153 | for (cnt = 0; cnt < tc->num_peers; cnt++) | ||
1154 | { | ||
1155 | for (neighbour = 0; neighbour < tc->num_peers; neighbour++) | ||
1156 | { | ||
1157 | if (neighbour == cnt) | ||
1158 | continue; | ||
1159 | make_link (offset, cnt, neighbour, tc); | ||
1160 | offset++; | ||
1161 | } | ||
834 | } | 1162 | } |
835 | } | 1163 | } |
836 | 1164 | ||
@@ -915,21 +1243,23 @@ GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls, | |||
915 | va_list va) | 1243 | va_list va) |
916 | { | 1244 | { |
917 | struct TopologyContext *tc; | 1245 | struct TopologyContext *tc; |
1246 | struct TopologyContextOverlay *overlay; | ||
918 | struct GNUNET_TESTBED_Operation *op; | 1247 | struct GNUNET_TESTBED_Operation *op; |
919 | struct GNUNET_TESTBED_Controller *c; | 1248 | struct GNUNET_TESTBED_Controller *c; |
920 | enum GNUNET_TESTBED_TopologyOption secondary_option; | 1249 | enum GNUNET_TESTBED_TopologyOption secondary_option; |
921 | unsigned int cnt; | ||
922 | 1250 | ||
923 | if (num_peers < 2) | 1251 | if (num_peers < 2) |
924 | return NULL; | 1252 | return NULL; |
925 | c = peers[0]->controller; | 1253 | c = peers[0]->controller; |
926 | tc = GNUNET_new (struct TopologyContext); | 1254 | tc = GNUNET_new (struct TopologyContext); |
927 | tc->peers = peers; | 1255 | tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY; |
1256 | overlay = &tc->u.overlay; | ||
1257 | overlay->peers = peers; | ||
928 | tc->num_peers = num_peers; | 1258 | tc->num_peers = num_peers; |
929 | tc->op_cls = op_cls; | 1259 | overlay->op_cls = op_cls; |
930 | tc->retry_cnt = DEFAULT_RETRY_CNT; | 1260 | overlay->retry_cnt = DEFAULT_RETRY_CNT; |
931 | tc->comp_cb = comp_cb; | 1261 | overlay->comp_cb = comp_cb; |
932 | tc->comp_cb_cls = comp_cb_cls; | 1262 | overlay->comp_cb_cls = comp_cb_cls; |
933 | switch (topo) | 1263 | switch (topo) |
934 | { | 1264 | { |
935 | case GNUNET_TESTBED_TOPOLOGY_LINE: | 1265 | case GNUNET_TESTBED_TOPOLOGY_LINE: |
@@ -946,28 +1276,7 @@ GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls, | |||
946 | gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES); | 1276 | gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES); |
947 | break; | 1277 | break; |
948 | case GNUNET_TESTBED_TOPOLOGY_CLIQUE: | 1278 | case GNUNET_TESTBED_TOPOLOGY_CLIQUE: |
949 | tc->link_array_size = num_peers * (num_peers - 1); | 1279 | gen_topo_clique (tc); |
950 | tc->link_array = | ||
951 | GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); | ||
952 | { | ||
953 | unsigned int offset; | ||
954 | |||
955 | offset = 0; | ||
956 | for (cnt = 0; cnt < num_peers; cnt++) | ||
957 | { | ||
958 | unsigned int neighbour; | ||
959 | |||
960 | for (neighbour = 0; neighbour < num_peers; neighbour++) | ||
961 | { | ||
962 | if (neighbour == cnt) | ||
963 | continue; | ||
964 | tc->link_array[offset].A = cnt; | ||
965 | tc->link_array[offset].B = neighbour; | ||
966 | tc->link_array[offset].tc = tc; | ||
967 | offset++; | ||
968 | } | ||
969 | } | ||
970 | } | ||
971 | break; | 1280 | break; |
972 | case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: | 1281 | case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: |
973 | gen_topo_2dtorus (tc); | 1282 | gen_topo_2dtorus (tc); |
@@ -984,7 +1293,7 @@ GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls, | |||
984 | 1293 | ||
985 | cap = (uint16_t) va_arg (va, unsigned int); | 1294 | cap = (uint16_t) va_arg (va, unsigned int); |
986 | m = (uint8_t) va_arg (va, unsigned int); | 1295 | m = (uint8_t) va_arg (va, unsigned int); |
987 | gen_scale_free (tc, cap, m); | 1296 | gen_topo_scale_free (tc, cap, m); |
988 | } | 1297 | } |
989 | break; | 1298 | break; |
990 | case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: | 1299 | case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: |
@@ -1009,14 +1318,14 @@ GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls, | |||
1009 | switch (secondary_option) | 1318 | switch (secondary_option) |
1010 | { | 1319 | { |
1011 | case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT: | 1320 | case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT: |
1012 | tc->retry_cnt = va_arg (va, unsigned int); | 1321 | overlay->retry_cnt = va_arg (va, unsigned int); |
1013 | break; | 1322 | break; |
1014 | case GNUNET_TESTBED_TOPOLOGY_OPTION_END: | 1323 | case GNUNET_TESTBED_TOPOLOGY_OPTION_END: |
1015 | break; | 1324 | break; |
1016 | default: | 1325 | default: |
1017 | GNUNET_break (0); /* Should not use any other option apart from | 1326 | GNUNET_break (0); /* Should not use any other option apart from |
1018 | * the ones handled here */ | 1327 | * the ones handled here */ |
1019 | GNUNET_free_non_null (tc->link_array); | 1328 | GNUNET_free_non_null (overlay->link_array); |
1020 | GNUNET_free (tc); | 1329 | GNUNET_free (tc); |
1021 | return NULL; | 1330 | return NULL; |
1022 | } | 1331 | } |
@@ -1125,4 +1434,106 @@ GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology) | |||
1125 | return GNUNET_strdup (topology_strings[topology]); | 1434 | return GNUNET_strdup (topology_strings[topology]); |
1126 | } | 1435 | } |
1127 | 1436 | ||
1437 | |||
1438 | /** | ||
1439 | * Function to construct an underlay topology | ||
1440 | * | ||
1441 | * @param num_peers the number of peers for which the topology should be | ||
1442 | * generated | ||
1443 | * @param proc the underlay link processor callback. Will be called for each | ||
1444 | * underlay link generated unless a previous call to this callback | ||
1445 | * returned GNUNET_SYSERR. Cannot be NULL. | ||
1446 | * @param cls closure for proc | ||
1447 | * @param ... variable arguments denoting the topology and its parameters. They | ||
1448 | * should start with the type of topology to generate followed by their | ||
1449 | * options. | ||
1450 | * @return GNUNET_OK if underlay link generation is successful; GNUNET_SYSERR | ||
1451 | * upon error in generating the underlay or if any calls to the | ||
1452 | * underlay link processor returned GNUNET_SYSERR | ||
1453 | */ | ||
1454 | int | ||
1455 | GNUNET_TESTBED_underlay_construct_ (int num_peers, | ||
1456 | underlay_link_processor proc, | ||
1457 | void *cls, | ||
1458 | ...) | ||
1459 | { | ||
1460 | struct TopologyContext tc; | ||
1461 | struct TopologyContextUnderlay *underlay; | ||
1462 | struct UnderlayLink *ulink; | ||
1463 | va_list vargs; | ||
1464 | enum GNUNET_TESTBED_TopologyOption topology; | ||
1465 | unsigned int cnt; | ||
1466 | int ret; | ||
1467 | |||
1468 | GNUNET_assert (NULL != proc); | ||
1469 | ret = GNUNET_OK; | ||
1470 | memset (&tc, 0, sizeof (tc)); | ||
1471 | tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY; | ||
1472 | underlay = &tc.u.underlay; | ||
1473 | va_start (vargs, cls); | ||
1474 | topology = va_arg (vargs, enum GNUNET_TESTBED_TopologyOption); | ||
1475 | switch (topology) | ||
1476 | { | ||
1477 | case GNUNET_TESTBED_TOPOLOGY_LINE: | ||
1478 | gen_topo_line (&tc); | ||
1479 | break; | ||
1480 | case GNUNET_TESTBED_TOPOLOGY_RING: | ||
1481 | gen_topo_ring (&tc); | ||
1482 | break; | ||
1483 | case GNUNET_TESTBED_TOPOLOGY_CLIQUE: | ||
1484 | gen_topo_clique (&tc); | ||
1485 | break; | ||
1486 | case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: | ||
1487 | gen_topo_2dtorus (&tc); | ||
1488 | break; | ||
1489 | case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: | ||
1490 | gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO); | ||
1491 | break; | ||
1492 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: | ||
1493 | gen_topo_ring (&tc); | ||
1494 | gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES); | ||
1495 | break; | ||
1496 | case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: | ||
1497 | gen_topo_2dtorus (&tc); | ||
1498 | gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES); | ||
1499 | break; | ||
1500 | case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: | ||
1501 | { | ||
1502 | const char *filename; | ||
1503 | filename = va_arg (vargs, char *); | ||
1504 | GNUNET_assert (NULL != filename); | ||
1505 | gen_topo_from_file (&tc, filename); | ||
1506 | } | ||
1507 | break; | ||
1508 | case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: | ||
1509 | { | ||
1510 | uint16_t cap; | ||
1511 | uint8_t m; | ||
1512 | cap = (uint16_t) va_arg (vargs, unsigned int); | ||
1513 | m = (uint8_t) va_arg (vargs, unsigned int); | ||
1514 | gen_topo_scale_free (&tc, cap, m); | ||
1515 | } | ||
1516 | break; | ||
1517 | default: | ||
1518 | GNUNET_assert (0); | ||
1519 | } | ||
1520 | va_end (vargs); | ||
1521 | for (cnt = 0; cnt < tc.link_array_size; cnt++) | ||
1522 | { | ||
1523 | ulink = &underlay->link_array[cnt]; | ||
1524 | if (GNUNET_SYSERR == proc (cls, | ||
1525 | ulink->A, | ||
1526 | ulink->B, | ||
1527 | ulink->bandwidth, | ||
1528 | ulink->latency, | ||
1529 | ulink->loss)) | ||
1530 | { | ||
1531 | ret = GNUNET_SYSERR; | ||
1532 | break; | ||
1533 | } | ||
1534 | } | ||
1535 | GNUNET_free_non_null (underlay->link_array); | ||
1536 | return ret; | ||
1537 | } | ||
1538 | |||
1128 | /* end of testbed_api_topology.c */ | 1539 | /* end of testbed_api_topology.c */ |