2 This file is part of GNUnet.
3 (C) 2010-2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file ats/perf_ats.c
22 * @brief ats benchmark: start peers and modify preferences, monitor change over time
23 * @author Christian Grothoff
24 * @author Matthias Wachs
27 #include "gnunet_util_lib.h"
28 #include "gnunet_testbed_service.h"
29 #include "gnunet_ats_service.h"
30 #include "gnunet_core_service.h"
32 #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
33 #define BENCHMARK_DURATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
34 #define TESTNAME_PREFIX "perf_ats_"
35 #define DEFAULT_SLAVES_NUM 3
36 #define DEFAULT_MASTERS_NUM 1
38 #define TEST_MESSAGE_TYPE_PING 12345
39 #define TEST_MESSAGE_TYPE_PONG 12346
40 #define TEST_MESSAGE_SIZE 1000
41 #define TEST_MESSAGE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
45 * Information we track for a peer in the testbed.
50 * Handle with testbed.
52 struct GNUNET_TESTBED_Peer *peer;
60 * master: GNUNET_YES/NO
67 struct GNUNET_PeerIdentity id;
72 struct GNUNET_CORE_Handle *ch;
75 * Testbed operation to connect to ATS performance service
77 struct GNUNET_TESTBED_Operation *ats_perf_op;
80 * Testbed operation to get peer information
82 struct GNUNET_TESTBED_Operation *info_op;
85 * Testbed operation to connect to core
87 struct GNUNET_TESTBED_Operation *core_op;
90 * ATS performance handle
92 struct GNUNET_ATS_PerformanceHandle *p_handle;
95 * Testbed connecect operation
97 struct ConnectOperation *connect_ops;
100 * ATS Measurement Partner
102 struct BenchmarkPeer *destination;
104 GNUNET_SCHEDULER_TaskIdentifier ats_task;
106 /* Message exchange */
109 * Core transmit handle
111 struct GNUNET_CORE_TransmitHandle *cth;
114 * DLL for pending messages: head
116 struct PendingMessages *p_head;
119 * DLL for pending messages: tail
121 struct PendingMessages *p_tail;
124 * Bit-mask for next partner selection
129 * Current message for partner?
134 * Number of core connections
136 int core_connections;
139 * Number of slave connections
141 int slave_connections;
146 unsigned int messages_sent;
147 unsigned int messages_sent_partner;
148 unsigned int messages_received;
152 static int c_master_peers;
155 * Array of master peers
156 * Preferences to be set for
158 static struct BenchmarkPeer *bp_master;
160 static int c_slave_peers;
163 * Array of slave peers
164 * Peer used for measurements
166 static struct BenchmarkPeer *bp_slaves;
169 struct BenchmarkState
171 /* Are we connected to ATS service of all peers: GNUNET_YES/NO */
172 int connected_ATS_service;
174 /* Are we connected to CORE service of all peers: GNUNET_YES/NO */
175 int connected_CORE_service;
177 /* Are we connected to all peers: GNUNET_YES/NO */
180 /* Are we connected to all slave peers on CORE level: GNUNET_YES/NO */
183 /* Are we connected to CORE service of all peers: GNUNET_YES/NO */
186 int *core_connections;
188 uint32_t partner_map;
191 static struct BenchmarkState state;
196 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
200 static char *preference;
205 struct PendingMessages
207 struct PendingMessages *prev;
208 struct PendingMessages *next;
209 struct GNUNET_PeerIdentity target;
214 * Information we track for a peer in the testbed.
216 struct ConnectOperation
218 struct BenchmarkPeer *master;
220 struct BenchmarkPeer *slave;
222 * Testbed operation to connect peers
224 struct GNUNET_TESTBED_Operation *connect_op;
230 core_connect_completion_cb (void *cls,
231 struct GNUNET_TESTBED_Operation *op,
236 static void evaluate ()
239 struct BenchmarkPeer *bp;
243 for (c_p = 0; c_p < c_master_peers; c_p++)
245 bp = &bp_master[c_p];
246 total_out = (bp->messages_sent * TEST_MESSAGE_SIZE) / 10240;
247 partner_out = (bp->messages_sent_partner * TEST_MESSAGE_SIZE) / 10240;
248 fprintf (stderr, _("Peer %u: Out total: %u KiB/s, out partner %u KiB/s\n"),
250 total_out, partner_out
251 /*partner_out / (total_out / 100)*/);
259 * @param tc the task context
262 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
266 struct PendingMessages *cur;
267 struct PendingMessages *next;
269 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
271 state.benchmarking = GNUNET_NO;
274 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n"));
276 for (c_p = 0; c_p < c_master_peers; c_p++)
278 next = bp_master[c_p].p_head;
279 for (cur = next; cur != NULL; cur = next )
282 GNUNET_CONTAINER_DLL_remove (bp_master[c_p].p_head, bp_master[c_p].p_tail, cur);
286 if (GNUNET_SCHEDULER_NO_TASK != bp_master[c_p].ats_task)
288 GNUNET_SCHEDULER_cancel (bp_master[c_p].ats_task);
289 bp_master[c_p].ats_task = GNUNET_SCHEDULER_NO_TASK;
292 if (NULL != bp_master[c_p].cth)
294 GNUNET_CORE_notify_transmit_ready_cancel(bp_master[c_p].cth);
295 bp_master[c_p].cth = NULL;
298 if (NULL != bp_master[c_p].ats_perf_op)
300 GNUNET_TESTBED_operation_done (bp_master[c_p].ats_perf_op);
301 bp_master[c_p].ats_perf_op = NULL;
304 if (NULL != bp_master[c_p].core_op)
306 GNUNET_TESTBED_operation_done (bp_master[c_p].core_op);
307 bp_master[c_p].core_op = NULL;
310 if (NULL != bp_master[c_p].info_op)
313 GNUNET_TESTBED_operation_done (bp_master[c_p].info_op);
314 bp_master[c_p].info_op = NULL;
317 for (c_op = 0; c_op < c_slave_peers; c_op++)
319 if (NULL != bp_master[c_p].connect_ops[c_op].connect_op)
321 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Failed to connect peer 0 and %u\n"), c_p);
322 GNUNET_TESTBED_operation_done (bp_master[c_p].connect_ops[c_op].connect_op);
323 bp_master[c_p].connect_ops[c_op].connect_op = NULL;
327 GNUNET_free (bp_master[c_p].connect_ops);
330 for (c_p = 0; c_p < c_slave_peers; c_p++)
332 next = bp_slaves[c_p].p_head;
333 for (cur = next; cur != NULL; cur = next )
336 GNUNET_CONTAINER_DLL_remove (bp_slaves[c_p].p_head, bp_slaves[c_p].p_tail, cur);
340 if (NULL != bp_slaves[c_p].cth)
342 GNUNET_CORE_notify_transmit_ready_cancel(bp_slaves[c_p].cth);
343 bp_slaves[c_p].cth = NULL;
346 if (NULL != bp_slaves[c_p].ats_perf_op)
348 GNUNET_TESTBED_operation_done (bp_slaves[c_p].ats_perf_op);
349 bp_slaves[c_p].ats_perf_op = NULL;
352 if (NULL != bp_slaves[c_p].core_op)
354 GNUNET_TESTBED_operation_done (bp_slaves[c_p].core_op);
355 bp_slaves[c_p].core_op = NULL;
358 if (NULL != bp_slaves[c_p].info_op)
361 GNUNET_TESTBED_operation_done (bp_slaves[c_p].info_op);
362 bp_slaves[c_p].info_op = NULL;
367 GNUNET_SCHEDULER_shutdown();
370 static struct BenchmarkPeer *
371 find_peer (const struct GNUNET_PeerIdentity * peer)
375 for (c_p = 0; c_p < c_master_peers; c_p++)
377 if (0 == memcmp (&bp_master[c_p].id, peer, sizeof (struct GNUNET_PeerIdentity)))
378 return &bp_master[c_p];
381 for (c_p = 0; c_p < c_slave_peers; c_p++)
383 if (0 == memcmp (&bp_slaves[c_p].id, peer, sizeof (struct GNUNET_PeerIdentity)))
384 return &bp_slaves[c_p];
392 store_information (struct GNUNET_PeerIdentity *id,
393 const struct GNUNET_HELLO_Address *address,
395 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
396 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
397 const struct GNUNET_ATS_Information *ats,
400 struct BenchmarkPeer *bp;
412 ats_performance_info_cb (void *cls,
413 const struct GNUNET_HELLO_Address *address,
415 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
416 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
417 const struct GNUNET_ATS_Information *ats,
420 struct BenchmarkPeer *bp = cls;
424 peer_id = GNUNET_strdup (GNUNET_i2s (&bp->id));
425 for (c_a = 0; c_a < ats_count; c_a++)
427 /*GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("%c %03u: %s %s %u\n"),
428 (GNUNET_YES == p->master) ? 'M' : 'S',
430 GNUNET_i2s (&address->peer),
431 GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)),
432 ntohl(ats[c_a].value));*/
435 if ((GNUNET_YES == bp->master) &&
436 (0 == memcmp (&address->peer, &bp->destination->id,
437 sizeof (struct GNUNET_PeerIdentity))))
439 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Bandwidth for master %u: %lu %lu\n",
441 (long unsigned int) ntohl(bandwidth_in.value__),
442 (long unsigned int) ntohl(bandwidth_in.value__));
445 store_information (&bp->id, address, address_active,
446 bandwidth_in, bandwidth_out,
449 GNUNET_free (peer_id);
453 core_send_ready (void *cls, size_t size, void *buf)
455 static char msgbuf[TEST_MESSAGE_SIZE];
456 struct BenchmarkPeer *bp = cls;
457 struct GNUNET_MessageHeader *msg;
461 bp->messages_sent ++;
462 if (GNUNET_YES == bp->partner_msg)
464 bp->messages_sent_partner ++;
465 bp->partner_msg = GNUNET_NO;
468 msg = (struct GNUNET_MessageHeader *) &msgbuf;
469 memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
470 msg->type = htons (TEST_MESSAGE_TYPE_PING);
471 msg->size = htons (TEST_MESSAGE_SIZE);
472 memcpy (buf, msg, TEST_MESSAGE_SIZE);
473 return TEST_MESSAGE_SIZE;
476 static struct BenchmarkPeer *
477 get_next (struct BenchmarkPeer *p)
483 if (0 == p->send_mask)
484 p->send_mask = (1 << c_slave_peers) - 1; /* Next round */
486 GNUNET_assert (p->send_mask <= (1 << c_slave_peers) - 1);
490 index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, c_slave_peers);
491 b_index = 1 << index;
494 while ((b_index != (p->send_mask & b_index)) && (counter < c_slave_peers));
495 if ((b_index != (p->send_mask & b_index)) && (counter == c_slave_peers))
497 /* To many random attempts use fcfs */
498 for (index = 0; index < c_slave_peers - 1; index ++)
500 b_index = 1 << index;
501 if (b_index == (p->send_mask & b_index))
505 p->send_mask ^= b_index; /* Remove bit */
506 return &bp_slaves[index];
512 ats_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
514 static double last = 1;
515 struct BenchmarkPeer *bp = cls;
517 bp->ats_task = GNUNET_SCHEDULER_NO_TASK;
519 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Set preference for master %u: %f\n",
521 GNUNET_ATS_performance_change_preference (bp->p_handle, &bp->destination->id,
522 GNUNET_ATS_PREFERENCE_BANDWIDTH, (double) last,
523 GNUNET_ATS_PREFERENCE_END);
525 bp->ats_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
534 struct BenchmarkPeer *s;
535 struct BenchmarkPeer *bp;
537 if ((state.connected_ATS_service == GNUNET_NO) ||
538 (state.connected_CORE_service == GNUNET_NO) ||
539 (state.connected_PEERS == GNUNET_NO) ||
540 (state.connected_CORE == GNUNET_NO))
543 state.benchmarking = GNUNET_YES;
544 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
545 _("Benchmarking start\n"));
547 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
548 GNUNET_SCHEDULER_cancel (shutdown_task);
549 shutdown_task = GNUNET_SCHEDULER_add_delayed (BENCHMARK_DURATION, &do_shutdown, NULL);
551 /* Start sending test messages */
552 for (c_m = 0; c_m < c_master_peers; c_m ++)
554 bp = &bp_master[c_m];
556 if (0 == memcmp(&s->id, &bp->destination->id, sizeof (struct GNUNET_PeerIdentity)))
557 bp->partner_msg = GNUNET_YES;
558 bp->cth = GNUNET_CORE_notify_transmit_ready (bp->ch,
559 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
561 TEST_MESSAGE_SIZE, &core_send_ready, bp);
562 bp->ats_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
571 connect_completion_callback (void *cls,
572 struct GNUNET_TESTBED_Operation *op,
575 struct ConnectOperation *cop = cls;
580 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
581 _("Connected master peer %u with peer %u\n"), cop->master->no, cop->slave->no);
585 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
586 _("Failed to connect master peer%u with peer %u\n"), cop->master->no, cop->slave->no);
588 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
589 GNUNET_SCHEDULER_cancel(shutdown_task);
590 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
592 GNUNET_TESTBED_operation_done(op);
594 for (c = 0; c < c_slave_peers; c++)
596 if (cop == &cop->master->connect_ops[c])
597 cop->master->connect_ops[c].connect_op = NULL;
599 if (ops == c_master_peers * c_slave_peers)
601 state.connected_PEERS = GNUNET_YES;
602 GNUNET_SCHEDULER_add_now (&do_benchmark, NULL);
608 do_connect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
612 struct BenchmarkPeer *bp;
614 if ((state.connected_ATS_service == GNUNET_NO) ||
615 (state.connected_CORE_service == GNUNET_NO))
620 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connecting peers on CORE level\n"));
622 for (c_m = 0; c_m < c_master_peers; c_m ++)
624 bp = &bp_master[c_m];
625 bp->connect_ops = GNUNET_malloc (c_slave_peers * sizeof (struct ConnectOperation));
627 for (c_s = 0; c_s < c_slave_peers; c_s ++)
629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Connecting master peer %u with slave peer %u\n"),
630 bp->no, bp_slaves[c_s].no);
632 bp->connect_ops[c_s].master = bp;
633 bp->connect_ops[c_s].slave = &bp_slaves[c_s];
634 bp->connect_ops[c_s].connect_op = GNUNET_TESTBED_overlay_connect( NULL,
635 &connect_completion_callback,
636 &bp->connect_ops[c_s],
640 if (NULL == bp->connect_ops[c_s].connect_op)
642 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
643 _("Could not connect master peer %u and slave peer %u\n"),
644 bp->no, bp_slaves[c_s].no);
646 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
647 GNUNET_SCHEDULER_cancel(shutdown_task);
648 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
657 * Controller event callback
660 * @param event the controller event
663 controller_event_cb (void *cls,
664 const struct GNUNET_TESTBED_EventInformation *event)
666 //struct BenchmarkPeer *p = cls;
669 case GNUNET_TESTBED_ET_CONNECT:
671 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
676 GNUNET_SCHEDULER_cancel (shutdown_task);
677 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
682 * Method called whenever a given peer connects.
685 * @param peer peer identity this notification is about
688 core_connect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
690 struct BenchmarkPeer *p = cls;
691 struct BenchmarkPeer *t;
696 id = GNUNET_strdup (GNUNET_i2s (&p->id));
698 t = find_peer (peer);
705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
706 "%s %s connected to %s %s\n",
707 (p->master == GNUNET_YES) ? "Master": "Slave",
709 (t->master == GNUNET_YES) ? "Master": "Slave",
712 p->core_connections ++;
713 if ((GNUNET_YES == p->master) && (GNUNET_NO == t->master) && (GNUNET_NO == state.connected_CORE))
715 p->slave_connections ++;
717 if (p->slave_connections == c_slave_peers)
719 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
720 "Master %u connected all slaves\n", p->no);
723 for (c = 0; c < c_master_peers; c ++)
725 if (bp_master[c].slave_connections != c_slave_peers)
728 if (GNUNET_YES == cs)
730 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
731 "All master peers connected all slave peers\n", id, GNUNET_i2s (peer));
732 state.connected_CORE = GNUNET_YES;
733 GNUNET_SCHEDULER_add_now (&do_benchmark, NULL);
741 * Method called whenever a peer disconnects.
744 * @param peer peer identity this notification is about
747 core_disconnect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
749 struct BenchmarkPeer *p = cls;
750 struct BenchmarkPeer *t;
753 t = find_peer (peer);
760 id = GNUNET_strdup (GNUNET_i2s (&p->id));
761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
762 "%s disconnected from %s \n", id, GNUNET_i2s (peer));
763 GNUNET_assert (p->core_connections > 0);
764 p->core_connections --;
766 if ((GNUNET_YES == state.benchmarking) &&
767 ((GNUNET_YES == p->master) || (GNUNET_YES == t->master)))
769 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
770 "%s disconnected from %s while benchmarking \n", id, GNUNET_i2s (peer));
777 core_send_echo_queued_ready (void *cls, size_t size, void *buf);
780 core_send_echo_ready (void *cls, size_t size, void *buf)
782 static char msgbuf[TEST_MESSAGE_SIZE];
783 struct BenchmarkPeer *bp = cls;
784 struct GNUNET_MessageHeader *msg;
788 msg = (struct GNUNET_MessageHeader *) &msgbuf;
789 memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
790 msg->type = htons (TEST_MESSAGE_TYPE_PONG);
791 msg->size = htons (TEST_MESSAGE_SIZE);
792 memcpy (buf, msg, TEST_MESSAGE_SIZE);
795 if (NULL != bp->p_head)
796 bp->cth = GNUNET_CORE_notify_transmit_ready (bp->ch,
797 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
799 TEST_MESSAGE_SIZE, &core_send_echo_queued_ready, bp);
801 return TEST_MESSAGE_SIZE;
805 core_send_echo_queued_ready (void *cls, size_t size, void *buf)
807 struct BenchmarkPeer *bp = cls;
808 struct PendingMessages *pm;
809 GNUNET_assert (NULL != bp->p_head);
812 GNUNET_CONTAINER_DLL_remove (bp->p_head, bp->p_tail, pm);
816 return core_send_echo_ready (cls, size, buf);
822 core_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other,
823 const struct GNUNET_MessageHeader *message)
825 struct BenchmarkPeer *me = cls;
826 struct BenchmarkPeer *remote;
827 struct PendingMessages *pm;
829 remote = find_peer (other);
834 return GNUNET_SYSERR;
839 pm = GNUNET_malloc (sizeof (struct PendingMessages));
840 pm->target = (*other);
841 GNUNET_CONTAINER_DLL_insert_tail (me->p_head, me->p_tail, pm);
845 if (GNUNET_NO == remote->master)
851 me->messages_received ++;
853 me->cth = GNUNET_CORE_notify_transmit_ready (me->ch,
854 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
856 TEST_MESSAGE_SIZE, &core_send_echo_ready, me);
861 core_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other,
862 const struct GNUNET_MessageHeader *message)
864 struct BenchmarkPeer *me = cls;
865 struct BenchmarkPeer *remote;
866 struct BenchmarkPeer *next;
868 remote = find_peer (other);
873 return GNUNET_SYSERR;
882 if (GNUNET_YES == remote->master)
887 me->messages_received ++;
888 next = get_next (me);
889 if (0 == memcmp(&remote->id, &me->destination->id, sizeof (struct GNUNET_PeerIdentity)))
890 me->partner_msg = GNUNET_YES;
891 me->cth = GNUNET_CORE_notify_transmit_ready (me->ch,
892 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
894 TEST_MESSAGE_SIZE, &core_send_ready, me);
901 * Called to open a connection to the peer's ATS performance
903 * @param cls peer context
904 * @param cfg configuration of the peer to connect to; will be available until
905 * GNUNET_TESTBED_operation_done() is called on the operation returned
906 * from GNUNET_TESTBED_service_connect()
907 * @return service handle to return in 'op_result', NULL on error
910 core_connect_adapter (void *cls,
911 const struct GNUNET_CONFIGURATION_Handle *cfg)
913 struct BenchmarkPeer *peer = cls;
915 static const struct GNUNET_CORE_MessageHandler handlers[] = {
916 {&core_handle_ping, TEST_MESSAGE_TYPE_PING, 0},
917 {&core_handle_pong, TEST_MESSAGE_TYPE_PONG, 0},
921 peer->ch = GNUNET_CORE_connect(cfg, peer, NULL,
922 core_connect_cb, core_disconnect_cb,
923 NULL, GNUNET_NO, NULL, GNUNET_NO, handlers);
924 if (NULL == peer->ch)
925 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
926 "Failed to create core connection \n");
932 * Callback to be called when a service connect operation is completed
934 * @param cls the callback closure from functions generating an operation
935 * @param op the operation that has been finished
936 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
937 * @param emsg error message in case the operation has failed; will be NULL if
938 * operation has executed successfully.
941 core_connect_completion_cb (void *cls,
942 struct GNUNET_TESTBED_Operation *op,
946 static int core_done = 0;
947 if ((NULL != emsg) || (NULL == ca_result))
949 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
950 _("Initialization failed, shutdown\n"));
952 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
953 GNUNET_SCHEDULER_cancel(shutdown_task);
954 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
959 if (core_done == c_slave_peers + c_master_peers)
961 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
962 "Connected to all CORE services\n");
963 state.connected_CORE_service = GNUNET_YES;
964 GNUNET_SCHEDULER_add_now (&do_connect_peers, NULL);
970 * Called to disconnect from peer's statistics service
972 * @param cls peer context
973 * @param op_result service handle returned from the connect adapter
976 core_disconnect_adapter (void *cls, void *op_result)
978 struct BenchmarkPeer *peer = cls;
980 GNUNET_CORE_disconnect (peer->ch);
985 do_connect_core (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
988 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
989 "Connecting to all CORE services\n");
990 for (c_p = 0; c_p < c_master_peers; c_p++)
992 bp_master[c_p].core_op = GNUNET_TESTBED_service_connect (NULL,
993 bp_master[c_p].peer, "core",
994 core_connect_completion_cb, NULL,
995 &core_connect_adapter,
996 &core_disconnect_adapter,
1001 for (c_p = 0; c_p < c_slave_peers; c_p++)
1003 bp_slaves[c_p].core_op = GNUNET_TESTBED_service_connect (NULL,
1004 bp_slaves[c_p].peer, "core",
1005 core_connect_completion_cb, NULL,
1006 &core_connect_adapter,
1007 &core_disconnect_adapter,
1015 * Called to open a connection to the peer's ATS performance
1017 * @param cls peer context
1018 * @param cfg configuration of the peer to connect to; will be available until
1019 * GNUNET_TESTBED_operation_done() is called on the operation returned
1020 * from GNUNET_TESTBED_service_connect()
1021 * @return service handle to return in 'op_result', NULL on error
1024 ats_perf_connect_adapter (void *cls,
1025 const struct GNUNET_CONFIGURATION_Handle *cfg)
1027 struct BenchmarkPeer *peer = cls;
1029 peer->p_handle = GNUNET_ATS_performance_init (cfg, &ats_performance_info_cb, peer);
1030 if (NULL == peer->p_handle)
1031 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create ATS performance handle \n");
1032 return peer->p_handle;
1037 * Called to disconnect from peer's statistics service
1039 * @param cls peer context
1040 * @param op_result service handle returned from the connect adapter
1043 ats_perf_disconnect_adapter (void *cls, void *op_result)
1045 struct BenchmarkPeer *peer = cls;
1047 GNUNET_ATS_performance_done(peer->p_handle);
1048 peer->p_handle = NULL;
1053 * Callback to be called when a service connect operation is completed
1055 * @param cls the callback closure from functions generating an operation
1056 * @param op the operation that has been finished
1057 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
1058 * @param emsg error message in case the operation has failed; will be NULL if
1059 * operation has executed successfully.
1062 ats_connect_completion_cb (void *cls,
1063 struct GNUNET_TESTBED_Operation *op,
1067 static int op_done = 0;
1068 if ((NULL != emsg) || (NULL == ca_result))
1070 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1071 _("Initialization failed, shutdown\n"));
1073 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
1074 GNUNET_SCHEDULER_cancel(shutdown_task);
1075 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
1080 if (op_done == (c_slave_peers + c_master_peers))
1082 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1083 "Connected to all ATS services\n");
1084 state.connected_ATS_service = GNUNET_YES;
1085 GNUNET_SCHEDULER_add_now (&do_connect_core, NULL);
1090 do_connect_ats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1093 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1094 "Connecting to all ATS services %u\n", c_slave_peers);
1095 for (c_p = 0; c_p < c_master_peers; c_p++)
1097 bp_master[c_p].ats_perf_op = GNUNET_TESTBED_service_connect (NULL,
1098 bp_master[c_p].peer, "ats",
1099 ats_connect_completion_cb, NULL,
1100 &ats_perf_connect_adapter,
1101 &ats_perf_disconnect_adapter,
1106 for (c_p = 0; c_p < c_slave_peers; c_p++)
1108 bp_slaves[c_p].ats_perf_op = GNUNET_TESTBED_service_connect (NULL,
1109 bp_slaves[c_p].peer, "ats",
1110 ats_connect_completion_cb, NULL,
1111 &ats_perf_connect_adapter,
1112 &ats_perf_disconnect_adapter,
1120 * Callback to be called when the requested peer information is available
1122 * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
1123 * @param op the operation this callback corresponds to
1124 * @param pinfo the result; will be NULL if the operation has failed
1125 * @param emsg error message if the operation has failed; will be NULL if the
1126 * operation is successfull
1129 peerinformation_cb (void *cb_cls,
1130 struct GNUNET_TESTBED_Operation *op,
1131 const struct GNUNET_TESTBED_PeerInformation*pinfo,
1134 struct BenchmarkPeer *p = cb_cls;
1135 static int done = 0;
1137 if (pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY)
1139 p->id = *pinfo->result.id;
1140 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1141 "[%c %03u] Peers %s\n",
1142 (p->master == GNUNET_YES) ? 'M' : 'S', p->no, GNUNET_i2s (&p->id));
1148 GNUNET_TESTBED_operation_done (op);
1152 if (done == c_master_peers + c_slave_peers)
1154 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1155 "Retrieved all peer ID, connect to ATS\n");
1156 state.connected_CORE_service = GNUNET_YES;
1157 GNUNET_SCHEDULER_add_now (&do_connect_ats, NULL);
1163 * Signature of a main function for a testcase.
1165 * @param cls closure
1166 * @param num_peers number of peers in 'peers'
1167 * @param peers_ handle to peers run in the testbed
1168 * @param links_succeeded the number of overlay link connection attempts that
1170 * @param links_failed the number of overlay link connection attempts that
1174 test_main (void *cls, unsigned int num_peers,
1175 struct GNUNET_TESTBED_RunHandle *h,
1176 struct GNUNET_TESTBED_Peer **peers_,
1177 unsigned int links_succeeded,
1178 unsigned int links_failed)
1182 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1183 _("Benchmarking solver `%s' on preference `%s' with %u master and %u slave peers\n"),
1184 solver, preference, c_master_peers, c_slave_peers);
1186 shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(TEST_TIMEOUT, c_master_peers + c_slave_peers), &do_shutdown, NULL);
1188 GNUNET_assert (NULL == cls);
1189 GNUNET_assert (c_slave_peers + c_master_peers == num_peers);
1190 GNUNET_assert (NULL != peers_);
1192 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1193 _("Initializing... \n"));
1195 for (c_p = 0; c_p < c_master_peers; c_p++)
1197 GNUNET_assert (NULL != peers_[c_p]);
1198 bp_master[c_p].no = c_p;
1199 bp_master[c_p].send_mask = (1 << c_slave_peers) - 1;
1200 bp_master[c_p].master = GNUNET_YES;
1201 bp_master[c_p].peer = peers_[c_p];
1202 bp_master[c_p].info_op = GNUNET_TESTBED_peer_get_information (bp_master[c_p].peer,
1203 GNUNET_TESTBED_PIT_IDENTITY,
1204 &peerinformation_cb, &bp_master[c_p]);
1206 /* Select ATS measurement partner */
1207 bp_master[c_p].destination = &bp_slaves[c_p];
1210 for (c_p = 0; c_p < c_slave_peers; c_p++)
1212 GNUNET_assert (NULL != peers_[c_p + c_master_peers]);
1213 bp_slaves[c_p].no = c_p + c_master_peers;
1214 bp_slaves[c_p].master = GNUNET_NO;
1215 bp_slaves[c_p].peer = peers_[c_p + c_master_peers];
1216 bp_slaves[c_p].info_op = GNUNET_TESTBED_peer_get_information (bp_slaves[c_p].peer,
1217 GNUNET_TESTBED_PIT_IDENTITY,
1218 &peerinformation_cb, &bp_slaves[c_p]);
1225 main (int argc, char *argv[])
1236 /* figure out testname */
1237 tmp = strstr (argv[0], TESTNAME_PREFIX);
1240 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1241 return GNUNET_SYSERR;
1243 tmp += strlen(TESTNAME_PREFIX);
1244 solver = GNUNET_strdup (tmp);
1245 if (NULL != (dotexe = strstr (solver, ".exe")) &&
1248 tmp_sep = strchr (solver, '_');
1249 if (NULL == tmp_sep)
1251 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1252 GNUNET_free (solver);
1253 return GNUNET_SYSERR;
1256 preference = GNUNET_strdup(tmp_sep + 1);
1258 GNUNET_asprintf(&conf_name, "%s%s_%s.conf", TESTNAME_PREFIX, solver, preference);
1259 GNUNET_asprintf(&test_name, "%s%s_%s", TESTNAME_PREFIX, solver, preference);
1261 for (c = 0; c < (argc -1); c++)
1263 if (0 == strcmp(argv[c], "-s"))
1268 if ((0L != (c_slave_peers = strtol (argv[c + 1], NULL, 10))) && (c_slave_peers >= 1))
1269 fprintf (stderr, "Starting %u slave peers\n", c_slave_peers);
1271 c_slave_peers = DEFAULT_SLAVES_NUM;
1274 c_slave_peers = DEFAULT_SLAVES_NUM;
1276 for (c = 0; c < (argc -1); c++)
1278 if (0 == strcmp(argv[c], "-m"))
1283 if ((0L != (c_master_peers = strtol (argv[c + 1], NULL, 10))) && (c_master_peers >= 2))
1284 fprintf (stderr, "Starting %u master peers\n", c_master_peers);
1286 c_master_peers = DEFAULT_MASTERS_NUM;
1289 c_master_peers = DEFAULT_MASTERS_NUM;
1291 bp_slaves = GNUNET_malloc (c_slave_peers * sizeof (struct BenchmarkPeer));
1292 bp_master = GNUNET_malloc (c_master_peers * sizeof (struct BenchmarkPeer));
1294 state.connected_ATS_service = GNUNET_NO;
1295 state.connected_CORE_service = GNUNET_NO;
1296 state.connected_PEERS = GNUNET_NO;
1298 /* Start topology */
1299 uint64_t event_mask;
1301 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
1302 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
1303 (void) GNUNET_TESTBED_test_run (test_name,
1304 conf_name, c_slave_peers + c_master_peers,
1305 event_mask, &controller_event_cb, NULL,
1308 GNUNET_free (solver);
1309 GNUNET_free (preference);
1310 GNUNET_free (conf_name);
1311 GNUNET_free (test_name);
1312 GNUNET_free (bp_slaves);
1317 /* end of file perf_ats.c */