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;
250 fprintf (stderr, _("Master peer %u: Out total: %u KiB/s, out partner %u KiB/s\n"),
252 total_out, partner_out
253 /*partner_out / (total_out / 100)*/);
261 * @param tc the task context
264 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
268 struct PendingMessages *cur;
269 struct PendingMessages *next;
271 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
273 state.benchmarking = GNUNET_NO;
276 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n"));
278 for (c_p = 0; c_p < c_master_peers; c_p++)
280 next = bp_master[c_p].p_head;
281 for (cur = next; cur != NULL; cur = next )
284 GNUNET_CONTAINER_DLL_remove (bp_master[c_p].p_head, bp_master[c_p].p_tail, cur);
288 if (GNUNET_SCHEDULER_NO_TASK != bp_master[c_p].ats_task)
290 GNUNET_SCHEDULER_cancel (bp_master[c_p].ats_task);
291 bp_master[c_p].ats_task = GNUNET_SCHEDULER_NO_TASK;
294 if (NULL != bp_master[c_p].cth)
296 GNUNET_CORE_notify_transmit_ready_cancel(bp_master[c_p].cth);
297 bp_master[c_p].cth = NULL;
300 if (NULL != bp_master[c_p].ats_perf_op)
302 GNUNET_TESTBED_operation_done (bp_master[c_p].ats_perf_op);
303 bp_master[c_p].ats_perf_op = NULL;
306 if (NULL != bp_master[c_p].core_op)
308 GNUNET_TESTBED_operation_done (bp_master[c_p].core_op);
309 bp_master[c_p].core_op = NULL;
312 if (NULL != bp_master[c_p].info_op)
315 GNUNET_TESTBED_operation_done (bp_master[c_p].info_op);
316 bp_master[c_p].info_op = NULL;
319 for (c_op = 0; c_op < c_slave_peers; c_op++)
321 if (NULL != bp_master[c_p].connect_ops[c_op].connect_op)
323 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Failed to connect peer 0 and %u\n"), c_p);
324 GNUNET_TESTBED_operation_done (bp_master[c_p].connect_ops[c_op].connect_op);
325 bp_master[c_p].connect_ops[c_op].connect_op = NULL;
329 GNUNET_free (bp_master[c_p].connect_ops);
332 for (c_p = 0; c_p < c_slave_peers; c_p++)
334 next = bp_slaves[c_p].p_head;
335 for (cur = next; cur != NULL; cur = next )
338 GNUNET_CONTAINER_DLL_remove (bp_slaves[c_p].p_head, bp_slaves[c_p].p_tail, cur);
342 if (NULL != bp_slaves[c_p].cth)
344 GNUNET_CORE_notify_transmit_ready_cancel(bp_slaves[c_p].cth);
345 bp_slaves[c_p].cth = NULL;
348 if (NULL != bp_slaves[c_p].ats_perf_op)
350 GNUNET_TESTBED_operation_done (bp_slaves[c_p].ats_perf_op);
351 bp_slaves[c_p].ats_perf_op = NULL;
354 if (NULL != bp_slaves[c_p].core_op)
356 GNUNET_TESTBED_operation_done (bp_slaves[c_p].core_op);
357 bp_slaves[c_p].core_op = NULL;
360 if (NULL != bp_slaves[c_p].info_op)
363 GNUNET_TESTBED_operation_done (bp_slaves[c_p].info_op);
364 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];
511 ats_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
513 static double last = 1;
514 struct BenchmarkPeer *bp = cls;
516 bp->ats_task = GNUNET_SCHEDULER_NO_TASK;
518 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Set preference for master %u: %f\n",
520 GNUNET_ATS_performance_change_preference (bp->p_handle, &bp->destination->id,
521 pref_val, (double) last,
522 GNUNET_ATS_PREFERENCE_END);
524 bp->ats_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
533 struct BenchmarkPeer *s;
534 struct BenchmarkPeer *bp;
536 if ((state.connected_ATS_service == GNUNET_NO) ||
537 (state.connected_CORE_service == GNUNET_NO) ||
538 (state.connected_PEERS == GNUNET_NO) ||
539 (state.connected_CORE == GNUNET_NO))
542 state.benchmarking = GNUNET_YES;
543 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
544 _("Benchmarking start\n"));
546 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
547 GNUNET_SCHEDULER_cancel (shutdown_task);
548 shutdown_task = GNUNET_SCHEDULER_add_delayed (BENCHMARK_DURATION, &do_shutdown, NULL);
550 /* Start sending test messages */
551 for (c_m = 0; c_m < c_master_peers; c_m ++)
553 bp = &bp_master[c_m];
555 if (0 == memcmp(&s->id, &bp->destination->id, sizeof (struct GNUNET_PeerIdentity)))
556 bp->partner_msg = GNUNET_YES;
557 bp->cth = GNUNET_CORE_notify_transmit_ready (bp->ch,
558 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
559 &s->id, TEST_MESSAGE_SIZE, &core_send_ready, bp);
560 bp->ats_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
567 connect_completion_callback (void *cls,
568 struct GNUNET_TESTBED_Operation *op,
571 struct ConnectOperation *cop = cls;
576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
577 _("Connected master peer %u with peer %u\n"), cop->master->no, cop->slave->no);
581 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
582 _("Failed to connect master peer%u with peer %u\n"), cop->master->no, cop->slave->no);
584 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
585 GNUNET_SCHEDULER_cancel(shutdown_task);
586 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
588 GNUNET_TESTBED_operation_done(op);
590 for (c = 0; c < c_slave_peers; c++)
592 if (cop == &cop->master->connect_ops[c])
593 cop->master->connect_ops[c].connect_op = NULL;
595 if (ops == c_master_peers * c_slave_peers)
597 state.connected_PEERS = GNUNET_YES;
598 GNUNET_SCHEDULER_add_now (&do_benchmark, NULL);
604 do_connect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
608 struct BenchmarkPeer *bp;
610 if ((state.connected_ATS_service == GNUNET_NO) ||
611 (state.connected_CORE_service == GNUNET_NO))
616 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connecting peers on CORE level\n"));
618 for (c_m = 0; c_m < c_master_peers; c_m ++)
620 bp = &bp_master[c_m];
621 bp->connect_ops = GNUNET_malloc (c_slave_peers * sizeof (struct ConnectOperation));
623 for (c_s = 0; c_s < c_slave_peers; c_s ++)
625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
626 _("Connecting master peer %u with slave peer %u\n"),
627 bp->no, bp_slaves[c_s].no);
628 bp->connect_ops[c_s].master = bp;
629 bp->connect_ops[c_s].slave = &bp_slaves[c_s];
630 bp->connect_ops[c_s].connect_op = GNUNET_TESTBED_overlay_connect( NULL,
631 &connect_completion_callback,
632 &bp->connect_ops[c_s],
635 if (NULL == bp->connect_ops[c_s].connect_op)
637 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
638 _("Could not connect master peer %u and slave peer %u\n"),
639 bp->no, bp_slaves[c_s].no);
641 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
642 GNUNET_SCHEDULER_cancel(shutdown_task);
643 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
652 * Controller event callback
655 * @param event the controller event
658 controller_event_cb (void *cls,
659 const struct GNUNET_TESTBED_EventInformation *event)
661 //struct BenchmarkPeer *p = cls;
664 case GNUNET_TESTBED_ET_CONNECT:
666 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
671 GNUNET_SCHEDULER_cancel (shutdown_task);
672 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
677 * Method called whenever a given peer connects.
680 * @param peer peer identity this notification is about
683 core_connect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
685 struct BenchmarkPeer *p = cls;
686 struct BenchmarkPeer *t;
691 t = find_peer (peer);
698 id = GNUNET_strdup (GNUNET_i2s (&p->id));
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
700 "%s %s connected to %s %s\n",
701 (p->master == GNUNET_YES) ? "Master": "Slave",
703 (t->master == GNUNET_YES) ? "Master": "Slave",
706 p->core_connections ++;
707 if ((GNUNET_YES == p->master) && (GNUNET_NO == t->master) && (GNUNET_NO == state.connected_CORE))
709 p->slave_connections ++;
711 if (p->slave_connections == c_slave_peers)
713 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
714 "Master %u connected all slaves\n", p->no);
717 for (c = 0; c < c_master_peers; c ++)
719 if (bp_master[c].slave_connections != c_slave_peers)
722 if (GNUNET_YES == cs)
724 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
725 "All master peers connected all slave peers\n", id, GNUNET_i2s (peer));
726 state.connected_CORE = GNUNET_YES;
727 GNUNET_SCHEDULER_add_now (&do_benchmark, NULL);
735 * Method called whenever a peer disconnects.
738 * @param peer peer identity this notification is about
741 core_disconnect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
743 struct BenchmarkPeer *p = cls;
744 struct BenchmarkPeer *t;
747 t = find_peer (peer);
754 id = GNUNET_strdup (GNUNET_i2s (&p->id));
755 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
756 "%s disconnected from %s \n", id, GNUNET_i2s (peer));
757 GNUNET_assert (p->core_connections > 0);
758 p->core_connections --;
760 if ((GNUNET_YES == state.benchmarking) &&
761 ((GNUNET_YES == p->master) || (GNUNET_YES == t->master)))
763 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
764 "%s disconnected from %s while benchmarking \n", id, GNUNET_i2s (peer));
771 core_send_echo_queued_ready (void *cls, size_t size, void *buf);
774 core_send_echo_ready (void *cls, size_t size, void *buf)
776 static char msgbuf[TEST_MESSAGE_SIZE];
777 struct BenchmarkPeer *bp = cls;
778 struct GNUNET_MessageHeader *msg;
782 msg = (struct GNUNET_MessageHeader *) &msgbuf;
783 memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
784 msg->type = htons (TEST_MESSAGE_TYPE_PONG);
785 msg->size = htons (TEST_MESSAGE_SIZE);
786 memcpy (buf, msg, TEST_MESSAGE_SIZE);
789 if (NULL != bp->p_head)
790 bp->cth = GNUNET_CORE_notify_transmit_ready (bp->ch,
791 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
793 TEST_MESSAGE_SIZE, &core_send_echo_queued_ready, bp);
795 return TEST_MESSAGE_SIZE;
799 core_send_echo_queued_ready (void *cls, size_t size, void *buf)
801 struct BenchmarkPeer *bp = cls;
802 struct PendingMessages *pm;
803 GNUNET_assert (NULL != bp->p_head);
806 GNUNET_CONTAINER_DLL_remove (bp->p_head, bp->p_tail, pm);
810 return core_send_echo_ready (cls, size, buf);
816 core_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other,
817 const struct GNUNET_MessageHeader *message)
819 struct BenchmarkPeer *me = cls;
820 struct BenchmarkPeer *remote;
821 struct PendingMessages *pm;
823 remote = find_peer (other);
828 return GNUNET_SYSERR;
833 pm = GNUNET_malloc (sizeof (struct PendingMessages));
834 pm->target = (*other);
835 GNUNET_CONTAINER_DLL_insert_tail (me->p_head, me->p_tail, pm);
839 if (GNUNET_NO == remote->master)
845 me->messages_received ++;
847 me->cth = GNUNET_CORE_notify_transmit_ready (me->ch,
848 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
850 TEST_MESSAGE_SIZE, &core_send_echo_ready, me);
855 core_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other,
856 const struct GNUNET_MessageHeader *message)
858 struct BenchmarkPeer *me = cls;
859 struct BenchmarkPeer *remote;
860 struct BenchmarkPeer *next;
862 remote = find_peer (other);
867 return GNUNET_SYSERR;
876 if (GNUNET_YES == remote->master)
881 me->messages_received ++;
882 next = get_next (me);
883 if (0 == memcmp(&remote->id, &me->destination->id, sizeof (struct GNUNET_PeerIdentity)))
884 me->partner_msg = GNUNET_YES;
885 me->cth = GNUNET_CORE_notify_transmit_ready (me->ch,
886 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
888 TEST_MESSAGE_SIZE, &core_send_ready, me);
895 * Called to open a connection to the peer's ATS performance
897 * @param cls peer context
898 * @param cfg configuration of the peer to connect to; will be available until
899 * GNUNET_TESTBED_operation_done() is called on the operation returned
900 * from GNUNET_TESTBED_service_connect()
901 * @return service handle to return in 'op_result', NULL on error
904 core_connect_adapter (void *cls,
905 const struct GNUNET_CONFIGURATION_Handle *cfg)
907 struct BenchmarkPeer *peer = cls;
909 static const struct GNUNET_CORE_MessageHandler handlers[] = {
910 {&core_handle_ping, TEST_MESSAGE_TYPE_PING, 0},
911 {&core_handle_pong, TEST_MESSAGE_TYPE_PONG, 0},
915 peer->ch = GNUNET_CORE_connect(cfg, peer, NULL,
916 core_connect_cb, core_disconnect_cb,
917 NULL, GNUNET_NO, NULL, GNUNET_NO, handlers);
918 if (NULL == peer->ch)
919 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
920 "Failed to create core connection \n");
926 * Callback to be called when a service connect operation is completed
928 * @param cls the callback closure from functions generating an operation
929 * @param op the operation that has been finished
930 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
931 * @param emsg error message in case the operation has failed; will be NULL if
932 * operation has executed successfully.
935 core_connect_completion_cb (void *cls,
936 struct GNUNET_TESTBED_Operation *op,
940 static int core_done = 0;
941 if ((NULL != emsg) || (NULL == ca_result))
943 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
944 _("Initialization failed, shutdown\n"));
946 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
947 GNUNET_SCHEDULER_cancel(shutdown_task);
948 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
953 if (core_done == c_slave_peers + c_master_peers)
955 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
956 "Connected to all CORE services\n");
957 state.connected_CORE_service = GNUNET_YES;
958 GNUNET_SCHEDULER_add_now (&do_connect_peers, NULL);
964 * Called to disconnect from peer's statistics service
966 * @param cls peer context
967 * @param op_result service handle returned from the connect adapter
970 core_disconnect_adapter (void *cls, void *op_result)
972 struct BenchmarkPeer *peer = cls;
974 GNUNET_CORE_disconnect (peer->ch);
979 do_connect_core (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
982 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
983 "Connecting to all CORE services\n");
984 for (c_p = 0; c_p < c_master_peers; c_p++)
986 bp_master[c_p].core_op = GNUNET_TESTBED_service_connect (NULL,
987 bp_master[c_p].peer, "core",
988 core_connect_completion_cb, NULL,
989 &core_connect_adapter,
990 &core_disconnect_adapter,
994 for (c_p = 0; c_p < c_slave_peers; c_p++)
996 bp_slaves[c_p].core_op = GNUNET_TESTBED_service_connect (NULL,
997 bp_slaves[c_p].peer, "core",
998 core_connect_completion_cb, NULL,
999 &core_connect_adapter,
1000 &core_disconnect_adapter,
1008 * Called to open a connection to the peer's ATS performance
1010 * @param cls peer context
1011 * @param cfg configuration of the peer to connect to; will be available until
1012 * GNUNET_TESTBED_operation_done() is called on the operation returned
1013 * from GNUNET_TESTBED_service_connect()
1014 * @return service handle to return in 'op_result', NULL on error
1017 ats_perf_connect_adapter (void *cls,
1018 const struct GNUNET_CONFIGURATION_Handle *cfg)
1020 struct BenchmarkPeer *peer = cls;
1022 peer->p_handle = GNUNET_ATS_performance_init (cfg, &ats_performance_info_cb, peer);
1023 if (NULL == peer->p_handle)
1024 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create ATS performance handle \n");
1025 return peer->p_handle;
1030 * Called to disconnect from peer's statistics service
1032 * @param cls peer context
1033 * @param op_result service handle returned from the connect adapter
1036 ats_perf_disconnect_adapter (void *cls, void *op_result)
1038 struct BenchmarkPeer *peer = cls;
1040 GNUNET_ATS_performance_done(peer->p_handle);
1041 peer->p_handle = NULL;
1046 * Callback to be called when a service connect operation is completed
1048 * @param cls the callback closure from functions generating an operation
1049 * @param op the operation that has been finished
1050 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
1051 * @param emsg error message in case the operation has failed; will be NULL if
1052 * operation has executed successfully.
1055 ats_connect_completion_cb (void *cls,
1056 struct GNUNET_TESTBED_Operation *op,
1060 static int op_done = 0;
1061 if ((NULL != emsg) || (NULL == ca_result))
1063 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1064 _("Initialization failed, shutdown\n"));
1066 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
1067 GNUNET_SCHEDULER_cancel(shutdown_task);
1068 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
1073 if (op_done == (c_slave_peers + c_master_peers))
1075 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1076 "Connected to all ATS services\n");
1077 state.connected_ATS_service = GNUNET_YES;
1078 GNUNET_SCHEDULER_add_now (&do_connect_core, NULL);
1083 do_connect_ats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1086 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1087 "Connecting to all ATS services %u\n", c_slave_peers);
1088 for (c_p = 0; c_p < c_master_peers; c_p++)
1090 bp_master[c_p].ats_perf_op = GNUNET_TESTBED_service_connect (NULL,
1091 bp_master[c_p].peer, "ats",
1092 ats_connect_completion_cb, NULL,
1093 &ats_perf_connect_adapter,
1094 &ats_perf_disconnect_adapter,
1099 for (c_p = 0; c_p < c_slave_peers; c_p++)
1101 bp_slaves[c_p].ats_perf_op = GNUNET_TESTBED_service_connect (NULL,
1102 bp_slaves[c_p].peer, "ats",
1103 ats_connect_completion_cb, NULL,
1104 &ats_perf_connect_adapter,
1105 &ats_perf_disconnect_adapter,
1113 * Callback to be called when the requested peer information is available
1115 * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
1116 * @param op the operation this callback corresponds to
1117 * @param pinfo the result; will be NULL if the operation has failed
1118 * @param emsg error message if the operation has failed; will be NULL if the
1119 * operation is successfull
1122 peerinformation_cb (void *cb_cls,
1123 struct GNUNET_TESTBED_Operation *op,
1124 const struct GNUNET_TESTBED_PeerInformation*pinfo,
1127 struct BenchmarkPeer *p = cb_cls;
1128 static int done = 0;
1130 if (pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY)
1132 p->id = *pinfo->result.id;
1133 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1134 "[%c %03u] Peers %s\n",
1135 (p->master == GNUNET_YES) ? 'M' : 'S', p->no, GNUNET_i2s (&p->id));
1141 GNUNET_TESTBED_operation_done (op);
1145 if (done == c_master_peers + c_slave_peers)
1147 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1148 "Retrieved all peer ID, connect to ATS\n");
1149 state.connected_CORE_service = GNUNET_YES;
1150 GNUNET_SCHEDULER_add_now (&do_connect_ats, NULL);
1156 * Signature of a main function for a testcase.
1158 * @param cls closure
1159 * @param num_peers number of peers in 'peers'
1160 * @param peers_ handle to peers run in the testbed
1161 * @param links_succeeded the number of overlay link connection attempts that
1163 * @param links_failed the number of overlay link connection attempts that
1167 test_main (void *cls,
1168 struct GNUNET_TESTBED_RunHandle *h,
1169 unsigned int num_peers,
1170 struct GNUNET_TESTBED_Peer **peers_,
1171 unsigned int links_succeeded,
1172 unsigned int links_failed)
1176 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1177 _("Benchmarking solver `%s' on preference `%s' with %u master and %u slave peers\n"),
1178 solver, pref_str, c_master_peers, c_slave_peers);
1180 shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(TEST_TIMEOUT, c_master_peers + c_slave_peers), &do_shutdown, NULL);
1182 GNUNET_assert (NULL == cls);
1183 GNUNET_assert (c_slave_peers + c_master_peers == num_peers);
1184 GNUNET_assert (NULL != peers_);
1186 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1187 _("Initializing... \n"));
1189 /* Setup master peers */
1190 for (c_p = 0; c_p < c_master_peers; c_p++)
1192 GNUNET_assert (NULL != peers_[c_p]);
1193 bp_master[c_p].no = c_p;
1194 bp_master[c_p].send_mask = (1 << c_slave_peers) - 1;
1195 bp_master[c_p].master = GNUNET_YES;
1196 bp_master[c_p].peer = peers_[c_p];
1197 bp_master[c_p].info_op = GNUNET_TESTBED_peer_get_information (bp_master[c_p].peer,
1198 GNUNET_TESTBED_PIT_IDENTITY,
1199 &peerinformation_cb, &bp_master[c_p]);
1201 /* Select ATS measurement partner */
1202 bp_master[c_p].destination = &bp_slaves[c_p];
1205 /* Setup slave peers */
1206 for (c_p = 0; c_p < c_slave_peers; c_p++)
1208 GNUNET_assert (NULL != peers_[c_p + c_master_peers]);
1209 bp_slaves[c_p].no = c_p + c_master_peers;
1210 bp_slaves[c_p].master = GNUNET_NO;
1211 bp_slaves[c_p].peer = peers_[c_p + c_master_peers];
1212 bp_slaves[c_p].info_op = GNUNET_TESTBED_peer_get_information (bp_slaves[c_p].peer,
1213 GNUNET_TESTBED_PIT_IDENTITY,
1214 &peerinformation_cb, &bp_slaves[c_p]);
1221 main (int argc, char *argv[])
1228 char *prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
1233 /* figure out testname */
1234 tmp = strstr (argv[0], TESTNAME_PREFIX);
1237 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1238 return GNUNET_SYSERR;
1240 tmp += strlen(TESTNAME_PREFIX);
1241 solver = GNUNET_strdup (tmp);
1242 if (NULL != (dotexe = strstr (solver, ".exe")) &&
1245 tmp_sep = strchr (solver, '_');
1246 if (NULL == tmp_sep)
1248 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1249 GNUNET_free (solver);
1250 return GNUNET_SYSERR;
1253 pref_str = GNUNET_strdup(tmp_sep + 1);
1255 GNUNET_asprintf(&conf_name, "%s%s_%s.conf", TESTNAME_PREFIX, solver, pref_str);
1256 GNUNET_asprintf(&test_name, "%s%s_%s", TESTNAME_PREFIX, solver, pref_str);
1258 for (c = 0; c <= strlen (pref_str); c++)
1260 pref_str[c] = toupper(pref_str[c]);
1263 for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
1265 if (0 == strcmp (pref_str, prefs[c]))
1273 fprintf (stderr, "Unknown preference: `%s'\n", pref_str);
1274 GNUNET_free (solver);
1275 GNUNET_free (pref_str);
1279 for (c = 0; c < (argc -1); c++)
1281 if (0 == strcmp(argv[c], "-s"))
1286 if ((0L != (c_slave_peers = strtol (argv[c + 1], NULL, 10))) && (c_slave_peers >= 1))
1287 fprintf (stderr, "Starting %u slave peers\n", c_slave_peers);
1289 c_slave_peers = DEFAULT_SLAVES_NUM;
1292 c_slave_peers = DEFAULT_SLAVES_NUM;
1294 for (c = 0; c < (argc -1); c++)
1296 if (0 == strcmp(argv[c], "-m"))
1301 if ((0L != (c_master_peers = strtol (argv[c + 1], NULL, 10))) && (c_master_peers >= 2))
1302 fprintf (stderr, "Starting %u master peers\n", c_master_peers);
1304 c_master_peers = DEFAULT_MASTERS_NUM;
1307 c_master_peers = DEFAULT_MASTERS_NUM;
1309 bp_slaves = GNUNET_malloc (c_slave_peers * sizeof (struct BenchmarkPeer));
1310 bp_master = GNUNET_malloc (c_master_peers * sizeof (struct BenchmarkPeer));
1312 state.connected_ATS_service = GNUNET_NO;
1313 state.connected_CORE_service = GNUNET_NO;
1314 state.connected_PEERS = GNUNET_NO;
1316 /* Start topology */
1317 uint64_t event_mask;
1319 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
1320 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
1321 (void) GNUNET_TESTBED_test_run ("perf_ats",
1322 conf_name, c_slave_peers + c_master_peers,
1323 event_mask, &controller_event_cb, NULL,
1326 GNUNET_free (solver);
1327 GNUNET_free (pref_str);
1328 GNUNET_free (conf_name);
1329 GNUNET_free (test_name);
1330 GNUNET_free (bp_slaves);
1335 /* end of file perf_ats.c */