GNUnet  0.10.x
testbed_api_topology.c
Go to the documentation of this file.
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 
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 
36 #define LOG(kind, ...) \
37  GNUNET_log_from(kind, "testbed-api-topology", __VA_ARGS__)
38 
39 
43 #define DEFAULT_RETRY_CNT 3
44 
45 
49 struct TopologyContext;
50 
51 
55 struct OverlayLink {
60 
65 
69  uint32_t A;
70 
74  uint32_t B;
75 };
76 
77 
81 struct UnderlayLink {
85  uint32_t A;
86 
90  uint32_t B;
91 
95  uint32_t bandwidth;
96 
100  uint32_t latency;
101 
105  uint32_t loss;
106 };
107 
108 
114 
119 
123  struct OverlayLink *link;
124 };
125 
126 
135 
140 
144  void *op_cls;
145 
150 
154  void *comp_cb_cls;
155 
160 
165 
169  unsigned int retry_cnt;
170 
174  unsigned int nlinks;
175 
179  unsigned int ncompleted;
180 
184  unsigned int nsuccess;
185 
189  unsigned int nfailures;
190 };
191 
192 
201 };
202 
203 
211  enum {
215  TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0,
216 
220  TOPOLOGYCONTEXT_TYPE_OVERLAY
221  } type;
222 
223  union {
227  struct TopologyContextOverlay overlay;
228 
232  struct TopologyContextUnderlay underlay;
233  } u;
234 
238  unsigned int num_peers;
239 
243  unsigned int link_array_size;
244 };
245 
246 
251 static const char *topology_strings[] = {
256  "CLIQUE",
257 
258  /*
259  * Small-world network (2d torus plus random links). Followed
260  * by the number of random links to add (unsigned int).
261  */
262  "SMALL_WORLD",
263 
268  "SMALL_WORLD_RING",
269 
273  "RING",
274 
278  "STAR",
279 
283  "2D_TORUS",
284 
289  "RANDOM", // GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI
290 
296  "INTERNAT",
297 
303  "SCALE_FREE",
304 
308  "LINE",
309 
313  "FROM_FILE",
314 
318  "NONE",
319 
323  NULL
324 };
325 
326 
335 static void
338  const char *emsg)
339 {
340  struct OverlayLink *link = cls;
341  struct TopologyContext *tc;
342  struct TopologyContextOverlay *overlay;
343  struct RetryListEntry *retry_entry;
344 
345  GNUNET_assert(op == link->op);
347  link->op = NULL;
348  tc = link->tc;
349  GNUNET_assert(TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
350  overlay = &tc->u.overlay;
351  if (NULL != emsg)
352  {
353  overlay->nfailures++;
354  if (0 != overlay->retry_cnt)
355  {
357  "Error while establishing a link: %s -- Retrying\n",
358  emsg);
359  retry_entry = GNUNET_new(struct RetryListEntry);
360  retry_entry->link = link;
362  overlay->rl_tail,
363  retry_entry);
364  }
365  }
366  else
367  overlay->nsuccess++;
368  overlay->ncompleted++;
369  if (overlay->ncompleted < overlay->nlinks)
370  return;
371  if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head))
372  {
373  overlay->retry_cnt--;
374  overlay->ncompleted = 0;
375  overlay->nlinks = 0;
376  while (NULL != (retry_entry = overlay->rl_head))
377  {
378  link = retry_entry->link;
379  link->op =
382  link,
383  overlay->peers[link->A],
384  overlay->peers[link->B]);
385  overlay->nlinks++;
387  overlay->rl_tail,
388  retry_entry);
389  GNUNET_free(retry_entry);
390  }
391  return;
392  }
393  if (NULL != overlay->comp_cb)
394  {
395  overlay->comp_cb(overlay->comp_cb_cls,
396  overlay->nsuccess,
397  overlay->nfailures);
398  }
399 }
400 
401 
402 
408 static void
410 {
411  struct TopologyContext *tc = cls;
412  struct TopologyContextOverlay *overlay;
413  unsigned int p;
414 
415  GNUNET_assert(TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
416  overlay = &tc->u.overlay;
417  overlay->nlinks = tc->link_array_size;
418  for (p = 0; p < tc->link_array_size; p++)
419  {
420  overlay->link_array[p].op =
423  &overlay->link_array[p],
424  overlay->peers[overlay->link_array[p].A],
425  overlay->peers[overlay->link_array[p].B]);
426  }
427 }
428 
429 
435 static void
437 {
438  struct TopologyContext *tc = cls;
439  struct TopologyContextOverlay *overlay;
440  struct RetryListEntry *retry_entry;
441  unsigned int p;
442 
443  GNUNET_assert(TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
444  overlay = &tc->u.overlay;
445  while (NULL != (retry_entry = overlay->rl_head))
446  {
447  GNUNET_CONTAINER_DLL_remove(overlay->rl_head, overlay->rl_tail, retry_entry);
448  GNUNET_free(retry_entry);
449  }
450  if (NULL != overlay->link_array)
451  {
452  for (p = 0; p < tc->link_array_size; p++)
453  if (NULL != overlay->link_array[p].op)
455  GNUNET_free(overlay->link_array);
456  }
457  GNUNET_free(tc);
458 }
459 
460 
470 static void
471 make_link(unsigned int offset,
472  uint32_t A,
473  uint32_t B,
474  struct TopologyContext *tc)
475 {
476  GNUNET_assert(A != B);
477  switch (tc->type)
478  {
479  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
480  {
481  struct TopologyContextOverlay *overlay;
482  struct OverlayLink *olink;
483 
484  overlay = &tc->u.overlay;
485  GNUNET_assert(offset < tc->link_array_size);
486  olink = &overlay->link_array[offset];
487  LOG(GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A);
488  olink->A = A;
489  olink->B = B;
490  olink->op = NULL;
491  olink->tc = tc;
492  }
493  break;
494 
495  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
496  {
497  struct TopologyContextUnderlay *underlay;
498  struct UnderlayLink *ulink;
499 
500  underlay = &tc->u.underlay;
501  GNUNET_assert(offset < tc->link_array_size);
502  ulink = &underlay->link_array[offset];
503  ulink->A = A;
504  ulink->B = B;
505  }
506  break;
507  }
508 }
509 
510 
516 static void
518 {
519  unsigned int cnt;
520 
521  tc->link_array_size = tc->num_peers - 1;
522  switch (tc->type)
523  {
524  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
525  {
526  struct TopologyContextOverlay *overlay;
527 
528  overlay = &tc->u.overlay;
529  overlay->link_array =
531  struct OverlayLink);
532  }
533  break;
534 
535  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
536  {
537  struct TopologyContextUnderlay *underlay;
538 
539  underlay = &tc->u.underlay;
540  underlay->link_array =
542  struct UnderlayLink);
543  }
544  break;
545  }
546  for (cnt = 0; cnt < (tc->link_array_size); cnt++)
547  make_link(cnt, cnt, cnt + 1, tc);
548 }
549 
550 
556 static void
558 {
559  unsigned int cnt;
560 
561  tc->link_array_size = tc->num_peers - 1;
562  switch (tc->type)
563  {
564  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
565  {
566  struct TopologyContextOverlay *overlay;
567 
568  overlay = &tc->u.overlay;
569  overlay->link_array =
571  struct OverlayLink);
572  }
573  break;
574 
575  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
576  {
577  struct TopologyContextUnderlay *underlay;
578 
579  underlay = &tc->u.underlay;
580  underlay->link_array =
582  struct UnderlayLink);
583  }
584  break;
585  }
586  for (cnt = tc->link_array_size; cnt; cnt--)
587  make_link(cnt - 1,
588  0,
589  cnt,
590  tc);
591 }
592 
593 
599 static void
601 {
602  gen_topo_line(tc);
603  tc->link_array_size++;
604  switch (tc->type)
605  {
606  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
607  {
608  struct TopologyContextOverlay *overlay;
609 
610  overlay = &tc->u.overlay;
611  overlay->link_array =
612  GNUNET_realloc(overlay->link_array, sizeof(struct OverlayLink) *
613  tc->link_array_size);
614  }
615  break;
616 
617  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
618  {
619  struct TopologyContextUnderlay *underlay;
620 
621  underlay = &tc->u.underlay;
622  underlay->link_array =
623  GNUNET_realloc(underlay->link_array, sizeof(struct UnderlayLink) *
624  tc->link_array_size);
625  }
626  break;
627  }
628  make_link(tc->link_array_size - 1, tc->num_peers - 1, 0, tc);
629 }
630 
631 
644 unsigned int
645 GNUNET_TESTBED_2dtorus_calc_links(unsigned int num_peers, unsigned int *rows,
646  unsigned int **rows_len)
647 {
648  double sq;
649  unsigned int sq_floor;
650  unsigned int _rows;
651  unsigned int *_rows_len;
652  unsigned int x;
653  unsigned int y;
654  unsigned int _num_peers;
655  unsigned int cnt;
656 
657  sq = sqrt(num_peers);
658  sq = floor(sq);
659  sq_floor = (unsigned int)sq;
660  _rows = (sq_floor + 1);
661  _rows_len = GNUNET_malloc(sizeof(unsigned int) * _rows);
662  for (y = 0; y < _rows - 1; y++)
663  _rows_len[y] = sq_floor;
664  _num_peers = sq_floor * sq_floor;
665  cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers;
666  x = 0;
667  y = 0;
668  while (_num_peers < num_peers)
669  {
670  if (x < y)
671  _rows_len[_rows - 1] = ++x;
672  else
673  _rows_len[y++]++;
674  _num_peers++;
675  }
676  cnt += (x < 2) ? x : 2 * x;
677  cnt += (y < 2) ? y : 2 * y;
678  if (0 == _rows_len[_rows - 1])
679  _rows--;
680  if (NULL != rows)
681  *rows = _rows;
682  if (NULL != rows_len)
683  *rows_len = _rows_len;
684  else
685  GNUNET_free(_rows_len);
686  return cnt;
687 }
688 
689 
695 static void
697 {
698  unsigned int rows;
699  unsigned int *rows_len;
700  unsigned int x;
701  unsigned int y;
702  unsigned int cnt;
703  unsigned int offset;
704 
705  tc->link_array_size =
706  GNUNET_TESTBED_2dtorus_calc_links(tc->num_peers, &rows, &rows_len);
707  switch (tc->type)
708  {
709  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
710  {
711  struct TopologyContextOverlay *overlay;
712 
713  overlay = &tc->u.overlay;
714  overlay->link_array =
715  GNUNET_malloc(sizeof(struct OverlayLink) * tc->link_array_size);
716  }
717  break;
718 
719  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
720  {
721  struct TopologyContextUnderlay *underlay;
722 
723  underlay = &tc->u.underlay;
724  underlay->link_array =
725  GNUNET_malloc(sizeof(struct UnderlayLink) * tc->link_array_size);
726  break;
727  }
728  }
729  cnt = 0;
730  offset = 0;
731  for (y = 0; y < rows; y++)
732  {
733  for (x = 0; x < rows_len[y] - 1; x++)
734  {
735  make_link(cnt, offset + x, offset + x + 1, tc);
736  cnt++;
737  }
738  if (0 == x)
739  break;
740  make_link(cnt, offset + x, offset, tc);
741  cnt++;
742  offset += rows_len[y];
743  }
744  for (x = 0; x < rows_len[0]; x++)
745  {
746  offset = 0;
747  for (y = 0; y < rows - 1; y++)
748  {
749  if (x >= rows_len[y + 1])
750  break;
751  GNUNET_assert(x < rows_len[y + 1]);
752  make_link(cnt, offset + x, offset + rows_len[y] + x, tc);
753  offset += rows_len[y];
754  cnt++;
755  }
756  if (0 == offset)
757  break;
758  make_link(cnt, offset + x, x, tc);
759  cnt++;
760  }
761  GNUNET_assert(cnt == tc->link_array_size);
762  GNUNET_free(rows_len);
763 }
764 
765 
774 static void
776  unsigned int links,
777  int append)
778 {
779  unsigned int cnt;
780  unsigned int index;
781  uint32_t A_rand;
782  uint32_t B_rand;
783 
784  if (1 == tc->num_peers)
785  return;
786  if (GNUNET_YES == append)
787  {
788  index = tc->link_array_size;
789  tc->link_array_size += links;
790  }
791  else
792  {
793  index = 0;
794  tc->link_array_size = links;
795  }
796  switch (tc->type)
797  {
798  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
799  {
800  struct TopologyContextOverlay *overlay;
801 
802  overlay = &tc->u.overlay;
803  if (GNUNET_YES != append)
804  {
805  GNUNET_assert(NULL == overlay->link_array);
806  overlay->link_array =
807  GNUNET_malloc(sizeof(struct OverlayLink) * tc->link_array_size);
808  break;
809  }
810  GNUNET_assert((0 < tc->link_array_size) && (NULL != overlay->link_array));
811  overlay->link_array =
812  GNUNET_realloc(overlay->link_array,
813  sizeof(struct OverlayLink) * tc->link_array_size);
814  break;
815  }
816 
817  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
818  {
819  struct TopologyContextUnderlay *underlay;
820 
821  underlay = &tc->u.underlay;
822  if (GNUNET_YES != append)
823  {
824  GNUNET_assert(NULL == underlay->link_array);
825  underlay->link_array =
826  GNUNET_malloc(sizeof(struct UnderlayLink) * tc->link_array_size);
827  break;
828  }
829  GNUNET_assert((0 < tc->link_array_size) && (NULL != underlay->link_array));
830  underlay->link_array =
831  GNUNET_realloc(underlay->link_array,
832  sizeof(struct UnderlayLink) * tc->link_array_size);
833  break;
834  }
835  }
836  for (cnt = 0; cnt < links; cnt++)
837  {
838  do
839  {
840  A_rand =
842  B_rand =
844  }
845  while (A_rand == B_rand);
846  make_link(index + cnt, A_rand, B_rand, tc);
847  }
848 }
849 
850 
861 static void
863  uint16_t cap,
864  uint8_t m)
865 {
866  unsigned int *deg;
867  unsigned int *etab;
868  unsigned int *used;
869  unsigned int etaboff;
870  unsigned int cnt;
871  unsigned int cnt2;
872  unsigned int peer;
873  unsigned int random_peer;
874  unsigned int links;
875  unsigned int off;
876  unsigned int redo_threshold;
877 
878  etaboff = 0;
879  tc->link_array_size = tc->num_peers * m;
880  switch (tc->type)
881  {
882  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
883  {
884  struct TopologyContextOverlay *overlay;
885 
886  overlay = &tc->u.overlay;
887  overlay->link_array = GNUNET_malloc_large(sizeof(struct OverlayLink) *
888  tc->link_array_size);
889  }
890  break;
891 
892  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
893  {
894  struct TopologyContextUnderlay *underlay;
895 
896  underlay = &tc->u.underlay;
897  underlay->link_array = GNUNET_malloc_large(sizeof(struct UnderlayLink) *
898  tc->link_array_size);
899  }
900  break;
901  }
902  etab = GNUNET_malloc_large(sizeof(unsigned int) * 2 * tc->link_array_size);
903  deg = GNUNET_malloc(sizeof(unsigned int) * tc->num_peers);
904  used = GNUNET_malloc(sizeof(unsigned int) * m);
905  /* start by connecting peer 1 to peer 0 */
906  make_link(0, 0, 1, tc);
907  deg[0]++;
908  deg[1]++;
909  etab[etaboff++] = 0;
910  etab[etaboff++] = 1;
911  links = 1;
912  for (peer = 2; peer < tc->num_peers; peer++)
913  {
914  if (cap < deg[peer])
915  continue;
916  for (cnt = 0; cnt < GNUNET_MIN(peer, m); cnt++)
917  {
918  redo_threshold = 0;
919 redo:
921  random_peer = etab[off];
922  if (cap < deg[random_peer])
923  {
924  if (++redo_threshold > GNUNET_MAX(1, cap / 2))
925  {
926  redo_threshold = 0;
927  off = 0;
928  for (cnt2 = 0; cnt2 < etaboff; cnt2++)
929  {
930  if (random_peer == etab[cnt2])
931  {
932  off++;
933  continue;
934  }
935  etab[cnt2 - off] = etab[cnt2];
936  }
937  etaboff -= off;
938  }
939  goto redo;
940  }
941  for (cnt2 = 0; cnt2 < cnt; cnt2++)
942  if (random_peer == used[cnt2])
943  goto redo;
944  make_link(links + cnt, random_peer, peer, tc);
945  deg[random_peer]++;
946  deg[peer]++;
947  used[cnt] = random_peer;
948  }
949  for (cnt = 0; cnt < GNUNET_MIN(peer, m); cnt++)
950  {
951  etab[etaboff++] = used[cnt];
952  etab[etaboff++] = peer;
953  }
954  links += GNUNET_MIN(peer, m);
955  }
956  GNUNET_free(etab);
957  GNUNET_free(used);
958  GNUNET_free(deg);
959  GNUNET_assert(links <= tc->link_array_size);
960  tc->link_array_size = links;
961  switch (tc->type)
962  {
963  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
964  {
965  struct TopologyContextOverlay *overlay;
966 
967  overlay = &tc->u.overlay;
968  overlay->link_array =
969  GNUNET_realloc(overlay->link_array, sizeof(struct OverlayLink) * tc->link_array_size);
970  }
971  break;
972 
973  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
974  {
975  struct TopologyContextUnderlay *underlay;
976 
977  underlay = &tc->u.underlay;
978  underlay->link_array =
979  GNUNET_realloc(underlay->link_array, sizeof(struct UnderlayLink) * tc->link_array_size);
980  }
981  break;
982  }
983 }
984 
985 
992 static void
994  const char *filename)
995 {
996  char *data;
997  char *end;
998  char *buf;
999  uint64_t fs;
1000  uint64_t offset;
1001  unsigned long int peer_id;
1002  unsigned long int other_peer_id;
1003  enum ParseState {
1007  PEER_INDEX,
1008 
1012  OTHER_PEER_INDEX,
1013  } state;
1014  int status;
1015 
1016  status = GNUNET_SYSERR;
1017  if (GNUNET_YES != GNUNET_DISK_file_test(filename))
1018  {
1020  _("Topology file %s not found\n"),
1021  filename);
1022  return;
1023  }
1024  if (GNUNET_OK !=
1025  GNUNET_DISK_file_size(filename, &fs, GNUNET_YES, GNUNET_YES))
1026  {
1028  _("Topology file %s has no data\n"),
1029  filename);
1030  return;
1031  }
1032  data = GNUNET_malloc(fs);
1033  if (fs != GNUNET_DISK_fn_read(filename, data, fs))
1034  {
1036  _("Topology file %s cannot be read\n"),
1037  filename);
1038  goto _exit;
1039  }
1040 
1041  offset = 0;
1042  peer_id = 0;
1043  state = PEER_INDEX;
1044  while (offset < fs)
1045  {
1046  if (0 != isspace((unsigned char)data[offset]))
1047  {
1048  offset++;
1049  continue;
1050  }
1051  switch (state)
1052  {
1053  case PEER_INDEX:
1054  buf = strchr(&data[offset], ':');
1055  if (NULL == buf)
1056  {
1058  _("Failed to read peer index from toology file: %s"), filename);
1059  goto _exit;
1060  }
1061  *buf = '\0';
1062  errno = 0;
1063  peer_id = (unsigned int)strtoul(&data[offset], &end, 10);
1064  if (0 != errno)
1065  {
1067  _("Value in given topology file: %s out of range\n"), filename);
1068  goto _exit;
1069  }
1070  if (&data[offset] == end)
1071  {
1073  _("Failed to read peer index from topology file: %s"), filename);
1074  goto _exit;
1075  }
1076  if (tc->num_peers <= peer_id)
1077  {
1079  _("Topology file needs more peers than given ones\n"), filename);
1080  goto _exit;
1081  }
1082  state = OTHER_PEER_INDEX;
1083  offset += ((unsigned int)(buf - &data[offset])) + 1;
1084  break;
1085 
1086  case OTHER_PEER_INDEX:
1087  errno = 0;
1088  other_peer_id = (unsigned int)strtoul(&data[offset], &end, 10);
1089  if (0 != errno)
1090  {
1092  _("Value in given topology file: %s out of range\n"), filename);
1093  goto _exit;
1094  }
1095  if (&data[offset] == end)
1096  {
1098  _("Failed to read peer index from topology file: %s"), filename);
1099  goto _exit;
1100  }
1101  if (tc->num_peers <= other_peer_id)
1102  {
1104  _("Topology file needs more peers than given ones\n"), filename);
1105  goto _exit;
1106  }
1107  if (peer_id != other_peer_id)
1108  {
1109  tc->link_array_size++;
1110  switch (tc->type)
1111  {
1112  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1113  {
1114  struct TopologyContextOverlay *overlay;
1115 
1116  overlay = &tc->u.overlay;
1117  overlay->link_array =
1118  GNUNET_realloc(overlay->link_array,
1119  sizeof(struct OverlayLink) * tc->link_array_size);
1120  }
1121  break;
1122 
1123  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1124  {
1125  struct TopologyContextUnderlay *underlay;
1126 
1127  underlay = &tc->u.underlay;
1128  underlay->link_array =
1129  GNUNET_realloc(underlay->link_array,
1130  sizeof(struct UnderlayLink) * tc->link_array_size);
1131  }
1132  break;
1133  }
1134  offset += end - &data[offset];
1135  make_link(tc->link_array_size - 1, peer_id, other_peer_id, tc);
1136  }
1137  else
1139  _("Ignoring to connect peer %u to peer %u\n"),
1140  peer_id,
1141  other_peer_id);
1142  while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs))
1143  offset++;
1144  if ((offset < fs) &&
1145  ('\n' == data[offset]))
1146  state = PEER_INDEX;
1147  else if ((offset < fs) &&
1148  ('|' == data[offset]))
1149  {
1150  state = OTHER_PEER_INDEX;
1151  offset++;
1152  }
1153  break;
1154  }
1155  }
1156  status = GNUNET_OK;
1157 
1158 _exit:
1159  GNUNET_free(data);
1160  if (GNUNET_OK != status)
1161  {
1163  "Removing link data read from the file\n");
1164  tc->link_array_size = 0;
1165  switch (tc->type)
1166  {
1167  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1168  {
1169  struct TopologyContextOverlay *overlay;
1170 
1171  overlay = &tc->u.overlay;
1172  GNUNET_free_non_null(overlay->link_array);
1173  overlay->link_array = NULL;
1174  }
1175  break;
1176 
1177  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1178  {
1179  struct TopologyContextUnderlay *underlay;
1180 
1181  underlay = &tc->u.underlay;
1182  GNUNET_free_non_null(underlay->link_array);
1183  underlay->link_array = NULL;
1184  }
1185  break;
1186  }
1187  }
1188 }
1189 
1190 
1196 static void
1198 {
1199  unsigned int cnt;
1200  unsigned int offset;
1201  unsigned int neighbour;
1202 
1203  tc->link_array_size = tc->num_peers * (tc->num_peers - 1);
1204  switch (tc->type)
1205  {
1206  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1207  {
1208  struct TopologyContextOverlay *overlay;
1209 
1210  overlay = &tc->u.overlay;
1212  struct OverlayLink);
1213  }
1214  break;
1215 
1216  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1217  {
1218  struct TopologyContextUnderlay *underlay;
1219 
1220  underlay = &tc->u.underlay;
1222  struct UnderlayLink);
1223  }
1224  }
1225  offset = 0;
1226  for (cnt = 0; cnt < tc->num_peers; cnt++)
1227  {
1228  for (neighbour = 0; neighbour < tc->num_peers; neighbour++)
1229  {
1230  if (neighbour == cnt)
1231  continue;
1232  make_link(offset, cnt, neighbour, tc);
1233  offset++;
1234  }
1235  }
1236 }
1237 
1238 
1250 struct GNUNET_TESTBED_Operation *
1252  unsigned int num_peers,
1253  struct GNUNET_TESTBED_Peer
1254  **peers,
1255  enum
1257  topo, va_list ap)
1258 {
1259  GNUNET_break(0);
1260  return NULL;
1261 }
1262 
1263 
1275 struct GNUNET_TESTBED_Operation *
1277  unsigned int num_peers,
1278  struct GNUNET_TESTBED_Peer **peers,
1280  topo, ...)
1281 {
1282  GNUNET_break(0);
1283  return NULL;
1284 }
1285 
1286 
1307 struct GNUNET_TESTBED_Operation *
1309  unsigned int num_peers,
1310  struct GNUNET_TESTBED_Peer **peers,
1311  unsigned int *max_connections,
1313  comp_cb,
1314  void *comp_cb_cls,
1316  va_list va)
1317 {
1318  struct TopologyContext *tc;
1319  struct TopologyContextOverlay *overlay;
1320  struct GNUNET_TESTBED_Operation *op;
1321  struct GNUNET_TESTBED_Controller *c;
1322  enum GNUNET_TESTBED_TopologyOption secondary_option;
1323 
1324  if (num_peers < 2)
1325  return NULL;
1326  c = peers[0]->controller;
1327  tc = GNUNET_new(struct TopologyContext);
1328  tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY;
1329  overlay = &tc->u.overlay;
1330  overlay->peers = peers;
1331  tc->num_peers = num_peers;
1332  overlay->op_cls = op_cls;
1333  overlay->retry_cnt = DEFAULT_RETRY_CNT;
1334  overlay->comp_cb = comp_cb;
1335  overlay->comp_cb_cls = comp_cb_cls;
1336  switch (topo)
1337  {
1339  gen_topo_line(tc);
1340  break;
1341 
1343  gen_topo_star(tc);
1344  break;
1345 
1347  gen_topo_ring(tc);
1348  break;
1349 
1351  gen_topo_random(tc, va_arg(va, unsigned int), GNUNET_NO);
1352  break;
1353 
1355  gen_topo_ring(tc);
1356  gen_topo_random(tc, va_arg(va, unsigned int), GNUNET_YES);
1357  break;
1358 
1360  gen_topo_clique(tc);
1361  break;
1362 
1364  gen_topo_2dtorus(tc);
1365  break;
1366 
1368  gen_topo_2dtorus(tc);
1369  gen_topo_random(tc, va_arg(va, unsigned int), GNUNET_YES);
1370 
1371  break;
1372 
1374  {
1375  uint16_t cap;
1376  uint8_t m;
1377 
1378  cap = (uint16_t)va_arg(va, unsigned int);
1379  m = (uint8_t)va_arg(va, unsigned int);
1380  gen_topo_scale_free(tc, cap, m);
1381  }
1382  break;
1383 
1385  {
1386  const char *filename;
1387 
1388  filename = va_arg(va, const char *);
1389 
1390  GNUNET_assert(NULL != filename);
1391  gen_topo_from_file(tc, filename);
1392  }
1393  break;
1394 
1395  default:
1396  GNUNET_break(0);
1397  GNUNET_free(tc);
1398  return NULL;
1399  }
1400  do
1401  {
1402  secondary_option = GNUNET_VA_ARG_ENUM(va, GNUNET_TESTBED_TopologyOption);
1403 
1404  switch (secondary_option)
1405  {
1407  overlay->retry_cnt = va_arg(va, unsigned int);
1408  break;
1409 
1411  break;
1412 
1413  default:
1414  GNUNET_break(0); /* Should not use any other option apart from
1415  * the ones handled here */
1416  GNUNET_free_non_null(overlay->link_array);
1417  GNUNET_free(tc);
1418  return NULL;
1419  }
1420  }
1421  while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option);
1429  "Generated %u connections\n",
1430  tc->link_array_size);
1431  if (NULL != max_connections)
1432  *max_connections = tc->link_array_size;
1433  return op;
1434 }
1435 
1436 
1457 struct GNUNET_TESTBED_Operation *
1459  unsigned int num_peers,
1460  struct GNUNET_TESTBED_Peer **peers,
1461  unsigned int *max_connections,
1463  comp_cb,
1464  void *comp_cb_cls,
1466  ...)
1467 {
1468  struct GNUNET_TESTBED_Operation *op;
1469  va_list vargs;
1470 
1472  va_start(vargs, topo);
1473  op = GNUNET_TESTBED_overlay_configure_topology_va(op_cls, num_peers, peers,
1474  max_connections,
1475  comp_cb, comp_cb_cls,
1476  topo,
1477  vargs);
1478  va_end(vargs);
1479  return op;
1480 }
1481 
1482 
1492 int
1494  const char *topology_string)
1495 {
1496  unsigned int cnt;
1497 
1498  for (cnt = 0; NULL != topology_strings[cnt]; cnt++)
1499  {
1500  if (0 == strcasecmp(topology_string, topology_strings[cnt]))
1501  {
1502  if (NULL != topology)
1503  *topology = (enum GNUNET_TESTBED_TopologyOption)cnt;
1505  return GNUNET_YES;
1506  }
1507  }
1508  return GNUNET_NO;
1509 }
1510 
1511 
1519 char *
1521 {
1522  if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology)
1523  return NULL;
1524  return GNUNET_strdup(topology_strings[topology]);
1525 }
1526 
1527 
1544 int
1547  void *cls,
1548  ...)
1549 {
1550  struct TopologyContext tc;
1551  struct TopologyContextUnderlay *underlay;
1552  struct UnderlayLink *ulink;
1553  va_list vargs;
1555  unsigned int cnt;
1556  int ret;
1557 
1558  GNUNET_assert(NULL != proc);
1559  ret = GNUNET_OK;
1560  memset(&tc, 0, sizeof(tc));
1561  tc.num_peers = num_peers;
1562  tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY;
1563  underlay = &tc.u.underlay;
1564  va_start(vargs, cls);
1566  switch (topology)
1567  {
1569  gen_topo_line(&tc);
1570  break;
1571 
1573  gen_topo_star(&tc);
1574  break;
1575 
1577  gen_topo_ring(&tc);
1578  break;
1579 
1581  gen_topo_clique(&tc);
1582  break;
1583 
1585  gen_topo_2dtorus(&tc);
1586  break;
1587 
1589  gen_topo_random(&tc, va_arg(vargs, unsigned int), GNUNET_NO);
1590  break;
1591 
1593  gen_topo_ring(&tc);
1594  gen_topo_random(&tc, va_arg(vargs, unsigned int), GNUNET_YES);
1595  break;
1596 
1598  gen_topo_2dtorus(&tc);
1599  gen_topo_random(&tc, va_arg(vargs, unsigned int), GNUNET_YES);
1600  break;
1601 
1603  {
1604  const char *filename;
1605  filename = va_arg(vargs, char *);
1606  GNUNET_assert(NULL != filename);
1607  gen_topo_from_file(&tc, filename);
1608  }
1609  break;
1610 
1612  {
1613  uint16_t cap;
1614  uint8_t m;
1615  cap = (uint16_t)va_arg(vargs, unsigned int);
1616  m = (uint8_t)va_arg(vargs, unsigned int);
1617  gen_topo_scale_free(&tc, cap, m);
1618  }
1619  break;
1620 
1621  default:
1622  GNUNET_assert(0);
1623  }
1624  va_end(vargs);
1625  for (cnt = 0; cnt < tc.link_array_size; cnt++)
1626  {
1627  ulink = &underlay->link_array[cnt];
1628  if (GNUNET_SYSERR == proc(cls,
1629  ulink->A,
1630  ulink->B,
1631  ulink->bandwidth,
1632  ulink->latency,
1633  ulink->loss))
1634  {
1635  ret = GNUNET_SYSERR;
1636  break;
1637  }
1638  }
1639  GNUNET_free_non_null(underlay->link_array);
1640  return ret;
1641 }
1642 
1643 /* end of testbed_api_topology.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:541
struct RetryListEntry * next
the next pointer for the DLL
A clique (everyone connected to everyone else).
static void gen_topo_scale_free(struct TopologyContext *tc, uint16_t cap, uint8_t m)
Generates scale free network.
static void overlay_link_completed(void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
Callback to be called when an overlay_link operation complete.
unsigned int nsuccess
Total successfully established overlay connections.
static int retry_entry(void *cls, const struct GNUNET_HashCode *key, void *entry)
Add entries to the message queue.
Definition: fs_download.c:746
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_underlay_configure_topology_va(void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, enum GNUNET_TESTBED_TopologyOption topo, va_list ap)
Configure overall network topology to have a particular shape.
int GNUNET_TESTBED_underlay_construct_(int num_peers, underlay_link_processor proc, void *cls,...)
Function to construct an underlay topology.
internal API to access the &#39;operations&#39; subsystem
GNUNET_TESTBED_TopologyOption
Topologies and topology options supported for testbeds.
unsigned int GNUNET_TESTBED_2dtorus_calc_links(unsigned int num_peers, unsigned int *rows, unsigned int **rows_len)
Returns the number of links that are required to generate a 2d torus for the given number of peers...
static void gen_topo_star(struct TopologyContext *tc)
Generates star topology.
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
Handle to interact with a GNUnet testbed controller.
Definition: testbed_api.h:191
struct TopologyContextOverlay overlay
Topology context information for overlay topology.
#define LOG(kind,...)
Generic loggins shorthand.
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_overlay_connect(void *op_cls, GNUNET_TESTBED_OperationCompletionCallback cb, void *cb_cls, struct GNUNET_TESTBED_Peer *p1, struct GNUNET_TESTBED_Peer *p2)
Both peers must have been started before calling this function.
struct RetryListEntry * rl_tail
DLL tail for retry list.
unsigned int num_peers
The number of peers.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Random on unsigned 64-bit values.
static unsigned long long max_connections
If there are at least this many connections, old ones will be removed.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
static void gen_topo_clique(struct TopologyContext *tc)
Generates clique topology.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_operation_create_(void *cls, OperationStart start, OperationRelease release)
Create an &#39;operation&#39; to be performed.
struct UnderlayLink * link_array
The link array.
enum TopologyContext::@73 type
The type of this context.
unsigned int ncompleted
How many links have been completed.
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_underlay_configure_topology(void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, enum GNUNET_TESTBED_TopologyOption topo,...)
Configure overall network topology to have a particular shape.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
unsigned int link_array_size
The size of the link array.
enum GNUNET_TESTBED_TopologyOption topology
The topology to generate.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void gen_topo_ring(struct TopologyContext *tc)
Generates ring topology.
static void gen_topo_line(struct TopologyContext *tc)
Generates line topology.
void GNUNET_TESTBED_operation_queue_insert_(struct OperationQueue *queue, struct GNUNET_TESTBED_Operation *op)
Add an operation to a queue.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_malloc_large(size)
Wrapper around malloc.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
Opaque handle to an abstract operation to be executed by the testing framework.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
void * op_cls
The operation closure.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
Read a topology from a given file.
struct GNUNET_TESTBED_Peer ** peers
The array of peers.
enum State state
current state of profiling
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
GNUNET_TESTBED_TopologyCompletionCallback comp_cb
topology generation completion callback
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
How many times should the failed overlay connect operations be retried before giving up...
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:82
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_overlay_configure_topology(void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int *max_connections, GNUNET_TESTBED_TopologyCompletionCallback comp_cb, void *comp_cb_cls, enum GNUNET_TESTBED_TopologyOption topo,...)
All peers must have been started before calling this function.
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:80
uint16_t status
See PRISM_STATUS_*-constants.
static char buf[2048]
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
static char * filename
unsigned int retry_cnt
How many retries to do before we give up.
struct GNUNET_TESTBED_Controller * controller
Our controller context (not necessarily the controller that is responsible for starting/running the p...
Topology context information for underlay topologies.
void GNUNET_TESTBED_operation_done(struct GNUNET_TESTBED_Operation *operation)
This function is used to signal that the event information (struct GNUNET_TESTBED_EventInformation) f...
Definition: testbed_api.c:2037
unsigned int nfailures
Total failed overlay connections.
unsigned int nlinks
Number of links to try.
static void gen_topo_random(struct TopologyContext *tc, unsigned int links, int append)
Generates ring topology.
struct RetryListEntry * prev
the prev pointer for the DLL
The options should always end with this.
static const char * topology_strings[]
A array of names representing topologies.
void(* GNUNET_TESTBED_TopologyCompletionCallback)(void *cls, unsigned int nsuccess, unsigned int nfailures)
Callbacks of this type are called when topology configuration is completed.
static void gen_topo_from_file(struct TopologyContext *tc, const char *filename)
Generates topology from the given file.
struct OperationQueue * opq_parallel_topology_config_operations
Operation queue for simultaneous topology configuration operations.
Definition: testbed_api.h:251
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
Small-world network (2d torus plus random links).
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
struct TopologyContextUnderlay underlay
Topology context information for underlay topology.
static unsigned int num_peers
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_overlay_configure_topology_va(void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int *max_connections, GNUNET_TESTBED_TopologyCompletionCallback comp_cb, void *comp_cb_cls, enum GNUNET_TESTBED_TopologyOption topo, va_list va)
All peers must have been started before calling this function.
static struct GNUNET_FS_Handle * fs
Handle to FS service.
Definition: gnunet-fs.c:36
int GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:254
internal API to access the &#39;peers&#39; subsystem
static struct GNUNET_CONTAINER_MultiPeerMap * links
Map from PIDs to struct VirtualLink entries describing links CORE knows to exist. ...
Interface for functions internally exported from testbed_api.c.
void * comp_cb_cls
The closure for the above callback.
struct RetryListEntry * rl_head
DLL head for retry list.
void GNUNET_TESTBED_operation_begin_wait_(struct GNUNET_TESTBED_Operation *op)
Marks the given operation as waiting on the queues.
static void gen_topo_2dtorus(struct TopologyContext *tc)
Generates ring topology.
#define GNUNET_VA_ARG_ENUM(va, X)
wrap va_arg for enums
static struct CadetPeer * peers
Operation to get peer ids.
int(* underlay_link_processor)(void *cls, unsigned int A, unsigned int B, unsigned int bandwidth, unsigned int latency, unsigned int loss)
Functions of this type are called to process underlay link.
struct OverlayLink * link
The link to be retired.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
#define GNUNET_YES
Definition: gnunet_common.h:77
struct OverlayLink * link_array
An array of links; this array is of size link_array_size.
A peer controlled by the testing framework.
union TopologyContext::@74 u
uint32_t data
The data value.
static void opstart_overlay_configure_topology(void *cls)
Function called when a overlay connect operation is ready.
char * GNUNET_TESTBED_topology_to_str_(enum GNUNET_TESTBED_TopologyOption topology)
Returns the string corresponding to the given topology.
Context information for overlay topologies.
Context information for topology operations.
header for intra library exported functions
static void oprelease_overlay_configure_topology(void *cls)
Callback which will be called when overlay connect operation is released.
#define DEFAULT_RETRY_CNT
Default number of retires.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_malloc(size)
Wrapper around malloc.
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:791
#define GNUNET_free(ptr)
Wrapper around free.
int GNUNET_TESTBED_topology_get_(enum GNUNET_TESTBED_TopologyOption *topology, const char *topology_string)
Get a topology from a string input.
static void make_link(unsigned int offset, uint32_t A, uint32_t B, struct TopologyContext *tc)
Populates the OverlayLink structure.
Small-world network (ring plus random links).