aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2014-03-13 15:01:34 +0000
committerBart Polot <bart@net.in.tum.de>2014-03-13 15:01:34 +0000
commit9d85380a4e8188cdc026233c139c0d251bfeb4fc (patch)
tree73d045977080e1c6420897b7be56000b403228c6 /src
parentdbdb091b11204e1e1caaa3f4260bb6cf1168cbd2 (diff)
downloadgnunet-9d85380a4e8188cdc026233c139c0d251bfeb4fc.tar.gz
gnunet-9d85380a4e8188cdc026233c139c0d251bfeb4fc.zip
- inital mesh_profiler commit
Diffstat (limited to 'src')
-rw-r--r--src/mesh/mesh_profiler.c1021
1 files changed, 1021 insertions, 0 deletions
diff --git a/src/mesh/mesh_profiler.c b/src/mesh/mesh_profiler.c
new file mode 100644
index 000000000..094d41c58
--- /dev/null
+++ b/src/mesh/mesh_profiler.c
@@ -0,0 +1,1021 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 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 mesh/mesh_profiler.c
22 *
23 * @brief Profiler for mesh experiments.
24 */
25#include <stdio.h>
26#include "platform.h"
27#include "mesh_test_lib.h"
28#include "gnunet_mesh_service.h"
29#include "gnunet_statistics_service.h"
30#include <gauger.h>
31
32
33/**
34 * How namy messages to send
35 */
36#define TOTAL_PACKETS 1000
37
38/**
39 * How namy peers to run
40 */
41#define TOTAL_PEERS 1000
42
43/**
44 * How long until we give up on connecting the peers?
45 */
46#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
47
48/**
49 * Time to wait for stuff that should be rather fast
50 */
51#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
52
53
54/**
55 * How many events have happened
56 */
57static int ok;
58
59/**
60 * Number of events expected to conclude the test successfully.
61 */
62int ok_goal;
63
64/**
65 * Size of each test packet
66 */
67size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t);
68
69/**
70 * Operation to get peer ids.
71 */
72struct GNUNET_TESTBED_Operation *t_op[TOTAL_PEERS];
73
74/**
75 * Peer ids.
76 */
77struct GNUNET_PeerIdentity *p_id[TOTAL_PEERS];
78
79/**
80 * Mesh handle for the root peer
81 */
82static struct GNUNET_MESH_Handle *mesh_h[TOTAL_PEERS];
83
84/**
85 * Channel handle for the root peer
86 */
87static struct GNUNET_MESH_Channel *ch;
88
89/**
90 * Channel handle for the dest peer
91 */
92static struct GNUNET_MESH_Channel *incoming_ch;
93
94/**
95 * Peer ids counter.
96 */
97unsigned int p_ids;
98
99/**
100 * Is the setup initialized?
101 */
102static int initialized;
103
104/**
105 * Number of payload packes sent
106 */
107static int data_sent;
108
109/**
110 * Number of payload packets received
111 */
112static int data_received;
113
114/**
115 * Number of payload packed explicitly (app level) acknowledged
116 */
117static int data_ack;
118
119/**
120 * Total number of currently running peers.
121 */
122static unsigned long long peers_running;
123
124/**
125 * Test context (to shut down).
126 */
127struct GNUNET_MESH_TEST_Context *test_ctx;
128
129/**
130 * Task called to shutdown test.
131 */
132static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
133
134/**
135 * Task called to disconnect peers, before shutdown.
136 */
137static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
138
139/**
140 * Task to perform tests
141 */
142static GNUNET_SCHEDULER_TaskIdentifier test_task;
143
144/**
145 * Time we started the data transmission (after channel has been established
146 * and initilized).
147 */
148static struct GNUNET_TIME_Absolute start_time;
149
150static struct GNUNET_TESTBED_Peer **testbed_peers;
151
152/**
153 *
154 */
155static struct GNUNET_STATISTICS_Handle *stats;
156static struct GNUNET_STATISTICS_GetHandle *stats_get;
157static struct GNUNET_TESTBED_Operation *stats_op;
158static unsigned int ka_sent;
159static unsigned int ka_received;
160
161
162/**
163 * Show the results of the test (banwidth acheived) and log them to GAUGER
164 */
165static void
166show_end_data (void)
167{
168 static struct GNUNET_TIME_Absolute end_time;
169 static struct GNUNET_TIME_Relative total_time;
170
171 end_time = GNUNET_TIME_absolute_get();
172 total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
173 FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
174 FPRINTF (stderr, "Test time %s\n",
175 GNUNET_STRINGS_relative_time_to_string (total_time,
176 GNUNET_YES));
177 FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
178 4 * TOTAL_PACKETS * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms
179 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
180 TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms
181 GAUGER ("MESH", test_name,
182 TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000),
183 "packets/s");
184}
185
186
187/**
188 * Shut down peergroup, clean up.
189 *
190 * @param cls Closure (unused).
191 * @param tc Task Context.
192 */
193static void
194shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
195{
196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
197 shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
198}
199
200
201/**
202 * Disconnect from mesh services af all peers, call shutdown.
203 *
204 * @param cls Closure (unused).
205 * @param tc Task Context.
206 */
207static void
208disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
209{
210 long line = (long) cls;
211 unsigned int i;
212
213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
214 "disconnecting mesh service of peers, called from line %ld\n",
215 line);
216 disconnect_task = GNUNET_SCHEDULER_NO_TASK;
217 for (i = 0; i < 2; i++)
218 {
219 GNUNET_TESTBED_operation_done (t_op[i]);
220 }
221 if (NULL != ch)
222 {
223 GNUNET_MESH_channel_destroy (ch);
224 ch = NULL;
225 }
226 if (NULL != incoming_ch)
227 {
228 GNUNET_MESH_channel_destroy (incoming_ch);
229 incoming_ch = NULL;
230 }
231 GNUNET_MESH_TEST_cleanup (test_ctx);
232 if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
233 {
234 GNUNET_SCHEDULER_cancel (shutdown_handle);
235 }
236 if (NULL != stats_get)
237 GNUNET_STATISTICS_get_cancel (stats_get);
238 shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
239}
240
241
242/**
243 * Abort test: schedule disconnect and shutdown immediately
244 *
245 * @param line Line in the code the abort is requested from (__LINE__).
246 */
247static void
248abort_test (long line)
249{
250 if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
251 {
252 GNUNET_SCHEDULER_cancel (disconnect_task);
253 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
254 (void *) line);
255 }
256}
257
258/**
259 * Transmit ready callback.
260 *
261 * @param cls Closure (message type).
262 * @param size Size of the tranmist buffer.
263 * @param buf Pointer to the beginning of the buffer.
264 *
265 * @return Number of bytes written to buf.
266 */
267static size_t
268tmt_rdy (void *cls, size_t size, void *buf);
269
270
271/**
272 * Task to schedule a new data transmission.
273 *
274 * @param cls Closure (peer #).
275 * @param tc Task Context.
276 */
277static void
278data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
279{
280 struct GNUNET_MESH_TransmitHandle *th;
281 struct GNUNET_MESH_Channel *channel;
282
283 if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
284 return;
285
286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n");
287 if (GNUNET_YES == test_backwards)
288 {
289 channel = incoming_ch;
290 }
291 else
292 {
293 channel = ch;
294 }
295 th = GNUNET_MESH_notify_transmit_ready (channel, GNUNET_NO,
296 GNUNET_TIME_UNIT_FOREVER_REL,
297 size_payload, &tmt_rdy, (void *) 1L);
298 if (NULL == th)
299 {
300 unsigned long i = (unsigned long) cls;
301
302 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n");
303 if (0 == i)
304 {
305 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " in 1 ms\n");
306 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
307 &data_task, (void *)1UL);
308 }
309 else
310 {
311 i++;
312 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i);
313 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(
314 GNUNET_TIME_UNIT_MILLISECONDS,
315 i),
316 &data_task, (void *)i);
317 }
318 }
319}
320
321
322/**
323 * Transmit ready callback
324 *
325 * @param cls Closure (message type).
326 * @param size Size of the buffer we have.
327 * @param buf Buffer to copy data to.
328 */
329size_t
330tmt_rdy (void *cls, size_t size, void *buf)
331{
332 struct GNUNET_MessageHeader *msg = buf;
333 uint32_t *data;
334
335 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
336 "tmt_rdy called, filling buffer\n");
337 if (size < size_payload || NULL == buf)
338 {
339 GNUNET_break (ok >= ok_goal - 2);
340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
341 "size %u, buf %p, data_sent %u, data_received %u\n",
342 size, buf, data_sent, data_received);
343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ok %u, ok goal %u\n", ok, ok_goal);
344
345 return 0;
346 }
347 msg->size = htons (size);
348 msg->type = htons ((long) cls);
349 data = (uint32_t *) &msg[1];
350 *data = htonl (data_sent);
351 if (GNUNET_NO == initialized)
352 {
353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
354 "sending initializer\n");
355 }
356 else if (SPEED == test)
357 {
358 data_sent++;
359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
360 " Sent packet %d\n", data_sent);
361 if (data_sent < TOTAL_PACKETS)
362 {
363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
364 " Scheduling packet %d\n", data_sent + 1);
365 GNUNET_SCHEDULER_add_now (&data_task, NULL);
366 }
367 }
368
369 return size_payload;
370}
371
372
373/**
374 * Function is called whenever a message is received.
375 *
376 * @param cls closure (set from GNUNET_MESH_connect)
377 * @param channel connection to the other end
378 * @param channel_ctx place to store local state associated with the channel
379 * @param message the actual message
380 * @return GNUNET_OK to keep the connection open,
381 * GNUNET_SYSERR to close it (signal serious error)
382 */
383int
384data_callback (void *cls, struct GNUNET_MESH_Channel *channel,
385 void **channel_ctx,
386 const struct GNUNET_MessageHeader *message)
387{
388 long client = (long) cls;
389 long expected_target_client;
390 uint32_t *data;
391
392 ok++;
393
394 GNUNET_MESH_receive_done (channel);
395
396 if ((ok % 20) == 0)
397 {
398 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
399 {
400 GNUNET_SCHEDULER_cancel (disconnect_task);
401 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
402 &disconnect_mesh_peers,
403 (void *) __LINE__);
404 }
405 }
406
407 switch (client)
408 {
409 case 0L:
410 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
411 break;
412 case 4L:
413 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
414 "Leaf client %li got a message.\n",
415 client);
416 break;
417 default:
418 GNUNET_assert (0);
419 break;
420 }
421 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
422 data = (uint32_t *) &message[1];
423 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data));
424 if (SPEED == test && GNUNET_YES == test_backwards)
425 {
426 expected_target_client = 0L;
427 }
428 else
429 {
430 expected_target_client = 4L;
431 }
432
433 if (GNUNET_NO == initialized)
434 {
435 initialized = GNUNET_YES;
436 start_time = GNUNET_TIME_absolute_get ();
437 if (SPEED == test)
438 {
439 GNUNET_assert (4L == client);
440 GNUNET_SCHEDULER_add_now (&data_task, NULL);
441 return GNUNET_OK;
442 }
443 }
444
445 if (client == expected_target_client) // Normally 4
446 {
447 data_received++;
448 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received);
449 if (SPEED != test || (ok_goal - 2) == ok)
450 {
451 GNUNET_MESH_notify_transmit_ready (channel, GNUNET_NO,
452 GNUNET_TIME_UNIT_FOREVER_REL,
453 size_payload, &tmt_rdy, (void *) 1L);
454 return GNUNET_OK;
455 }
456 else
457 {
458 if (data_received < TOTAL_PACKETS)
459 return GNUNET_OK;
460 }
461 }
462 else // Normally 0
463 {
464 if (test == SPEED_ACK || test == SPEED)
465 {
466 data_ack++;
467 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", data_ack);
468 GNUNET_MESH_notify_transmit_ready (channel, GNUNET_NO,
469 GNUNET_TIME_UNIT_FOREVER_REL,
470 size_payload, &tmt_rdy, (void *) 1L);
471 if (data_ack < TOTAL_PACKETS && SPEED != test)
472 return GNUNET_OK;
473 if (ok == 2 && SPEED == test)
474 return GNUNET_OK;
475 show_end_data();
476 }
477 if (test == P2P_SIGNAL)
478 {
479 GNUNET_MESH_channel_destroy (incoming_ch);
480 incoming_ch = NULL;
481 }
482 else
483 {
484 GNUNET_MESH_channel_destroy (ch);
485 ch = NULL;
486 }
487 }
488
489 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
490 {
491 GNUNET_SCHEDULER_cancel (disconnect_task);
492 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
493 &disconnect_mesh_peers,
494 (void *) __LINE__);
495 }
496
497 return GNUNET_OK;
498}
499
500
501/**
502 * Adapter function called to establish a connection to the statistics service.
503 *
504 * @param cls closure
505 * @param cfg configuration of the peer to connect to; will be available until
506 * GNUNET_TESTBED_operation_done() is called on the operation returned
507 * from GNUNET_TESTBED_service_connect()
508 * @return service handle to return in 'op_result', NULL on error
509 */
510static void *
511stats_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
512{
513 return GNUNET_STATISTICS_create ("<test_mesh>", cfg);
514}
515
516
517/**
518 * Adapter function called to destroy a connection to
519 * statistics service.
520 *
521 * @param cls Closure (unused).
522 * @param op_result service handle returned from the connect adapter
523 */
524static void
525stats_da (void *cls, void *op_result)
526{
527 GNUNET_assert (op_result == stats);
528 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
529 stats = NULL;
530}
531
532
533/**
534 * Function called by testbed once we are connected to stats
535 * service. Get the statistics of interest.
536 *
537 * @param cls Closure (unused).
538 * @param op connect operation handle
539 * @param ca_result handle to stats service
540 * @param emsg error message on failure
541 */
542static void
543stats_connect_cb (void *cls,
544 struct GNUNET_TESTBED_Operation *op,
545 void *ca_result,
546 const char *emsg);
547
548/**
549 * Stats callback. Finish the stats testbed operation and when all stats have
550 * been iterated, shutdown the test.
551 *
552 * @param cls closure
553 * @param success GNUNET_OK if statistics were
554 * successfully obtained, GNUNET_SYSERR if not.
555 */
556static void
557stats_cont (void *cls, int success)
558{
559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stats_cont for peer %u\n", cls);
560 GNUNET_TESTBED_operation_done (stats_op);
561 stats_get = NULL;
562 if (NULL == cls)
563 {
564 stats_op = GNUNET_TESTBED_service_connect (NULL,
565 testbed_peers[4],
566 "statistics",
567 &stats_connect_cb,
568 (void *)4,
569 &stats_ca,
570 &stats_da,
571 (void *)4);
572 }
573 else
574 {
575 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
576 GNUNET_SCHEDULER_cancel (disconnect_task);
577 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
578 (void *) __LINE__);
579 }
580}
581
582
583/**
584 * Process statistic values.
585 *
586 * @param cls closure
587 * @param subsystem name of subsystem that created the statistic
588 * @param name the name of the datum
589 * @param value the current value
590 * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
591 * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
592 */
593static int
594stats_iterator (void *cls, const char *subsystem, const char *name,
595 uint64_t value, int is_persistent)
596{
597 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u - %s [%s]: %llu\n",
598 cls, subsystem, name, value);
599 if (0 == strncmp("# keepalives sent", name,
600 strlen("# keepalives sent"))
601 && 0 == (long) cls)
602 ka_sent = value;
603
604 if (0 == strncmp("# keepalives received", name,
605 strlen ("# keepalives received"))
606 && 4 == (long) cls)
607 {
608 ka_received = value;
609 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " sent: %u, received: %u\n",
610 ka_sent, ka_received);
611 if (ka_sent < 2 || ka_sent > ka_received + 1)
612 ok--;
613 }
614
615 return GNUNET_OK;
616}
617
618
619/**
620 * Function called by testbed once we are connected to stats
621 * service. Get the statistics of interest.
622 *
623 * @param cls Closure (unused).
624 * @param op connect operation handle
625 * @param ca_result handle to stats service
626 * @param emsg error message on failure
627 */
628static void
629stats_connect_cb (void *cls,
630 struct GNUNET_TESTBED_Operation *op,
631 void *ca_result,
632 const char *emsg)
633{
634 if (NULL == ca_result || NULL != emsg)
635 {
636 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
637 "Failed to connect to statistics service: %s\n", emsg);
638 return;
639 }
640
641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stats for peer %u\n", cls);
642 stats = ca_result;
643
644 stats_get = GNUNET_STATISTICS_get (stats, "mesh", NULL,
645 GNUNET_TIME_UNIT_FOREVER_REL,
646 &stats_cont, &stats_iterator, cls);
647 if (NULL == stats_get)
648 {
649 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
650 "Could not get statistics of peer %u!\n", cls);
651 }
652}
653
654
655/**
656 * Task check that keepalives were sent and received.
657 *
658 * @param cls Closure (NULL).
659 * @param tc Task Context.
660 */
661static void
662check_keepalives (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
663{
664 if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
665 return;
666
667 disconnect_task = GNUNET_SCHEDULER_NO_TASK;
668 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "check keepalives\n");
669 GNUNET_MESH_channel_destroy (ch);
670 stats_op = GNUNET_TESTBED_service_connect (NULL,
671 testbed_peers[0],
672 "statistics",
673 &stats_connect_cb,
674 NULL,
675 &stats_ca,
676 &stats_da,
677 NULL);
678}
679
680
681/**
682 * Handlers, for diverse services
683 */
684static struct GNUNET_MESH_MessageHandler handlers[] = {
685 {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)},
686 {NULL, 0, 0}
687};
688
689
690/**
691 * Method called whenever another peer has added us to a channel
692 * the other peer initiated.
693 *
694 * @param cls Closure.
695 * @param channel New handle to the channel.
696 * @param initiator Peer that started the channel.
697 * @param port Port this channel is connected to.
698 * @param options channel option flags
699 * @return Initial channel context for the channel
700 * (can be NULL -- that's not an error).
701 */
702static void *
703incoming_channel (void *cls, struct GNUNET_MESH_Channel *channel,
704 const struct GNUNET_PeerIdentity *initiator,
705 uint32_t port, enum GNUNET_MESH_ChannelOption options)
706{
707 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
708 "Incoming channel from %s to peer %d\n",
709 GNUNET_i2s (initiator), (long) cls);
710 ok++;
711 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
712 if ((long) cls == 4L)
713 incoming_ch = channel;
714 else
715 {
716 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
717 "Incoming channel for unknown client %lu\n", (long) cls);
718 GNUNET_break(0);
719 }
720 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
721 {
722 GNUNET_SCHEDULER_cancel (disconnect_task);
723 if (KEEPALIVE == test)
724 {
725 struct GNUNET_TIME_Relative delay;
726 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS , 5);
727 disconnect_task =
728 GNUNET_SCHEDULER_add_delayed (delay, &check_keepalives, NULL);
729 }
730 else
731 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
732 &disconnect_mesh_peers,
733 (void *) __LINE__);
734 }
735
736 return NULL;
737}
738
739/**
740 * Function called whenever an inbound channel is destroyed. Should clean up
741 * any associated state.
742 *
743 * @param cls closure (set from GNUNET_MESH_connect)
744 * @param channel connection to the other end (henceforth invalid)
745 * @param channel_ctx place where local state associated
746 * with the channel is stored
747 */
748static void
749channel_cleaner (void *cls, const struct GNUNET_MESH_Channel *channel,
750 void *channel_ctx)
751{
752 long i = (long) cls;
753
754 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
755 "Incoming channel disconnected at peer %d\n",
756 i);
757 if (4L == i)
758 {
759 ok++;
760 GNUNET_break (channel == incoming_ch);
761 incoming_ch = NULL;
762 }
763 else if (0L == i)
764 {
765 if (P2P_SIGNAL == test)
766 {
767 ok ++;
768 }
769 GNUNET_break (channel == ch);
770 ch = NULL;
771 }
772 else
773 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
774 "Unknown peer! %d\n", i);
775 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
776
777 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
778 {
779 GNUNET_SCHEDULER_cancel (disconnect_task);
780 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
781 (void *) __LINE__);
782 }
783
784 return;
785}
786
787
788/**
789 * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE MESH SERVICES.
790 *
791 * Testcase continues when the root receives confirmation of connected peers,
792 * on callback funtion ch.
793 *
794 * @param cls Closure (unsued).
795 * @param tc Task Context.
796 */
797static void
798do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
799{
800 enum GNUNET_MESH_ChannelOption flags;
801
802 if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
803 return;
804
805 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n");
806
807 if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
808 {
809 GNUNET_SCHEDULER_cancel (disconnect_task);
810 }
811
812 flags = GNUNET_MESH_OPTION_DEFAULT;
813 if (SPEED_REL == test)
814 {
815 test = SPEED;
816 flags |= GNUNET_MESH_OPTION_RELIABLE;
817 }
818 ch = GNUNET_MESH_channel_create (h1, NULL, p_id[1], 1, flags);
819
820 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
821 &disconnect_mesh_peers,
822 (void *) __LINE__);
823 if (KEEPALIVE == test)
824 return; /* Don't send any data. */
825
826 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
827 "Sending data initializer...\n");
828 data_ack = 0;
829 data_received = 0;
830 data_sent = 0;
831 GNUNET_MESH_notify_transmit_ready (ch, GNUNET_NO,
832 GNUNET_TIME_UNIT_FOREVER_REL,
833 size_payload, &tmt_rdy, (void *) 1L);
834}
835
836/**
837 * Callback to be called when the requested peer information is available
838 *
839 * @param cls the closure from GNUNET_TESTBED_peer_get_information()
840 * @param op the operation this callback corresponds to
841 * @param pinfo the result; will be NULL if the operation has failed
842 * @param emsg error message if the operation has failed;
843 * NULL if the operation is successfull
844 */
845static void
846pi_cb (void *cls,
847 struct GNUNET_TESTBED_Operation *op,
848 const struct GNUNET_TESTBED_PeerInformation *pinfo,
849 const char *emsg)
850{
851 long i = (long) cls;
852
853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i);
854
855 if (NULL == pinfo || NULL != emsg)
856 {
857 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
858 abort_test (__LINE__);
859 return;
860 }
861 p_id[i] = pinfo->result.id;
862 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i]));
863 p_ids++;
864 if (p_ids < 2)
865 return;
866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
867 test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
868 &do_test, NULL);
869}
870
871/**
872 * test main: start test when all peers are connected
873 *
874 * @param cls Closure.
875 * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
876 * @param num_peers Number of peers that are running.
877 * @param peers Array of peers.
878 * @param meshes Handle to each of the MESHs of the peers.
879 */
880static void
881tmain (void *cls,
882 struct GNUNET_MESH_TEST_Context *ctx,
883 unsigned int num_peers,
884 struct GNUNET_TESTBED_Peer **peers,
885 struct GNUNET_MESH_Handle **meshes)
886{
887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
888 ok = 0;
889 test_ctx = ctx;
890 peers_running = num_peers;
891 testbed_peers = peers;
892 h1 = meshes[0];
893 h2 = meshes[num_peers - 1];
894 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
895 &disconnect_mesh_peers,
896 (void *) __LINE__);
897 shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
898 &shutdown_task, NULL);
899 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
900 GNUNET_TESTBED_PIT_IDENTITY,
901 &pi_cb, (void *) 0L);
902 t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
903 GNUNET_TESTBED_PIT_IDENTITY,
904 &pi_cb, (void *) 1L);
905 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
906}
907
908
909/**
910 * Main: start test
911 */
912int
913main (int argc, char *argv[])
914{
915 initialized = GNUNET_NO;
916 uint32_t ports[2];
917 const char *config_file;
918
919 GNUNET_log_setup ("test", "DEBUG", NULL);
920 config_file = "test_mesh.conf";
921
922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n");
923 if (strstr (argv[0], "_small_forward") != NULL)
924 {
925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n");
926 test = FORWARD;
927 test_name = "unicast";
928 ok_goal = 4;
929 }
930 else if (strstr (argv[0], "_small_signal") != NULL)
931 {
932 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
933 test = P2P_SIGNAL;
934 test_name = "signal";
935 ok_goal = 4;
936 }
937 else if (strstr (argv[0], "_small_speed_ack") != NULL)
938 {
939 /* Test is supposed to generate the following callbacks:
940 * 1 incoming channel (@dest)
941 * TOTAL_PACKETS received data packet (@dest)
942 * TOTAL_PACKETS received data packet (@orig)
943 * 1 received channel destroy (@dest)
944 */
945 ok_goal = TOTAL_PACKETS * 2 + 2;
946 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
947 test = SPEED_ACK;
948 test_name = "speed ack";
949 }
950 else if (strstr (argv[0], "_small_speed") != NULL)
951 {
952 /* Test is supposed to generate the following callbacks:
953 * 1 incoming channel (@dest)
954 * 1 initial packet (@dest)
955 * TOTAL_PACKETS received data packet (@dest)
956 * 1 received data packet (@orig)
957 * 1 received channel destroy (@dest)
958 */
959 ok_goal = TOTAL_PACKETS + 4;
960 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
961 if (strstr (argv[0], "_reliable") != NULL)
962 {
963 test = SPEED_REL;
964 test_name = "speed reliable";
965 config_file = "test_mesh_drop.conf";
966 }
967 else
968 {
969 test = SPEED;
970 test_name = "speed";
971 }
972 }
973 else if (strstr (argv[0], "_keepalive") != NULL)
974 {
975 test = KEEPALIVE;
976 /* Test is supposed to generate the following callbacks:
977 * 1 incoming channel (@dest)
978 * [wait]
979 * 1 received channel destroy (@dest)
980 */
981 ok_goal = 2;
982 }
983 else
984 {
985 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
986 test = SETUP;
987 ok_goal = 0;
988 }
989
990 if (strstr (argv[0], "backwards") != NULL)
991 {
992 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n");
993 test_backwards = GNUNET_YES;
994 GNUNET_asprintf (&test_name, "backwards %s", test_name);
995 }
996
997 p_ids = 0;
998 ports[0] = 1;
999 ports[1] = 0;
1000 GNUNET_MESH_TEST_run ("test_mesh_small",
1001 config_file,
1002 5,
1003 &tmain,
1004 NULL, /* tmain cls */
1005 &incoming_channel,
1006 &channel_cleaner,
1007 handlers,
1008 ports);
1009
1010 if (ok_goal > ok)
1011 {
1012 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1013 "FAILED! (%d/%d)\n", ok, ok_goal);
1014 return 1;
1015 }
1016 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
1017 return 0;
1018}
1019
1020/* end of test_mesh_small.c */
1021