GNUnet  0.11.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 {
61 
66 
70  uint32_t A;
71 
75  uint32_t B;
76 };
77 
78 
83 {
87  uint32_t A;
88 
92  uint32_t B;
93 
97  uint32_t bandwidth;
98 
102  uint32_t latency;
103 
107  uint32_t loss;
108 };
109 
110 
112 {
117 
122 
126  struct OverlayLink *link;
127 };
128 
129 
134 {
139 
144 
148  void *op_cls;
149 
154 
158  void *comp_cb_cls;
159 
164 
169 
173  unsigned int retry_cnt;
174 
178  unsigned int nlinks;
179 
183  unsigned int ncompleted;
184 
188  unsigned int nsuccess;
189 
193  unsigned int nfailures;
194 };
195 
196 
201 {
206 };
207 
208 
213 {
217  enum
218  {
222  TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0,
223 
227  TOPOLOGYCONTEXT_TYPE_OVERLAY
228  } type;
229 
230  union
231  {
235  struct TopologyContextOverlay overlay;
236 
240  struct TopologyContextUnderlay underlay;
241  } u;
242 
246  unsigned int num_peers;
247 
251  unsigned int link_array_size;
252 };
253 
254 
259 static const char *topology_strings[] = {
264  "CLIQUE",
265 
266  /*
267  * Small-world network (2d torus plus random links). Followed
268  * by the number of random links to add (unsigned int).
269  */
270  "SMALL_WORLD",
271 
276  "SMALL_WORLD_RING",
277 
281  "RING",
282 
286  "STAR",
287 
291  "2D_TORUS",
292 
297  "RANDOM", // GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI
298 
304  "INTERNAT",
305 
311  "SCALE_FREE",
312 
316  "LINE",
317 
321  "FROM_FILE",
322 
326  "NONE",
327 
331  NULL
332 };
333 
334 
343 static void
346  const char *emsg)
347 {
348  struct OverlayLink *link = cls;
349  struct TopologyContext *tc;
350  struct TopologyContextOverlay *overlay;
351  struct RetryListEntry *retry_entry;
352 
353  GNUNET_assert (op == link->op);
355  link->op = NULL;
356  tc = link->tc;
357  GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
358  overlay = &tc->u.overlay;
359  if (NULL != emsg)
360  {
361  overlay->nfailures++;
362  if (0 != overlay->retry_cnt)
363  {
365  "Error while establishing a link: %s -- Retrying\n",
366  emsg);
367  retry_entry = GNUNET_new (struct RetryListEntry);
368  retry_entry->link = link;
370  overlay->rl_tail,
371  retry_entry);
372  }
373  }
374  else
375  overlay->nsuccess++;
376  overlay->ncompleted++;
377  if (overlay->ncompleted < overlay->nlinks)
378  return;
379  if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head))
380  {
381  overlay->retry_cnt--;
382  overlay->ncompleted = 0;
383  overlay->nlinks = 0;
384  while (NULL != (retry_entry = overlay->rl_head))
385  {
386  link = retry_entry->link;
387  link->op =
390  link,
391  overlay->peers[link->A],
392  overlay->peers[link->B]);
393  overlay->nlinks++;
395  overlay->rl_tail,
396  retry_entry);
397  GNUNET_free (retry_entry);
398  }
399  return;
400  }
401  if (NULL != overlay->comp_cb)
402  {
403  overlay->comp_cb (overlay->comp_cb_cls,
404  overlay->nsuccess,
405  overlay->nfailures);
406  }
407 }
408 
409 
415 static void
417 {
418  struct TopologyContext *tc = cls;
419  struct TopologyContextOverlay *overlay;
420  unsigned int p;
421 
422  GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
423  overlay = &tc->u.overlay;
424  overlay->nlinks = tc->link_array_size;
425  for (p = 0; p < tc->link_array_size; p++)
426  {
427  overlay->link_array[p].op =
430  &overlay->link_array[p],
431  overlay->peers[overlay->link_array[p].A],
432  overlay->peers[overlay->link_array[p].B]);
433  }
434 }
435 
436 
442 static void
444 {
445  struct TopologyContext *tc = cls;
446  struct TopologyContextOverlay *overlay;
447  struct RetryListEntry *retry_entry;
448  unsigned int p;
449 
450  GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
451  overlay = &tc->u.overlay;
452  while (NULL != (retry_entry = overlay->rl_head))
453  {
454  GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail,
455  retry_entry);
456  GNUNET_free (retry_entry);
457  }
458  if (NULL != overlay->link_array)
459  {
460  for (p = 0; p < tc->link_array_size; p++)
461  if (NULL != overlay->link_array[p].op)
463  GNUNET_free (overlay->link_array);
464  }
465  GNUNET_free (tc);
466 }
467 
468 
478 static void
479 make_link (unsigned int offset,
480  uint32_t A,
481  uint32_t B,
482  struct TopologyContext *tc)
483 {
484  GNUNET_assert (A != B);
485  switch (tc->type)
486  {
487  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
488  {
489  struct TopologyContextOverlay *overlay;
490  struct OverlayLink *olink;
491 
492  overlay = &tc->u.overlay;
493  GNUNET_assert (offset < tc->link_array_size);
494  olink = &overlay->link_array[offset];
495  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A);
496  olink->A = A;
497  olink->B = B;
498  olink->op = NULL;
499  olink->tc = tc;
500  }
501  break;
502 
503  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
504  {
505  struct TopologyContextUnderlay *underlay;
506  struct UnderlayLink *ulink;
507 
508  underlay = &tc->u.underlay;
509  GNUNET_assert (offset < tc->link_array_size);
510  ulink = &underlay->link_array[offset];
511  ulink->A = A;
512  ulink->B = B;
513  }
514  break;
515  }
516 }
517 
518 
524 static void
526 {
527  unsigned int cnt;
528 
529  tc->link_array_size = tc->num_peers - 1;
530  switch (tc->type)
531  {
532  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
533  {
534  struct TopologyContextOverlay *overlay;
535 
536  overlay = &tc->u.overlay;
537  overlay->link_array =
539  struct OverlayLink);
540  }
541  break;
542 
543  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
544  {
545  struct TopologyContextUnderlay *underlay;
546 
547  underlay = &tc->u.underlay;
548  underlay->link_array =
550  struct UnderlayLink);
551  }
552  break;
553  }
554  for (cnt = 0; cnt < (tc->link_array_size); cnt++)
555  make_link (cnt, cnt, cnt + 1, tc);
556 }
557 
558 
564 static void
566 {
567  unsigned int cnt;
568 
569  tc->link_array_size = tc->num_peers - 1;
570  switch (tc->type)
571  {
572  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
573  {
574  struct TopologyContextOverlay *overlay;
575 
576  overlay = &tc->u.overlay;
577  overlay->link_array =
579  struct OverlayLink);
580  }
581  break;
582 
583  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
584  {
585  struct TopologyContextUnderlay *underlay;
586 
587  underlay = &tc->u.underlay;
588  underlay->link_array =
590  struct UnderlayLink);
591  }
592  break;
593  }
594  for (cnt = tc->link_array_size; cnt; cnt--)
595  make_link (cnt - 1,
596  0,
597  cnt,
598  tc);
599 }
600 
601 
607 static void
609 {
610  gen_topo_line (tc);
611  tc->link_array_size++;
612  switch (tc->type)
613  {
614  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
615  {
616  struct TopologyContextOverlay *overlay;
617 
618  overlay = &tc->u.overlay;
619  overlay->link_array =
620  GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink)
621  * tc->link_array_size);
622  }
623  break;
624 
625  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
626  {
627  struct TopologyContextUnderlay *underlay;
628 
629  underlay = &tc->u.underlay;
630  underlay->link_array =
631  GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink)
632  * tc->link_array_size);
633  }
634  break;
635  }
636  make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc);
637 }
638 
639 
652 unsigned int
653 GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows,
654  unsigned int **rows_len)
655 {
656  double sq;
657  unsigned int sq_floor;
658  unsigned int _rows;
659  unsigned int *_rows_len;
660  unsigned int x;
661  unsigned int y;
662  unsigned int _num_peers;
663  unsigned int cnt;
664 
665  sq = sqrt (num_peers);
666  sq = floor (sq);
667  sq_floor = (unsigned int) sq;
668  _rows = (sq_floor + 1);
669  _rows_len = GNUNET_malloc (sizeof(unsigned int) * _rows);
670  for (y = 0; y < _rows - 1; y++)
671  _rows_len[y] = sq_floor;
672  _num_peers = sq_floor * sq_floor;
673  cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers;
674  x = 0;
675  y = 0;
676  while (_num_peers < num_peers)
677  {
678  if (x < y)
679  _rows_len[_rows - 1] = ++x;
680  else
681  _rows_len[y++]++;
682  _num_peers++;
683  }
684  cnt += (x < 2) ? x : 2 * x;
685  cnt += (y < 2) ? y : 2 * y;
686  if (0 == _rows_len[_rows - 1])
687  _rows--;
688  if (NULL != rows)
689  *rows = _rows;
690  if (NULL != rows_len)
691  *rows_len = _rows_len;
692  else
693  GNUNET_free (_rows_len);
694  return cnt;
695 }
696 
697 
703 static void
705 {
706  unsigned int rows;
707  unsigned int *rows_len;
708  unsigned int x;
709  unsigned int y;
710  unsigned int cnt;
711  unsigned int offset;
712 
713  tc->link_array_size =
714  GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len);
715  switch (tc->type)
716  {
717  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
718  {
719  struct TopologyContextOverlay *overlay;
720 
721  overlay = &tc->u.overlay;
722  overlay->link_array =
723  GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size);
724  }
725  break;
726 
727  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
728  {
729  struct TopologyContextUnderlay *underlay;
730 
731  underlay = &tc->u.underlay;
732  underlay->link_array =
733  GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size);
734  break;
735  }
736  }
737  cnt = 0;
738  offset = 0;
739  for (y = 0; y < rows; y++)
740  {
741  for (x = 0; x < rows_len[y] - 1; x++)
742  {
743  make_link (cnt, offset + x, offset + x + 1, tc);
744  cnt++;
745  }
746  if (0 == x)
747  break;
748  make_link (cnt, offset + x, offset, tc);
749  cnt++;
750  offset += rows_len[y];
751  }
752  for (x = 0; x < rows_len[0]; x++)
753  {
754  offset = 0;
755  for (y = 0; y < rows - 1; y++)
756  {
757  if (x >= rows_len[y + 1])
758  break;
759  GNUNET_assert (x < rows_len[y + 1]);
760  make_link (cnt, offset + x, offset + rows_len[y] + x, tc);
761  offset += rows_len[y];
762  cnt++;
763  }
764  if (0 == offset)
765  break;
766  make_link (cnt, offset + x, x, tc);
767  cnt++;
768  }
769  GNUNET_assert (cnt == tc->link_array_size);
770  GNUNET_free (rows_len);
771 }
772 
773 
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 !=
819  overlay->link_array));
820  overlay->link_array =
821  GNUNET_realloc (overlay->link_array,
822  sizeof(struct OverlayLink) * tc->link_array_size);
823  break;
824  }
825 
826  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
827  {
828  struct TopologyContextUnderlay *underlay;
829 
830  underlay = &tc->u.underlay;
831  if (GNUNET_YES != append)
832  {
833  GNUNET_assert (NULL == underlay->link_array);
834  underlay->link_array =
835  GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size);
836  break;
837  }
838  GNUNET_assert ((0 < tc->link_array_size) && (NULL !=
839  underlay->link_array));
840  underlay->link_array =
841  GNUNET_realloc (underlay->link_array,
842  sizeof(struct UnderlayLink) * tc->link_array_size);
843  break;
844  }
845  }
846  for (cnt = 0; cnt < links; cnt++)
847  {
848  do
849  {
850  A_rand =
852  B_rand =
854  }
855  while (A_rand == B_rand);
856  make_link (index + cnt, A_rand, B_rand, tc);
857  }
858 }
859 
860 
871 static void
873  uint16_t cap,
874  uint8_t m)
875 {
876  unsigned int *deg;
877  unsigned int *etab;
878  unsigned int *used;
879  unsigned int etaboff;
880  unsigned int cnt;
881  unsigned int cnt2;
882  unsigned int peer;
883  unsigned int random_peer;
884  unsigned int links;
885  unsigned int off;
886  unsigned int redo_threshold;
887 
888  etaboff = 0;
889  tc->link_array_size = tc->num_peers * m;
890  switch (tc->type)
891  {
892  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
893  {
894  struct TopologyContextOverlay *overlay;
895 
896  overlay = &tc->u.overlay;
897  overlay->link_array = GNUNET_malloc_large (sizeof(struct OverlayLink)
898  * tc->link_array_size);
899  }
900  break;
901 
902  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
903  {
904  struct TopologyContextUnderlay *underlay;
905 
906  underlay = &tc->u.underlay;
907  underlay->link_array = GNUNET_malloc_large (sizeof(struct UnderlayLink)
908  * tc->link_array_size);
909  }
910  break;
911  }
912  etab = GNUNET_malloc_large (sizeof(unsigned int) * 2 * tc->link_array_size);
913  deg = GNUNET_malloc (sizeof(unsigned int) * tc->num_peers);
914  used = GNUNET_malloc (sizeof(unsigned int) * m);
915  /* start by connecting peer 1 to peer 0 */
916  make_link (0, 0, 1, tc);
917  deg[0]++;
918  deg[1]++;
919  etab[etaboff++] = 0;
920  etab[etaboff++] = 1;
921  links = 1;
922  for (peer = 2; peer < tc->num_peers; peer++)
923  {
924  if (cap < deg[peer])
925  continue;
926  for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
927  {
928  redo_threshold = 0;
929 redo:
931  random_peer = etab[off];
932  if (cap < deg[random_peer])
933  {
934  if (++redo_threshold > GNUNET_MAX (1, cap / 2))
935  {
936  redo_threshold = 0;
937  off = 0;
938  for (cnt2 = 0; cnt2 < etaboff; cnt2++)
939  {
940  if (random_peer == etab[cnt2])
941  {
942  off++;
943  continue;
944  }
945  etab[cnt2 - off] = etab[cnt2];
946  }
947  etaboff -= off;
948  }
949  goto redo;
950  }
951  for (cnt2 = 0; cnt2 < cnt; cnt2++)
952  if (random_peer == used[cnt2])
953  goto redo;
954  make_link (links + cnt, random_peer, peer, tc);
955  deg[random_peer]++;
956  deg[peer]++;
957  used[cnt] = random_peer;
958  }
959  for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
960  {
961  etab[etaboff++] = used[cnt];
962  etab[etaboff++] = peer;
963  }
964  links += GNUNET_MIN (peer, m);
965  }
966  GNUNET_free (etab);
967  GNUNET_free (used);
968  GNUNET_free (deg);
969  GNUNET_assert (links <= tc->link_array_size);
970  tc->link_array_size = links;
971  switch (tc->type)
972  {
973  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
974  {
975  struct TopologyContextOverlay *overlay;
976 
977  overlay = &tc->u.overlay;
978  overlay->link_array =
979  GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink)
980  * tc->link_array_size);
981  }
982  break;
983 
984  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
985  {
986  struct TopologyContextUnderlay *underlay;
987 
988  underlay = &tc->u.underlay;
989  underlay->link_array =
990  GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink)
991  * tc->link_array_size);
992  }
993  break;
994  }
995 }
996 
997 
1004 static void
1006  const char *filename)
1007 {
1008  char *data;
1009  char *end;
1010  char *buf;
1011  uint64_t fs;
1012  uint64_t offset;
1013  unsigned long int peer_id;
1014  unsigned long int other_peer_id;
1015  enum ParseState
1016  {
1020  PEER_INDEX,
1021 
1025  OTHER_PEER_INDEX,
1026  } state;
1027  int status;
1028 
1029  status = GNUNET_SYSERR;
1030  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1031  {
1033  _ ("Topology file %s not found\n"),
1034  filename);
1035  return;
1036  }
1037  if (GNUNET_OK !=
1038  GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
1039  {
1041  _ ("Topology file %s has no data\n"),
1042  filename);
1043  return;
1044  }
1045  data = GNUNET_malloc (fs);
1046  if (fs != GNUNET_DISK_fn_read (filename, data, fs))
1047  {
1049  _ ("Topology file %s cannot be read\n"),
1050  filename);
1051  goto _exit;
1052  }
1053 
1054  offset = 0;
1055  peer_id = 0;
1056  state = PEER_INDEX;
1057  while (offset < fs)
1058  {
1059  if (0 != isspace ((unsigned char) data[offset]))
1060  {
1061  offset++;
1062  continue;
1063  }
1064  switch (state)
1065  {
1066  case PEER_INDEX:
1067  buf = strchr (&data[offset], ':');
1068  if (NULL == buf)
1069  {
1071  _ ("Failed to read peer index from toology file: %s"), filename);
1072  goto _exit;
1073  }
1074  *buf = '\0';
1075  errno = 0;
1076  peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1077  if (0 != errno)
1078  {
1080  _ ("Value in given topology file: %s out of range\n"), filename);
1081  goto _exit;
1082  }
1083  if (&data[offset] == end)
1084  {
1086  _ ("Failed to read peer index from topology file: %s"), filename);
1087  goto _exit;
1088  }
1089  if (tc->num_peers <= peer_id)
1090  {
1092  _ ("Topology file needs more peers than given ones\n"), filename);
1093  goto _exit;
1094  }
1095  state = OTHER_PEER_INDEX;
1096  offset += ((unsigned int) (buf - &data[offset])) + 1;
1097  break;
1098 
1099  case OTHER_PEER_INDEX:
1100  errno = 0;
1101  other_peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
1102  if (0 != errno)
1103  {
1105  _ ("Value in given topology file: %s out of range\n"), filename);
1106  goto _exit;
1107  }
1108  if (&data[offset] == end)
1109  {
1111  _ ("Failed to read peer index from topology file: %s"), filename);
1112  goto _exit;
1113  }
1114  if (tc->num_peers <= other_peer_id)
1115  {
1117  _ ("Topology file needs more peers than given ones\n"), filename);
1118  goto _exit;
1119  }
1120  if (peer_id != other_peer_id)
1121  {
1122  tc->link_array_size++;
1123  switch (tc->type)
1124  {
1125  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1126  {
1127  struct TopologyContextOverlay *overlay;
1128 
1129  overlay = &tc->u.overlay;
1130  overlay->link_array =
1131  GNUNET_realloc (overlay->link_array,
1132  sizeof(struct OverlayLink) * tc->link_array_size);
1133  }
1134  break;
1135 
1136  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1137  {
1138  struct TopologyContextUnderlay *underlay;
1139 
1140  underlay = &tc->u.underlay;
1141  underlay->link_array =
1142  GNUNET_realloc (underlay->link_array,
1143  sizeof(struct UnderlayLink)
1144  * tc->link_array_size);
1145  }
1146  break;
1147  }
1148  offset += end - &data[offset];
1149  make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc);
1150  }
1151  else
1153  _ ("Ignoring to connect peer %u to peer %u\n"),
1154  peer_id,
1155  other_peer_id);
1156  while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs))
1157  offset++;
1158  if ((offset < fs) &&
1159  ('\n' == data[offset]))
1160  state = PEER_INDEX;
1161  else if ((offset < fs) &&
1162  ('|' == data[offset]))
1163  {
1164  state = OTHER_PEER_INDEX;
1165  offset++;
1166  }
1167  break;
1168  }
1169  }
1170  status = GNUNET_OK;
1171 
1172 _exit:
1173  GNUNET_free (data);
1174  if (GNUNET_OK != status)
1175  {
1177  "Removing link data read from the file\n");
1178  tc->link_array_size = 0;
1179  switch (tc->type)
1180  {
1181  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1182  {
1183  struct TopologyContextOverlay *overlay;
1184 
1185  overlay = &tc->u.overlay;
1186  GNUNET_free_non_null (overlay->link_array);
1187  overlay->link_array = NULL;
1188  }
1189  break;
1190 
1191  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1192  {
1193  struct TopologyContextUnderlay *underlay;
1194 
1195  underlay = &tc->u.underlay;
1196  GNUNET_free_non_null (underlay->link_array);
1197  underlay->link_array = NULL;
1198  }
1199  break;
1200  }
1201  }
1202 }
1203 
1204 
1210 static void
1212 {
1213  unsigned int cnt;
1214  unsigned int offset;
1215  unsigned int neighbour;
1216 
1217  tc->link_array_size = tc->num_peers * (tc->num_peers - 1);
1218  switch (tc->type)
1219  {
1220  case TOPOLOGYCONTEXT_TYPE_OVERLAY:
1221  {
1222  struct TopologyContextOverlay *overlay;
1223 
1224  overlay = &tc->u.overlay;
1226  struct OverlayLink);
1227  }
1228  break;
1229 
1230  case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
1231  {
1232  struct TopologyContextUnderlay *underlay;
1233 
1234  underlay = &tc->u.underlay;
1235  underlay->link_array = GNUNET_new_array (tc->link_array_size,
1236  struct UnderlayLink);
1237  }
1238  }
1239  offset = 0;
1240  for (cnt = 0; cnt < tc->num_peers; cnt++)
1241  {
1242  for (neighbour = 0; neighbour < tc->num_peers; neighbour++)
1243  {
1244  if (neighbour == cnt)
1245  continue;
1246  make_link (offset, cnt, neighbour, tc);
1247  offset++;
1248  }
1249  }
1250 }
1251 
1252 
1264 struct GNUNET_TESTBED_Operation *
1266  unsigned int num_peers,
1267  struct GNUNET_TESTBED_Peer
1268  **peers,
1269  enum
1271  topo, va_list ap)
1272 {
1273  GNUNET_break (0);
1274  return NULL;
1275 }
1276 
1277 
1289 struct GNUNET_TESTBED_Operation *
1291  unsigned int num_peers,
1292  struct GNUNET_TESTBED_Peer **peers,
1294  topo, ...)
1295 {
1296  GNUNET_break (0);
1297  return NULL;
1298 }
1299 
1300 
1321 struct GNUNET_TESTBED_Operation *
1323  unsigned int num_peers,
1324  struct GNUNET_TESTBED_Peer **peers,
1325  unsigned int *max_connections,
1327  comp_cb,
1328  void *comp_cb_cls,
1330  topo,
1331  va_list va)
1332 {
1333  struct TopologyContext *tc;
1334  struct TopologyContextOverlay *overlay;
1335  struct GNUNET_TESTBED_Operation *op;
1336  struct GNUNET_TESTBED_Controller *c;
1337  enum GNUNET_TESTBED_TopologyOption secondary_option;
1338 
1339  if (num_peers < 2)
1340  return NULL;
1341  c = peers[0]->controller;
1342  tc = GNUNET_new (struct TopologyContext);
1343  tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY;
1344  overlay = &tc->u.overlay;
1345  overlay->peers = peers;
1346  tc->num_peers = num_peers;
1347  overlay->op_cls = op_cls;
1348  overlay->retry_cnt = DEFAULT_RETRY_CNT;
1349  overlay->comp_cb = comp_cb;
1350  overlay->comp_cb_cls = comp_cb_cls;
1351  switch (topo)
1352  {
1354  gen_topo_line (tc);
1355  break;
1356 
1358  gen_topo_star (tc);
1359  break;
1360 
1362  gen_topo_ring (tc);
1363  break;
1364 
1366  gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_NO);
1367  break;
1368 
1370  gen_topo_ring (tc);
1371  gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1372  break;
1373 
1375  gen_topo_clique (tc);
1376  break;
1377 
1379  gen_topo_2dtorus (tc);
1380  break;
1381 
1383  gen_topo_2dtorus (tc);
1384  gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
1385 
1386  break;
1387 
1389  {
1390  uint16_t cap;
1391  uint8_t m;
1392 
1393  cap = (uint16_t) va_arg (va, unsigned int);
1394  m = (uint8_t) va_arg (va, unsigned int);
1395  gen_topo_scale_free (tc, cap, m);
1396  }
1397  break;
1398 
1400  {
1401  const char *filename;
1402 
1403  filename = va_arg (va, const char *);
1404 
1405  GNUNET_assert (NULL != filename);
1406  gen_topo_from_file (tc, filename);
1407  }
1408  break;
1409 
1410  default:
1411  GNUNET_break (0);
1412  GNUNET_free (tc);
1413  return NULL;
1414  }
1415  do
1416  {
1417  secondary_option = GNUNET_VA_ARG_ENUM (va, GNUNET_TESTBED_TopologyOption);
1418 
1419  switch (secondary_option)
1420  {
1422  overlay->retry_cnt = va_arg (va, unsigned int);
1423  break;
1424 
1426  break;
1427 
1428  default:
1429  GNUNET_break (0); /* Should not use any other option apart from
1430  * the ones handled here */
1431  GNUNET_free_non_null (overlay->link_array);
1432  GNUNET_free (tc);
1433  return NULL;
1434  }
1435  }
1436  while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option);
1444  "Generated %u connections\n",
1445  tc->link_array_size);
1446  if (NULL != max_connections)
1447  *max_connections = tc->link_array_size;
1448  return op;
1449 }
1450 
1451 
1472 struct GNUNET_TESTBED_Operation *
1474  unsigned int num_peers,
1475  struct GNUNET_TESTBED_Peer **peers,
1476  unsigned int *max_connections,
1478  comp_cb,
1479  void *comp_cb_cls,
1481  topo,
1482  ...)
1483 {
1484  struct GNUNET_TESTBED_Operation *op;
1485  va_list vargs;
1486 
1488  va_start (vargs, topo);
1489  op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers,
1490  max_connections,
1491  comp_cb, comp_cb_cls,
1492  topo,
1493  vargs);
1494  va_end (vargs);
1495  return op;
1496 }
1497 
1498 
1508 int
1510  const char *topology_string)
1511 {
1512  unsigned int cnt;
1513 
1514  for (cnt = 0; NULL != topology_strings[cnt]; cnt++)
1515  {
1516  if (0 == strcasecmp (topology_string, topology_strings[cnt]))
1517  {
1518  if (NULL != topology)
1519  *topology = (enum GNUNET_TESTBED_TopologyOption) cnt;
1521  (enum GNUNET_TESTBED_TopologyOption) cnt);
1522  return GNUNET_YES;
1523  }
1524  }
1525  return GNUNET_NO;
1526 }
1527 
1528 
1536 char *
1538 {
1539  if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology)
1540  return NULL;
1541  return GNUNET_strdup (topology_strings[topology]);
1542 }
1543 
1544 
1561 int
1564  void *cls,
1565  ...)
1566 {
1567  struct TopologyContext tc;
1568  struct TopologyContextUnderlay *underlay;
1569  struct UnderlayLink *ulink;
1570  va_list vargs;
1572  unsigned int cnt;
1573  int ret;
1574 
1575  GNUNET_assert (NULL != proc);
1576  ret = GNUNET_OK;
1577  memset (&tc, 0, sizeof(tc));
1578  tc.num_peers = num_peers;
1579  tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY;
1580  underlay = &tc.u.underlay;
1581  va_start (vargs, cls);
1583  switch (topology)
1584  {
1586  gen_topo_line (&tc);
1587  break;
1588 
1590  gen_topo_star (&tc);
1591  break;
1592 
1594  gen_topo_ring (&tc);
1595  break;
1596 
1598  gen_topo_clique (&tc);
1599  break;
1600 
1602  gen_topo_2dtorus (&tc);
1603  break;
1604 
1606  gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO);
1607  break;
1608 
1610  gen_topo_ring (&tc);
1611  gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1612  break;
1613 
1615  gen_topo_2dtorus (&tc);
1616  gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
1617  break;
1618 
1620  {
1621  const char *filename;
1622  filename = va_arg (vargs, char *);
1623  GNUNET_assert (NULL != filename);
1624  gen_topo_from_file (&tc, filename);
1625  }
1626  break;
1627 
1629  {
1630  uint16_t cap;
1631  uint8_t m;
1632  cap = (uint16_t) va_arg (vargs, unsigned int);
1633  m = (uint8_t) va_arg (vargs, unsigned int);
1634  gen_topo_scale_free (&tc, cap, m);
1635  }
1636  break;
1637 
1638  default:
1639  GNUNET_assert (0);
1640  }
1641  va_end (vargs);
1642  for (cnt = 0; cnt < tc.link_array_size; cnt++)
1643  {
1644  ulink = &underlay->link_array[cnt];
1645  if (GNUNET_SYSERR == proc (cls,
1646  ulink->A,
1647  ulink->B,
1648  ulink->bandwidth,
1649  ulink->latency,
1650  ulink->loss))
1651  {
1652  ret = GNUNET_SYSERR;
1653  break;
1654  }
1655  }
1656  GNUNET_free_non_null (underlay->link_array);
1657  return ret;
1658 }
1659 
1660 
1661 /* 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:544
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:193
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.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
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.
#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:104
Read a topology from a given file.
enum TopologyContext::@70 type
The type of this context.
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:2044
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:254
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
union TopologyContext::@71 u
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:257
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.
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:794
#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).