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 *pref_str;
206 struct PendingMessages
208 struct PendingMessages *prev;
209 struct PendingMessages *next;
210 struct GNUNET_PeerIdentity target;
215 * Information we track for a peer in the testbed.
217 struct ConnectOperation
219 struct BenchmarkPeer *master;
221 struct BenchmarkPeer *slave;
223 * Testbed operation to connect peers
225 struct GNUNET_TESTBED_Operation *connect_op;
231 core_connect_completion_cb (void *cls,
232 struct GNUNET_TESTBED_Operation *op,
237 static void evaluate ()
240 struct BenchmarkPeer *bp;
244 for (c_p = 0; c_p < c_master_peers; c_p++)
246 bp = &bp_master[c_p];
247 total_out = (bp->messages_sent * TEST_MESSAGE_SIZE) / 10240;
248 partner_out = (bp->messages_sent_partner * TEST_MESSAGE_SIZE) / 10240;
249 fprintf (stderr, _("Peer %u: Out total: %u KiB/s, out partner %u KiB/s\n"),
251 total_out, partner_out
252 /*partner_out / (total_out / 100)*/);
260 * @param tc the task context
263 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
267 struct PendingMessages *cur;
268 struct PendingMessages *next;
270 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
272 state.benchmarking = GNUNET_NO;
275 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n"));
277 for (c_p = 0; c_p < c_master_peers; c_p++)
279 next = bp_master[c_p].p_head;
280 for (cur = next; cur != NULL; cur = next )
283 GNUNET_CONTAINER_DLL_remove (bp_master[c_p].p_head, bp_master[c_p].p_tail, cur);
287 if (GNUNET_SCHEDULER_NO_TASK != bp_master[c_p].ats_task)
289 GNUNET_SCHEDULER_cancel (bp_master[c_p].ats_task);
290 bp_master[c_p].ats_task = GNUNET_SCHEDULER_NO_TASK;
293 if (NULL != bp_master[c_p].cth)
295 GNUNET_CORE_notify_transmit_ready_cancel(bp_master[c_p].cth);
296 bp_master[c_p].cth = NULL;
299 if (NULL != bp_master[c_p].ats_perf_op)
301 GNUNET_TESTBED_operation_done (bp_master[c_p].ats_perf_op);
302 bp_master[c_p].ats_perf_op = NULL;
305 if (NULL != bp_master[c_p].core_op)
307 GNUNET_TESTBED_operation_done (bp_master[c_p].core_op);
308 bp_master[c_p].core_op = NULL;
311 if (NULL != bp_master[c_p].info_op)
314 GNUNET_TESTBED_operation_done (bp_master[c_p].info_op);
315 bp_master[c_p].info_op = NULL;
318 for (c_op = 0; c_op < c_slave_peers; c_op++)
320 if (NULL != bp_master[c_p].connect_ops[c_op].connect_op)
322 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Failed to connect peer 0 and %u\n"), c_p);
323 GNUNET_TESTBED_operation_done (bp_master[c_p].connect_ops[c_op].connect_op);
324 bp_master[c_p].connect_ops[c_op].connect_op = NULL;
328 GNUNET_free (bp_master[c_p].connect_ops);
331 for (c_p = 0; c_p < c_slave_peers; c_p++)
333 next = bp_slaves[c_p].p_head;
334 for (cur = next; cur != NULL; cur = next )
337 GNUNET_CONTAINER_DLL_remove (bp_slaves[c_p].p_head, bp_slaves[c_p].p_tail, cur);
341 if (NULL != bp_slaves[c_p].cth)
343 GNUNET_CORE_notify_transmit_ready_cancel(bp_slaves[c_p].cth);
344 bp_slaves[c_p].cth = NULL;
347 if (NULL != bp_slaves[c_p].ats_perf_op)
349 GNUNET_TESTBED_operation_done (bp_slaves[c_p].ats_perf_op);
350 bp_slaves[c_p].ats_perf_op = NULL;
353 if (NULL != bp_slaves[c_p].core_op)
355 GNUNET_TESTBED_operation_done (bp_slaves[c_p].core_op);
356 bp_slaves[c_p].core_op = NULL;
359 if (NULL != bp_slaves[c_p].info_op)
362 GNUNET_TESTBED_operation_done (bp_slaves[c_p].info_op);
363 bp_slaves[c_p].info_op = NULL;
368 GNUNET_SCHEDULER_shutdown();
371 static struct BenchmarkPeer *
372 find_peer (const struct GNUNET_PeerIdentity * peer)
376 for (c_p = 0; c_p < c_master_peers; c_p++)
378 if (0 == memcmp (&bp_master[c_p].id, peer, sizeof (struct GNUNET_PeerIdentity)))
379 return &bp_master[c_p];
382 for (c_p = 0; c_p < c_slave_peers; c_p++)
384 if (0 == memcmp (&bp_slaves[c_p].id, peer, sizeof (struct GNUNET_PeerIdentity)))
385 return &bp_slaves[c_p];
393 store_information (struct GNUNET_PeerIdentity *id,
394 const struct GNUNET_HELLO_Address *address,
396 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
397 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
398 const struct GNUNET_ATS_Information *ats,
401 struct BenchmarkPeer *bp;
413 ats_performance_info_cb (void *cls,
414 const struct GNUNET_HELLO_Address *address,
416 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
417 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
418 const struct GNUNET_ATS_Information *ats,
421 struct BenchmarkPeer *bp = cls;
425 peer_id = GNUNET_strdup (GNUNET_i2s (&bp->id));
426 for (c_a = 0; c_a < ats_count; c_a++)
428 /*GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("%c %03u: %s %s %u\n"),
429 (GNUNET_YES == p->master) ? 'M' : 'S',
431 GNUNET_i2s (&address->peer),
432 GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)),
433 ntohl(ats[c_a].value));*/
436 if ((GNUNET_YES == bp->master) &&
437 (0 == memcmp (&address->peer, &bp->destination->id,
438 sizeof (struct GNUNET_PeerIdentity))))
440 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Bandwidth for master %u: %lu %lu\n",
442 (long unsigned int) ntohl(bandwidth_in.value__),
443 (long unsigned int) ntohl(bandwidth_in.value__));
446 store_information (&bp->id, address, address_active,
447 bandwidth_in, bandwidth_out,
450 GNUNET_free (peer_id);
454 core_send_ready (void *cls, size_t size, void *buf)
456 static char msgbuf[TEST_MESSAGE_SIZE];
457 struct BenchmarkPeer *bp = cls;
458 struct GNUNET_MessageHeader *msg;
462 bp->messages_sent ++;
463 if (GNUNET_YES == bp->partner_msg)
465 bp->messages_sent_partner ++;
466 bp->partner_msg = GNUNET_NO;
469 msg = (struct GNUNET_MessageHeader *) &msgbuf;
470 memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
471 msg->type = htons (TEST_MESSAGE_TYPE_PING);
472 msg->size = htons (TEST_MESSAGE_SIZE);
473 memcpy (buf, msg, TEST_MESSAGE_SIZE);
474 return TEST_MESSAGE_SIZE;
477 static struct BenchmarkPeer *
478 get_next (struct BenchmarkPeer *p)
484 if (0 == p->send_mask)
485 p->send_mask = (1 << c_slave_peers) - 1; /* Next round */
487 GNUNET_assert (p->send_mask <= (1 << c_slave_peers) - 1);
491 index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, c_slave_peers);
492 b_index = 1 << index;
495 while ((b_index != (p->send_mask & b_index)) && (counter < c_slave_peers));
496 if ((b_index != (p->send_mask & b_index)) && (counter == c_slave_peers))
498 /* To many random attempts use fcfs */
499 for (index = 0; index < c_slave_peers - 1; index ++)
501 b_index = 1 << index;
502 if (b_index == (p->send_mask & b_index))
506 p->send_mask ^= b_index; /* Remove bit */
507 return &bp_slaves[index];
513 ats_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
515 static double last = 1;
516 struct BenchmarkPeer *bp = cls;
518 bp->ats_task = GNUNET_SCHEDULER_NO_TASK;
520 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Set preference for master %u: %f\n",
522 GNUNET_ATS_performance_change_preference (bp->p_handle, &bp->destination->id,
523 pref_val, (double) last,
524 GNUNET_ATS_PREFERENCE_END);
526 bp->ats_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
535 struct BenchmarkPeer *s;
536 struct BenchmarkPeer *bp;
538 if ((state.connected_ATS_service == GNUNET_NO) ||
539 (state.connected_CORE_service == GNUNET_NO) ||
540 (state.connected_PEERS == GNUNET_NO) ||
541 (state.connected_CORE == GNUNET_NO))
544 state.benchmarking = GNUNET_YES;
545 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
546 _("Benchmarking start\n"));
548 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
549 GNUNET_SCHEDULER_cancel (shutdown_task);
550 shutdown_task = GNUNET_SCHEDULER_add_delayed (BENCHMARK_DURATION, &do_shutdown, NULL);
552 /* Start sending test messages */
553 for (c_m = 0; c_m < c_master_peers; c_m ++)
555 bp = &bp_master[c_m];
557 if (0 == memcmp(&s->id, &bp->destination->id, sizeof (struct GNUNET_PeerIdentity)))
558 bp->partner_msg = GNUNET_YES;
559 bp->cth = GNUNET_CORE_notify_transmit_ready (bp->ch,
560 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
562 TEST_MESSAGE_SIZE, &core_send_ready, bp);
563 bp->ats_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
572 connect_completion_callback (void *cls,
573 struct GNUNET_TESTBED_Operation *op,
576 struct ConnectOperation *cop = cls;
581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
582 _("Connected master peer %u with peer %u\n"), cop->master->no, cop->slave->no);
586 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
587 _("Failed to connect master peer%u with peer %u\n"), cop->master->no, cop->slave->no);
589 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
590 GNUNET_SCHEDULER_cancel(shutdown_task);
591 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
593 GNUNET_TESTBED_operation_done(op);
595 for (c = 0; c < c_slave_peers; c++)
597 if (cop == &cop->master->connect_ops[c])
598 cop->master->connect_ops[c].connect_op = NULL;
600 if (ops == c_master_peers * c_slave_peers)
602 state.connected_PEERS = GNUNET_YES;
603 GNUNET_SCHEDULER_add_now (&do_benchmark, NULL);
609 do_connect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
613 struct BenchmarkPeer *bp;
615 if ((state.connected_ATS_service == GNUNET_NO) ||
616 (state.connected_CORE_service == GNUNET_NO))
621 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connecting peers on CORE level\n"));
623 for (c_m = 0; c_m < c_master_peers; c_m ++)
625 bp = &bp_master[c_m];
626 bp->connect_ops = GNUNET_malloc (c_slave_peers * sizeof (struct ConnectOperation));
628 for (c_s = 0; c_s < c_slave_peers; c_s ++)
630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Connecting master peer %u with slave peer %u\n"),
631 bp->no, bp_slaves[c_s].no);
633 bp->connect_ops[c_s].master = bp;
634 bp->connect_ops[c_s].slave = &bp_slaves[c_s];
635 bp->connect_ops[c_s].connect_op = GNUNET_TESTBED_overlay_connect( NULL,
636 &connect_completion_callback,
637 &bp->connect_ops[c_s],
641 if (NULL == bp->connect_ops[c_s].connect_op)
643 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
644 _("Could not connect master peer %u and slave peer %u\n"),
645 bp->no, bp_slaves[c_s].no);
647 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
648 GNUNET_SCHEDULER_cancel(shutdown_task);
649 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
658 * Controller event callback
661 * @param event the controller event
664 controller_event_cb (void *cls,
665 const struct GNUNET_TESTBED_EventInformation *event)
667 //struct BenchmarkPeer *p = cls;
670 case GNUNET_TESTBED_ET_CONNECT:
672 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
677 GNUNET_SCHEDULER_cancel (shutdown_task);
678 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
683 * Method called whenever a given peer connects.
686 * @param peer peer identity this notification is about
689 core_connect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
691 struct BenchmarkPeer *p = cls;
692 struct BenchmarkPeer *t;
697 t = find_peer (peer);
704 id = GNUNET_strdup (GNUNET_i2s (&p->id));
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,
1175 struct GNUNET_TESTBED_RunHandle *h,
1176 unsigned int num_peers,
1177 struct GNUNET_TESTBED_Peer **peers_,
1178 unsigned int links_succeeded,
1179 unsigned int links_failed)
1183 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1184 _("Benchmarking solver `%s' on preference `%s' with %u master and %u slave peers\n"),
1185 solver, pref_str, c_master_peers, c_slave_peers);
1187 shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(TEST_TIMEOUT, c_master_peers + c_slave_peers), &do_shutdown, NULL);
1189 GNUNET_assert (NULL == cls);
1190 GNUNET_assert (c_slave_peers + c_master_peers == num_peers);
1191 GNUNET_assert (NULL != peers_);
1193 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1194 _("Initializing... \n"));
1196 for (c_p = 0; c_p < c_master_peers; c_p++)
1198 GNUNET_assert (NULL != peers_[c_p]);
1199 bp_master[c_p].no = c_p;
1200 bp_master[c_p].send_mask = (1 << c_slave_peers) - 1;
1201 bp_master[c_p].master = GNUNET_YES;
1202 bp_master[c_p].peer = peers_[c_p];
1203 bp_master[c_p].info_op = GNUNET_TESTBED_peer_get_information (bp_master[c_p].peer,
1204 GNUNET_TESTBED_PIT_IDENTITY,
1205 &peerinformation_cb, &bp_master[c_p]);
1207 /* Select ATS measurement partner */
1208 bp_master[c_p].destination = &bp_slaves[c_p];
1211 for (c_p = 0; c_p < c_slave_peers; c_p++)
1213 GNUNET_assert (NULL != peers_[c_p + c_master_peers]);
1214 bp_slaves[c_p].no = c_p + c_master_peers;
1215 bp_slaves[c_p].master = GNUNET_NO;
1216 bp_slaves[c_p].peer = peers_[c_p + c_master_peers];
1217 bp_slaves[c_p].info_op = GNUNET_TESTBED_peer_get_information (bp_slaves[c_p].peer,
1218 GNUNET_TESTBED_PIT_IDENTITY,
1219 &peerinformation_cb, &bp_slaves[c_p]);
1226 main (int argc, char *argv[])
1233 char *prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
1238 /* figure out testname */
1239 tmp = strstr (argv[0], TESTNAME_PREFIX);
1242 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1243 return GNUNET_SYSERR;
1245 tmp += strlen(TESTNAME_PREFIX);
1246 solver = GNUNET_strdup (tmp);
1247 if (NULL != (dotexe = strstr (solver, ".exe")) &&
1250 tmp_sep = strchr (solver, '_');
1251 if (NULL == tmp_sep)
1253 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1254 GNUNET_free (solver);
1255 return GNUNET_SYSERR;
1258 pref_str = GNUNET_strdup(tmp_sep + 1);
1260 GNUNET_asprintf(&conf_name, "%s%s_%s.conf", TESTNAME_PREFIX, solver, pref_str);
1261 GNUNET_asprintf(&test_name, "%s%s_%s", TESTNAME_PREFIX, solver, pref_str);
1263 for (c = 0; c <= strlen (pref_str); c++)
1265 pref_str[c] = toupper(pref_str[c]);
1268 for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
1270 if (0 == strcmp (pref_str, prefs[c]))
1278 fprintf (stderr, "Unknown preference: `%s'\n", pref_str);
1279 GNUNET_free (solver);
1280 GNUNET_free (pref_str);
1284 for (c = 0; c < (argc -1); c++)
1286 if (0 == strcmp(argv[c], "-s"))
1291 if ((0L != (c_slave_peers = strtol (argv[c + 1], NULL, 10))) && (c_slave_peers >= 1))
1292 fprintf (stderr, "Starting %u slave peers\n", c_slave_peers);
1294 c_slave_peers = DEFAULT_SLAVES_NUM;
1297 c_slave_peers = DEFAULT_SLAVES_NUM;
1299 for (c = 0; c < (argc -1); c++)
1301 if (0 == strcmp(argv[c], "-m"))
1306 if ((0L != (c_master_peers = strtol (argv[c + 1], NULL, 10))) && (c_master_peers >= 2))
1307 fprintf (stderr, "Starting %u master peers\n", c_master_peers);
1309 c_master_peers = DEFAULT_MASTERS_NUM;
1312 c_master_peers = DEFAULT_MASTERS_NUM;
1314 bp_slaves = GNUNET_malloc (c_slave_peers * sizeof (struct BenchmarkPeer));
1315 bp_master = GNUNET_malloc (c_master_peers * sizeof (struct BenchmarkPeer));
1317 state.connected_ATS_service = GNUNET_NO;
1318 state.connected_CORE_service = GNUNET_NO;
1319 state.connected_PEERS = GNUNET_NO;
1321 /* Start topology */
1322 uint64_t event_mask;
1324 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
1325 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
1326 (void) GNUNET_TESTBED_test_run (test_name,
1327 conf_name, c_slave_peers + c_master_peers,
1328 event_mask, &controller_event_cb, NULL,
1331 GNUNET_free (solver);
1332 GNUNET_free (pref_str);
1333 GNUNET_free (conf_name);
1334 GNUNET_free (test_name);
1335 GNUNET_free (bp_slaves);
1340 /* end of file perf_ats.c */