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 
56 {
57 
62 
67 
71  uint32_t A;
72 
76  uint32_t B;
77 
78 };
79 
80 
85 {
89  uint32_t A;
90 
94  uint32_t B;
95 
99  uint32_t bandwidth;
100 
104  uint32_t latency;
105 
109  uint32_t loss;
110 };
111 
112 
114 {
119 
124 
128  struct OverlayLink *link;
129 };
130 
131 
136 {
141 
146 
150  void *op_cls;
151 
156 
160  void *comp_cb_cls;
161 
166 
171 
175  unsigned int retry_cnt;
176 
180  unsigned int nlinks;
181 
185  unsigned int ncompleted;
186 
190  unsigned int nsuccess;
191 
195  unsigned int nfailures;
196 };
197 
198 
203 {
208 };
209 
210 
215 {
219  enum {
220 
224  TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0,
225 
229  TOPOLOGYCONTEXT_TYPE_OVERLAY
230 
231  } type;
232 
233  union {
234 
238  struct TopologyContextOverlay overlay;
239 
243  struct TopologyContextUnderlay underlay;
244  } u;
245 
249  unsigned int num_peers;
250 
254  unsigned int link_array_size;
255 
256 };
257 
258 
263 static const char *topology_strings[] = {
264 
269  "CLIQUE",
270 
271  /*
272  * Small-world network (2d torus plus random links). Followed
273  * by the number of random links to add (unsigned int).
274  */
275  "SMALL_WORLD",
276 
281  "SMALL_WORLD_RING",
282 
286  "RING",
287 
291  "STAR",
292 
296  "2D_TORUS",
297 
302  "RANDOM", // GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI
303 
309  "INTERNAT",
310 
316  "SCALE_FREE",
317 
321  "LINE",
322 
326  "FROM_FILE",
327 
331  "NONE",
332 
336  NULL
337 };
338 
339 
348 static void
351  const char *emsg)
352 {
353  struct OverlayLink *link = cls;
354  struct TopologyContext *tc;
355  struct TopologyContextOverlay *overlay;
356  struct RetryListEntry *retry_entry;
357 
358  GNUNET_assert (op == link->op);
360  link->op = NULL;
361  tc = link->tc;
362  GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
363  overlay = &tc->u.overlay;
364  if (NULL != emsg)
365  {
366  overlay->nfailures++;
367  if (0 != overlay->retry_cnt)
368  {
370  "Error while establishing a link: %s -- Retrying\n",
371  emsg);
372  retry_entry = GNUNET_new (struct RetryListEntry);
373  retry_entry->link = link;
375  overlay->rl_tail,
376  retry_entry);
377  }
378  }
379  else
380  overlay->nsuccess++;
381  overlay->ncompleted++;
382  if (overlay->ncompleted < overlay->nlinks)
383  return;
384  if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head))
385  {
386  overlay->retry_cnt--;
387  overlay->ncompleted = 0;
388  overlay->nlinks = 0;
389  while (NULL != (retry_entry = overlay->rl_head))
390  {
391  link = retry_entry->link;
392  link->op =
395  link,
396  overlay->peers[link->A],
397  overlay->peers[link->B]);
398  overlay->nlinks++;
400  overlay->rl_tail,
401  retry_entry);
402  GNUNET_free (retry_entry);
403  }
404  return;
405  }
406  if (NULL != overlay->comp_cb)
407  {
408  overlay->comp_cb (overlay->comp_cb_cls,
409  overlay->nsuccess,
410  overlay->nfailures);
411  }
412 }
413 
414 
415 
421 static void
423 {
424  struct TopologyContext *tc = cls;
425  struct TopologyContextOverlay *overlay;
426  unsigned int p;
427 
428  GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
429  overlay = &tc->u.overlay;
430  overlay->nlinks = tc->link_array_size;
431  for (p = 0; p < tc->link_array_size; p++)
432  {
433  overlay->link_array[p].op =
436  &overlay->link_array[p],
437  overlay->peers[overlay->link_array[p].A],
438  overlay->peers[overlay->link_array[p].B]);
439  }
440 }
441 
442 
448 static void
450 {
451  struct TopologyContext *tc = cls;
452  struct TopologyContextOverlay *overlay;
453  struct RetryListEntry *retry_entry;
454  unsigned int p;
455 
456  GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
457  overlay = &tc->u.overlay;
458  while (NULL != (retry_entry = overlay->rl_head))
459  {
460  GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, retry_entry);
461  GNUNET_free (retry_entry);
462  }
463  if (NULL != overlay->link_array)
464  {
465  for (p = 0; p < tc->link_array_size; p++)
466  if (NULL != overlay->link_array[p].op)
468  GNUNET_free (overlay->link_array);
469  }
470  GNUNET_free (tc);
471 }
472 
473 
483 static void
484 make_link (unsigned int offset,
485  uint32_t A,
486  uint32_t B,
487  struct TopologyContext *tc)
488 {
489  GNUNET_assert (A != B);
490  switch (tc->type)
491  {
492  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
493  {
494  struct TopologyContextOverlay *overlay;
495  struct OverlayLink *olink;
496 
497  overlay = &tc->u.overlay;
498  GNUNET_assert (offset < tc->link_array_size);
499  olink = &overlay->link_array[offset];
500  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A);
501  olink->A = A;
502  olink->B = B;
503  olink->op = NULL;
504  olink->tc = tc;
505  }
506  break;
507  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
508  {
509  struct TopologyContextUnderlay *underlay;
510  struct UnderlayLink *ulink;
511 
512  underlay = &tc->u.underlay;
513  GNUNET_assert (offset < tc->link_array_size);
514  ulink = &underlay->link_array[offset];
515  ulink->A = A;
516  ulink->B = B;
517  }
518  break;
519  }
520 }
521 
522 
528 static void
530 {
531  unsigned int cnt;
532 
533  tc->link_array_size = tc->num_peers - 1;
534  switch (tc->type)
535  {
536  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
537  {
538  struct TopologyContextOverlay *overlay;
539 
540  overlay = &tc->u.overlay;
541  overlay->link_array =
543  struct OverlayLink);
544  }
545  break;
546  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
547  {
548  struct TopologyContextUnderlay *underlay;
549 
550  underlay = &tc->u.underlay;
551  underlay->link_array =
553  struct UnderlayLink);
554  }
555  break;
556  }
557  for (cnt = 0; cnt < (tc->link_array_size); cnt++)
558  make_link (cnt, cnt, cnt + 1, tc);
559 }
560 
561 
567 static void
569 {
570  unsigned int cnt;
571 
572  tc->link_array_size = tc->num_peers - 1;
573  switch (tc->type)
574  {
575  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
576  {
577  struct TopologyContextOverlay *overlay;
578 
579  overlay = &tc->u.overlay;
580  overlay->link_array =
582  struct OverlayLink);
583  }
584  break;
585  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
586  {
587  struct TopologyContextUnderlay *underlay;
588 
589  underlay = &tc->u.underlay;
590  underlay->link_array =
592  struct UnderlayLink);
593  }
594  break;
595  }
596  for (cnt = tc->link_array_size; cnt; cnt--)
597  make_link (cnt - 1,
598  0,
599  cnt,
600  tc);
601 }
602 
603 
609 static void
611 {
612  gen_topo_line (tc);
613  tc->link_array_size++;
614  switch (tc->type)
615  {
616  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
617  {
618  struct TopologyContextOverlay *overlay;
619 
620  overlay = &tc->u.overlay;
621  overlay->link_array =
622  GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) *
623  tc->link_array_size);
624  }
625  break;
626  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
627  {
628  struct TopologyContextUnderlay *underlay;
629 
630  underlay = &tc->u.underlay;
631  underlay->link_array =
632  GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) *
633  tc->link_array_size);
634  }
635  break;
636  }
637  make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc);
638 }
639 
640 
653 unsigned int
654 GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows,
655  unsigned int **rows_len)
656 {
657  double sq;
658  unsigned int sq_floor;
659  unsigned int _rows;
660  unsigned int *_rows_len;
661  unsigned int x;
662  unsigned int y;
663  unsigned int _num_peers;
664  unsigned int cnt;
665 
666  sq = sqrt (num_peers);
667  sq = floor (sq);
668  sq_floor = (unsigned int) sq;
669  _rows = (sq_floor + 1);
670  _rows_len = GNUNET_malloc (sizeof (unsigned int) * _rows);
671  for (y = 0; y < _rows - 1; y++)
672  _rows_len[y] = sq_floor;
673  _num_peers = sq_floor * sq_floor;
674  cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers;
675  x = 0;
676  y = 0;
677  while (_num_peers < num_peers)
678  {
679  if (x < y)
680  _rows_len[_rows - 1] = ++x;
681  else
682  _rows_len[y++]++;
683  _num_peers++;
684  }
685  cnt += (x < 2) ? x : 2 * x;
686  cnt += (y < 2) ? y : 2 * y;
687  if (0 == _rows_len[_rows - 1])
688  _rows--;
689  if (NULL != rows)
690  *rows = _rows;
691  if (NULL != rows_len)
692  *rows_len = _rows_len;
693  else
694  GNUNET_free (_rows_len);
695  return cnt;
696 }
697 
698 
704 static void
706 {
707  unsigned int rows;
708  unsigned int *rows_len;
709  unsigned int x;
710  unsigned int y;
711  unsigned int cnt;
712  unsigned int offset;
713 
714  tc->link_array_size =
715  GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len);
716  switch (tc->type)
717  {
718  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
719  {
720  struct TopologyContextOverlay *overlay;
721 
722  overlay = &tc->u.overlay;
723  overlay->link_array =
724  GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size);
725  }
726  break;
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 
782 static void
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 != overlay->link_array));
819  overlay->link_array =
820  GNUNET_realloc (overlay->link_array,
821  sizeof (struct OverlayLink) * tc->link_array_size);
822  break;
823  }
824  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
825  {
826  struct TopologyContextUnderlay *underlay;
827 
828  underlay = &tc->u.underlay;
829  if (GNUNET_YES != append)
830  {
831  GNUNET_assert (NULL == underlay->link_array);
832  underlay->link_array =
833  GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size);
834  break;
835  }
836  GNUNET_assert ((0 < tc->link_array_size) && (NULL != underlay->link_array));
837  underlay->link_array =
838  GNUNET_realloc (underlay->link_array,
839  sizeof (struct UnderlayLink) * tc->link_array_size);
840  break;
841  }
842  }
843  for (cnt = 0; cnt < links; cnt++)
844  {
845  do
846  {
847  A_rand =
849  B_rand =
851  }
852  while (A_rand == B_rand);
853  make_link (index+cnt, A_rand, B_rand, tc);
854  }
855 }
856 
857 
868 static void
870  uint16_t cap,
871  uint8_t m)
872 {
873  unsigned int *deg;
874  unsigned int *etab;
875  unsigned int *used;
876  unsigned int etaboff;
877  unsigned int cnt;
878  unsigned int cnt2;
879  unsigned int peer;
880  unsigned int random_peer;
881  unsigned int links;
882  unsigned int off;
883  unsigned int redo_threshold;
884 
885  etaboff = 0;
886  tc->link_array_size = tc->num_peers * m;
887  switch (tc->type)
888  {
889  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
890  {
891  struct TopologyContextOverlay *overlay;
892 
893  overlay = &tc->u.overlay;
894  overlay->link_array = GNUNET_malloc_large (sizeof (struct OverlayLink) *
895  tc->link_array_size);
896  }
897  break;
898  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
899  {
900  struct TopologyContextUnderlay *underlay;
901 
902  underlay = &tc->u.underlay;
903  underlay->link_array = GNUNET_malloc_large (sizeof (struct UnderlayLink) *
904  tc->link_array_size);
905  }
906  break;
907  }
908  etab = GNUNET_malloc_large (sizeof (unsigned int) * 2 * tc->link_array_size);
909  deg = GNUNET_malloc (sizeof (unsigned int) * tc->num_peers);
910  used = GNUNET_malloc (sizeof (unsigned int) * m);
911  /* start by connecting peer 1 to peer 0 */
912  make_link (0, 0, 1, tc);
913  deg[0]++;
914  deg[1]++;
915  etab[etaboff++] = 0;
916  etab[etaboff++] = 1;
917  links = 1;
918  for (peer = 2; peer < tc->num_peers; peer++)
919  {
920  if (cap < deg[peer])
921  continue;
922  for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
923  {
924  redo_threshold = 0;
925  redo:
927  random_peer = etab[off];
928  if (cap < deg[random_peer])
929  {
930  if (++redo_threshold > GNUNET_MAX (1, cap / 2))
931  {
932  redo_threshold = 0;
933  off = 0;
934  for (cnt2 = 0; cnt2 < etaboff; cnt2++)
935  {
936  if (random_peer == etab[cnt2])
937  {
938  off++;
939  continue;
940  }
941  etab[cnt2 - off] = etab[cnt2];
942  }
943  etaboff -= off;
944  }
945  goto redo;
946  }
947  for (cnt2 = 0; cnt2 < cnt; cnt2++)
948  if (random_peer == used[cnt2])
949  goto redo;
950  make_link (links + cnt, random_peer, peer, tc);
951  deg[random_peer]++;
952  deg[peer]++;
953  used[cnt] = random_peer;
954  }
955  for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
956  {
957  etab[etaboff++] = used[cnt];
958  etab[etaboff++] = peer;
959  }
960  links += GNUNET_MIN (peer, m);
961  }
962  GNUNET_free (etab);
963  GNUNET_free (used);
964  GNUNET_free (deg);
965  GNUNET_assert (links <= tc->link_array_size);
966  tc->link_array_size = links;
967  switch (tc->type)
968  {
969  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
970  {
971  struct TopologyContextOverlay *overlay;
972 
973  overlay = &tc->u.overlay;
974  overlay->link_array =
975  GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) * tc->link_array_size);
976  }
977  break;
978  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
979  {
980  struct TopologyContextUnderlay *underlay;
981 
982  underlay = &tc->u.underlay;
983  underlay->link_array =
984  GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) * tc->link_array_size);
985  }
986  break;
987  }
988 }
989 
990 
997 static void
999  const char *filename)
1000 {
1001  char *data;
1002  char *end;
1003  char *buf;
1004  uint64_t fs;
1005  uint64_t offset;
1006  unsigned long int peer_id;
1007  unsigned long int other_peer_id;
1008  enum ParseState
1009  {
1010 
1014  PEER_INDEX,
1015 
1019  OTHER_PEER_INDEX,
1020 
1021  } state;
1022  int status;
1023 
1024  status = GNUNET_SYSERR;
1025  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1026  {
1028  _("Topology file %s not found\n"),
1029  filename);
1030  return;
1031  }
1032  if (GNUNET_OK !=
1033  GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
1034  {
1036  _("Topology file %s has no data\n"),
1037  filename);
1038  return;
1039  }
1040  data = GNUNET_malloc (fs);
1041  if (fs != GNUNET_DISK_fn_read (filename, data, fs))
1042  {
1044  _("Topology file %s cannot be read\n"),
1045  filename);
1046  goto _exit;
1047  }
1048 
1049  offset = 0;
1050  peer_id = 0;
1051  state = PEER_INDEX;
1052  while (offset < fs)
1053  {
1054  if (0 != isspace ((unsigned char) data[offset]))
1055  {
1056  offset++;
1057  continue;
1058  }
1059  switch (state)
1060  {
1061  case PEER_INDEX:
1062  buf = strchr (&data[offset], ':');
1063  if (NULL == buf)
1064  {
1066  _("Failed to read peer index from toology file: %s"), filename);
1067  goto _exit;
1068  }
1069  *buf = '\0';
1070  errno = 0;
1071  peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1072  if (0 != errno)
1073  {
1075  _("Value in given topology file: %s out of range\n"), filename);
1076  goto _exit;
1077  }
1078  if (&data[offset] == end)
1079  {
1081  _("Failed to read peer index from topology file: %s"), filename);
1082  goto _exit;
1083  }
1084  if (tc->num_peers <= peer_id)
1085  {
1087  _("Topology file needs more peers than given ones\n"), filename);
1088  goto _exit;
1089  }
1090  state = OTHER_PEER_INDEX;
1091  offset += ((unsigned int) (buf - &data[offset])) + 1;
1092  break;
1093  case OTHER_PEER_INDEX:
1094  errno = 0;
1095  other_peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1096  if (0 != errno)
1097  {
1099  _("Value in given topology file: %s out of range\n"), filename);
1100  goto _exit;
1101  }
1102  if (&data[offset] == end)
1103  {
1105  _("Failed to read peer index from topology file: %s"), filename);
1106  goto _exit;
1107  }
1108  if (tc->num_peers <= other_peer_id)
1109  {
1111  _("Topology file needs more peers than given ones\n"), filename);
1112  goto _exit;
1113  }
1114  if (peer_id != other_peer_id)
1115  {
1116  tc->link_array_size++;
1117  switch (tc->type)
1118  {
1119  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1120  {
1121  struct TopologyContextOverlay *overlay;
1122 
1123  overlay = &tc->u.overlay;
1124  overlay->link_array =
1125  GNUNET_realloc (overlay->link_array,
1126  sizeof (struct OverlayLink) * tc->link_array_size);
1127  }
1128  break;
1129  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1130  {
1131  struct TopologyContextUnderlay *underlay;
1132 
1133  underlay = &tc->u.underlay;
1134  underlay->link_array =
1135  GNUNET_realloc (underlay->link_array,
1136  sizeof (struct UnderlayLink) * tc->link_array_size);
1137  }
1138  break;
1139  }
1140  offset += end - &data[offset];
1141  make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc);
1142  }
1143  else
1145  _("Ignoring to connect peer %u to peer %u\n"),
1146  peer_id,
1147  other_peer_id);
1148  while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs))
1149  offset++;
1150  if ( (offset < fs) &&
1151  ('\n' == data[offset]) )
1152  state = PEER_INDEX;
1153  else if ( (offset < fs) &&
1154  ('|' == data[offset]) )
1155  {
1156  state = OTHER_PEER_INDEX;
1157  offset++;
1158  }
1159  break;
1160  }
1161  }
1162  status = GNUNET_OK;
1163 
1164 _exit:
1165  GNUNET_free (data);
1166  if (GNUNET_OK != status)
1167  {
1169  "Removing link data read from the file\n");
1170  tc->link_array_size = 0;
1171  switch (tc->type)
1172  {
1173  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1174  {
1175  struct TopologyContextOverlay *overlay;
1176 
1177  overlay = &tc->u.overlay;
1178  GNUNET_free_non_null (overlay->link_array);
1179  overlay->link_array = NULL;
1180  }
1181  break;
1182  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1183  {
1184  struct TopologyContextUnderlay *underlay;
1185 
1186  underlay = &tc->u.underlay;
1187  GNUNET_free_non_null (underlay->link_array);
1188  underlay->link_array = NULL;
1189  }
1190  break;
1191  }
1192  }
1193 }
1194 
1195 
1201 static void
1203 {
1204  unsigned int cnt;
1205  unsigned int offset;
1206  unsigned int neighbour;
1207 
1208  tc->link_array_size = tc->num_peers * (tc->num_peers - 1);
1209  switch (tc->type)
1210  {
1211  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1212  {
1213  struct TopologyContextOverlay *overlay;
1214 
1215  overlay = &tc->u.overlay;
1217  struct OverlayLink);
1218  }
1219  break;
1220  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1221  {
1222  struct TopologyContextUnderlay *underlay;
1223 
1224  underlay = &tc->u.underlay;
1225  underlay->link_array = GNUNET_new_array (tc->link_array_size,
1226  struct UnderlayLink);
1227  }
1228  }
1229  offset = 0;
1230  for (cnt = 0; cnt < tc->num_peers; cnt++)
1231  {
1232  for (neighbour = 0; neighbour < tc->num_peers; neighbour++)
1233  {
1234  if (neighbour == cnt)
1235  continue;
1236  make_link (offset, cnt, neighbour, tc);
1237  offset++;
1238  }
1239  }
1240 }
1241 
1242 
1254 struct GNUNET_TESTBED_Operation *
1256  unsigned int num_peers,
1257  struct GNUNET_TESTBED_Peer
1258  **peers,
1259  enum
1261  topo, va_list ap)
1262 {
1263  GNUNET_break (0);
1264  return NULL;
1265 }
1266 
1267 
1279 struct GNUNET_TESTBED_Operation *
1281  unsigned int num_peers,
1282  struct GNUNET_TESTBED_Peer **peers,
1284  topo, ...)
1285 {
1286  GNUNET_break (0);
1287  return NULL;
1288 }
1289 
1290 
1311 struct GNUNET_TESTBED_Operation *
1313  unsigned int num_peers,
1314  struct GNUNET_TESTBED_Peer **peers,
1315  unsigned int *max_connections,
1317  comp_cb,
1318  void *comp_cb_cls,
1320  va_list va)
1321 {
1322  struct TopologyContext *tc;
1323  struct TopologyContextOverlay *overlay;
1324  struct GNUNET_TESTBED_Operation *op;
1325  struct GNUNET_TESTBED_Controller *c;
1326  enum GNUNET_TESTBED_TopologyOption secondary_option;
1327 
1328  if (num_peers < 2)
1329  return NULL;
1330  c = peers[0]->controller;
1331  tc = GNUNET_new (struct TopologyContext);
1332  tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY;
1333  overlay = &tc->u.overlay;
1334  overlay->peers = peers;
1335  tc->num_peers = num_peers;
1336  overlay->op_cls = op_cls;
1337  overlay->retry_cnt = DEFAULT_RETRY_CNT;
1338  overlay->comp_cb = comp_cb;
1339  overlay->comp_cb_cls = comp_cb_cls;
1340  switch (topo)
1341  {
1343  gen_topo_line (tc);
1344  break;
1346  gen_topo_star (tc);
1347  break;
1349  gen_topo_ring (tc);
1350  break;
1352  gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_NO);
1353  break;
1355  gen_topo_ring (tc);
1356  gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1357  break;
1359  gen_topo_clique (tc);
1360  break;
1362  gen_topo_2dtorus (tc);
1363  break;
1365  gen_topo_2dtorus (tc);
1366  gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1367 
1368  break;
1370  {
1371  uint16_t cap;
1372  uint8_t m;
1373 
1374  cap = (uint16_t) va_arg (va, unsigned int);
1375  m = (uint8_t) va_arg (va, unsigned int);
1376  gen_topo_scale_free (tc, cap, m);
1377  }
1378  break;
1380  {
1381  const char *filename;
1382 
1383  filename = va_arg (va, const char *);
1384 
1385  GNUNET_assert (NULL != filename);
1386  gen_topo_from_file (tc, filename);
1387  }
1388  break;
1389  default:
1390  GNUNET_break (0);
1391  GNUNET_free (tc);
1392  return NULL;
1393  }
1394  do
1395  {
1396  secondary_option = GNUNET_VA_ARG_ENUM (va, GNUNET_TESTBED_TopologyOption);
1397 
1398  switch (secondary_option)
1399  {
1401  overlay->retry_cnt = va_arg (va, unsigned int);
1402  break;
1404  break;
1405  default:
1406  GNUNET_break (0); /* Should not use any other option apart from
1407  * the ones handled here */
1408  GNUNET_free_non_null (overlay->link_array);
1409  GNUNET_free (tc);
1410  return NULL;
1411  }
1412  }
1413  while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option);
1421  "Generated %u connections\n",
1422  tc->link_array_size);
1423  if (NULL != max_connections)
1424  *max_connections = tc->link_array_size;
1425  return op;
1426 }
1427 
1428 
1449 struct GNUNET_TESTBED_Operation *
1451  unsigned int num_peers,
1452  struct GNUNET_TESTBED_Peer **peers,
1453  unsigned int *max_connections,
1455  comp_cb,
1456  void *comp_cb_cls,
1458  ...)
1459 {
1460  struct GNUNET_TESTBED_Operation *op;
1461  va_list vargs;
1462 
1464  va_start (vargs, topo);
1465  op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers,
1466  max_connections,
1467  comp_cb, comp_cb_cls,
1468  topo,
1469  vargs);
1470  va_end (vargs);
1471  return op;
1472 }
1473 
1474 
1484 int
1486  const char *topology_string)
1487 {
1488  unsigned int cnt;
1489 
1490  for (cnt = 0; NULL != topology_strings[cnt]; cnt++)
1491  {
1492  if (0 == strcasecmp (topology_string, topology_strings[cnt]))
1493  {
1494  if (NULL != topology)
1495  *topology = (enum GNUNET_TESTBED_TopologyOption) cnt;
1497  return GNUNET_YES;
1498  }
1499  }
1500  return GNUNET_NO;
1501 }
1502 
1503 
1511 char *
1513 {
1514  if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology)
1515  return NULL;
1516  return GNUNET_strdup (topology_strings[topology]);
1517 }
1518 
1519 
1536 int
1539  void *cls,
1540  ...)
1541 {
1542  struct TopologyContext tc;
1543  struct TopologyContextUnderlay *underlay;
1544  struct UnderlayLink *ulink;
1545  va_list vargs;
1547  unsigned int cnt;
1548  int ret;
1549 
1550  GNUNET_assert (NULL != proc);
1551  ret = GNUNET_OK;
1552  memset (&tc, 0, sizeof (tc));
1553  tc.num_peers = num_peers;
1554  tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY;
1555  underlay = &tc.u.underlay;
1556  va_start (vargs, cls);
1558  switch (topology)
1559  {
1561  gen_topo_line (&tc);
1562  break;
1564  gen_topo_star (&tc);
1565  break;
1567  gen_topo_ring (&tc);
1568  break;
1570  gen_topo_clique (&tc);
1571  break;
1573  gen_topo_2dtorus (&tc);
1574  break;
1576  gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO);
1577  break;
1579  gen_topo_ring (&tc);
1580  gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1581  break;
1583  gen_topo_2dtorus (&tc);
1584  gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1585  break;
1587  {
1588  const char *filename;
1589  filename = va_arg (vargs, char *);
1590  GNUNET_assert (NULL != filename);
1591  gen_topo_from_file (&tc, filename);
1592  }
1593  break;
1595  {
1596  uint16_t cap;
1597  uint8_t m;
1598  cap = (uint16_t) va_arg (vargs, unsigned int);
1599  m = (uint8_t) va_arg (vargs, unsigned int);
1600  gen_topo_scale_free (&tc, cap, m);
1601  }
1602  break;
1603  default:
1604  GNUNET_assert (0);
1605  }
1606  va_end (vargs);
1607  for (cnt = 0; cnt < tc.link_array_size; cnt++)
1608  {
1609  ulink = &underlay->link_array[cnt];
1610  if (GNUNET_SYSERR == proc (cls,
1611  ulink->A,
1612  ulink->B,
1613  ulink->bandwidth,
1614  ulink->latency,
1615  ulink->loss))
1616  {
1617  ret = GNUNET_SYSERR;
1618  break;
1619  }
1620  }
1621  GNUNET_free_non_null (underlay->link_array);
1622  return ret;
1623 }
1624 
1625 /* 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:669
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:747
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:194
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:81
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:78
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:208
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:85
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:83
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:2046
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:255
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
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:289
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:80
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:1019
#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).