aboutsummaryrefslogtreecommitdiff
path: root/src/ats/perf_ats.c
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2013-09-06 11:41:42 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2013-09-06 11:41:42 +0000
commite268f4d047f92e5e4e1a78aabbd323c5953debcd (patch)
tree7df22c008f4c85e8814c91bf3421afd562312829 /src/ats/perf_ats.c
parent07da5a62c47fdbf91ffa99364ee117e2cf8ced5e (diff)
downloadgnunet-e268f4d047f92e5e4e1a78aabbd323c5953debcd.tar.gz
gnunet-e268f4d047f92e5e4e1a78aabbd323c5953debcd.zip
removing tests moved to ../ats-tests
Diffstat (limited to 'src/ats/perf_ats.c')
-rw-r--r--src/ats/perf_ats.c1316
1 files changed, 0 insertions, 1316 deletions
diff --git a/src/ats/perf_ats.c b/src/ats/perf_ats.c
deleted file mode 100644
index 2cb6a0116..000000000
--- a/src/ats/perf_ats.c
+++ /dev/null
@@ -1,1316 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010-2013 Christian Grothoff (and other contributing authors)
4
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.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
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.
19*/
20/**
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
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testbed_service.h"
29#include "gnunet_ats_service.h"
30#include "gnunet_core_service.h"
31
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
37
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)
42
43
44/**
45 * Information we track for a peer in the testbed.
46 */
47struct BenchmarkPeer
48{
49 /**
50 * Handle with testbed.
51 */
52 struct GNUNET_TESTBED_Peer *peer;
53
54 /**
55 * Unique identifier
56 */
57 int no;
58
59 /**
60 * master: GNUNET_YES/NO
61 */
62 int master;
63
64 /**
65 * Peer ID
66 */
67 struct GNUNET_PeerIdentity id;
68
69 /**
70 * Core handle
71 */
72 struct GNUNET_CORE_Handle *ch;
73
74 /**
75 * Testbed operation to connect to ATS performance service
76 */
77 struct GNUNET_TESTBED_Operation *ats_perf_op;
78
79 /**
80 * Testbed operation to get peer information
81 */
82 struct GNUNET_TESTBED_Operation *info_op;
83
84 /**
85 * Testbed operation to connect to core
86 */
87 struct GNUNET_TESTBED_Operation *core_op;
88
89 /**
90 * ATS performance handle
91 */
92 struct GNUNET_ATS_PerformanceHandle *p_handle;
93
94 /**
95 * Testbed connecect operation
96 */
97 struct ConnectOperation *connect_ops;
98
99 /**
100 * ATS Measurement Partner
101 */
102 struct BenchmarkPeer *destination;
103
104 GNUNET_SCHEDULER_TaskIdentifier ats_task;
105
106 /* Message exchange */
107
108 /**
109 * Core transmit handle
110 */
111 struct GNUNET_CORE_TransmitHandle *cth;
112
113 /**
114 * DLL for pending messages: head
115 */
116 struct PendingMessages *p_head;
117
118 /**
119 * DLL for pending messages: tail
120 */
121 struct PendingMessages *p_tail;
122
123 /**
124 * Bit-mask for next partner selection
125 */
126 uint32_t send_mask;
127
128 /**
129 * Current message for partner?
130 */
131 int partner_msg;
132
133 /**
134 * Number of core connections
135 */
136 int core_connections;
137
138 /**
139 * Number of slave connections
140 */
141 int slave_connections;
142
143 /**
144 * Statistics
145 */
146 unsigned int messages_sent;
147 unsigned int messages_sent_partner;
148 unsigned int messages_received;
149};
150
151
152static int c_master_peers;
153
154/**
155 * Array of master peers
156 * Preferences to be set for
157 */
158static struct BenchmarkPeer *bp_master;
159
160static int c_slave_peers;
161
162/**
163 * Array of slave peers
164 * Peer used for measurements
165 */
166static struct BenchmarkPeer *bp_slaves;
167
168
169struct BenchmarkState
170{
171 /* Are we connected to ATS service of all peers: GNUNET_YES/NO */
172 int connected_ATS_service;
173
174 /* Are we connected to CORE service of all peers: GNUNET_YES/NO */
175 int connected_CORE_service;
176
177 /* Are we connected to all peers: GNUNET_YES/NO */
178 int connected_PEERS;
179
180 /* Are we connected to all slave peers on CORE level: GNUNET_YES/NO */
181 int connected_CORE;
182
183 /* Are we connected to CORE service of all peers: GNUNET_YES/NO */
184 int benchmarking;
185
186 int *core_connections;
187
188 uint32_t partner_map;
189};
190
191static struct BenchmarkState state;
192
193/**
194 * Shutdown task
195 */
196static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
197
198static int result;
199static char *solver;
200static char *preference;
201
202/**
203 * Pending Responses
204 */
205struct PendingMessages
206{
207 struct PendingMessages *prev;
208 struct PendingMessages *next;
209 struct GNUNET_PeerIdentity target;
210};
211
212
213/**
214 * Information we track for a peer in the testbed.
215 */
216struct ConnectOperation
217{
218 struct BenchmarkPeer *master;
219
220 struct BenchmarkPeer *slave;
221 /**
222 * Testbed operation to connect peers
223 */
224 struct GNUNET_TESTBED_Operation *connect_op;
225
226};
227
228
229static void
230core_connect_completion_cb (void *cls,
231 struct GNUNET_TESTBED_Operation *op,
232 void *ca_result,
233 const char *emsg );
234
235
236static void evaluate ()
237{
238 int c_p;
239 struct BenchmarkPeer *bp;
240 int total_out;
241 int partner_out;
242
243 for (c_p = 0; c_p < c_master_peers; c_p++)
244 {
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"),
249 bp->no,
250 total_out, partner_out
251 /*partner_out / (total_out / 100)*/);
252 }
253}
254
255/**
256 * Shutdown nicely
257 *
258 * @param cls NULL
259 * @param tc the task context
260 */
261static void
262do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
263{
264 int c_p;
265 int c_op;
266 struct PendingMessages *cur;
267 struct PendingMessages *next;
268
269 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
270
271 state.benchmarking = GNUNET_NO;
272
273 evaluate ();
274 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n"));
275
276 for (c_p = 0; c_p < c_master_peers; c_p++)
277 {
278 next = bp_master[c_p].p_head;
279 for (cur = next; cur != NULL; cur = next )
280 {
281 next = cur->next;
282 GNUNET_CONTAINER_DLL_remove (bp_master[c_p].p_head, bp_master[c_p].p_tail, cur);
283 GNUNET_free (cur);
284 }
285
286 if (GNUNET_SCHEDULER_NO_TASK != bp_master[c_p].ats_task)
287 {
288 GNUNET_SCHEDULER_cancel (bp_master[c_p].ats_task);
289 bp_master[c_p].ats_task = GNUNET_SCHEDULER_NO_TASK;
290 }
291
292 if (NULL != bp_master[c_p].cth)
293 {
294 GNUNET_CORE_notify_transmit_ready_cancel(bp_master[c_p].cth);
295 bp_master[c_p].cth = NULL;
296 }
297
298 if (NULL != bp_master[c_p].ats_perf_op)
299 {
300 GNUNET_TESTBED_operation_done (bp_master[c_p].ats_perf_op);
301 bp_master[c_p].ats_perf_op = NULL;
302 }
303
304 if (NULL != bp_master[c_p].core_op)
305 {
306 GNUNET_TESTBED_operation_done (bp_master[c_p].core_op);
307 bp_master[c_p].core_op = NULL;
308 }
309
310 if (NULL != bp_master[c_p].info_op)
311 {
312 GNUNET_break (0);
313 GNUNET_TESTBED_operation_done (bp_master[c_p].info_op);
314 bp_master[c_p].info_op = NULL;
315 }
316
317 for (c_op = 0; c_op < c_slave_peers; c_op++)
318 {
319 if (NULL != bp_master[c_p].connect_ops[c_op].connect_op)
320 {
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;
324 result = 1;
325 }
326 }
327 GNUNET_free (bp_master[c_p].connect_ops);
328 }
329
330 for (c_p = 0; c_p < c_slave_peers; c_p++)
331 {
332 next = bp_slaves[c_p].p_head;
333 for (cur = next; cur != NULL; cur = next )
334 {
335 next = cur->next;
336 GNUNET_CONTAINER_DLL_remove (bp_slaves[c_p].p_head, bp_slaves[c_p].p_tail, cur);
337 GNUNET_free (cur);
338 }
339
340 if (NULL != bp_slaves[c_p].cth)
341 {
342 GNUNET_CORE_notify_transmit_ready_cancel(bp_slaves[c_p].cth);
343 bp_slaves[c_p].cth = NULL;
344 }
345
346 if (NULL != bp_slaves[c_p].ats_perf_op)
347 {
348 GNUNET_TESTBED_operation_done (bp_slaves[c_p].ats_perf_op);
349 bp_slaves[c_p].ats_perf_op = NULL;
350 }
351
352 if (NULL != bp_slaves[c_p].core_op)
353 {
354 GNUNET_TESTBED_operation_done (bp_slaves[c_p].core_op);
355 bp_slaves[c_p].core_op = NULL;
356 }
357
358 if (NULL != bp_slaves[c_p].info_op)
359 {
360 GNUNET_break (0);
361 GNUNET_TESTBED_operation_done (bp_slaves[c_p].info_op);
362 bp_slaves[c_p].info_op = NULL;
363 }
364
365 }
366
367 GNUNET_SCHEDULER_shutdown();
368}
369
370static struct BenchmarkPeer *
371find_peer (const struct GNUNET_PeerIdentity * peer)
372{
373 int c_p;
374
375 for (c_p = 0; c_p < c_master_peers; c_p++)
376 {
377 if (0 == memcmp (&bp_master[c_p].id, peer, sizeof (struct GNUNET_PeerIdentity)))
378 return &bp_master[c_p];
379 }
380
381 for (c_p = 0; c_p < c_slave_peers; c_p++)
382 {
383 if (0 == memcmp (&bp_slaves[c_p].id, peer, sizeof (struct GNUNET_PeerIdentity)))
384 return &bp_slaves[c_p];
385 }
386
387 return NULL;
388}
389
390
391static void
392store_information (struct GNUNET_PeerIdentity *id,
393 const struct GNUNET_HELLO_Address *address,
394 int address_active,
395 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
396 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
397 const struct GNUNET_ATS_Information *ats,
398 uint32_t ats_count)
399{
400 struct BenchmarkPeer *bp;
401
402 bp = find_peer (id);
403
404 if (NULL == bp)
405 {
406 GNUNET_break (0);
407 return;
408 }
409}
410
411static void
412ats_performance_info_cb (void *cls,
413 const struct GNUNET_HELLO_Address *address,
414 int address_active,
415 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
416 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
417 const struct GNUNET_ATS_Information *ats,
418 uint32_t ats_count)
419{
420 struct BenchmarkPeer *bp = cls;
421 int c_a;
422 char *peer_id;
423
424 peer_id = GNUNET_strdup (GNUNET_i2s (&bp->id));
425 for (c_a = 0; c_a < ats_count; c_a++)
426 {
427 /*GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("%c %03u: %s %s %u\n"),
428 (GNUNET_YES == p->master) ? 'M' : 'S',
429 p->no,
430 GNUNET_i2s (&address->peer),
431 GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)),
432 ntohl(ats[c_a].value));*/
433 }
434
435 if ((GNUNET_YES == bp->master) &&
436 (0 == memcmp (&address->peer, &bp->destination->id,
437 sizeof (struct GNUNET_PeerIdentity))))
438 {
439 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Bandwidth for master %u: %lu %lu\n",
440 bp->no,
441 (long unsigned int) ntohl(bandwidth_in.value__),
442 (long unsigned int) ntohl(bandwidth_in.value__));
443 }
444
445 store_information (&bp->id, address, address_active,
446 bandwidth_in, bandwidth_out,
447 ats, ats_count);
448
449 GNUNET_free (peer_id);
450}
451
452static size_t
453core_send_ready (void *cls, size_t size, void *buf)
454{
455 static char msgbuf[TEST_MESSAGE_SIZE];
456 struct BenchmarkPeer *bp = cls;
457 struct GNUNET_MessageHeader *msg;
458
459 bp->cth = NULL;
460
461 bp->messages_sent ++;
462 if (GNUNET_YES == bp->partner_msg)
463 {
464 bp->messages_sent_partner ++;
465 bp->partner_msg = GNUNET_NO;
466 }
467
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;
474}
475
476static struct BenchmarkPeer *
477get_next (struct BenchmarkPeer *p)
478{
479 uint32_t b_index;
480 uint32_t index;
481 int counter;
482
483 if (0 == p->send_mask)
484 p->send_mask = (1 << c_slave_peers) - 1; /* Next round */
485
486 GNUNET_assert (p->send_mask <= (1 << c_slave_peers) - 1);
487 counter = 0;
488 do
489 {
490 index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, c_slave_peers);
491 b_index = 1 << index;
492 counter++;
493 }
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))
496 {
497 /* To many random attempts use fcfs */
498 for (index = 0; index < c_slave_peers - 1; index ++)
499 {
500 b_index = 1 << index;
501 if (b_index == (p->send_mask & b_index))
502 break;
503 }
504 }
505 p->send_mask ^= b_index; /* Remove bit */
506 return &bp_slaves[index];
507
508}
509
510
511static void
512ats_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
513{
514 static double last = 1;
515 struct BenchmarkPeer *bp = cls;
516
517 bp->ats_task = GNUNET_SCHEDULER_NO_TASK;
518
519 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Set preference for master %u: %f\n",
520 bp->no, last);
521 GNUNET_ATS_performance_change_preference (bp->p_handle, &bp->destination->id,
522 GNUNET_ATS_PREFERENCE_BANDWIDTH, (double) last,
523 GNUNET_ATS_PREFERENCE_END);
524 last++;
525 bp->ats_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
526 &ats_pref_task, bp);
527}
528
529
530static void
531do_benchmark ()
532{
533 int c_m;
534 struct BenchmarkPeer *s;
535 struct BenchmarkPeer *bp;
536
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))
541 return;
542
543 state.benchmarking = GNUNET_YES;
544 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
545 _("Benchmarking start\n"));
546
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);
550
551 /* Start sending test messages */
552 for (c_m = 0; c_m < c_master_peers; c_m ++)
553 {
554 bp = &bp_master[c_m];
555 s = get_next (bp);
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,
560 &s->id,
561 TEST_MESSAGE_SIZE, &core_send_ready, bp);
562 bp->ats_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
563 &ats_pref_task, bp);
564 }
565
566
567}
568
569
570static void
571connect_completion_callback (void *cls,
572 struct GNUNET_TESTBED_Operation *op,
573 const char *emsg)
574{
575 struct ConnectOperation *cop = cls;
576 static int ops = 0 ;
577 int c;
578 if (NULL == emsg)
579 {
580 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
581 _("Connected master peer %u with peer %u\n"), cop->master->no, cop->slave->no);
582 }
583 else
584 {
585 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
586 _("Failed to connect master peer%u with peer %u\n"), cop->master->no, cop->slave->no);
587 GNUNET_break (0);
588 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
589 GNUNET_SCHEDULER_cancel(shutdown_task);
590 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
591 }
592 GNUNET_TESTBED_operation_done(op);
593 ops++;
594 for (c = 0; c < c_slave_peers; c++)
595 {
596 if (cop == &cop->master->connect_ops[c])
597 cop->master->connect_ops[c].connect_op = NULL;
598 }
599 if (ops == c_master_peers * c_slave_peers)
600 {
601 state.connected_PEERS = GNUNET_YES;
602 GNUNET_SCHEDULER_add_now (&do_benchmark, NULL);
603 }
604}
605
606
607static void
608do_connect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
609{
610 int c_m;
611 int c_s;
612 struct BenchmarkPeer *bp;
613
614 if ((state.connected_ATS_service == GNUNET_NO) ||
615 (state.connected_CORE_service == GNUNET_NO))
616 {
617 return;
618 }
619
620 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connecting peers on CORE level\n"));
621
622 for (c_m = 0; c_m < c_master_peers; c_m ++)
623 {
624 bp = &bp_master[c_m];
625 bp->connect_ops = GNUNET_malloc (c_slave_peers * sizeof (struct ConnectOperation));
626
627 for (c_s = 0; c_s < c_slave_peers; c_s ++)
628 {
629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Connecting master peer %u with slave peer %u\n"),
630 bp->no, bp_slaves[c_s].no);
631
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],
637 bp_slaves[c_s].peer,
638 bp->peer);
639
640 if (NULL == bp->connect_ops[c_s].connect_op)
641 {
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);
645 GNUNET_break (0);
646 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
647 GNUNET_SCHEDULER_cancel(shutdown_task);
648 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
649 return;
650 }
651 }
652 }
653}
654
655
656/**
657 * Controller event callback
658 *
659 * @param cls NULL
660 * @param event the controller event
661 */
662static void
663controller_event_cb (void *cls,
664 const struct GNUNET_TESTBED_EventInformation *event)
665{
666 //struct BenchmarkPeer *p = cls;
667 switch (event->type)
668 {
669 case GNUNET_TESTBED_ET_CONNECT:
670 break;
671 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
672 break;
673 default:
674 GNUNET_break (0);
675 result = 2;
676 GNUNET_SCHEDULER_cancel (shutdown_task);
677 shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
678 }
679}
680
681/**
682 * Method called whenever a given peer connects.
683 *
684 * @param cls closure
685 * @param peer peer identity this notification is about
686 */
687static void
688core_connect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
689{
690 struct BenchmarkPeer *p = cls;
691 struct BenchmarkPeer *t;
692 char *id;
693 int c;
694 int cs;
695
696 id = GNUNET_strdup (GNUNET_i2s (&p->id));
697
698 t = find_peer (peer);
699 if (NULL == t)
700 {
701 GNUNET_break (0);
702 return;
703 }
704
705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
706 "%s %s connected to %s %s\n",
707 (p->master == GNUNET_YES) ? "Master": "Slave",
708 id,
709 (t->master == GNUNET_YES) ? "Master": "Slave",
710 GNUNET_i2s (peer));
711
712 p->core_connections ++;
713 if ((GNUNET_YES == p->master) && (GNUNET_NO == t->master) && (GNUNET_NO == state.connected_CORE))
714 {
715 p->slave_connections ++;
716
717 if (p->slave_connections == c_slave_peers)
718 {
719 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
720 "Master %u connected all slaves\n", p->no);
721 }
722 cs = GNUNET_YES;
723 for (c = 0; c < c_master_peers; c ++)
724 {
725 if (bp_master[c].slave_connections != c_slave_peers)
726 cs = GNUNET_NO;
727 }
728 if (GNUNET_YES == cs)
729 {
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);
734 }
735 }
736 GNUNET_free (id);
737}
738
739
740/**
741 * Method called whenever a peer disconnects.
742 *
743 * @param cls closure
744 * @param peer peer identity this notification is about
745 */
746static void
747core_disconnect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
748{
749 struct BenchmarkPeer *p = cls;
750 struct BenchmarkPeer *t;
751 char *id;
752
753 t = find_peer (peer);
754 if (NULL == t)
755 {
756 GNUNET_break (0);
757 return;
758 }
759
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 --;
765
766 if ((GNUNET_YES == state.benchmarking) &&
767 ((GNUNET_YES == p->master) || (GNUNET_YES == t->master)))
768 {
769 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
770 "%s disconnected from %s while benchmarking \n", id, GNUNET_i2s (peer));
771 }
772
773 GNUNET_free (id);
774}
775
776static size_t
777core_send_echo_queued_ready (void *cls, size_t size, void *buf);
778
779static size_t
780core_send_echo_ready (void *cls, size_t size, void *buf)
781{
782 static char msgbuf[TEST_MESSAGE_SIZE];
783 struct BenchmarkPeer *bp = cls;
784 struct GNUNET_MessageHeader *msg;
785
786 bp->cth = NULL;
787
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);
793
794 /* send echo */
795 if (NULL != bp->p_head)
796 bp->cth = GNUNET_CORE_notify_transmit_ready (bp->ch,
797 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
798 &bp->p_head->target,
799 TEST_MESSAGE_SIZE, &core_send_echo_queued_ready, bp);
800
801 return TEST_MESSAGE_SIZE;
802}
803
804static size_t
805core_send_echo_queued_ready (void *cls, size_t size, void *buf)
806{
807 struct BenchmarkPeer *bp = cls;
808 struct PendingMessages *pm;
809 GNUNET_assert (NULL != bp->p_head);
810
811 pm = bp->p_head;
812 GNUNET_CONTAINER_DLL_remove (bp->p_head, bp->p_tail, pm);
813 GNUNET_free (pm);
814
815
816 return core_send_echo_ready (cls, size, buf);
817
818}
819
820
821static int
822core_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other,
823 const struct GNUNET_MessageHeader *message)
824{
825 struct BenchmarkPeer *me = cls;
826 struct BenchmarkPeer *remote;
827 struct PendingMessages *pm;
828
829 remote = find_peer (other);
830
831 if (NULL == remote)
832 {
833 GNUNET_break (0);
834 return GNUNET_SYSERR;
835 }
836
837 if (NULL != me->cth)
838 {
839 pm = GNUNET_malloc (sizeof (struct PendingMessages));
840 pm->target = (*other);
841 GNUNET_CONTAINER_DLL_insert_tail (me->p_head, me->p_tail, pm);
842 return GNUNET_OK;
843 }
844
845 if (GNUNET_NO == remote->master)
846 {
847 GNUNET_break (0);
848 return GNUNET_OK;
849 }
850
851 me->messages_received ++;
852 /* send echo */
853 me->cth = GNUNET_CORE_notify_transmit_ready (me->ch,
854 GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES,
855 &remote->id,
856 TEST_MESSAGE_SIZE, &core_send_echo_ready, me);
857 return GNUNET_OK;
858}
859
860static int
861core_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other,
862 const struct GNUNET_MessageHeader *message)
863{
864 struct BenchmarkPeer *me = cls;
865 struct BenchmarkPeer *remote;
866 struct BenchmarkPeer *next;
867
868 remote = find_peer (other);
869
870 if (NULL == remote)
871 {
872 GNUNET_break (0);
873 return GNUNET_SYSERR;
874 }
875
876 if (NULL != me->cth)
877 {
878 GNUNET_break (0);
879 return GNUNET_OK;
880 }
881
882 if (GNUNET_YES == remote->master)
883 {
884 GNUNET_break (0);
885 return GNUNET_OK;
886 }
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,
893 &next->id,
894 TEST_MESSAGE_SIZE, &core_send_ready, me);
895
896 return GNUNET_OK;
897}
898
899
900/**
901 * Called to open a connection to the peer's ATS performance
902 *
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
908 */
909static void *
910core_connect_adapter (void *cls,
911 const struct GNUNET_CONFIGURATION_Handle *cfg)
912{
913 struct BenchmarkPeer *peer = cls;
914
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},
918 {NULL, 0, 0}
919 };
920
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");
927 return peer->ch;
928}
929
930
931/**
932 * Callback to be called when a service connect operation is completed
933 *
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.
939 */
940static void
941core_connect_completion_cb (void *cls,
942 struct GNUNET_TESTBED_Operation *op,
943 void *ca_result,
944 const char *emsg )
945{
946 static int core_done = 0;
947 if ((NULL != emsg) || (NULL == ca_result))
948 {
949 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
950 _("Initialization failed, shutdown\n"));
951 GNUNET_break (0);
952 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
953 GNUNET_SCHEDULER_cancel(shutdown_task);
954 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
955 return;
956 }
957 core_done ++;
958
959 if (core_done == c_slave_peers + c_master_peers)
960 {
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);
965 }
966}
967
968
969/**
970 * Called to disconnect from peer's statistics service
971 *
972 * @param cls peer context
973 * @param op_result service handle returned from the connect adapter
974 */
975static void
976core_disconnect_adapter (void *cls, void *op_result)
977{
978 struct BenchmarkPeer *peer = cls;
979
980 GNUNET_CORE_disconnect (peer->ch);
981 peer->ch = NULL;
982}
983
984static void
985do_connect_core (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
986{
987 int c_p;
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++)
991 {
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,
997 &bp_master[c_p]);
998
999 }
1000
1001 for (c_p = 0; c_p < c_slave_peers; c_p++)
1002 {
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,
1008 &bp_slaves[c_p]);
1009 }
1010}
1011
1012
1013
1014/**
1015 * Called to open a connection to the peer's ATS performance
1016 *
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
1022 */
1023static void *
1024ats_perf_connect_adapter (void *cls,
1025 const struct GNUNET_CONFIGURATION_Handle *cfg)
1026{
1027 struct BenchmarkPeer *peer = cls;
1028
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;
1033}
1034
1035
1036/**
1037 * Called to disconnect from peer's statistics service
1038 *
1039 * @param cls peer context
1040 * @param op_result service handle returned from the connect adapter
1041 */
1042static void
1043ats_perf_disconnect_adapter (void *cls, void *op_result)
1044{
1045 struct BenchmarkPeer *peer = cls;
1046
1047 GNUNET_ATS_performance_done(peer->p_handle);
1048 peer->p_handle = NULL;
1049}
1050
1051
1052/**
1053 * Callback to be called when a service connect operation is completed
1054 *
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.
1060 */
1061static void
1062ats_connect_completion_cb (void *cls,
1063 struct GNUNET_TESTBED_Operation *op,
1064 void *ca_result,
1065 const char *emsg )
1066{
1067 static int op_done = 0;
1068 if ((NULL != emsg) || (NULL == ca_result))
1069 {
1070 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1071 _("Initialization failed, shutdown\n"));
1072 GNUNET_break (0);
1073 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
1074 GNUNET_SCHEDULER_cancel(shutdown_task);
1075 shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
1076 return;
1077 }
1078
1079 op_done ++;
1080 if (op_done == (c_slave_peers + c_master_peers))
1081 {
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);
1086 }
1087}
1088
1089static void
1090do_connect_ats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1091{
1092 int c_p;
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++)
1096 {
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,
1102 &bp_master[c_p]);
1103
1104 }
1105
1106 for (c_p = 0; c_p < c_slave_peers; c_p++)
1107 {
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,
1113 &bp_slaves[c_p]);
1114 }
1115
1116}
1117
1118
1119/**
1120 * Callback to be called when the requested peer information is available
1121 *
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
1127 */
1128static void
1129peerinformation_cb (void *cb_cls,
1130 struct GNUNET_TESTBED_Operation *op,
1131 const struct GNUNET_TESTBED_PeerInformation*pinfo,
1132 const char *emsg)
1133{
1134 struct BenchmarkPeer *p = cb_cls;
1135 static int done = 0;
1136
1137 if (pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY)
1138 {
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));
1143 }
1144 else
1145 {
1146 GNUNET_assert (0);
1147 }
1148 GNUNET_TESTBED_operation_done (op);
1149 p->info_op = NULL;
1150 done++;
1151
1152 if (done == c_master_peers + c_slave_peers)
1153 {
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);
1158 }
1159}
1160
1161
1162/**
1163 * Signature of a main function for a testcase.
1164 *
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
1169 * succeeded
1170 * @param links_failed the number of overlay link connection attempts that
1171 * failed
1172 */
1173static void
1174test_main (void *cls, unsigned int num_peers,
1175 struct GNUNET_TESTBED_Peer **peers_,
1176 unsigned int links_succeeded,
1177 unsigned int links_failed)
1178{
1179 int c_p;
1180
1181 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1182 _("Benchmarking solver `%s' on preference `%s' with %u master and %u slave peers\n"),
1183 solver, preference, c_master_peers, c_slave_peers);
1184
1185 shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(TEST_TIMEOUT, c_master_peers + c_slave_peers), &do_shutdown, NULL);
1186
1187 GNUNET_assert (NULL == cls);
1188 GNUNET_assert (c_slave_peers + c_master_peers == num_peers);
1189 GNUNET_assert (NULL != peers_);
1190
1191 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1192 _("Initializing... \n"));
1193
1194 for (c_p = 0; c_p < c_master_peers; c_p++)
1195 {
1196 GNUNET_assert (NULL != peers_[c_p]);
1197 bp_master[c_p].no = c_p;
1198 bp_master[c_p].send_mask = (1 << c_slave_peers) - 1;
1199 bp_master[c_p].master = GNUNET_YES;
1200 bp_master[c_p].peer = peers_[c_p];
1201 bp_master[c_p].info_op = GNUNET_TESTBED_peer_get_information (bp_master[c_p].peer,
1202 GNUNET_TESTBED_PIT_IDENTITY,
1203 &peerinformation_cb, &bp_master[c_p]);
1204
1205 /* Select ATS measurement partner */
1206 bp_master[c_p].destination = &bp_slaves[c_p];
1207 }
1208
1209 for (c_p = 0; c_p < c_slave_peers; c_p++)
1210 {
1211 GNUNET_assert (NULL != peers_[c_p + c_master_peers]);
1212 bp_slaves[c_p].no = c_p + c_master_peers;
1213 bp_slaves[c_p].master = GNUNET_NO;
1214 bp_slaves[c_p].peer = peers_[c_p + c_master_peers];
1215 bp_slaves[c_p].info_op = GNUNET_TESTBED_peer_get_information (bp_slaves[c_p].peer,
1216 GNUNET_TESTBED_PIT_IDENTITY,
1217 &peerinformation_cb, &bp_slaves[c_p]);
1218 }
1219
1220}
1221
1222
1223int
1224main (int argc, char *argv[])
1225{
1226 char *tmp;
1227 char *tmp_sep;
1228 char *test_name;
1229 char *conf_name;
1230 char *dotexe;
1231 int c;
1232
1233 result = 0;
1234
1235 /* figure out testname */
1236 tmp = strstr (argv[0], TESTNAME_PREFIX);
1237 if (NULL == tmp)
1238 {
1239 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1240 return GNUNET_SYSERR;
1241 }
1242 tmp += strlen(TESTNAME_PREFIX);
1243 solver = GNUNET_strdup (tmp);
1244 if (NULL != (dotexe = strstr (solver, ".exe")) &&
1245 dotexe[4] == '\0')
1246 dotexe[0] = '\0';
1247 tmp_sep = strchr (solver, '_');
1248 if (NULL == tmp_sep)
1249 {
1250 fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]);
1251 GNUNET_free (solver);
1252 return GNUNET_SYSERR;
1253 }
1254 tmp_sep[0] = '\0';
1255 preference = GNUNET_strdup(tmp_sep + 1);
1256
1257 GNUNET_asprintf(&conf_name, "%s%s_%s.conf", TESTNAME_PREFIX, solver, preference);
1258 GNUNET_asprintf(&test_name, "%s%s_%s", TESTNAME_PREFIX, solver, preference);
1259
1260 for (c = 0; c < (argc -1); c++)
1261 {
1262 if (0 == strcmp(argv[c], "-s"))
1263 break;
1264 }
1265 if (c < argc-1)
1266 {
1267 if ((0L != (c_slave_peers = strtol (argv[c + 1], NULL, 10))) && (c_slave_peers >= 1))
1268 fprintf (stderr, "Starting %u slave peers\n", c_slave_peers);
1269 else
1270 c_slave_peers = DEFAULT_SLAVES_NUM;
1271 }
1272 else
1273 c_slave_peers = DEFAULT_SLAVES_NUM;
1274
1275 for (c = 0; c < (argc -1); c++)
1276 {
1277 if (0 == strcmp(argv[c], "-m"))
1278 break;
1279 }
1280 if (c < argc-1)
1281 {
1282 if ((0L != (c_master_peers = strtol (argv[c + 1], NULL, 10))) && (c_master_peers >= 2))
1283 fprintf (stderr, "Starting %u master peers\n", c_master_peers);
1284 else
1285 c_master_peers = DEFAULT_MASTERS_NUM;
1286 }
1287 else
1288 c_master_peers = DEFAULT_MASTERS_NUM;
1289
1290 bp_slaves = GNUNET_malloc (c_slave_peers * sizeof (struct BenchmarkPeer));
1291 bp_master = GNUNET_malloc (c_master_peers * sizeof (struct BenchmarkPeer));
1292
1293 state.connected_ATS_service = GNUNET_NO;
1294 state.connected_CORE_service = GNUNET_NO;
1295 state.connected_PEERS = GNUNET_NO;
1296
1297 /* Start topology */
1298 uint64_t event_mask;
1299 event_mask = 0;
1300 event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
1301 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
1302 (void) GNUNET_TESTBED_test_run (test_name,
1303 conf_name, c_slave_peers + c_master_peers,
1304 event_mask, &controller_event_cb, NULL,
1305 &test_main, NULL);
1306
1307 GNUNET_free (solver);
1308 GNUNET_free (preference);
1309 GNUNET_free (conf_name);
1310 GNUNET_free (test_name);
1311 GNUNET_free (bp_slaves);
1312
1313 return result;
1314}
1315
1316/* end of file perf_ats.c */