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"
33 #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
34 #define BENCHMARK_DURATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
35 #define TESTNAME_PREFIX "perf_ats_"
36 #define DEFAULT_SLAVES_NUM 3
37 #define DEFAULT_MASTERS_NUM 1
39 #define TEST_ATS_PREFRENCE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
40 #define TEST_ATS_PREFRENCE_START 1.0
41 #define TEST_ATS_PREFRENCE_DELTA 1.0
43 #define TEST_MESSAGE_TYPE_PING 12345
44 #define TEST_MESSAGE_TYPE_PONG 12346
45 #define TEST_MESSAGE_SIZE 1000
46 #define TEST_MESSAGE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
49 * Connect peers with testbed
51 struct TestbedConnectOperation
54 * The benchmarking master initiating this connection
56 struct BenchmarkPeer *master;
59 * The benchmarking slave to connect to
61 struct BenchmarkPeer *slave;
64 * Testbed operation to connect peers
66 struct GNUNET_TESTBED_Operation *connect_op;
70 * Overall state of the performance benchmark
74 /* Are we connected to ATS service of all peers: GNUNET_YES/NO */
75 int connected_ATS_service;
77 /* Are we connected to CORE service of all peers: GNUNET_YES/NO */
78 int connected_COMM_service;
80 /* Are we connected to all peers: GNUNET_YES/NO */
83 /* Are we connected to all slave peers on CORE level: GNUNET_YES/NO */
86 /* Are we connected to CORE service of all peers: GNUNET_YES/NO */
93 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
98 static GNUNET_SCHEDULER_TaskIdentifier progress_task;
106 * Test result logging
110 /**Test core (GNUNET_YES) or transport (GNUNET_NO)
112 static int test_core;
122 static char *pref_str;
125 * ATS preference value
130 * Number master peers
132 static int num_masters;
135 * Array of master peers
137 struct BenchmarkPeer *mps;
142 static int num_slaves;
144 * Array of slave peers
146 struct BenchmarkPeer *sps;
151 static struct BenchmarkState state;
158 unsigned int duration;
159 struct BenchmarkPeer *mp;
161 duration = (BENCHMARK_DURATION.rel_value_us / (1000 * 1000));
162 for (c_m = 0; c_m < num_masters; c_m++)
166 _("Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. = %u KiB/s\n"),
167 mp->no, mp->total_bytes_sent / 1024, duration,
168 (mp->total_bytes_sent / 1024) / duration,
169 mp->total_bytes_received / 1024, duration,
170 (mp->total_bytes_received / 1024) / duration);
172 for (c_s = 0; c_s < num_slaves; c_s++)
175 "%c Master [%u] -> Slave [%u]: sent %u KiB/s (%.2f \%), received %u KiB/s (%.2f \%)\n",
176 (mp->pref_partner == mp->partners[c_s].dest) ? '*' : ' ',
177 mp->no, mp->partners[c_s].dest->no,
178 (mp->partners[c_s].bytes_sent / 1024) / duration,
179 ((double) mp->partners[c_s].bytes_sent * 100) / mp->total_bytes_sent,
180 (mp->partners[c_s].bytes_received / 1024) / duration,
181 ((double) mp->partners[c_s].bytes_received * 100) / mp->total_bytes_received );
190 * @param tc the task context
193 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
199 if (GNUNET_YES == logging)
202 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
203 if (GNUNET_SCHEDULER_NO_TASK != progress_task)
205 fprintf (stderr, "0\n");
206 GNUNET_SCHEDULER_cancel (progress_task);
208 progress_task = GNUNET_SCHEDULER_NO_TASK;
211 state.benchmarking = GNUNET_NO;
212 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n"));
214 for (c_m = 0; c_m < num_masters; c_m++)
216 if (NULL != mps[c_m].peer_id_op)
218 GNUNET_TESTBED_operation_done (mps[c_m].peer_id_op);
219 mps[c_m].peer_id_op = NULL;
222 if (GNUNET_SCHEDULER_NO_TASK != mps[c_m].ats_task)
223 GNUNET_SCHEDULER_cancel (mps[c_m].ats_task);
224 mps[c_m].ats_task = GNUNET_SCHEDULER_NO_TASK;
226 for (c_op = 0; c_op < num_slaves; c_op++)
229 if (NULL != mps[c_m].partners[c_op].cth)
231 GNUNET_CORE_notify_transmit_ready_cancel (mps[c_m].partners[c_op].cth);
232 mps[c_m].partners[c_op].cth = NULL;
234 if (NULL != mps[c_m].partners[c_op].tth)
236 GNUNET_TRANSPORT_notify_transmit_ready_cancel (mps[c_m].partners[c_op].tth);
237 mps[c_m].partners[c_op].tth = NULL;
241 if (NULL != mps[c_m].core_connect_ops[c_op].connect_op)
243 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
244 _("Failed to connect peer 0 and %u\n"), c_op);
245 GNUNET_TESTBED_operation_done (
246 mps[c_m].core_connect_ops[c_op].connect_op);
247 mps[c_m].core_connect_ops[c_op].connect_op = NULL;
252 if (NULL != mps[c_m].ats_perf_op)
254 GNUNET_TESTBED_operation_done (mps[c_m].ats_perf_op);
255 mps[c_m].ats_perf_op = NULL;
258 if (NULL != mps[c_m].comm_op)
260 GNUNET_TESTBED_operation_done (mps[c_m].comm_op);
261 mps[c_m].comm_op = NULL;
263 GNUNET_free(mps[c_m].core_connect_ops);
264 GNUNET_free(mps[c_m].partners);
265 mps[c_m].partners = NULL;
268 for (c_s = 0; c_s < num_slaves; c_s++)
270 if (NULL != sps[c_s].peer_id_op)
272 GNUNET_TESTBED_operation_done (sps[c_s].peer_id_op);
273 sps[c_s].peer_id_op = NULL;
276 for (c_op = 0; c_op < num_slaves; c_op++)
278 if (NULL != sps[c_s].partners[c_op].cth)
280 GNUNET_CORE_notify_transmit_ready_cancel (sps[c_s].partners[c_op].cth);
281 sps[c_s].partners[c_op].cth = NULL;
284 if (NULL != sps[c_s].partners[c_op].tth)
286 GNUNET_TRANSPORT_notify_transmit_ready_cancel (sps[c_s].partners[c_op].tth);
287 sps[c_s].partners[c_op].tth = NULL;
291 if (NULL != sps[c_s].ats_perf_op)
293 GNUNET_TESTBED_operation_done (sps[c_s].ats_perf_op);
294 sps[c_s].ats_perf_op = NULL;
296 if (NULL != sps[c_s].comm_op)
298 GNUNET_TESTBED_operation_done (sps[c_s].comm_op);
299 sps[c_s].comm_op = NULL;
302 GNUNET_free(sps[c_s].partners);
303 sps[c_s].partners = NULL;
306 GNUNET_SCHEDULER_shutdown ();
309 static struct BenchmarkPeer *
310 find_peer (const struct GNUNET_PeerIdentity * peer)
314 for (c_p = 0; c_p < num_masters; c_p++)
316 if (0 == memcmp (&mps[c_p].id, peer, sizeof(struct GNUNET_PeerIdentity)))
320 for (c_p = 0; c_p < num_slaves; c_p++)
322 if (0 == memcmp (&sps[c_p].id, peer, sizeof(struct GNUNET_PeerIdentity)))
329 * Controller event callback
332 * @param event the controller event
335 controller_event_cb (void *cls,
336 const struct GNUNET_TESTBED_EventInformation *event)
338 //struct BenchmarkPeer *p = cls;
341 case GNUNET_TESTBED_ET_CONNECT:
343 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
348 GNUNET_SCHEDULER_cancel (shutdown_task);
349 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL );
354 comm_send_ready (void *cls, size_t size, void *buf)
356 static char msgbuf[TEST_MESSAGE_SIZE];
357 struct BenchmarkPartner *partner = cls;
358 struct GNUNET_MessageHeader *msg;
360 if (GNUNET_YES == test_core)
365 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Master [%u]: Sending PING to [%u]\n",
366 partner->me->no, partner->dest->no);
368 partner->messages_sent++;
369 partner->bytes_sent += TEST_MESSAGE_SIZE;
370 partner->me->total_messages_sent++;
371 partner->me->total_bytes_sent += TEST_MESSAGE_SIZE;
373 msg = (struct GNUNET_MessageHeader *) &msgbuf;
374 memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
375 msg->type = htons (TEST_MESSAGE_TYPE_PING);
376 msg->size = htons (TEST_MESSAGE_SIZE);
377 memcpy (buf, msg, TEST_MESSAGE_SIZE);
378 return TEST_MESSAGE_SIZE;
385 progress_task = GNUNET_SCHEDULER_NO_TASK;
387 fprintf (stderr, "%llu..",
388 (long long unsigned) BENCHMARK_DURATION.rel_value_us / (1000 * 1000) - calls);
391 progress_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
392 &print_progress, NULL );
396 ats_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
398 struct BenchmarkPeer *me = cls;
400 me->ats_task = GNUNET_SCHEDULER_NO_TASK;
402 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, " Master [%u] set preference for slave [%u] to %f\n",
403 me->no, me->pref_partner->no, me->pref_value);
404 GNUNET_ATS_performance_change_preference (me->ats_perf_handle,
405 &me->pref_partner->id,
406 pref_val, me->pref_value, GNUNET_ATS_PREFERENCE_END);
407 me->pref_value += TEST_ATS_PREFRENCE_DELTA;
408 me->ats_task = GNUNET_SCHEDULER_add_delayed (TEST_ATS_PREFRENCE_FREQUENCY,
409 &ats_pref_task, cls);
418 if ((state.connected_ATS_service == GNUNET_NO)
419 || (state.connected_COMM_service == GNUNET_NO)
420 || (state.connected_PEERS == GNUNET_NO)
421 || (state.connected_CORE == GNUNET_NO))
424 state.benchmarking = GNUNET_YES;
425 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking start\n"));
427 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
428 GNUNET_SCHEDULER_cancel (shutdown_task);
429 shutdown_task = GNUNET_SCHEDULER_add_delayed (BENCHMARK_DURATION,
430 &do_shutdown, NULL );
432 progress_task = GNUNET_SCHEDULER_add_now (&print_progress, NULL );
434 /* Start sending test messages */
435 for (c_m = 0; c_m < num_masters; c_m++)
437 for (c_s = 0; c_s < num_slaves; c_s++)
439 if (GNUNET_YES == test_core)
440 mps[c_m].partners[c_s].cth = GNUNET_CORE_notify_transmit_ready (
441 mps[c_m].ch, GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES, &sps[c_s].id,
442 TEST_MESSAGE_SIZE, &comm_send_ready, &mps[c_m].partners[c_s]);
445 mps[c_m].partners[c_s].tth = GNUNET_TRANSPORT_notify_transmit_ready (
446 mps[c_m].th, &sps[c_s].id, TEST_MESSAGE_SIZE, 0,GNUNET_TIME_UNIT_MINUTES,
447 &comm_send_ready, &mps[c_m].partners[c_s]);
450 if (pref_val != GNUNET_ATS_PREFERENCE_END)
451 mps[c_m].ats_task = GNUNET_SCHEDULER_add_now (&ats_pref_task, &mps[c_m]);
453 if (GNUNET_YES == logging)
454 perf_logging_start (mps, num_masters);
458 connect_completion_callback (void *cls, struct GNUNET_TESTBED_Operation *op,
461 struct TestbedConnectOperation *cop = cls;
466 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
467 _("Connected master [%u] with slave [%u]\n"), cop->master->no,
472 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
473 _("Failed to connect master peer [%u] with slave [%u]\n"),
474 cop->master->no, cop->slave->no);
476 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
477 GNUNET_SCHEDULER_cancel (shutdown_task);
478 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
480 GNUNET_TESTBED_operation_done (op);
482 for (c = 0; c < num_slaves; c++)
484 if (cop == &cop->master->core_connect_ops[c])
485 cop->master->core_connect_ops[c].connect_op = NULL;
487 if (ops == num_masters * num_slaves)
489 state.connected_PEERS = GNUNET_YES;
490 GNUNET_SCHEDULER_add_now (&do_benchmark, NULL );
495 do_connect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
499 struct BenchmarkPeer *p;
501 if ((state.connected_ATS_service == GNUNET_NO)
502 || (state.connected_COMM_service == GNUNET_NO))
505 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Connecting peers on CORE level\n"));
507 for (c_m = 0; c_m < num_masters; c_m++)
510 p->core_connect_ops = GNUNET_malloc (num_slaves *
511 sizeof (struct TestbedConnectOperation));
513 for (c_s = 0; c_s < num_slaves; c_s++)
515 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
516 _("Connecting master [%u] with slave [%u]\n"), p->no, sps[c_s].no);
517 p->core_connect_ops[c_s].master = p;
518 p->core_connect_ops[c_s].slave = &sps[c_s];
519 p->core_connect_ops[c_s].connect_op = GNUNET_TESTBED_overlay_connect (
520 NULL, &connect_completion_callback, &p->core_connect_ops[c_s],
521 sps[c_s].peer, p->peer);
522 if (NULL == p->core_connect_ops[c_s].connect_op)
524 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
525 _("Could not connect master [%u] and slave [%u]\n"), p->no,
528 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
529 GNUNET_SCHEDULER_cancel (shutdown_task);
530 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
538 * Method called whenever a given peer connects.
541 * @param peer peer identity this notification is about
544 comm_connect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
546 struct BenchmarkPeer *me = cls;
547 struct BenchmarkPeer *remote;
552 remote = find_peer (peer);
559 id = GNUNET_strdup (GNUNET_i2s (&me->id));
560 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s [%u] `%s' connected to %s [%u] %s\n",
561 (me->master == GNUNET_YES) ? "Master": "Slave", me->no, id,
562 (remote->master == GNUNET_YES) ? "Master": "Slave", remote->no,
565 me->core_connections++;
566 if ((GNUNET_YES == me->master) && (GNUNET_NO == remote->master)
567 && (GNUNET_NO == state.connected_CORE))
569 me->core_slave_connections++;
571 if (me->core_slave_connections == num_slaves)
573 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Master [%u] connected all slaves\n",
576 completed = GNUNET_YES;
577 for (c = 0; c < num_masters; c++)
579 if (mps[c].core_slave_connections != num_slaves)
580 completed = GNUNET_NO;
582 if (GNUNET_YES == completed)
584 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
585 "All master peers connected all slave peers\n", id,
587 state.connected_CORE = GNUNET_YES;
588 GNUNET_SCHEDULER_add_now (&do_benchmark, NULL );
595 comm_disconnect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
597 struct BenchmarkPeer *me = cls;
598 struct BenchmarkPeer *remote;
601 remote = find_peer (peer);
608 id = GNUNET_strdup (GNUNET_i2s (&me->id));
609 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s disconnected from %s \n", id,
611 GNUNET_assert(me->core_connections > 0);
612 me->core_connections--;
614 if ((GNUNET_YES == state.benchmarking)
615 && ((GNUNET_YES == me->master) || (GNUNET_YES == remote->master)))
617 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
618 "%s disconnected from %s while benchmarking \n", id, GNUNET_i2s (peer));
624 comm_send_pong_ready (void *cls, size_t size, void *buf)
626 static char msgbuf[TEST_MESSAGE_SIZE];
627 struct BenchmarkPartner *p = cls;
628 struct GNUNET_MessageHeader *msg;
630 if (GNUNET_YES == test_core)
636 p->bytes_sent += TEST_MESSAGE_SIZE;
637 p->me->total_messages_sent++;
638 p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
640 msg = (struct GNUNET_MessageHeader *) &msgbuf;
641 memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
642 msg->type = htons (TEST_MESSAGE_TYPE_PONG);
643 msg->size = htons (TEST_MESSAGE_SIZE);
644 memcpy (buf, msg, TEST_MESSAGE_SIZE);
646 return TEST_MESSAGE_SIZE;
650 comm_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other,
651 const struct GNUNET_MessageHeader *message)
654 struct BenchmarkPeer *me = cls;
655 struct BenchmarkPartner *p = NULL;
656 for (c_m = 0; c_m < num_masters; c_m++)
659 == memcmp (other, &me->partners[c_m].dest->id,
660 sizeof(struct GNUNET_PeerIdentity)))
662 p = &me->partners[c_m];
669 return GNUNET_SYSERR;
672 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
673 "Slave [%u]: Received PING from [%u], sending PONG\n", me->no,
676 p->messages_received++;
677 p->bytes_received += TEST_MESSAGE_SIZE;
678 p->me->total_messages_received++;
679 p->me->total_bytes_received += TEST_MESSAGE_SIZE;
681 if (GNUNET_YES == test_core)
683 GNUNET_assert (NULL == p->cth);
684 p->cth = GNUNET_CORE_notify_transmit_ready (me->ch, GNUNET_NO, 0,
685 GNUNET_TIME_UNIT_MINUTES, &p->dest->id, TEST_MESSAGE_SIZE,
686 &comm_send_pong_ready, p);
690 GNUNET_assert (NULL == p->tth);
691 p->tth = GNUNET_TRANSPORT_notify_transmit_ready (me->th, &p->dest->id,
692 TEST_MESSAGE_SIZE, 0, GNUNET_TIME_UNIT_MINUTES, &comm_send_pong_ready,
699 comm_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other,
700 const struct GNUNET_MessageHeader *message)
703 struct BenchmarkPeer *me = cls;
704 struct BenchmarkPartner *p = NULL;
706 for (c_s = 0; c_s < num_slaves; c_s++)
709 == memcmp (other, &me->partners[c_s].dest->id,
710 sizeof(struct GNUNET_PeerIdentity)))
712 p = &me->partners[c_s];
719 return GNUNET_SYSERR;
722 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
723 "Master [%u]: Received PONG from [%u], next message\n", me->no,
726 p->messages_received++;
727 p->bytes_received += TEST_MESSAGE_SIZE;
728 p->me->total_messages_received++;
729 p->me->total_bytes_received += TEST_MESSAGE_SIZE;
731 if (GNUNET_YES == test_core)
733 GNUNET_assert (NULL == p->cth);
734 p->cth = GNUNET_CORE_notify_transmit_ready (me->ch, GNUNET_NO, 0,
735 GNUNET_TIME_UNIT_MINUTES, &p->dest->id, TEST_MESSAGE_SIZE,
736 &comm_send_ready, p);
740 GNUNET_assert (NULL == p->tth);
741 p->tth = GNUNET_TRANSPORT_notify_transmit_ready (
742 me->th, &p->dest->id, TEST_MESSAGE_SIZE, 0,GNUNET_TIME_UNIT_MINUTES,
743 &comm_send_ready, p);
750 core_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
752 struct BenchmarkPeer *me = cls;
754 static const struct GNUNET_CORE_MessageHandler handlers[] = { {
755 &comm_handle_ping, TEST_MESSAGE_TYPE_PING, 0 }, { &comm_handle_pong,
756 TEST_MESSAGE_TYPE_PONG, 0 }, { NULL, 0, 0 } };
758 me->ch = GNUNET_CORE_connect (cfg, me, NULL, comm_connect_cb,
759 comm_disconnect_cb, NULL, GNUNET_NO, NULL, GNUNET_NO, handlers);
761 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create core connection \n");
766 core_disconnect_adapter (void *cls, void *op_result)
768 struct BenchmarkPeer *me = cls;
770 GNUNET_CORE_disconnect (me->ch);
775 comm_connect_completion_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
776 void *ca_result, const char *emsg)
778 static int comm_done = 0;
779 if ((NULL != emsg) || (NULL == ca_result))
781 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initialization failed, shutdown\n"));
783 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
784 GNUNET_SCHEDULER_cancel (shutdown_task);
785 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
790 if (comm_done == num_slaves + num_masters)
792 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connected to all %s services\n",
793 (GNUNET_YES == test_core) ? "CORE" : "TRANSPORT");
794 state.connected_COMM_service = GNUNET_YES;
795 GNUNET_SCHEDULER_add_now (&do_connect_peers, NULL );
800 transport_recv_cb (void *cls,
801 const struct GNUNET_PeerIdentity * peer,
802 const struct GNUNET_MessageHeader * message)
804 if (TEST_MESSAGE_SIZE != ntohs (message->size) ||
805 (TEST_MESSAGE_TYPE_PING != ntohs (message->type) &&
806 TEST_MESSAGE_TYPE_PONG != ntohs (message->type)))
810 if (TEST_MESSAGE_TYPE_PING == ntohs (message->type))
811 comm_handle_ping (cls, peer, message);
813 if (TEST_MESSAGE_TYPE_PONG == ntohs (message->type))
814 comm_handle_pong (cls, peer, message);
819 transport_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
821 struct BenchmarkPeer *me = cls;
823 me->th = GNUNET_TRANSPORT_connect (cfg, &me->id, me, &transport_recv_cb,
824 &comm_connect_cb, &comm_disconnect_cb);
826 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create transport connection \n");
831 transport_disconnect_adapter (void *cls, void *op_result)
833 struct BenchmarkPeer *me = cls;
835 GNUNET_TRANSPORT_disconnect (me->th);
840 do_comm_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
844 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connecting to all %s services\n",
845 (GNUNET_YES == test_core) ? "CORE" : "TRANSPORT");
846 for (c_m = 0; c_m < num_masters; c_m++)
848 if (GNUNET_YES == test_core)
849 mps[c_m].comm_op = GNUNET_TESTBED_service_connect (NULL, mps[c_m].peer,
850 "core", &comm_connect_completion_cb, NULL, &core_connect_adapter,
851 &core_disconnect_adapter, &mps[c_m]);
854 mps[c_m].comm_op = GNUNET_TESTBED_service_connect (NULL, mps[c_m].peer,
855 "transport", &comm_connect_completion_cb, NULL, &transport_connect_adapter,
856 &transport_disconnect_adapter, &mps[c_m]);
860 for (c_s = 0; c_s < num_slaves; c_s++)
862 if (GNUNET_YES == test_core)
863 sps[c_s].comm_op = GNUNET_TESTBED_service_connect (NULL, sps[c_s].peer,
864 "core", &comm_connect_completion_cb, NULL, &core_connect_adapter,
865 &core_disconnect_adapter, &sps[c_s]);
868 sps[c_s].comm_op = GNUNET_TESTBED_service_connect (NULL, sps[c_s].peer,
869 "transport", &comm_connect_completion_cb, NULL, &transport_connect_adapter,
870 &transport_disconnect_adapter, &sps[c_s]);
876 ats_performance_info_cb (void *cls, const struct GNUNET_HELLO_Address *address,
877 int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
878 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
879 const struct GNUNET_ATS_Information *ats, uint32_t ats_count)
881 struct BenchmarkPeer *me = cls;
885 peer_id = GNUNET_strdup (GNUNET_i2s (&me->id));
886 for (c_a = 0; c_a < ats_count; c_a++)
888 /*GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("%c %03u: %s %s %u\n"),
889 (GNUNET_YES == p->master) ? 'M' : 'S',
891 GNUNET_i2s (&address->peer),
892 GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)),
893 ntohl(ats[c_a].value));*/
896 if ((GNUNET_YES == me->master)
897 && (0 == memcmp (&address->peer, &me->destination->id,
898 sizeof(struct GNUNET_PeerIdentity))))
900 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Bandwidth for master %u: %lu %lu\n",
901 me->no, (long unsigned int ) ntohl (bandwidth_in.value__),
902 (long unsigned int ) ntohl (bandwidth_in.value__));
905 store_information (&bp->id, address, address_active, bandwidth_in,
906 bandwidth_out, ats, ats_count);
908 GNUNET_free(peer_id);
912 ats_perf_connect_adapter (void *cls,
913 const struct GNUNET_CONFIGURATION_Handle *cfg)
915 struct BenchmarkPeer *me = cls;
917 me->ats_perf_handle = GNUNET_ATS_performance_init (cfg,
918 &ats_performance_info_cb, me);
919 if (NULL == me->ats_perf_handle)
920 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
921 "Failed to create ATS performance handle \n");
922 return me->ats_perf_handle;
926 ats_perf_disconnect_adapter (void *cls, void *op_result)
928 struct BenchmarkPeer *me = cls;
930 GNUNET_ATS_performance_done (me->ats_perf_handle);
931 me->ats_perf_handle = NULL;
935 ats_connect_completion_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
936 void *ca_result, const char *emsg)
938 static int op_done = 0;
940 if ((NULL != emsg) || (NULL == ca_result))
942 GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initialization failed, shutdown\n"));
944 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
945 GNUNET_SCHEDULER_cancel (shutdown_task);
946 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
950 if (op_done == (num_masters + num_slaves))
952 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connected to all ATS services\n");
953 state.connected_ATS_service = GNUNET_YES;
954 GNUNET_SCHEDULER_add_now (&do_comm_connect, NULL );
959 do_connect_ats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
964 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connecting to all ATS services\n");
965 for (c_m = 0; c_m < num_masters; c_m++)
967 mps[c_m].ats_perf_op = GNUNET_TESTBED_service_connect (NULL, mps[c_m].peer,
968 "ats", ats_connect_completion_cb, NULL, &ats_perf_connect_adapter,
969 &ats_perf_disconnect_adapter, &mps[c_m]);
973 for (c_s = 0; c_s < num_slaves; c_s++)
975 sps[c_s].ats_perf_op = GNUNET_TESTBED_service_connect (NULL, sps[c_s].peer,
976 "ats", ats_connect_completion_cb, NULL, &ats_perf_connect_adapter,
977 &ats_perf_disconnect_adapter, &sps[c_s]);
983 peerinformation_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op,
984 const struct GNUNET_TESTBED_PeerInformation*pinfo, const char *emsg)
986 struct BenchmarkPeer *p = cb_cls;
989 GNUNET_assert(pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY);
991 p->id = *pinfo->result.id;
992 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "%s [%u] has peer id `%s'\n",
993 (p->master == GNUNET_YES) ? "Master" : "Slave", p->no,
994 GNUNET_i2s (&p->id));
996 GNUNET_TESTBED_operation_done (op);
997 p->peer_id_op = NULL;
1000 if (done == num_slaves + num_masters)
1002 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1003 "Retrieved all peer ID, connect to ATS\n");
1004 GNUNET_SCHEDULER_add_now (&do_connect_ats, NULL );
1009 * Signature of a main function for a testcase.
1011 * @param cls closure
1012 * @param num_peers number of peers in 'peers'
1013 * @param peers_ handle to peers run in the testbed
1014 * @param links_succeeded the number of overlay link connection attempts that
1016 * @param links_failed the number of overlay link connection attempts that
1020 main_run (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers,
1021 struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded,
1022 unsigned int links_failed)
1026 GNUNET_assert(NULL == cls);
1027 GNUNET_assert(num_masters + num_slaves == num_peers);
1028 GNUNET_assert(NULL != peers_);
1030 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1031 _("Benchmarking solver `%s' on preference `%s' with %u master and %u slave peers\n"),
1032 solver, pref_str, num_masters, num_slaves);
1034 shutdown_task = GNUNET_SCHEDULER_add_delayed (
1035 GNUNET_TIME_relative_multiply (TEST_TIMEOUT, num_masters + num_slaves),
1036 &do_shutdown, NULL );
1038 /* Setup master peers */
1039 for (c_m = 0; c_m < num_masters; c_m++)
1041 GNUNET_assert(NULL != peers_[c_m]);
1042 mps[c_m].peer = peers_[c_m];
1044 mps[c_m].master = GNUNET_YES;
1045 mps[c_m].pref_partner = &sps[c_m];
1046 mps[c_m].pref_value = TEST_ATS_PREFRENCE_START;
1048 GNUNET_malloc (num_slaves * sizeof (struct BenchmarkPeer));
1049 mps[c_m].num_partners = num_slaves;
1050 /* Initialize partners */
1051 for (c_s = 0; c_s < num_slaves; c_s++)
1053 mps[c_m].partners[c_s].me = &mps[c_m];
1054 mps[c_m].partners[c_s].dest = &sps[c_s];
1056 mps[c_m].peer_id_op = GNUNET_TESTBED_peer_get_information (mps[c_m].peer,
1057 GNUNET_TESTBED_PIT_IDENTITY, &peerinformation_cb, &mps[c_m]);
1060 /* Setup slave peers */
1061 for (c_s = 0; c_s < num_slaves; c_s++)
1063 GNUNET_assert(NULL != peers_[c_s + num_masters]);
1064 sps[c_s].peer = peers_[c_s + num_masters];
1065 sps[c_s].no = c_s + num_masters;
1066 sps[c_s].master = GNUNET_NO;
1068 GNUNET_malloc (num_masters * sizeof (struct BenchmarkPeer));
1069 sps[c_s].num_partners = num_masters;
1070 /* Initialize partners */
1071 for (c_m = 0; c_m < num_masters; c_m++)
1073 sps[c_s].partners[c_m].me = &sps[c_s];
1074 sps[c_s].partners[c_m].dest = &mps[c_m];
1076 sps[c_s].peer_id_op = GNUNET_TESTBED_peer_get_information (sps[c_s].peer,
1077 GNUNET_TESTBED_PIT_IDENTITY, &peerinformation_cb, &sps[c_s]);
1082 main (int argc, char *argv[])
1090 char *prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
1095 /* figure out testname */
1096 tmp = strstr (argv[0], TESTNAME_PREFIX);
1099 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1100 return GNUNET_SYSERR;
1102 tmp += strlen (TESTNAME_PREFIX);
1103 solver = GNUNET_strdup (tmp);
1104 if (NULL != (dotexe = strstr (solver, ".exe")) && dotexe[4] == '\0')
1106 tmp_sep = strchr (solver, '_');
1107 if (NULL == tmp_sep)
1109 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1110 GNUNET_free(solver);
1111 return GNUNET_SYSERR;
1114 comm_name = GNUNET_strdup (&tmp_sep[1]);
1115 tmp_sep = strchr (comm_name, '_');
1116 if (NULL == tmp_sep)
1118 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1119 GNUNET_free(solver);
1120 return GNUNET_SYSERR;
1123 for (c = 0; c <= strlen (comm_name); c++)
1124 comm_name[c] = toupper (comm_name[c]);
1125 if (0 == strcmp (comm_name, "CORE"))
1126 test_core = GNUNET_YES;
1127 else if (0 == strcmp (comm_name, "TRANSPORT"))
1128 test_core = GNUNET_NO;
1131 GNUNET_free (comm_name);
1132 GNUNET_free (solver);
1133 return GNUNET_SYSERR;
1136 pref_str = GNUNET_strdup(tmp_sep + 1);
1138 GNUNET_asprintf (&conf_name, "%s%s_%s.conf", TESTNAME_PREFIX, solver,
1140 GNUNET_asprintf (&test_name, "%s%s_%s", TESTNAME_PREFIX, solver, pref_str);
1142 for (c = 0; c <= strlen (pref_str); c++)
1143 pref_str[c] = toupper (pref_str[c]);
1146 if (0 != strcmp (pref_str, "NONE"))
1148 for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
1150 if (0 == strcmp (pref_str, prefs[c]))
1159 /* abuse terminator to indicate no pref */
1160 pref_val = GNUNET_ATS_PREFERENCE_END;
1164 fprintf (stderr, "Unknown preference: `%s'\n", pref_str);
1165 GNUNET_free(solver);
1166 GNUNET_free(pref_str);
1167 GNUNET_free (comm_name);
1171 for (c = 0; c < (argc - 1); c++)
1173 if (0 == strcmp (argv[c], "-s"))
1178 if ((0L != (num_slaves = strtol (argv[c + 1], NULL, 10)))
1179 && (num_slaves >= 1))
1180 fprintf (stderr, "Starting %u slave peers\n", num_slaves);
1182 num_slaves = DEFAULT_SLAVES_NUM;
1185 num_slaves = DEFAULT_SLAVES_NUM;
1187 for (c = 0; c < (argc - 1); c++)
1189 if (0 == strcmp (argv[c], "-m"))
1194 if ((0L != (num_masters = strtol (argv[c + 1], NULL, 10)))
1195 && (num_masters >= 2))
1196 fprintf (stderr, "Starting %u master peers\n", num_masters);
1198 num_masters = DEFAULT_MASTERS_NUM;
1201 num_masters = DEFAULT_MASTERS_NUM;
1203 logging = GNUNET_NO;
1204 for (c = 0; c < argc; c++)
1206 if (0 == strcmp (argv[c], "-l"))
1207 logging = GNUNET_YES;
1211 if (num_slaves < num_masters)
1213 fprintf (stderr, "Number of master peers is lower than slaves! exit...\n");
1214 GNUNET_free(test_name);
1215 GNUNET_free(solver);
1216 GNUNET_free(pref_str);
1217 GNUNET_free (comm_name);
1218 return GNUNET_SYSERR;
1221 state.connected_ATS_service = GNUNET_NO;
1222 state.connected_COMM_service = GNUNET_NO;
1223 state.connected_PEERS = GNUNET_NO;
1224 state.benchmarking = GNUNET_NO;
1225 state.connected_PEERS = GNUNET_NO;
1227 mps = GNUNET_malloc (num_masters * sizeof (struct BenchmarkPeer));
1228 sps = GNUNET_malloc (num_slaves * sizeof (struct BenchmarkPeer));
1230 /* Start topology */
1231 uint64_t event_mask;
1233 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
1234 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
1235 (void) GNUNET_TESTBED_test_run ("perf-ats", conf_name,
1236 num_slaves + num_masters, event_mask, &controller_event_cb, NULL,
1239 GNUNET_free(solver);
1240 GNUNET_free(pref_str);
1241 GNUNET_free(conf_name);
1242 GNUNET_free(test_name);
1243 GNUNET_free (comm_name);
1250 /* end of file perf_ats.c */