GNUnet  0.19.4
gnunet-rps-profiler.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2012 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  */
27 #include "platform.h"
28 // #include "rps_test_lib.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_testbed_service.h"
31 
32 #include "gnunet_rps_service.h"
33 #include "rps-test_util.h"
35 
36 #include <inttypes.h>
37 
38 
39 #define BIT(n) (1 << (n))
40 
44 static uint32_t num_peers;
45 
49 static unsigned bits_needed;
50 
54 static struct GNUNET_TIME_Relative duration;
55 
59 static struct GNUNET_TIME_Relative timeout;
60 
61 
62 // /**
63 // * Portion of malicious peers
64 // */
65 // static double portion = .1;
66 
70 static unsigned int mal_type = 0;
71 
76 
78 {
111  STAT_TYPE_MAX, /* 32 */
112 };
113 
114 static char*stat_type_strings[] = {
115  "# rounds",
116  "# rounds blocked",
117  "# rounds blocked - too many pushes",
118  "# rounds blocked - no pushes",
119  "# rounds blocked - no pull replies",
120  "# rounds blocked - too many pushes, no pull replies",
121  "# rounds blocked - no pushes, no pull replies",
122  "# push send issued",
123  "# push send issued (multi-hop peer)",
124  "# pull request send issued",
125  "# pull request send issued (multi-hop peer)",
126  "# pull reply send issued",
127  "# pushes sent",
128  "# pull requests sent",
129  "# pull requests sent (multi-hop peer)",
130  "# pull replies sent",
131  "# push message received",
132  "# push message received (multi-hop peer)",
133  "# pull request message received",
134  "# pull request message received (multi-hop peer)",
135  "# pull reply messages received",
136  "# pull reply messages received (multi-hop peer)",
137  "view size",
138  "# known peers",
139  "# valid peers",
140  "# learnd peers",
141  "# pending online checks",
142  "# unrequested pull replies",
143  "# peers in push map at end of round",
144  "# peers in pull map at end of round",
145  "# peers in view at end of round",
146  "view size aim",
147 };
148 
149 struct STATcls
150 {
151  struct RPSPeer *rps_peer;
152  enum STAT_TYPE stat_type;
153 };
154 
155 
163 enum STAT_TYPE
164 stat_str_2_type (const char *stat_str)
165 {
166  if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS_NO_PULL],
167  stat_str,
169  {
171  }
173  stat_str,
174  strlen (
176  {
178  }
179  else if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS_MANY_PUSH],
180  stat_str,
181  strlen (
183  {
185  }
186  else if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL],
187  stat_str,
188  strlen (
190  {
192  }
193  else if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS_NO_PUSH],
194  stat_str,
196  {
198  }
199  else if (0 == strncmp (stat_type_strings[STAT_TYPE_BLOCKS],
200  stat_str,
202  {
203  return STAT_TYPE_BLOCKS;
204  }
205  else if (0 == strncmp (stat_type_strings[STAT_TYPE_ROUNDS],
206  stat_str,
208  {
209  return STAT_TYPE_ROUNDS;
210  }
211  else if (0 == strncmp (stat_type_strings[STAT_TYPE_ISSUED_PUSH_SEND],
212  stat_str,
213  strlen (
215  {
217  }
218  else if (0 == strncmp (stat_type_strings[STAT_TYPE_ISSUED_PUSH_SEND_MH],
219  stat_str,
220  strlen (
222  {
224  }
225  else if (0 == strncmp (stat_type_strings[STAT_TYPE_ISSUED_PULL_REQ],
226  stat_str,
228  {
230  }
231  else if (0 == strncmp (stat_type_strings[STAT_TYPE_ISSUED_PULL_REQ_MH],
232  stat_str,
233  strlen (
235  {
237  }
238  else if (0 == strncmp (stat_type_strings[STAT_TYPE_ISSUED_PULL_REP],
239  stat_str,
241  {
243  }
244  else if (0 == strncmp (stat_type_strings[STAT_TYPE_SENT_PUSH_SEND],
245  stat_str,
247  {
249  }
250  else if (0 == strncmp (stat_type_strings[STAT_TYPE_SENT_PULL_REQ],
251  stat_str,
253  {
255  }
256  else if (0 == strncmp (stat_type_strings[STAT_TYPE_SENT_PULL_REQ_MH],
257  stat_str,
258  strlen (
260  {
262  }
263  else if (0 == strncmp (stat_type_strings[STAT_TYPE_SENT_PULL_REP],
264  stat_str,
266  {
268  }
269  else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PUSH_SEND],
270  stat_str,
272  {
274  }
275  else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PUSH_SEND_MH],
276  stat_str,
277  strlen (
279  {
281  }
282  else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PULL_REQ],
283  stat_str,
285  {
287  }
288  else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PULL_REQ_MH],
289  stat_str,
290  strlen (
292  {
294  }
295  else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PULL_REP],
296  stat_str,
298  {
300  }
301  else if (0 == strncmp (stat_type_strings[STAT_TYPE_RECV_PULL_REP_MH],
302  stat_str,
303  strlen (
305  {
307  }
308  else if (0 == strncmp (stat_type_strings[STAT_TYPE_VIEW_SIZE],
309  stat_str,
311  {
312  return STAT_TYPE_VIEW_SIZE;
313  }
314  else if (0 == strncmp (stat_type_strings[STAT_TYPE_KNOWN_PEERS],
315  stat_str,
317  {
318  return STAT_TYPE_KNOWN_PEERS;
319  }
320  else if (0 == strncmp (stat_type_strings[STAT_TYPE_VALID_PEERS],
321  stat_str,
323  {
324  return STAT_TYPE_VALID_PEERS;
325  }
326  else if (0 == strncmp (stat_type_strings[STAT_TYPE_LEARND_PEERS],
327  stat_str,
329  {
330  return STAT_TYPE_LEARND_PEERS;
331  }
332  else if (0 == strncmp (stat_type_strings[STAT_TYPE_PENDING_ONLINE_CHECKS],
333  stat_str,
334  strlen (
336  {
338  }
340  stat_str,
341  strlen (
343  {
345  }
346  else if (0 == strncmp (stat_type_strings[STAT_TYPE_PEERS_IN_PUSH_MAP],
347  stat_str,
348  strlen (
350  {
352  }
353  else if (0 == strncmp (stat_type_strings[STAT_TYPE_PEERS_IN_PULL_MAP],
354  stat_str,
355  strlen (
357  {
359  }
360  else if (0 == strncmp (stat_type_strings[STAT_TYPE_PEERS_IN_VIEW],
361  stat_str,
363  {
365  }
366  else if (0 == strncmp (stat_type_strings[STAT_TYPE_VIEW_SIZE_AIM],
367  stat_str,
369  {
371  }
372  return STAT_TYPE_MAX;
373 }
374 
375 
380 {
389 };
390 
394 struct OpListEntry
395 {
399  struct OpListEntry *next;
400 
404  struct OpListEntry *prev;
405 
410 
416 
420  unsigned int index;
421 };
422 
426 static struct OpListEntry *oplist_head;
427 
431 static struct OpListEntry *oplist_tail;
432 
433 
438 {
444 
449 
453  struct RPSPeer *rps_peer;
454 };
455 
456 
461 {
467 
472 
476  struct RPSPeer *rps_peer;
477 };
478 
479 
483 struct RPSPeer
484 {
488  uint32_t index;
489 
494 
499 
504 
508  // struct GNUNET_RPS_Request_Handle *req_handle;
509 
513  int online;
514 
518  unsigned int num_ids_to_request;
519 
525 
529  unsigned int num_pending_reqs;
530 
536 
540  unsigned int num_pending_reps;
541 
545  unsigned int num_recv_ids;
546 
551 
556 
561 
568 
572  const char *file_name_stats;
573 
577  const char *file_name_probs;
578 
582  const char *file_name_probs_hist;
583 
588 
592  uint32_t cur_view_count;
593 
597  uint32_t count_in_views;
598 
602  uint64_t stats[STAT_TYPE_MAX];
607 
613 };
614 
618 static struct RPSPeer *rps_peers;
619 
624 
629 
634 
638 static unsigned int num_peers_online;
639 
643 static unsigned int view_sizes;
644 
648 static int ok;
649 
654 
659 
660 
665 
669 typedef void (*InitPeer) (struct RPSPeer *rps_peer);
670 
677 typedef void (*PreTest) (struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h);
678 
688 typedef void (*MainTest) (struct RPSPeer *rps_peer);
689 
693 typedef void (*ReplyHandle) (void *cls,
694  uint64_t n,
695  const struct GNUNET_PeerIdentity *recv_peers);
696 
700 typedef void (*PostTest) (struct RPSPeer *peer);
701 
705 typedef int (*EvaluationCallback) (void);
706 
711 {
720 };
721 
726 {
731 
736 };
737 
742 {
747 
752 };
753 
758 {
763 
768 };
769 
774 {
778  char *name;
779 
784 
789 
794 
799 
804 
809 
814 
818  uint32_t num_requests;
819 
824 
829 
834 
839 
846 
850 static int post_test;
851 
855 static int in_shutdown;
856 
860 static void
861 tofile_ (const char *file_name, const char *line)
862 {
863  struct GNUNET_DISK_FileHandle *f;
864  /* char output_buffer[512]; */
865  size_t size;
866  /* int size; */
867  size_t size2;
868 
869  if (NULL == (f = GNUNET_DISK_file_open (file_name,
877  {
879  "Not able to open file %s\n",
880  file_name);
881  return;
882  }
883  /* size = GNUNET_snprintf (output_buffer,
884  sizeof (output_buffer),
885  "%llu %s\n",
886  GNUNET_TIME_absolute_get ().abs_value_us,
887  line);
888  if (0 > size)
889  {
890  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
891  "Failed to write string to buffer (size: %i)\n",
892  size);
893  return;
894  } */size = strlen (line) * sizeof(char);
895 
896  size2 = GNUNET_DISK_file_write (f, line, size);
897  if (size != size2)
898  {
900  "Unable to write to file! (Size: %lu, size2: %lu)\n",
901  size,
902  size2);
904  {
906  "Unable to close file\n");
907  }
908  return;
909  }
910 
912  {
914  "Unable to close file\n");
915  }
916 }
917 
918 
922 #define tofile(file_name, ...) do { \
923  char tmp_buf[512]; \
924  int size; \
925  size = GNUNET_snprintf (tmp_buf, sizeof(tmp_buf), __VA_ARGS__); \
926  if (0 > size) \
927  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
928  "Failed to create tmp_buf\n"); \
929  else \
930  tofile_ (file_name, tmp_buf); \
931 } while (0);
932 
933 
938 /* static void
939  ids_to_file (char *file_name,
940  struct GNUNET_PeerIdentity *peer_ids,
941  unsigned int num_peer_ids)
942  {
943  unsigned int i;
944 
945  for (i=0 ; i < num_peer_ids ; i++)
946  {
947  to_file (file_name,
948  "%u\t%s",
949  i,
950  GNUNET_i2s_full (&peer_ids[i]));
951  }
952  } */
953 
957 static int
958 evaluate (void)
959 {
960  unsigned int i;
961  int tmp_ok;
962 
963  tmp_ok = 1;
964 
965  for (i = 0; i < num_peers; i++)
966  {
968  "%u. peer [%s] received %u of %u expected peer_ids: %i\n",
969  i,
971  rps_peers[i].num_recv_ids,
972  rps_peers[i].num_ids_to_request,
973  (rps_peers[i].num_ids_to_request == rps_peers[i].num_recv_ids));
974  tmp_ok &= (rps_peers[i].num_ids_to_request == rps_peers[i].num_recv_ids);
975  }
976  return tmp_ok ? 0 : 1;
977 }
978 
979 
983 static struct OpListEntry *
985 {
986  struct OpListEntry *entry;
987 
988  entry = GNUNET_new (struct OpListEntry);
990  return entry;
991 }
992 
993 
1003 static int
1005  const struct RPSPeer *rps_peer)
1006 {
1009  & rps_peer->stat_collected_flags))
1010  {
1011  return GNUNET_NO;
1012  }
1013  return GNUNET_YES;
1014 }
1015 
1016 
1024 static int
1026 {
1027  uint32_t i;
1028 
1029  for (i = 0; i < num_peers; i++)
1030  {
1032  &rps_peers[i]))
1033  {
1035  "At least Peer %" PRIu32
1036  " did not yet receive all statistics values\n",
1037  i);
1038  return GNUNET_NO;
1039  }
1040  }
1042  "All peers received their statistics values\n");
1043  return GNUNET_YES;
1044 }
1045 
1046 
1047 static void
1048 rps_disconnect_adapter (void *cls,
1049  void *op_result);
1050 
1051 static void
1052 cancel_pending_req (struct PendingRequest *pending_req)
1053 {
1054  struct RPSPeer *rps_peer;
1055 
1056  rps_peer = pending_req->rps_peer;
1058  rps_peer->pending_req_tail,
1059  pending_req);
1060  rps_peer->num_pending_reqs--;
1062  "Cancelling pending rps get request\n");
1063  GNUNET_SCHEDULER_cancel (pending_req->request_task);
1064  GNUNET_free (pending_req);
1065 }
1066 
1067 
1068 static void
1069 cancel_request (struct PendingReply *pending_rep)
1070 {
1071  struct RPSPeer *rps_peer;
1072 
1073  rps_peer = pending_rep->rps_peer;
1075  rps_peer->pending_rep_tail,
1076  pending_rep);
1077  rps_peer->num_pending_reps--;
1079  "Cancelling rps get reply\n");
1080  GNUNET_assert (NULL != pending_rep->req_handle);
1082  pending_rep->req_handle = NULL;
1083  GNUNET_free (pending_rep);
1084  pending_rep = NULL;
1085 }
1086 
1087 
1088 void
1089 clean_peer (unsigned peer_index)
1090 {
1091  struct PendingRequest *pending_req;
1092 
1093  while (NULL != (pending_req = rps_peers[peer_index].pending_req_head))
1094  {
1095  cancel_pending_req (pending_req);
1096  }
1097  pending_req = rps_peers[peer_index].pending_req_head;
1098  rps_disconnect_adapter (&rps_peers[peer_index],
1099  &rps_peers[peer_index].rps_handle);
1100  for (unsigned stat_type = STAT_TYPE_ROUNDS;
1101  stat_type < STAT_TYPE_MAX;
1102  stat_type++)
1103  {
1104  if (NULL != rps_peers[peer_index].h_stat_get[stat_type])
1105  {
1107  "(%u) did not yet receive stat value for `%s'\n",
1108  rps_peers[peer_index].index,
1109  stat_type_strings[stat_type]);
1111  rps_peers[peer_index].h_stat_get[stat_type]);
1112  }
1113  }
1114  if (NULL != rps_peers[peer_index].op)
1115  {
1117  rps_peers[peer_index].op = NULL;
1118  }
1119 }
1120 
1121 
1125 static void
1126 shutdown_op (void *cls)
1127 {
1128  unsigned int i;
1129  struct OpListEntry *entry;
1130 
1131  (void) cls;
1132 
1134  "Shutdown task scheduled, going down.\n");
1136 
1137  if (NULL != shutdown_task)
1138  {
1140  shutdown_task = NULL;
1141  }
1142  if (NULL != post_test_task)
1143  {
1145  post_test_task = NULL;
1146  }
1147  if (NULL != churn_task)
1148  {
1150  churn_task = NULL;
1151  }
1152  entry = oplist_head;
1153  while (NULL != (entry = oplist_head))
1154  {
1156  "Operation still pending on shutdown (%u)\n",
1157  entry->index);
1160  GNUNET_free (entry);
1161  }
1162  for (i = 0; i < num_peers; i++)
1163  {
1164  clean_peer (i);
1165  }
1166  close_all_files ();
1167 }
1168 
1169 
1170 static void
1171 trigger_shutdown (void *cls)
1172 {
1173  (void) cls;
1174 
1176  "Shutdown was triggered by timeout, going down.\n");
1177  shutdown_task = NULL;
1179 }
1180 
1181 
1185 static void
1186 post_test_op (void *cls)
1187 {
1188  unsigned int i;
1189 
1190  (void) cls;
1191 
1192  post_test_task = NULL;
1195  "Executing post test op.\n");
1196  if (NULL != churn_task)
1197  {
1199  churn_task = NULL;
1200  }
1201  for (i = 0; i < num_peers; i++)
1202  {
1204  "Executing post test op. (peer %" PRIu32 ")\n",
1205  rps_peers[i].index);
1206  if (NULL != rps_peers[i].op)
1207  {
1209  rps_peers[i].op = NULL;
1211  "Cancelled testbed operation\n");
1212  }
1213  if (NULL != cur_test_run.post_test)
1214  {
1215  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing post_test for peer %u\n",
1216  i);
1218  }
1219  }
1220  /* If we do not collect statistics, shut down directly */
1223  {
1225  shutdown_task = NULL;
1227  }
1228 }
1229 
1230 
1234 void
1235 info_cb (void *cb_cls,
1236  struct GNUNET_TESTBED_Operation *op,
1237  const struct GNUNET_TESTBED_PeerInformation *pinfo,
1238  const char *emsg)
1239 {
1240  struct OpListEntry *entry = (struct OpListEntry *) cb_cls;
1241 
1242  (void) op;
1243 
1244  if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1245  {
1246  return;
1247  }
1248 
1249  if ((NULL == pinfo) || (NULL != emsg))
1250  {
1251  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
1253  return;
1254  }
1255 
1257  "Peer %u is %s\n",
1258  entry->index,
1259  GNUNET_i2s (pinfo->result.id));
1260 
1261  rps_peer_ids[entry->index] = *(pinfo->result.id);
1262  rps_peers[entry->index].peer_id = &rps_peer_ids[entry->index];
1263 
1266  &rps_peer_ids[entry->index],
1267  &rps_peers[entry->index],
1269  tofile ("/tmp/rps/peer_ids",
1270  "%u\t%s\n",
1271  entry->index,
1272  GNUNET_i2s_full (&rps_peer_ids[entry->index]));
1273 
1276  GNUNET_free (entry);
1277 }
1278 
1279 
1289 static void
1291  struct GNUNET_TESTBED_Operation *op,
1292  void *ca_result,
1293  const char *emsg)
1294 {
1295  struct RPSPeer *rps_peer = cls;
1296  struct GNUNET_RPS_Handle *rps = ca_result;
1297 
1298  if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1299  {
1300  return;
1301  }
1302 
1303  rps_peer->rps_handle = rps;
1304  rps_peer->online = GNUNET_YES;
1305  num_peers_online++;
1306 
1307  GNUNET_assert (op == rps_peer->op);
1308  if (NULL != emsg)
1309  {
1311  "Failed to connect to RPS service: %s\n",
1312  emsg);
1313  ok = 1;
1315  return;
1316  }
1317 
1319  "Started client successfully (%u)\n",
1320  rps_peer->index);
1321 
1322  cur_test_run.main_test (rps_peer);
1323 }
1324 
1325 
1336 static void *
1338  const struct GNUNET_CONFIGURATION_Handle *cfg)
1339 {
1340  struct GNUNET_RPS_Handle *h;
1341 
1342  h = GNUNET_RPS_connect (cfg);
1343 
1344  if (NULL != cur_test_run.pre_test)
1345  cur_test_run.pre_test (cls, h);
1346 
1347  return h;
1348 }
1349 
1350 
1360 static void *
1362  const struct GNUNET_CONFIGURATION_Handle *cfg)
1363 {
1364  struct RPSPeer *peer = cls;
1365 
1366  peer->stats_h = GNUNET_STATISTICS_create ("rps-profiler", cfg);
1367  return peer->stats_h;
1368 }
1369 
1370 
1377 static void
1379 {
1380  struct RPSPeer *peer = cls;
1381 
1382  // GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
1383  // (peer->stats_h, "core", "# peers connected",
1384  // stat_iterator, peer));
1385  // GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel
1386  // (peer->stats_h, "nse", "# peers connected",
1387  // stat_iterator, peer));
1389  peer->stats_h = NULL;
1390 }
1391 
1392 
1403 static void
1404 stat_complete_cb (void *cls,
1405  struct GNUNET_TESTBED_Operation *op,
1406  void *ca_result,
1407  const char *emsg)
1408 {
1409  // struct GNUNET_STATISTICS_Handle *sh = ca_result;
1410  // struct RPSPeer *peer = (struct RPSPeer *) cls;
1411  (void) cls;
1412  (void) op;
1413  (void) ca_result;
1414 
1415  if (NULL != emsg)
1416  {
1417  GNUNET_break (0);
1418  return;
1419  }
1420  // GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
1421  // (sh, "core", "# peers connected",
1422  // stat_iterator, peer));
1423  // GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch
1424  // (sh, "nse", "# peers connected",
1425  // stat_iterator, peer));
1426 }
1427 
1428 
1436 static void
1438  void *op_result)
1439 {
1440  struct RPSPeer *peer = cls;
1441  struct GNUNET_RPS_Handle *h = op_result;
1442  struct PendingReply *pending_rep;
1443 
1445  "disconnect_adapter (%u)\n",
1446  peer->index);
1447  GNUNET_assert (NULL != peer);
1448  if (NULL != peer->rps_handle)
1449  {
1450  while (NULL != (pending_rep = peer->pending_rep_head))
1451  {
1452  cancel_request (pending_rep);
1453  }
1454  GNUNET_assert (h == peer->rps_handle);
1455  if (NULL != h)
1456  {
1458  h = NULL;
1459  }
1460  peer->rps_handle = NULL;
1461  }
1462 }
1463 
1464 
1465 /***********************************************************************
1466 * Definition of tests
1467 ***********************************************************************/
1468 
1476 static void
1478  uint64_t n,
1479  const struct GNUNET_PeerIdentity *recv_peers)
1480 {
1481  struct RPSPeer *rps_peer;
1482  struct PendingReply *pending_rep = (struct PendingReply *) cls;
1483  unsigned int i;
1484 
1485  rps_peer = pending_rep->rps_peer;
1488  pending_rep);
1491  "[%s] got %" PRIu64 " peers:\n",
1493  n);
1494 
1495  for (i = 0; i < n; i++)
1496  {
1498  "%u: %s\n",
1499  i,
1500  GNUNET_i2s (&recv_peers[i]));
1501 
1503  }
1504 
1505  if (GNUNET_YES != post_test)
1506  return;
1508  return;
1509  if (0 == evaluate ())
1510  {
1512  "Test succeeded before end of duration\n");
1513  if (NULL != post_test_task)
1516  GNUNET_assert (NULL != post_test_task);
1517  }
1518 }
1519 
1520 
1521 static void
1522 profiler_reply_handle_info (void *cls,
1523  const struct GNUNET_PeerIdentity *recv_peer,
1524  double probability,
1525  uint32_t num_observed);
1526 
1530 static void
1531 request_peers (void *cls)
1532 {
1533  struct PendingRequest *pending_req = cls;
1534  struct RPSPeer *rps_peer;
1535  struct PendingReply *pending_rep;
1536 
1537  rps_peer = pending_req->rps_peer;
1541  pending_req);
1543  if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1544  return;
1546  "Requesting one peer\n");
1547  pending_rep = GNUNET_new (struct PendingReply);
1548  pending_rep->rps_peer = rps_peer;
1549  // pending_rep->req_handle = GNUNET_RPS_request_peers (rps_peer->rps_handle,
1550  // 1,
1551  // cur_test_run.reply_handle,
1552  // pending_rep);
1555  pending_rep);
1558  pending_rep);
1560 }
1561 
1562 
1567 void
1569 {
1570  unsigned int i;
1571  struct PendingRequest *pending_req;
1572 
1574  "Scheduling %u - %u missing requests\n",
1580  i < rps_peer->num_ids_to_request; i++)
1581  {
1582  pending_req = GNUNET_new (struct PendingRequest);
1583  pending_req->rps_peer = rps_peer;
1587  request_peers,
1588  pending_req);
1591  pending_req);
1593  }
1594 }
1595 
1596 
1597 void
1599 {
1601  "Cancelling all (pending) requests.\n");
1602  while (NULL != rps_peer->pending_req_head)
1605  while (NULL != rps_peer->pending_rep_head)
1608 }
1609 
1610 
1611 /***********************************
1612 * MALICIOUS
1613 ***********************************/
1614 
1616 // * Initialise only non-mal RPSPeers
1617 // */
1618 //static void
1619 //mal_init_peer (struct RPSPeer *rps_peer)
1620 //{
1621 // if (rps_peer->index >= round (portion * num_peers))
1622 // rps_peer->num_ids_to_request = 1;
1623 //}
1624 
1625 
1627 // * @brief Set peers to (non-)malicious before execution
1628 // *
1629 // * Of signature #PreTest
1630 // *
1631 // * @param rps_peer the peer to set (non-) malicious
1632 // * @param h the handle to the service
1633 // */
1634 //static void
1635 //mal_pre (struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h)
1636 //{
1637 // #if ENABLE_MALICIOUS
1638 // uint32_t num_mal_peers;
1639 //
1640 // GNUNET_assert ((1 >= portion) &&
1641 // (0 < portion));
1642 // num_mal_peers = round (portion * num_peers);
1643 //
1644 // if (rps_peer->index < num_mal_peers)
1645 // {
1646 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1647 // "%u. peer [%s] of %" PRIu32
1648 // " malicious peers turning malicious\n",
1649 // rps_peer->index,
1650 // GNUNET_i2s (rps_peer->peer_id),
1651 // num_mal_peers);
1652 //
1653 // GNUNET_RPS_act_malicious (h, mal_type, num_mal_peers,
1654 // rps_peer_ids, target_peer);
1655 // }
1656 // #endif /* ENABLE_MALICIOUS */
1657 //}
1658 
1659 
1660 // static void
1661 // mal_cb (struct RPSPeer *rps_peer)
1662 // {
1663 // if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1664 // {
1665 // return;
1666 // }
1667 //
1668 // #if ENABLE_MALICIOUS
1669 // uint32_t num_mal_peers;
1670 //
1671 // GNUNET_assert ((1 >= portion) &&
1672 // (0 < portion));
1673 // num_mal_peers = round (portion * num_peers);
1674 //
1675 // if (rps_peer->index >= num_mal_peers)
1676 // { /* It's useless to ask a malicious peer about a random sample -
1677 // it's not sampling */
1678 // GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (
1679 // GNUNET_TIME_UNIT_SECONDS, 2),
1680 // seed_peers, rps_peer);
1681 // schedule_missing_requests (rps_peer);
1682 // }
1683 // #endif /* ENABLE_MALICIOUS */
1684 // }
1685 
1686 
1687 /***********************************
1688 * CHURN
1689 ***********************************/
1690 
1691 static void
1692 churn (void *cls);
1693 
1694 
1695 /***********************************
1696 * PROFILER
1697 ***********************************/
1698 
1706 static void
1707 churn_cb (void *cls,
1708  struct GNUNET_TESTBED_Operation *op,
1709  const char *emsg)
1710 {
1711  // FIXME
1712  struct OpListEntry *entry = cls;
1713 
1714  (void) op;
1715 
1716  if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1717  {
1718  return;
1719  }
1720 
1722  if (NULL != emsg)
1723  {
1725  "Failed to start/stop RPS at a peer\n");
1727  return;
1728  }
1729  GNUNET_assert (0 != entry->delta);
1730 
1731  num_peers_online += entry->delta;
1732 
1733  if (PEER_GO_OFFLINE == entry->delta)
1734  { /* Peer hopefully just went offline */
1735  if (GNUNET_YES != rps_peers[entry->index].online)
1736  {
1738  "peer %s was expected to go offline but is still marked as online\n",
1739  GNUNET_i2s (rps_peers[entry->index].peer_id));
1740  GNUNET_break (0);
1741  }
1742  else
1743  {
1745  "peer %s probably went offline as expected\n",
1746  GNUNET_i2s (rps_peers[entry->index].peer_id));
1747  }
1748  rps_peers[entry->index].online = GNUNET_NO;
1749  }
1750 
1751  else if (PEER_GO_ONLINE < entry->delta)
1752  { /* Peer hopefully just went online */
1753  if (GNUNET_NO != rps_peers[entry->index].online)
1754  {
1756  "peer %s was expected to go online but is still marked as offline\n",
1757  GNUNET_i2s (rps_peers[entry->index].peer_id));
1758  GNUNET_break (0);
1759  }
1760  else
1761  {
1763  "peer %s probably went online as expected\n",
1764  GNUNET_i2s (rps_peers[entry->index].peer_id));
1765  if (NULL != cur_test_run.pre_test)
1766  {
1768  rps_peers[entry->index].rps_handle);
1770  }
1771  }
1772  rps_peers[entry->index].online = GNUNET_YES;
1773  }
1774  else
1775  {
1777  "Invalid value for delta: %i\n", entry->delta);
1778  GNUNET_break (0);
1779  }
1780 
1782  rps_peers[entry->index].entry_op_manage = NULL;
1783  GNUNET_free (entry);
1784  // if (num_peers_in_round[current_round] == peers_running)
1785  // run_round ();
1786 }
1787 
1788 
1797 static void
1798 manage_service_wrapper (unsigned int i, unsigned int j,
1799  enum PEER_ONLINE_DELTA delta,
1800  double prob_go_on_off)
1801 {
1802  struct OpListEntry *entry = NULL;
1803  uint32_t prob;
1804 
1805  /* make sure that management operation is not already scheduled */
1806  if (NULL != rps_peers[j].entry_op_manage)
1807  {
1808  return;
1809  }
1810 
1812  UINT32_MAX);
1814  "%u. selected peer (%u: %s) is %s.\n",
1815  i,
1816  j,
1818  (PEER_GO_ONLINE == delta) ? "online" : "offline");
1819  if (prob < prob_go_on_off * UINT32_MAX)
1820  {
1822  "%s goes %s\n",
1824  (PEER_GO_OFFLINE == delta) ? "offline" : "online");
1825 
1826  if (PEER_GO_OFFLINE == delta)
1828  entry = make_oplist_entry ();
1829  entry->delta = delta;
1830  entry->index = j;
1831  entry->op = GNUNET_TESTBED_peer_manage_service (NULL,
1832  testbed_peers[j],
1833  "rps",
1834  &churn_cb,
1835  entry,
1836  (PEER_GO_OFFLINE == delta) ?
1837  0 : 1);
1838  rps_peers[j].entry_op_manage = entry;
1839  }
1840 }
1841 
1842 
1843 static void
1844 churn (void *cls)
1845 {
1846  unsigned int i;
1847  unsigned int j;
1848  double portion_online;
1849  unsigned int *permut;
1850  double prob_go_offline;
1851  double portion_go_online;
1852  double portion_go_offline;
1853 
1854  (void) cls;
1855 
1856  if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
1857  {
1858  return;
1859  }
1861  "Churn function executing\n");
1862 
1863  churn_task = NULL; /* Should be invalid by now */
1864 
1865  /* Compute the probability for an online peer to go offline
1866  * this round */
1867  portion_online = num_peers_online * 1.0 / num_peers;
1869  "Portion online: %f\n",
1870  portion_online);
1871  portion_go_online = ((1 - portion_online) * .5 * .66);
1873  "Portion that should go online: %f\n",
1874  portion_go_online);
1875  portion_go_offline = (portion_online + portion_go_online) - .75;
1877  "Portion that probably goes offline: %f\n",
1878  portion_go_offline);
1879  prob_go_offline = portion_go_offline / (portion_online * .5);
1881  "Probability of a selected online peer to go offline: %f\n",
1882  prob_go_offline);
1883 
1885  (unsigned int) num_peers);
1886 
1887  /* Go over 50% randomly chosen peers */
1888  for (i = 0; i < .5 * num_peers; i++)
1889  {
1890  j = permut[i];
1891 
1892  /* If online, shut down with certain probability */
1893  if (GNUNET_YES == rps_peers[j].online)
1894  {
1895  manage_service_wrapper (i, j, -1, prob_go_offline);
1896  }
1897 
1898  /* If offline, restart with certain probability */
1899  else if (GNUNET_NO == rps_peers[j].online)
1900  {
1901  manage_service_wrapper (i, j, 1, 0.66);
1902  }
1903  }
1904 
1905  GNUNET_free (permut);
1906 
1909  churn,
1910  NULL);
1911 }
1912 
1913 
1917 static void
1918 profiler_init_peer (struct RPSPeer *rps_peer)
1919 {
1921  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer shall request %i peers\n",
1922  rps_peer->num_ids_to_request);
1923 }
1924 
1925 
1933 static void
1935  uint64_t n,
1936  const struct GNUNET_PeerIdentity *recv_peers)
1937 {
1938  struct RPSPeer *rps_peer;
1939  struct RPSPeer *rcv_rps_peer;
1940  char file_name_buf[128];
1941  char file_name_dh_buf[128];
1942  char file_name_dhr_buf[128];
1943  char file_name_dhru_buf[128];
1944  char *file_name = file_name_buf;
1945  char *file_name_dh = file_name_dh_buf;
1946  char *file_name_dhr = file_name_dhr_buf;
1947  char *file_name_dhru = file_name_dhru_buf;
1948  unsigned int i;
1949  struct PendingReply *pending_rep = (struct PendingReply *) cls;
1950 
1951  pending_rep->req_handle = NULL;
1952  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "profiler_reply_handle()\n");
1953  rps_peer = pending_rep->rps_peer;
1954  (void) GNUNET_asprintf (&file_name,
1955  "/tmp/rps/received_ids-%u",
1956  rps_peer->index);
1957 
1958  (void) GNUNET_asprintf (&file_name_dh,
1959  "/tmp/rps/diehard_input-%u",
1960  rps_peer->index);
1961  (void) GNUNET_asprintf (&file_name_dhr,
1962  "/tmp/rps/diehard_input_raw-%u",
1963  rps_peer->index);
1964  (void) GNUNET_asprintf (&file_name_dhru,
1965  "/tmp/rps/diehard_input_raw_aligned-%u",
1966  rps_peer->index);
1968  "[%s] got %" PRIu64 " peers:\n",
1970  n);
1971  for (i = 0; i < n; i++)
1972  {
1974  "%u: %s\n",
1975  i,
1976  GNUNET_i2s (&recv_peers[i]));
1977  tofile (file_name,
1978  "%s\n",
1979  GNUNET_i2s_full (&recv_peers[i]));
1980  rcv_rps_peer = GNUNET_CONTAINER_multipeermap_get (peer_map, &recv_peers[i]);
1981  GNUNET_assert (NULL != rcv_rps_peer);
1982  tofile (file_name_dh,
1983  "%" PRIu32 "\n",
1984  (uint32_t) rcv_rps_peer->index);
1985 #ifdef TO_FILE
1986  to_file_raw (file_name_dhr,
1987  (char *) &rcv_rps_peer->index,
1988  sizeof(uint32_t));
1989  to_file_raw_unaligned (file_name_dhru,
1990  (char *) &rcv_rps_peer->index,
1991  sizeof(uint32_t),
1992  bits_needed);
1993 #endif /* TO_FILE */
1994  }
1995  default_reply_handle (cls, n, recv_peers);
1996 }
1997 
1998 
2006 static void
2008  const struct GNUNET_PeerIdentity *recv_peer,
2009  double probability,
2010  uint32_t num_observed)
2011 {
2012  struct RPSPeer *rps_peer;
2013  struct RPSPeer *rcv_rps_peer;
2014  char file_name_buf[128];
2015  char file_name_dh_buf[128];
2016  char file_name_dhr_buf[128];
2017  char file_name_dhru_buf[128];
2018  char *file_name = file_name_buf;
2019  char *file_name_dh = file_name_dh_buf;
2020  char *file_name_dhr = file_name_dhr_buf;
2021  char *file_name_dhru = file_name_dhru_buf;
2022  struct PendingReply *pending_rep = (struct PendingReply *) cls;
2023 
2024  pending_rep->req_handle = NULL;
2025  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "profiler_reply_handle()\n");
2026  rps_peer = pending_rep->rps_peer;
2027  (void) GNUNET_asprintf (&file_name,
2028  "/tmp/rps/received_ids-%u",
2029  rps_peer->index);
2030 
2031  (void) GNUNET_asprintf (&file_name_dh,
2032  "/tmp/rps/diehard_input-%u",
2033  rps_peer->index);
2034  (void) GNUNET_asprintf (&file_name_dhr,
2035  "/tmp/rps/diehard_input_raw-%u",
2036  rps_peer->index);
2037  (void) GNUNET_asprintf (&file_name_dhru,
2038  "/tmp/rps/diehard_input_raw_aligned-%u",
2039  rps_peer->index);
2041  "[%s] got peer with info:\n",
2044  " %s\n",
2045  GNUNET_i2s (recv_peer));
2046  tofile (file_name,
2047  "%s %f %" PRIu32 " \n",
2048  GNUNET_i2s_full (recv_peer),
2049  probability,
2050  num_observed);
2051  rcv_rps_peer = GNUNET_CONTAINER_multipeermap_get (peer_map, recv_peer);
2052  GNUNET_assert (NULL != rcv_rps_peer);
2053  tofile (file_name_dh,
2054  "%" PRIu32 "\n",
2055  (uint32_t) rcv_rps_peer->index);
2056 #ifdef TO_FILE
2057  to_file_raw (file_name_dhr,
2058  (char *) &rcv_rps_peer->index,
2059  sizeof(uint32_t));
2060  to_file_raw_unaligned (file_name_dhru,
2061  (char *) &rcv_rps_peer->index,
2062  sizeof(uint32_t),
2063  bits_needed);
2064 #endif /* TO_FILE */
2065  default_reply_handle (cls, 1, recv_peer);
2066 }
2067 
2068 
2069 static void
2071 {
2072  if ((GNUNET_YES == in_shutdown) || (GNUNET_YES == post_test))
2073  {
2074  return;
2075  }
2076 
2077  /* Start churn */
2078  if ((HAVE_CHURN == cur_test_run.have_churn) && (NULL == churn_task))
2079  {
2081  "Starting churn task\n");
2084  churn,
2085  NULL);
2086  }
2087  else
2088  {
2090  "Not starting churn task\n");
2091  }
2092 
2093  /* Only request peer ids at one peer.
2094  * (It's the before-last because last one is target of the focused attack.)
2095  */
2096  if (0 < rps_peer->num_ids_to_request)
2098 }
2099 
2100 
2110 static int
2111 file_name_cb (void *cls, const char *filename)
2112 {
2113  if (NULL != strstr (filename, "sampler_el"))
2114  {
2115  struct RPS_SamplerElement *s_elem;
2116  struct GNUNET_CRYPTO_AuthKey auth_key;
2117  const char *key_char;
2118  uint32_t i;
2119  (void) cls;
2120 
2121  key_char = filename + 20; /* Length of "/tmp/rps/sampler_el-" */
2122  tofile (filename, "--------------------------\n");
2123 
2124  auth_key = string_to_auth_key (key_char);
2125  s_elem = RPS_sampler_elem_create ();
2126  RPS_sampler_elem_set (s_elem, auth_key);
2127 
2128  for (i = 0; i < num_peers; i++)
2129  {
2130  RPS_sampler_elem_next (s_elem, &rps_peer_ids[i]);
2131  }
2132  RPS_sampler_elem_destroy (s_elem);
2133  }
2134  return GNUNET_OK;
2135 }
2136 
2137 
2143 static int
2145 {
2146 #ifdef TO_FILE
2147  /* Compute perfect sample for each sampler element */
2148  if (-1 == GNUNET_DISK_directory_scan ("/tmp/rps/", file_name_cb, NULL))
2149  {
2150  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Scan of directory failed\n");
2151  }
2152 #endif /* TO_FILE */
2153 
2154  return evaluate ();
2155 }
2156 
2157 
2165 static int
2166 is_in_view (uint32_t a, uint32_t b)
2167 {
2168  uint32_t i;
2169 
2170  for (i = 0; i < rps_peers[a].cur_view_count; i++)
2171  {
2172  if (0 == memcmp (rps_peers[b].peer_id,
2173  &rps_peers[a].cur_view[i],
2174  sizeof(struct GNUNET_PeerIdentity)))
2175  {
2176  return GNUNET_YES;
2177  }
2178  }
2179  return GNUNET_NO;
2180 }
2181 
2182 
2183 static uint32_t
2185 {
2186  uint32_t i;
2187 
2188  for (i = 0; i < num_peers; i++)
2189  {
2190  if (0 == memcmp (pid,
2191  rps_peers[i].peer_id,
2192  sizeof(struct GNUNET_PeerIdentity)))
2193  {
2194  return i;
2195  }
2196  }
2197  // return 0; /* Should not happen - make compiler happy */
2199  "No known _PeerIdentity %s!\n",
2200  GNUNET_i2s_full (pid));
2201  GNUNET_assert (0);
2202 }
2203 
2204 
2213 static uint32_t
2214 count_containing_views (uint32_t a, uint32_t b)
2215 {
2216  uint32_t i;
2217  uint32_t peer_idx;
2218  uint32_t count = 0;
2219 
2220  for (i = 0; i < rps_peers[a].cur_view_count; i++)
2221  {
2222  peer_idx = get_idx_of_pid (&rps_peers[a].cur_view[i]);
2223  if (GNUNET_YES == is_in_view (peer_idx, b))
2224  {
2225  count++;
2226  }
2227  }
2228  return count;
2229 }
2230 
2231 
2238 static void
2239 compute_probabilities (uint32_t peer_idx)
2240 {
2241  // double probs[num_peers] = { 0 };
2242  double probs[num_peers];
2243  double probs_hist[num_peers]; /* Probability respecting the history */
2244  size_t probs_as_str_size = (num_peers * 10 + 2) * sizeof(char);
2245  char *probs_as_str = GNUNET_malloc (probs_as_str_size);
2246  char *probs_as_str_cpy;
2247  uint32_t i;
2248  double prob_push;
2249  double prob_pull;
2250  uint32_t view_size;
2251  uint32_t cont_views;
2252  uint32_t number_of_being_in_pull_events;
2253  int tmp;
2254  double sum_non_zero_prob = 0;
2255  double sum_non_zero_prob_hist = 0;
2256 
2258  "Computing probabilities for peer %" PRIu32 "\n", peer_idx);
2259  /* Firstly without knowledge of old views */
2260  for (i = 0; i < num_peers; i++)
2261  {
2263  "\tfor peer %" PRIu32 ":\n", i);
2264  view_size = rps_peers[i].cur_view_count;
2266  "\t\tview_size: %" PRIu32 "\n", view_size);
2267  /* For peer i the probability of being sampled is
2268  * evenly distributed among all possibly observed peers. */
2269  /* We could have observed a peer in three cases:
2270  * 1. peer sent a push
2271  * 2. peer was contained in a pull reply
2272  * 3. peer was in history (sampler) - ignored for now */
2273  /* 1. Probability of having received a push from peer i */
2274  if ((GNUNET_YES == is_in_view (i, peer_idx)) &&
2275  (1 <= (0.45 * view_size)))
2276  {
2277  if (0 == binom (view_size, 0.45 * view_size))
2278  prob_push = 0;
2279  else
2280  {
2281  prob_push = 1.0 * binom (0.45 * view_size, 1)
2282  /
2283  binom (view_size, 0.45 * view_size);
2284  }
2286  "\t\t%" PRIu32 " is in %" PRIu32 "'s view, prob: %f\n",
2287  peer_idx,
2288  i,
2289  prob_push);
2291  "\t\tposs choices from view: %" PRIu32 ", containing i: %"
2292  PRIu32 "\n",
2293  binom (view_size, 0.45 * view_size),
2294  binom (0.45 * view_size, 1));
2295  }
2296  else
2297  {
2298  prob_push = 0;
2300  "\t\t%" PRIu32 " is not in %" PRIu32 "'s view, prob: 0\n",
2301  peer_idx,
2302  i);
2303  }
2304  /* 2. Probability of peer i being contained in pulls */
2305  view_size = rps_peers[peer_idx].cur_view_count;
2306  cont_views = count_containing_views (peer_idx, i);
2307  number_of_being_in_pull_events =
2308  (binom (view_size, 0.45 * view_size)
2309  - binom (view_size - cont_views, 0.45 * view_size));
2310  if (0 != number_of_being_in_pull_events)
2311  {
2312  prob_pull = number_of_being_in_pull_events
2313  /
2314  (1.0 * binom (view_size, 0.45 * view_size));
2315  }
2316  else
2317  {
2318  prob_pull = 0;
2319  }
2320  probs[i] = prob_push + prob_pull - (prob_push * prob_pull);
2322  "\t\t%" PRIu32 " has %" PRIu32 " of %" PRIu32
2323  " peers in its view who know %" PRIu32 " prob: %f\n",
2324  peer_idx,
2325  cont_views,
2326  view_size,
2327  i,
2328  prob_pull);
2330  "\t\tnumber of possible pull combinations: %" PRIu32 "\n",
2331  binom (view_size, 0.45 * view_size));
2333  "\t\tnumber of possible pull combinations without %" PRIu32
2334  ": %" PRIu32 "\n",
2335  i,
2336  binom (view_size - cont_views, 0.45 * view_size));
2338  "\t\tnumber of possible pull combinations with %" PRIu32
2339  ": %" PRIu32 "\n",
2340  i,
2341  number_of_being_in_pull_events);
2342 
2343  probs_hist[i] = 0.9 * rps_peers[peer_idx].eval_probs_cache[i] + probs[i];
2344  rps_peers[peer_idx].eval_probs_cache[i] = probs_hist[i];
2345 
2346  sum_non_zero_prob += probs[i];
2347  sum_non_zero_prob_hist += probs_hist[i];
2348  }
2349  /* normalize */
2350  if (0 != sum_non_zero_prob)
2351  {
2352  for (i = 0; i < num_peers; i++)
2353  {
2354  probs[i] = probs[i] * (1.0 / sum_non_zero_prob);
2355  }
2356  }
2357  if (0 != sum_non_zero_prob_hist)
2358  {
2359  for (i = 0; i < num_peers; i++)
2360  {
2361  probs_hist[i] = probs_hist[i] * (1.0 / sum_non_zero_prob_hist);
2362  }
2363  }
2364 
2365  /* str repr */
2366  for (i = 0; i < num_peers; i++)
2367  {
2368  probs_as_str_cpy = GNUNET_strndup (probs_as_str, probs_as_str_size);
2369  tmp = GNUNET_snprintf (probs_as_str,
2370  probs_as_str_size,
2371  "%s %7.6f", probs_as_str_cpy, probs[i]);
2372  GNUNET_free (probs_as_str_cpy);
2373  GNUNET_assert (0 <= tmp);
2374  }
2375 
2376  to_file_w_len (rps_peers[peer_idx].file_name_probs,
2377  probs_as_str_size,
2378  "%s",
2379  probs_as_str);
2380 
2381  probs_as_str[0] = '\0';
2382  for (i = 0; i < num_peers; i++)
2383  {
2384  probs_as_str_cpy = GNUNET_strndup (probs_as_str, probs_as_str_size);
2385  tmp = GNUNET_snprintf (probs_as_str,
2386  probs_as_str_size,
2387  "%s %7.6f", probs_as_str_cpy, probs_hist[i]);
2388  GNUNET_free (probs_as_str_cpy);
2389  GNUNET_assert (0 <= tmp);
2390  }
2391 
2392  to_file_w_len (rps_peers[peer_idx].file_name_probs_hist,
2393  probs_as_str_size,
2394  "%s",
2395  probs_as_str);
2396  GNUNET_free (probs_as_str);
2397 }
2398 
2399 
2409 static uint32_t
2410 count_peer_in_views_2 (uint32_t peer_idx)
2411 {
2412  uint32_t i, j;
2413  uint32_t count = 0;
2414 
2415  for (i = 0; i < num_peers; i++) /* Peer in which view is counted */
2416  {
2417  for (j = 0; j < rps_peers[i].cur_view_count; j++) /* entry in view */
2418  {
2419  if (0 == memcmp (rps_peers[peer_idx].peer_id,
2420  &rps_peers[i].cur_view[j],
2421  sizeof(struct GNUNET_PeerIdentity)))
2422  {
2423  count++;
2424  break;
2425  }
2426  }
2427  }
2428  rps_peers[peer_idx].count_in_views = count;
2429  return count;
2430 }
2431 
2432 
2433 static uint32_t
2435 {
2436  uint32_t i;
2437 
2438  view_sizes = 0;
2439  for (i = 0; i < num_peers; i++) /* Peer in which view is counted */
2440  {
2442  }
2443  return view_sizes;
2444 }
2445 
2446 
2447 static void
2448 count_peer_in_views (uint32_t *count_peers)
2449 {
2450  uint32_t i, j;
2451 
2452  for (i = 0; i < num_peers; i++) /* Peer in which view is counted */
2453  {
2454  for (j = 0; j < rps_peers[i].cur_view_count; j++) /* entry in view */
2455  {
2456  if (0 == memcmp (rps_peers[i].peer_id,
2457  &rps_peers[i].cur_view[j],
2458  sizeof(struct GNUNET_PeerIdentity)))
2459  {
2460  count_peers[i]++;
2461  }
2462  }
2463  }
2464 }
2465 
2466 
2467 void
2469 {
2470  uint32_t i;
2471  /* ith entry represents the number of occurrences in other peer's views */
2472  uint32_t *count_peers = GNUNET_new_array (num_peers, uint32_t);
2473  uint32_t views_total_size;
2474  double expected;
2475  /* deviation from expected number of peers */
2476  double *deviation = GNUNET_new_array (num_peers, double);
2477 
2478  views_total_size = 0;
2479  expected = 0;
2480 
2481  /* For each peer count its representation in other peer's views*/
2482  for (i = 0; i < num_peers; i++) /* Peer to count */
2483  {
2484  views_total_size += rps_peers[i].cur_view_count;
2485  count_peer_in_views (count_peers);
2487  "Counted representation of %" PRIu32 "th peer [%s]: %" PRIu32
2488  "\n",
2489  i,
2491  count_peers[i]);
2492  }
2493 
2495  "size of all views combined: %" PRIu32 "\n",
2496  views_total_size);
2497  expected = ((double) 1 / num_peers) * views_total_size;
2499  "Expected number of occurrences of each peer in all views: %f\n",
2500  expected);
2501  for (i = 0; i < num_peers; i++) /* Peer to count */
2502  {
2503  deviation[i] = expected - count_peers[i];
2505  "Deviation from expectation: %f\n", deviation[i]);
2506  }
2507  GNUNET_free (count_peers);
2508  GNUNET_free (deviation);
2509 }
2510 
2511 
2512 void
2514 {
2515  uint32_t i;
2516 
2517  for (i = 0; i < num_peers; i++) /* Peer to count */
2518  {
2520  "View size of %" PRIu32 ". [%s] is %" PRIu32 "\n",
2521  i,
2523  rps_peers[i].cur_view_count);
2524  }
2525 }
2526 
2527 
2528 void
2530 {
2531  compute_diversity ();
2532  print_view_sizes ();
2533 }
2534 
2535 
2536 void
2537 view_update_cb (void *cls,
2538  uint64_t view_size,
2539  const struct GNUNET_PeerIdentity *peers)
2540 {
2542  "View was updated (%" PRIu64 ")\n", view_size);
2543  struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
2544  to_file ("/tmp/rps/view_sizes.txt",
2545  "%" PRIu32 " %" PRIu64 "",
2546  rps_peer->index,
2547  view_size);
2548  for (uint64_t i = 0; i < view_size; i++)
2549  {
2551  "\t%s\n", GNUNET_i2s (&peers[i]));
2552  }
2553  GNUNET_array_grow (rps_peer->cur_view,
2554  rps_peer->cur_view_count,
2555  view_size);
2556  // *rps_peer->cur_view = *peers;
2557  GNUNET_memcpy (rps_peer->cur_view,
2558  peers,
2559  view_size * sizeof(struct GNUNET_PeerIdentity));
2560  to_file ("/tmp/rps/count_in_views.txt",
2561  "%" PRIu32 " %" PRIu32 "",
2562  rps_peer->index,
2563  count_peer_in_views_2 (rps_peer->index));
2565  if (0 != view_size)
2566  {
2567  to_file ("/tmp/rps/repr.txt",
2568  "%" PRIu32 /* index */
2569  " %" PRIu32 /* occurrence in views */
2570  " %" PRIu32 /* view sizes */
2571  " %f" /* fraction of repr in views */
2572  " %f" /* average view size */
2573  " %f" /* prob of occurrence in view slot */
2574  " %f" "", /* exp frac of repr in views */
2575  rps_peer->index,
2576  count_peer_in_views_2 (rps_peer->index),
2577  view_sizes,
2578  count_peer_in_views_2 (rps_peer->index) / (view_size * 1.0), /* fraction of representation in views */
2579  view_sizes / (view_size * 1.0), /* average view size */
2580  1.0 / view_size, /* prob of occurrence in view slot */
2581  (1.0 / view_size) * (view_sizes / view_size) /* expected fraction of repr in views */
2582  );
2583  }
2584  compute_probabilities (rps_peer->index);
2586 }
2587 
2588 
2589 static void
2590 pre_profiler (struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h)
2591 {
2592  rps_peer->file_name_probs =
2593  store_prefix_file_name (rps_peer->index, "probs");
2594  rps_peer->file_name_probs_hist =
2595  store_prefix_file_name (rps_peer->index, "probs_hist");
2596  rps_peer->eval_probs_cache = GNUNET_new_array (num_peers, double);
2597  memset (rps_peer->eval_probs_cache, 0, num_peers * sizeof (double));
2598  GNUNET_RPS_view_request (h, 0, view_update_cb, rps_peer);
2599 }
2600 
2601 void
2603 {
2604  uint64_t sums[STAT_TYPE_MAX] = { 0 };
2605 
2606  for (uint32_t i = 0; i < num_peers; i++)
2607  {
2608  to_file ("/tmp/rps/final_stats.csv",
2609  "%" PRIu32 ", " /* index */
2610  "%s, %" /* id */
2611  PRIu64 ", %" /* rounds */
2612  PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %"
2613  PRIu64 ", %" /* blocking */
2614  PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" /* issued */
2615  PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" /* sent */
2616  PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %"
2617  PRIu64 ", %" /* recv */
2618  PRIu64 ", %" /* view size */
2619  PRIu64 ", %" /* known peers */
2620  PRIu64 ", %" /* valid peers */
2621  PRIu64 ", %" /* learned peers */
2622  PRIu64 ", %" /* pending online checks */
2623  PRIu64 ", %" /* unrequested pull replies */
2624  PRIu64 ", %" /* peers in push map */
2625  PRIu64 ", %" /* peers in pull map */
2626  PRIu64 ", %" /* peers in view */
2627  PRIu64 "\n" /* view size aim */,
2628  i,
2662  for (enum STAT_TYPE stat_type = STAT_TYPE_ROUNDS;
2663  stat_type < STAT_TYPE_MAX;
2664  stat_type++)
2665  {
2666  sums[stat_type] += rps_peers[i].stats[stat_type];
2667  }
2668  }
2669  to_file ("/tmp/rps/final_stats.dat",
2670  "SUM %"
2671  PRIu64 " %" /* rounds */
2672  PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64
2673  " %" /* blocking */
2674  PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" /* issued */
2675  PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" /* sent */
2676  PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %"
2677  PRIu64 ", %" /* recv */
2678  PRIu64 ", %" /* view size */
2679  PRIu64 ", %" /* known peers */
2680  PRIu64 ", %" /* valid peers */
2681  PRIu64 ", %" /* learned peers */
2682  PRIu64 ", %" /* pending online checks */
2683  PRIu64 ", %" /* unrequested pull replies */
2684  PRIu64 ", %" /* peers in push map */
2685  PRIu64 ", %" /* peers in pull map */
2686  PRIu64 ", %" /* peers in view */
2687  PRIu64 "\n" /* view size aim */,
2688  sums[STAT_TYPE_ROUNDS],
2689  sums[STAT_TYPE_BLOCKS],
2710  sums[STAT_TYPE_VIEW_SIZE],
2711  sums[STAT_TYPE_KNOWN_PEERS],
2712  sums[STAT_TYPE_VALID_PEERS],
2713  sums[STAT_TYPE_LEARND_PEERS],
2719  sums[STAT_TYPE_VIEW_SIZE_AIM]);
2720 }
2721 
2722 
2734 void
2736  int success)
2737 {
2738  struct STATcls *stat_cls = (struct STATcls *) cls;
2739  struct RPSPeer *rps_peer = stat_cls->rps_peer;
2740 
2741  rps_peer->h_stat_get[stat_cls->stat_type] = NULL;
2742  if (GNUNET_OK == success)
2743  {
2744  /* set flag that we we got the value */
2745  rps_peer->stat_collected_flags |= BIT (stat_cls->stat_type);
2746  }
2747  else
2748  {
2750  "Peer %u did not receive statistics value\n",
2751  rps_peer->index);
2752  GNUNET_free (stat_cls);
2753  GNUNET_break (0);
2754  return;
2755  }
2756 
2757  if ((NULL != rps_peer->stat_op) &&
2759  rps_peer)) )
2760  {
2762  }
2763 
2764  write_final_stats ();
2766  {
2767  // write_final_stats ();
2768  GNUNET_free (stat_cls);
2770  "Shutting down\n");
2772  }
2773  else
2774  {
2775  GNUNET_free (stat_cls);
2776  }
2777 }
2778 
2779 
2790 int
2791 stat_iterator (void *cls,
2792  const char *subsystem,
2793  const char *name,
2794  uint64_t value,
2795  int is_persistent)
2796 {
2797  const struct STATcls *stat_cls = (const struct STATcls *) cls;
2798  struct RPSPeer *rps_peer = (struct RPSPeer *) stat_cls->rps_peer;
2799  enum STAT_TYPE stat_type;
2800 
2801  (void) subsystem;
2802  (void) is_persistent;
2803 
2805  "Got stat value: %s - %" PRIu64 " (%u)\n",
2806  name,
2807  value,
2808  rps_peer->index);
2809  to_file (rps_peer->file_name_stats,
2810  "%s: %" PRIu64 "\n",
2811  name,
2812  value);
2813  stat_type = stat_str_2_type (name);
2814  GNUNET_assert (STAT_TYPE_ROUNDS <= stat_type &&
2815  STAT_TYPE_MAX > stat_type);
2816  rps_peer->stats[stat_type] = value;
2817  return GNUNET_OK;
2818 }
2819 
2820 
2821 void
2822 post_profiler (struct RPSPeer *rps_peer)
2823 {
2825  {
2826  return;
2827  }
2828 
2830  "Going to request statistic values with mask 0x%" PRIx32 "\n",
2832 
2833  struct STATcls *stat_cls;
2834  uint32_t stat_type;
2835  for (stat_type = STAT_TYPE_ROUNDS;
2837  stat_type++)
2838  {
2840  {
2841  stat_cls = GNUNET_malloc (sizeof(struct STATcls));
2842  stat_cls->rps_peer = rps_peer;
2843  stat_cls->stat_type = stat_type;
2848  "rps",
2851  stat_iterator,
2852  (struct STATcls *) stat_cls);
2853  GNUNET_assert (NULL != rps_peer->h_stat_get);
2855  "Requested statistics for %s (peer %" PRIu32 ")\n",
2857  rps_peer->index);
2858  }
2859  }
2861 }
2862 
2863 
2864 /***********************************************************************
2865 * /Definition of tests
2866 ***********************************************************************/
2867 
2868 
2881 static void
2882 test_run (void *cls,
2883  struct GNUNET_TESTBED_RunHandle *h,
2884  unsigned int n_peers,
2885  struct GNUNET_TESTBED_Peer **peers,
2886  unsigned int links_succeeded,
2887  unsigned int links_failed)
2888 {
2889  unsigned int i;
2890  struct OpListEntry *entry;
2891 
2892  (void) cls;
2893  (void) h;
2894  (void) links_failed;
2895 
2896  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RUN was called\n");
2897 
2898  /* Check whether we timed out */
2899  if ((n_peers != num_peers) ||
2900  (NULL == peers) ||
2901  (0 == links_succeeded) )
2902  {
2904  "Going down due to args (eg. timeout)\n");
2905  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tn_peers: %u\n", n_peers);
2906  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tnum_peers: %" PRIu32 "\n",
2907  num_peers);
2908  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tpeers: %p\n", peers);
2909  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tlinks_succeeded: %u\n",
2910  links_succeeded);
2911  ok = 1;
2913  return;
2914  }
2915 
2916 
2917  /* Initialize peers */
2918  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "going to initialise peers\n");
2919  testbed_peers = peers;
2920  num_peers_online = 0;
2921  for (i = 0; i < num_peers; i++)
2922  {
2923  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "initialising %u\n", i);
2924  entry = make_oplist_entry ();
2925  entry->index = i;
2926  rps_peers[i].index = i;
2927  if (NULL != cur_test_run.init_peer)
2930  {
2932  rps_peers->cur_view = NULL;
2933  }
2936  &info_cb,
2937  entry);
2938  }
2939 
2940  /* Bring peers up */
2941  GNUNET_assert (num_peers == n_peers);
2942  for (i = 0; i < n_peers; i++)
2943  {
2944  rps_peers[i].index = i;
2945  rps_peers[i].op =
2947  peers[i],
2948  "rps",
2950  &rps_peers[i],
2953  &rps_peers[i]);
2954  /* Connect all peers to statistics service */
2956  {
2958  "Connecting to statistics service\n");
2959  rps_peers[i].stat_op =
2961  peers[i],
2962  "statistics",
2964  &rps_peers[i],
2967  &rps_peers[i]);
2968  }
2969  }
2970 
2971  if (NULL != churn_task)
2974  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "timeout for shutdown is %lu\n",
2975  timeout.rel_value_us / 1000000);
2978  NULL);
2980 }
2981 
2982 
2989 static void
2990 run (void *cls,
2991  char *const *args,
2992  const char *cfgfile,
2993  const struct GNUNET_CONFIGURATION_Handle *cfg)
2994 {
2995  // int ret_value;
2996  (void) cls;
2997  (void) args;
2998  (void) cfgfile;
2999 
3000  /* Defaults for tests */
3001  churn_task = NULL;
3002 
3003  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "This is the profiler\n");
3004  cur_test_run.name = "test-rps-profiler";
3005  if (0 == num_peers)
3006  num_peers = 10;
3007  mal_type = 3;
3009  // cur_test_run.pre_test = mal_pre;
3016  if (0 == cur_test_run.num_requests)
3018  // cur_test_run.have_churn = HAVE_CHURN;
3023  | BIT (STAT_TYPE_BLOCKS)
3055 
3056  /* 'Clean' directory */
3057  (void) GNUNET_DISK_directory_remove ("/tmp/rps/");
3058  GNUNET_DISK_directory_create ("/tmp/rps/");
3059  if (0 == duration.rel_value_us)
3060  {
3061  if (0 == timeout.rel_value_us)
3062  {
3065  (90 * 1.2)
3066  + (0.01 * num_peers));
3067  }
3068  else
3069  {
3072  ( (double) timeout.rel_value_us / (double) 1000000)
3073  * 0.75);
3074  }
3075  }
3076  else
3077  {
3078  if (0 == timeout.rel_value_us)
3079  {
3082  / 1000000)
3083  * 1.2) + (0.01 * num_peers));
3084  }
3085  }
3088  "duration is %lus\n",
3089  duration.rel_value_us / 1000000);
3091  "timeout is %lus\n",
3092  timeout.rel_value_us / 1000000);
3093 
3094  /* Compute number of bits for representing largest peer id */
3095  for (bits_needed = 1; (uint32_t) (1 << bits_needed) < num_peers; bits_needed++)
3096  ;
3098  "Need %u bits to represent %" PRIu32 " peers\n",
3099  bits_needed,
3100  num_peers);
3101 
3105  if ((2 == mal_type) ||
3106  (3 == mal_type))
3108 
3109  ok = 1;
3110  GNUNET_TESTBED_run (NULL,
3111  cfg,
3112  num_peers,
3113  0, /* event mask */
3114  NULL,
3115  NULL,
3116  &test_run,
3117  NULL);
3118 }
3119 
3120 
3128 int
3129 main (int argc, char *argv[])
3130 {
3131  int ret_value;
3134  "num-peers",
3135  "COUNT",
3136  gettext_noop ("number of peers to start"),
3137  &num_peers),
3139  "duration",
3140  "DURATION",
3141  gettext_noop (
3142  "duration of the profiling"),
3143  &duration),
3145  "timeout",
3146  "TIMEOUT",
3147  gettext_noop (
3148  "timeout for the profiling"),
3149  &timeout),
3151  "num-requests",
3152  "COUNT",
3153  gettext_noop ("number of PeerIDs to request"),
3156  };
3157 
3158  unsetenv ("XDG_DATA_HOME");
3159  unsetenv ("XDG_CONFIG_HOME");
3160  // if (GNUNET_OK !=
3161  // GNUNET_STRINGS_get_utf8_args (argc, argv,
3162  // &argc, &argv))
3163  // return 2;
3164  ret_value = 0;
3165  if (GNUNET_OK !=
3166  GNUNET_PROGRAM_run (argc,
3167  argv,
3168  "gnunet-rps-profiler",
3169  gettext_noop (
3170  "Measure quality and performance of the RPS service."),
3171  options,
3172  &run,
3173  NULL))
3174  {
3175  ret_value = 1;
3176  }
3177  if (0 != ret_value)
3178  {
3180  "Test did not run successfully!\n");
3181  }
3182  else
3183  {
3184  ret_value = cur_test_run.eval_cb ();
3186  {
3189  0);
3190  }
3194  }
3195  return ret_value;
3196 }
3197 
3198 
3199 /* end of test_rps.c */
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
#define gettext_noop(String)
Definition: gettext.h:70
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static struct CadetPeer * peers
Operation to get peer ids.
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
static char * line
Desired phone line (string to be converted to a hash).
static char * file_name
Dump file name.
static char * filename
static char * value
Value of the record to add/remove.
static struct GNUNET_TESTBED_Peer ** testbed_peers
Handles to all of the running peers.
static int ok
Return value from 'main'.
@ STAT_TYPE_SENT_PULL_REQ_MH
@ STAT_TYPE_BLOCKS
@ STAT_TYPE_RECV_PULL_REP
@ STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL
@ STAT_TYPE_MAX
@ STAT_TYPE_LEARND_PEERS
@ STAT_TYPE_SENT_PULL_REP
@ STAT_TYPE_RECV_PUSH_SEND
@ STAT_TYPE_BLOCKS_NO_PULL
@ STAT_TYPE_ISSUED_PUSH_SEND
@ STAT_TYPE_ISSUED_PUSH_SEND_MH
@ STAT_TYPE_RECV_PULL_REQ_MH
@ STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL
@ STAT_TYPE_ISSUED_PULL_REQ
@ STAT_TYPE_VIEW_SIZE
@ STAT_TYPE_ISSUED_PULL_REP
@ STAT_TYPE_ISSUED_PULL_REQ_MH
@ STAT_TYPE_ROUNDS
@ STAT_TYPE_VALID_PEERS
@ STAT_TYPE_VIEW_SIZE_AIM
@ STAT_TYPE_PEERS_IN_PUSH_MAP
@ STAT_TYPE_SENT_PULL_REQ
@ STAT_TYPE_SENT_PUSH_SEND
@ STAT_TYPE_BLOCKS_MANY_PUSH
@ STAT_TYPE_RECV_PULL_REQ
@ STAT_TYPE_PEERS_IN_VIEW
@ STAT_TYPE_BLOCKS_NO_PUSH
@ STAT_TYPE_PEERS_IN_PULL_MAP
@ STAT_TYPE_UNREQUESTED_PULL_REPLIES
@ STAT_TYPE_KNOWN_PEERS
@ STAT_TYPE_RECV_PUSH_SEND_MH
@ STAT_TYPE_PENDING_ONLINE_CHECKS
@ STAT_TYPE_RECV_PULL_REP_MH
PEER_ONLINE_DELTA
Indicates whether peer should go off- or online.
@ PEER_GO_ONLINE
Indicates peer going online.
@ PEER_GO_OFFLINE
Indicates peer going offline.
static void default_reply_handle(void *cls, uint64_t n, const struct GNUNET_PeerIdentity *recv_peers)
Callback to call on receipt of a reply.
int main(int argc, char *argv[])
Entry point for the testcase, sets up the testbed.
static void trigger_shutdown(void *cls)
void schedule_missing_requests(struct RPSPeer *rps_peer)
Schedule requests for peer rps_peer that have neither been scheduled, nor issued, nor replied.
void info_cb(void *cb_cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg)
Get the id of peer i.
static struct GNUNET_CONTAINER_MultiPeerMap * peer_map
Peermap to get the index of a given peer ID quick.
static uint32_t get_idx_of_pid(const struct GNUNET_PeerIdentity *pid)
static void profiler_cb(struct RPSPeer *rps_peer)
static struct OpListEntry * oplist_head
OpList DLL head.
static struct GNUNET_SCHEDULER_Task * post_test_task
Identifier for the task that runs after the test to collect results.
static void profiler_reply_handle_info(void *cls, const struct GNUNET_PeerIdentity *recv_peer, double probability, uint32_t num_observed)
Callback to call on receipt of a reply.
OPTION_QUICK_QUIT
Is it ok to quit the test before the timeout?
@ HAVE_QUICK_QUIT
It is ok for the test to quit before the timeout triggers.
@ HAVE_NO_QUICK_QUIT
It is NOT ok for the test to quit before the timeout triggers.
static void stat_disconnect_adapter(void *cls, void *op_result)
Called to disconnect from peer's statistics service.
enum STAT_TYPE stat_str_2_type(const char *stat_str)
Converts string representation to the corresponding STAT_TYPE enum.
static uint32_t count_peer_in_views_2(uint32_t peer_idx)
This counts the number of peers in which views a given peer occurs.
static void * rps_connect_adapter(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Adapter function called to establish a connection to the RPS service.
void all_views_updated_cb()
static void test_run(void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int n_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed)
Actual "main" function for the testcase.
#define BIT(n)
OPTION_COLLECT_STATISTICS
Do we collect statistics at the end?
@ COLLECT_STATISTICS
We collect statistics at the end.
@ NO_COLLECT_STATISTICS
We do not collect statistics at the end.
static void compute_probabilities(uint32_t peer_idx)
Computes the probability for each other peer to be selected by the sampling process based on the view...
static struct OpListEntry * oplist_tail
OpList DLL tail.
int stat_iterator(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent)
Callback function to process statistic values.
static void count_peer_in_views(uint32_t *count_peers)
void(* InitPeer)(struct RPSPeer *rps_peer)
Called to initialise the given RPSPeer.
static struct RPSPeer * rps_peers
Information for all the peers.
void clean_peer(unsigned peer_index)
static struct GNUNET_PeerIdentity * rps_peer_ids
IDs of the peers.
static struct GNUNET_PeerIdentity * target_peer
ID of the targeted peer.
static void rps_disconnect_adapter(void *cls, void *op_result)
Adapter function called to destroy connection to RPS service.
OPTION_CHURN
Do we have Churn?
@ HAVE_CHURN
If we have churn this is set.
@ HAVE_NO_CHURN
If we have no churn this is set.
static int evaluate(void)
Write the ids and their according index in the given array to a file Unused.
static int file_name_cb(void *cls, const char *filename)
Function called from profiler_eval with a filename.
void(* MainTest)(struct RPSPeer *rps_peer)
Executes functions to test the api/service for a given peer.
static uint32_t count_containing_views(uint32_t a, uint32_t b)
Counts number of peers in view of a that have b in their view.
static void profiler_reply_handle(void *cls, uint64_t n, const struct GNUNET_PeerIdentity *recv_peers)
Callback to call on receipt of a reply.
void cancel_pending_req_rep(struct RPSPeer *rps_peer)
static int in_shutdown
Are we shutting down?
static void cancel_request(struct PendingReply *pending_rep)
static void churn_cb(void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
Callback to be called when RPS service is started or stopped at peers.
void compute_diversity()
struct SingleTestRun cur_test_run
static void manage_service_wrapper(unsigned int i, unsigned int j, enum PEER_ONLINE_DELTA delta, double prob_go_on_off)
Set the rps-service up or down for a specific peer.
static void churn(void *cls)
‍**
static int check_statistics_collect_completed_single_peer(const struct RPSPeer *rps_peer)
Checks if given peer already received its statistics value from the statistics service.
OPTION_COLLECT_VIEW
Do we collect views during run?
@ NO_COLLECT_VIEW
We do not collect the view during run.
@ COLLECT_VIEW
We collect view during run.
static struct GNUNET_TIME_Relative duration
How long do we run the test?
static uint32_t cumulated_view_sizes()
static int is_in_view(uint32_t a, uint32_t b)
is b in view of a?
static uint32_t num_peers
How many peers do we start?
static void pre_profiler(struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h)
static int check_statistics_collect_completed()
Checks if all peers already received their statistics value from the statistics service.
static int profiler_eval(void)
This is run after the test finished.
static unsigned int view_sizes
The added sizes of the peer's views.
static unsigned int num_peers_online
Number of online peers.
static unsigned int mal_type
Type of malicious peer to test.
static struct GNUNET_SCHEDULER_Task * churn_task
Identifier for the churn task that runs periodically.
static char * stat_type_strings[]
#define tofile(file_name,...)
This function is used to facilitate writing important information to disk.
void(* PostTest)(struct RPSPeer *peer)
Called directly before disconnecting from the service.
static struct GNUNET_SCHEDULER_Task * shutdown_task
Identifier for the shutdown task.
static struct GNUNET_TIME_Relative timeout
When do we do a hard shutdown?
static void request_peers(void *cls)
Request random peers.
void view_update_cb(void *cls, uint64_t view_size, const struct GNUNET_PeerIdentity *peers)
void(* PreTest)(struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h)
Called directly after connecting to the service.
void print_view_sizes()
static void tofile_(const char *file_name, const char *line)
Append arguments to file.
static void shutdown_op(void *cls)
Task run on timeout to shut everything down.
static void cancel_pending_req(struct PendingRequest *pending_req)
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Entry point for the testcase, sets up the testbed.
static unsigned bits_needed
number of bits required to represent the largest peer id
static struct OpListEntry * make_oplist_entry()
Creates an oplist entry and adds it to the oplist DLL.
void post_profiler(struct RPSPeer *rps_peer)
static void profiler_init_peer(struct RPSPeer *rps_peer)
Initialise given RPSPeer.
static void rps_connect_complete_cb(void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg)
Callback to be called when RPS service connect operation is completed.
void(* ReplyHandle)(void *cls, uint64_t n, const struct GNUNET_PeerIdentity *recv_peers)
Callback called once the requested random peers are available.
void write_final_stats(void)
void post_test_shutdown_ready_cb(void *cls, int success)
Continuation called by GNUNET_STATISTICS_get() functions.
static void * stat_connect_adapter(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Called to open a connection to the peer's statistics.
int(* EvaluationCallback)(void)
Function called after disconnect to evaluate test success.
static void post_test_op(void *cls)
Task run after duration to collect statistics and potentially shut down.
static int post_test
Did we finish the test?
static void stat_complete_cb(void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg)
Called after successfully opening a connection to a peer's statistics service; we register statistics...
static struct GNUNET_RPS_Handle * rps_handle
RPS handle.
Definition: gnunet-rps.c:36
struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
void RPS_sampler_elem_set(struct RPS_SamplerElement *sampler_elem, struct GNUNET_CRYPTO_AuthKey auth_key)
Set the min-wise independent function of the given sampler element.
void RPS_sampler_elem_destroy(struct RPS_SamplerElement *sampler_elem)
Destroy a sampler element.
void RPS_sampler_elem_next(struct RPS_SamplerElement *sampler_elem, const struct GNUNET_PeerIdentity *new_ID)
Update a sampler element with a PeerID.
struct RPS_SamplerElement * RPS_sampler_elem_create(void)
Create a sampler element and initialise it.
sampler element implementation
static char * subsystem
Set to subsystem that we're going to get stats for (or NULL for all).
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
API to the rps service.
API for writing tests and creating large-scale emulation testbeds for GNUnet.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
unsigned int * GNUNET_CRYPTO_random_permute(enum GNUNET_CRYPTO_Quality mode, unsigned int n)
Get an array with a random permutation of the numbers 0...n-1.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1237
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:686
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1087
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1308
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:496
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:814
@ GNUNET_DISK_OPEN_WRITE
Open the file for writing.
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_OPEN_APPEND
Append to the file.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_GROUP_READ
Group can read.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
@ GNUNET_DISK_PERM_OTHER_READ
Everybody can read.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_uint(char shortName, const char *name, const char *argumentHelp, const char *description, unsigned int *val)
Allow user to specify an unsigned int.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_relative_time(char shortName, const char *name, const char *argumentHelp, const char *description, struct GNUNET_TIME_Relative *val)
Allow user to specify a struct GNUNET_TIME_Relative (using human-readable "fancy" time).
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition: program.c:400
void GNUNET_RPS_view_request(struct GNUNET_RPS_Handle *rps_handle, uint32_t num_updates, GNUNET_RPS_NotifyReadyCB view_update_cb, void *cls)
Request updates of view.
Definition: rps_api.c:461
struct GNUNET_RPS_Request_Handle_Single_Info * GNUNET_RPS_request_peer_info(struct GNUNET_RPS_Handle *rps_handle, GNUNET_RPS_NotifyReadySingleInfoCB ready_cb, void *cls)
Request one random peer, getting additional information.
Definition: rps_api.c:995
struct GNUNET_RPS_Handle * GNUNET_RPS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the rps service.
Definition: rps_api.c:843
void GNUNET_RPS_disconnect(struct GNUNET_RPS_Handle *h)
Disconnect from the rps service.
Definition: rps_api.c:1263
void GNUNET_RPS_request_single_info_cancel(struct GNUNET_RPS_Request_Handle_Single_Info *rhs)
Cancel an issued single info request.
Definition: rps_api.c:1231
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1299
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1334
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1272
void GNUNET_STATISTICS_get_cancel(struct GNUNET_STATISTICS_GetHandle *gh)
Cancel a GNUNET_STATISTICS_get request.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
struct GNUNET_STATISTICS_GetHandle * GNUNET_STATISTICS_get(struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Callback cont, GNUNET_STATISTICS_Iterator proc, void *cls)
Get statistic from the peer.
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:2021
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_get_information(struct GNUNET_TESTBED_Peer *peer, enum GNUNET_TESTBED_PeerInformationType pit, GNUNET_TESTBED_PeerInfoCallback cb, void *cb_cls)
Request information about a peer.
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_manage_service(void *op_cls, struct GNUNET_TESTBED_Peer *peer, const char *service_name, GNUNET_TESTBED_OperationCompletionCallback cb, void *cb_cls, unsigned int start)
Start or stop given service at a peer.
void GNUNET_TESTBED_run(const char *host_filename, const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int num_peers, uint64_t event_mask, GNUNET_TESTBED_ControllerCallback cc, void *cc_cls, GNUNET_TESTBED_TestMaster test_master, void *test_master_cls)
Convenience method for running a testbed with a single call.
struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_service_connect(void *op_cls, struct GNUNET_TESTBED_Peer *peer, const char *service_name, GNUNET_TESTBED_ServiceConnectCompletionCallback cb, void *cb_cls, GNUNET_TESTBED_ConnectAdapter ca, GNUNET_TESTBED_DisconnectAdapter da, void *cada_cls)
Connect to a service offered by the given peer.
@ GNUNET_TESTBED_PIT_IDENTITY
What is the identity of the peer? Returns a 'const struct GNUNET_PeerIdentity *'.
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:484
static int op_result(struct GNUNET_OP_Handle *h, uint64_t op_id, int64_t result_code, const void *data, uint16_t data_size, void **ctx, uint8_t cancel)
Remove an operation, and call its result callback (unless it was cancelled).
Definition: op.c:246
static unsigned int size
Size of the "table".
Definition: peer.c:68
const char * name
void to_file_raw_unaligned(const char *file_name, const char *buf, size_t size_buf, unsigned bits_needed)
char * store_prefix_file_name(const unsigned int index, const char *prefix)
int close_all_files()
Close all files that were opened with get_file_handle.
void to_file_raw(const char *file_name, const char *buf, size_t size_buf)
struct GNUNET_CRYPTO_AuthKey string_to_auth_key(const char *str)
uint32_t binom(uint32_t n, uint32_t k)
Binomial coefficient (n choose k)
Some utils facilitating the view into the internals for the sampler needed for evaluation.
#define to_file_w_len(file_name, len,...)
Definition: rps-test_util.h:83
#define to_file(file_name,...)
This function is used to facilitate writing important information to disk.
Definition: rps-test_util.h:65
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
Internal representation of the hash map.
type for (message) authentication keys
Handle used to access files (and pipes).
Definition of a command line option.
The identity of the host (wraps the signing key of the peer).
Handler to handle requests from a client.
Definition: rps_api.c:79
Handler for a single request from a client.
Definition: rps_api.c:213
Entry in list of pending tasks.
Definition: scheduler.c:136
Linked list of things we still need to do.
Handle for the service.
Opaque handle to an abstract operation to be executed by the testing framework.
Data returned from GNUNET_TESTBED_peer_get_information.
union GNUNET_TESTBED_PeerInformation::@49 result
The result of the get information operation; Choose according to the pit.
struct GNUNET_PeerIdentity * id
The identity of the peer.
A peer controlled by the testing framework.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Operation map entry.
struct OpListEntry * prev
DLL prev ptr.
struct GNUNET_TESTBED_Operation * op
The testbed operation.
int delta
Depending on whether we start or stop NSE service at the peer set this to 1 or -1.
unsigned int index
Index of the regarding peer.
struct OpListEntry * next
DLL next ptr.
A pending reply: A request was sent and the reply is pending.
struct PendingReply * prev
struct RPSPeer * rps_peer
The peer that requested.
struct PendingReply * next
DLL next,prev ptr.
struct GNUNET_RPS_Request_Handle_Single_Info * req_handle
Handle to the request we are waiting for.
A pending request: A request was not made yet but is scheduled for later.
struct PendingRequest * next
DLL next,prev ptr.
struct RPSPeer * rps_peer
The peer that requested.
struct PendingRequest * prev
struct GNUNET_SCHEDULER_Task * request_task
Handle to the request we are waiting for.
Information we track for each peer.
struct PendingRequest * pending_req_tail
unsigned int num_pending_reps
Number of pending replies.
uint32_t stat_collected_flags
flags to indicate which statistics values have been already collected from the statistics service.
struct PendingReply * pending_rep_head
Pending replies DLL.
struct GNUNET_PeerIdentity * peer_id
ID of the peer.
unsigned int num_pending_reqs
Number of pending requests.
struct GNUNET_STATISTICS_Handle * stats_h
Handle to the statistics service.
struct PendingRequest * pending_req_head
Pending requests DLL.
const char * file_name_probs_hist
File name of the file the stats are finally written to.
double * eval_probs_cache
Keep the probabilities in cache for computing the probabilities with respect to history.
uint64_t stats[STAT_TYPE_MAX]
statistics values
const char * file_name_stats
File name of the file the stats are finally written to.
struct PendingReply * pending_rep_tail
const struct OpListEntry * entry_op_manage
Pending operation on that peer.
uint32_t count_in_views
Number of occurrences in other peer's view.
uint32_t index
Index of the peer.
struct GNUNET_STATISTICS_GetHandle * h_stat_get[STAT_TYPE_MAX]
Handle for the statistics get request.
struct GNUNET_PeerIdentity * cur_view
The current view.
int online
A request handle to check for an request.
uint32_t cur_view_count
Number of peers in the cur_view.
unsigned int num_ids_to_request
Number of Peer IDs to request during the whole test.
struct GNUNET_TESTBED_Operation * op
Handle for RPS connect operation.
struct GNUNET_RPS_Handle * rps_handle
Handle to RPS service.
const char * file_name_probs
File name of the file the stats are finally written to.
struct GNUNET_TESTBED_Operation * stat_op
Testbed operation to connect to statistics service.
unsigned int num_recv_ids
Number of received PeerIDs.
A sampler element sampling one PeerID at a time.
enum STAT_TYPE stat_type
struct RPSPeer * rps_peer
Structure to define a single test.
enum OPTION_COLLECT_STATISTICS have_collect_statistics
Collect statistics at the end?
uint32_t num_requests
Number of Requests to make.
EvaluationCallback eval_cb
Function to evaluate the test results.
uint32_t request_interval
Request interval.
MainTest main_test
Main function for each peer.
enum OPTION_COLLECT_VIEW have_collect_view
Collect view during run?
PostTest post_test
Called directly before disconnecting from the service.
uint32_t stat_collect_flags
Mark which values from the statistics service to collect at the end of the run.
enum OPTION_QUICK_QUIT have_quick_quit
Quit test before timeout?
char * name
Name of the test.
ReplyHandle reply_handle
Callback called once the requested peers are available.
enum OPTION_CHURN have_churn
Run with (-out) churn.
InitPeer init_peer
Called with a single peer in order to initialise that peer.
PreTest pre_test
Called directly after connecting to the service.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.