new logging functionality
[oweals/gnunet.git] / src / ats-tests / ats-testing.c
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-tests/ats-testing.c
22  * @brief ats testing library: setup topology
23  * solvers
24  * @author Christian Grothoff
25  * @author Matthias Wachs
26  */
27 #include "ats-testing.h"
28
29
30 /**
31  * Connect peers with testbed
32  */
33 struct TestbedConnectOperation
34 {
35   /**
36    * The benchmarking master initiating this connection
37    */
38   struct BenchmarkPeer *master;
39
40   /**
41    * The benchmarking slave to connect to
42    */
43   struct BenchmarkPeer *slave;
44
45   /**
46    * Testbed operation to connect peers
47    */
48   struct GNUNET_TESTBED_Operation *connect_op;
49 };
50
51
52 struct GNUNET_ATS_TEST_Topology *top;
53
54 /**
55  * Shutdown nicely
56  *
57  * @param cls NULL
58  * @param tc the task context
59  */
60 static void
61 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
62 {
63   int c_m;
64   int c_s;
65   int c_op;
66   struct BenchmarkPeer *p;
67
68   top->shutdown_task = GNUNET_SCHEDULER_NO_TASK;
69   top->state.benchmarking = GNUNET_NO;
70
71   GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n"));
72
73   GNUNET_ATS_TEST_generate_traffic_stop_all ();
74
75   for (c_m = 0; c_m < top->num_masters; c_m++)
76   {
77     p = &top->mps[c_m];
78     if (NULL != top->mps[c_m].peer_id_op)
79     {
80       GNUNET_TESTBED_operation_done (p->peer_id_op);
81       p->peer_id_op = NULL;
82     }
83
84     if (GNUNET_SCHEDULER_NO_TASK != p->ats_task)
85       GNUNET_SCHEDULER_cancel (p->ats_task);
86     p->ats_task = GNUNET_SCHEDULER_NO_TASK;
87
88     for (c_op = 0; c_op < p->num_partners; c_op++)
89     {
90       if (NULL != p->partners[c_op].cth)
91       {
92         GNUNET_CORE_notify_transmit_ready_cancel (p->partners[c_op].cth);
93         p->partners[c_op].cth = NULL;
94       }
95       if (NULL != p->partners[c_op].tth)
96       {
97         GNUNET_TRANSPORT_notify_transmit_ready_cancel (p->partners[c_op].tth);
98         p->partners[c_op].tth = NULL;
99       }
100       if ( (NULL != p->core_connect_ops) &&
101            (NULL != p->core_connect_ops[c_op].connect_op) )
102       {
103         GNUNET_log(GNUNET_ERROR_TYPE_INFO,
104             _("Failed to connect peer 0 and %u\n"), c_op);
105         GNUNET_TESTBED_operation_done (
106             p->core_connect_ops[c_op].connect_op);
107         p->core_connect_ops[c_op].connect_op = NULL;
108       }
109     }
110
111     if (NULL != p->ats_perf_op)
112     {
113       GNUNET_TESTBED_operation_done (p->ats_perf_op);
114       p->ats_perf_op = NULL;
115     }
116
117     if (NULL != p->comm_op)
118     {
119       GNUNET_TESTBED_operation_done (p->comm_op);
120       p->comm_op = NULL;
121     }
122     GNUNET_free_non_null (p->core_connect_ops);
123     GNUNET_free(p->partners);
124     p->partners = NULL;
125   }
126
127   for (c_s = 0; c_s < top->num_slaves; c_s++)
128   {
129     p = &top->sps[c_s];
130     if (NULL != p->peer_id_op)
131     {
132       GNUNET_TESTBED_operation_done (p->peer_id_op);
133       p->peer_id_op = NULL;
134     }
135
136     for (c_op = 0; c_op < p->num_partners; c_op++)
137     {
138       if (NULL != p->partners[c_op].cth)
139       {
140         GNUNET_CORE_notify_transmit_ready_cancel (p->partners[c_op].cth);
141         p->partners[c_op].cth = NULL;
142       }
143       if (NULL != p->partners[c_op].tth)
144       {
145         GNUNET_TRANSPORT_notify_transmit_ready_cancel (p->partners[c_op].tth);
146         p->partners[c_op].tth = NULL;
147       }
148     }
149     if (NULL != p->ats_perf_op)
150     {
151       GNUNET_TESTBED_operation_done (p->ats_perf_op);
152       p->ats_perf_op = NULL;
153     }
154     if (NULL != p->comm_op)
155     {
156       GNUNET_TESTBED_operation_done (p->comm_op);
157       p->comm_op = NULL;
158     }
159     GNUNET_free(p->partners);
160     p->partners = NULL;
161   }
162   GNUNET_SCHEDULER_shutdown ();
163   GNUNET_free (top);
164   top = NULL;
165 }
166
167 static struct BenchmarkPartner *
168 find_partner (struct BenchmarkPeer *me, const struct GNUNET_PeerIdentity * peer)
169 {
170   int c_m;
171   GNUNET_assert (NULL != me);
172   GNUNET_assert (NULL != peer);
173
174   for (c_m = 0; c_m < me->num_partners; c_m++)
175   {
176     /* Find a partner with other as destination */
177     if (0 == memcmp (peer, &me->partners[c_m].dest->id,
178             sizeof(struct GNUNET_PeerIdentity)))
179     {
180       return &me->partners[c_m];
181     }
182   }
183
184   return NULL;
185 }
186
187
188 static struct BenchmarkPeer *
189 find_peer (const struct GNUNET_PeerIdentity * peer)
190 {
191   int c_p;
192
193   for (c_p = 0; c_p < top->num_masters; c_p++)
194   {
195     if (0 == memcmp (&top->mps[c_p].id, peer, sizeof(struct GNUNET_PeerIdentity)))
196       return &top->mps[c_p];
197   }
198
199   for (c_p = 0; c_p < top->num_slaves; c_p++)
200   {
201     if (0 == memcmp (&top->sps[c_p].id, peer, sizeof(struct GNUNET_PeerIdentity)))
202       return &top->sps[c_p];
203   }
204   return NULL ;
205 }
206
207
208 /**
209  * Method called whenever a given peer connects.
210  *
211  * @param cls closure
212  * @param peer peer identity this notification is about
213  */
214 static void
215 comm_connect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
216 {
217   struct BenchmarkPeer *me = cls;
218   struct BenchmarkPeer *remote;
219   char *id;
220   int c;
221   int completed;
222
223   remote = find_peer (peer);
224   if (NULL == remote)
225   {
226     GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unknown peer connected: `%s'\n", GNUNET_i2s (peer));
227     GNUNET_break(0);
228     return;
229   }
230
231   id = GNUNET_strdup (GNUNET_i2s (&me->id));
232   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s [%u] `%s' connected to %s [%u] %s\n",
233       (me->master == GNUNET_YES) ? "Master": "Slave", me->no, id,
234       (remote->master == GNUNET_YES) ? "Master": "Slave", remote->no,
235       GNUNET_i2s (peer));
236
237   me->core_connections++;
238   if ((GNUNET_YES == me->master) && (GNUNET_NO == remote->master)
239       && (GNUNET_NO == top->state.connected_CORE))
240   {
241     me->core_slave_connections++;
242
243     if (me->core_slave_connections == top->num_slaves)
244     {
245       GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Master [%u] connected all slaves\n",
246           me->no);
247     }
248     completed = GNUNET_YES;
249     for (c = 0; c < top->num_masters; c++)
250     {
251       if (top->mps[c].core_slave_connections != top->num_slaves)
252         completed = GNUNET_NO;
253     }
254     if (GNUNET_YES == completed)
255     {
256       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
257           "All master peers connected all slave peers\n", id,
258           GNUNET_i2s (peer));
259       top->state.connected_CORE = GNUNET_YES;
260       /* Notify about setup done */
261       if (NULL != top->done_cb)
262         top->done_cb (top->done_cb_cls, top->mps, top->sps);
263     }
264   }
265   GNUNET_free(id);
266 }
267
268 static void
269 comm_disconnect_cb (void *cls, const struct GNUNET_PeerIdentity * peer)
270 {
271   struct BenchmarkPeer *me = cls;
272   struct BenchmarkPartner *p;
273   char *id;
274
275   if (NULL == (p = find_partner (me, peer)))
276     return;
277
278   id = GNUNET_strdup (GNUNET_i2s (&me->id));
279   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s disconnected from %s \n", id,
280       GNUNET_i2s (peer));
281   GNUNET_assert(me->core_connections > 0);
282   me->core_connections--;
283
284   if ((GNUNET_YES == top->state.benchmarking)
285       && ((GNUNET_YES == me->master) || (GNUNET_YES == p->dest->master)))
286   {
287     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
288         "%s disconnected from %s while benchmarking \n", id, GNUNET_i2s (peer));
289     if (NULL != p->tth)
290     {
291       GNUNET_TRANSPORT_notify_transmit_ready_cancel (p->tth);
292       p->tth = NULL;
293     }
294     if (NULL != p->cth)
295     {
296       GNUNET_CORE_notify_transmit_ready_cancel (p->cth);
297       p->cth = NULL;
298     }
299   }
300   GNUNET_free(id);
301 }
302
303
304 static void *
305 core_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
306 {
307   struct BenchmarkPeer *me = cls;
308
309   me->ch = GNUNET_CORE_connect (cfg, me, NULL, comm_connect_cb,
310       comm_disconnect_cb, NULL, GNUNET_NO, NULL, GNUNET_NO, top->handlers);
311   if (NULL == me->ch)
312     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create core connection \n");
313   return me->ch;
314 }
315
316 static void
317 core_disconnect_adapter (void *cls, void *op_result)
318 {
319   struct BenchmarkPeer *me = cls;
320
321   GNUNET_CORE_disconnect (me->ch);
322   me->ch = NULL;
323 }
324
325
326
327
328 static int
329 comm_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other,
330     const struct GNUNET_MessageHeader *message)
331 {
332   struct BenchmarkPeer *me = cls;
333   struct BenchmarkPartner *p = NULL;
334
335   if (NULL == (p = find_partner (me, other)))
336   {
337     GNUNET_break(0);
338     return GNUNET_SYSERR;
339   }
340
341   GNUNET_ATS_TEST_traffic_handle_pong (p);
342
343   return GNUNET_OK;
344 }
345
346 static int
347 comm_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other,
348     const struct GNUNET_MessageHeader *message)
349 {
350   struct BenchmarkPeer *me = cls;
351   struct BenchmarkPartner *p = NULL;
352
353   if (NULL == (p = find_partner(me, other)))
354   {
355     GNUNET_break(0);
356     return GNUNET_SYSERR;
357   }
358   GNUNET_ATS_TEST_traffic_handle_ping (p);
359   return GNUNET_OK;
360 }
361
362 static void
363 test_recv_cb (void *cls,
364                      const struct GNUNET_PeerIdentity * peer,
365                      const struct GNUNET_MessageHeader * message)
366 {
367   if (TEST_MESSAGE_SIZE != ntohs (message->size) ||
368       (TEST_MESSAGE_TYPE_PING != ntohs (message->type) &&
369      TEST_MESSAGE_TYPE_PONG != ntohs (message->type)))
370   {
371     return;
372   }
373   if (TEST_MESSAGE_TYPE_PING == ntohs (message->type))
374     comm_handle_ping (cls, peer, message);
375   if (TEST_MESSAGE_TYPE_PONG == ntohs (message->type))
376     comm_handle_pong (cls, peer, message);
377 }
378
379
380 static void *
381 transport_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
382 {
383   struct BenchmarkPeer *me = cls;
384
385   me->th = GNUNET_TRANSPORT_connect (cfg, &me->id, me, &test_recv_cb,
386       &comm_connect_cb, &comm_disconnect_cb);
387   if (NULL == me->th)
388     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create transport connection \n");
389   return me->th;
390 }
391
392 static void
393 transport_disconnect_adapter (void *cls, void *op_result)
394 {
395   struct BenchmarkPeer *me = cls;
396
397   GNUNET_TRANSPORT_disconnect (me->th);
398   me->th = NULL;
399 }
400
401
402 static void
403 connect_completion_callback (void *cls, struct GNUNET_TESTBED_Operation *op,
404     const char *emsg)
405 {
406   struct TestbedConnectOperation *cop = cls;
407   static int ops = 0;
408   int c;
409   if (NULL == emsg)
410   {
411     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
412         _("Connected master [%u] with slave [%u]\n"), cop->master->no,
413         cop->slave->no);
414   }
415   else
416   {
417     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
418         _("Failed to connect master peer [%u] with slave [%u]\n"),
419         cop->master->no, cop->slave->no);
420     GNUNET_break(0);
421     if (GNUNET_SCHEDULER_NO_TASK != top->shutdown_task)
422       GNUNET_SCHEDULER_cancel (top->shutdown_task);
423     top->shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
424   }
425   GNUNET_TESTBED_operation_done (op);
426   ops++;
427   for (c = 0; c < top->num_slaves; c++)
428   {
429     if (cop == &cop->master->core_connect_ops[c])
430       cop->master->core_connect_ops[c].connect_op = NULL;
431   }
432   if (ops == top->num_masters * top->num_slaves)
433   {
434     top->state.connected_PEERS = GNUNET_YES;
435   }
436 }
437
438 static void
439 do_connect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
440 {
441   int c_m;
442   int c_s;
443   struct BenchmarkPeer *p;
444
445   if ((top->state.connected_ATS_service == GNUNET_NO) ||
446       (top->state.connected_COMM_service == GNUNET_NO))
447     return;
448
449   GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Connecting peers on CORE level\n"));
450
451   for (c_m = 0; c_m < top->num_masters; c_m++)
452   {
453     p = &top->mps[c_m];
454     p->core_connect_ops = GNUNET_malloc (top->num_slaves *
455         sizeof (struct TestbedConnectOperation));
456
457     for (c_s = 0; c_s < top->num_slaves; c_s++)
458     {
459       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
460           _("Connecting master [%u] with slave [%u]\n"), p->no, top->sps[c_s].no);
461       p->core_connect_ops[c_s].master = p;
462       p->core_connect_ops[c_s].slave = &top->sps[c_s];
463       p->core_connect_ops[c_s].connect_op = GNUNET_TESTBED_overlay_connect (
464           NULL, &connect_completion_callback, &p->core_connect_ops[c_s],
465           top->sps[c_s].peer, p->peer);
466       if (NULL == p->core_connect_ops[c_s].connect_op)
467       {
468         GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
469             _("Could not connect master [%u] and slave [%u]\n"), p->no,
470             top->sps[c_s].no);
471         GNUNET_break(0);
472         if (GNUNET_SCHEDULER_NO_TASK != top->shutdown_task)
473           GNUNET_SCHEDULER_cancel (top->shutdown_task);
474         top->shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
475         return;
476       }
477     }
478   }
479 }
480
481
482 static void
483 comm_connect_completion_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
484     void *ca_result, const char *emsg)
485 {
486   static int comm_done = 0;
487   if ((NULL != emsg) || (NULL == ca_result))
488   {
489     GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initialization failed, shutdown\n"));
490     GNUNET_break(0);
491     if (GNUNET_SCHEDULER_NO_TASK != top->shutdown_task)
492       GNUNET_SCHEDULER_cancel (top->shutdown_task);
493     top->shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
494     return;
495   }
496   comm_done++;
497
498   if (comm_done == top->num_slaves + top->num_masters)
499   {
500     GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connected to all %s services\n",
501         (GNUNET_YES == top->test_core) ? "CORE" : "TRANSPORT");
502     top->state.connected_COMM_service = GNUNET_YES;
503     GNUNET_SCHEDULER_add_now (&do_connect_peers, NULL );
504   }
505 }
506
507 static void
508 do_comm_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
509 {
510   int c_s;
511   int c_m;
512   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connecting to all %s services\n",
513       (GNUNET_YES == top->test_core) ? "CORE" : "TRANSPORT");
514   for (c_m = 0; c_m < top->num_masters; c_m++)
515   {
516     if (GNUNET_YES == top->test_core)
517       top->mps[c_m].comm_op = GNUNET_TESTBED_service_connect (NULL, top->mps[c_m].peer,
518         "core", &comm_connect_completion_cb, NULL, &core_connect_adapter,
519         &core_disconnect_adapter, &top->mps[c_m]);
520     else
521     {
522       top->mps[c_m].comm_op = GNUNET_TESTBED_service_connect (NULL, top->mps[c_m].peer,
523         "transport", &comm_connect_completion_cb, NULL, &transport_connect_adapter,
524         &transport_disconnect_adapter, &top->mps[c_m]);
525     }
526   }
527
528   for (c_s = 0; c_s < top->num_slaves; c_s++)
529   {
530     if (GNUNET_YES == top->test_core)
531       top->sps[c_s].comm_op = GNUNET_TESTBED_service_connect (NULL, top->sps[c_s].peer,
532         "core", &comm_connect_completion_cb, NULL, &core_connect_adapter,
533         &core_disconnect_adapter, &top->sps[c_s]);
534     else
535     {
536       top->sps[c_s].comm_op = GNUNET_TESTBED_service_connect (NULL, top->sps[c_s].peer,
537         "transport", &comm_connect_completion_cb, NULL, &transport_connect_adapter,
538         &transport_disconnect_adapter, &top->sps[c_s]);
539     }
540   }
541 }
542
543 static void
544 ats_performance_info_cb (void *cls,
545     const struct GNUNET_HELLO_Address *address,
546     int address_active,
547     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
548     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
549     const struct GNUNET_ATS_Information *ats,
550     uint32_t ats_count)
551 {
552   struct BenchmarkPeer *me = cls;
553   struct BenchmarkPartner *p;
554   int c_a;
555   int log;
556   char *peer_id;
557
558   p = find_partner (me, &address->peer);
559   if (NULL == p)
560   {
561     /* This is not one of my partners
562      * Will happen since the peers will connect to each other due to gossiping
563      */
564     return;
565   }
566   peer_id = GNUNET_strdup (GNUNET_i2s (&me->id));
567
568   log = GNUNET_NO;
569   if ((p->bandwidth_in != ntohl (bandwidth_in.value__)) ||
570       (p->bandwidth_out != ntohl (bandwidth_out.value__)))
571       log = GNUNET_YES;
572   p->bandwidth_in = ntohl (bandwidth_in.value__);
573   p->bandwidth_out = ntohl (bandwidth_out.value__);
574
575   for (c_a = 0; c_a < ats_count; c_a++)
576   {
577     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s [%u] received ATS information: %s %s %u\n",
578         (GNUNET_YES == p->me->master) ? "Master" : "Slave",
579         p->me->no,
580         GNUNET_i2s (&p->dest->id),
581         GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)),
582         ntohl(ats[c_a].value));
583     switch (ntohl (ats[c_a].type ))
584     {
585       case GNUNET_ATS_ARRAY_TERMINATOR:
586         break;
587       case GNUNET_ATS_UTILIZATION_OUT:
588         if (p->ats_utilization_up != ntohl (ats[c_a].value))
589              log = GNUNET_YES;
590          p->ats_utilization_up = ntohl (ats[c_a].value);
591
592          break;
593        case GNUNET_ATS_UTILIZATION_IN:
594          if (p->ats_utilization_down != ntohl (ats[c_a].value))
595              log = GNUNET_YES;
596          p->ats_utilization_down = ntohl (ats[c_a].value);
597          break;
598        case GNUNET_ATS_NETWORK_TYPE:
599          if (p->ats_network_type != ntohl (ats[c_a].value))
600              log = GNUNET_YES;
601          p->ats_network_type = ntohl (ats[c_a].value);
602          break;
603        case GNUNET_ATS_QUALITY_NET_DELAY:
604          if (p->ats_delay != ntohl (ats[c_a].value))
605              log = GNUNET_YES;
606          p->ats_delay = ntohl (ats[c_a].value);
607          break;
608        case GNUNET_ATS_QUALITY_NET_DISTANCE:
609          if (p->ats_distance != ntohl (ats[c_a].value))
610              log = GNUNET_YES;
611          p->ats_distance = ntohl (ats[c_a].value);
612          GNUNET_break (0);
613          break;
614        case GNUNET_ATS_COST_WAN:
615          if (p->ats_cost_wan != ntohl (ats[c_a].value))
616              log = GNUNET_YES;
617          p->ats_cost_wan = ntohl (ats[c_a].value);
618          break;
619        case GNUNET_ATS_COST_LAN:
620          if (p->ats_cost_lan != ntohl (ats[c_a].value))
621              log = GNUNET_YES;
622          p->ats_cost_lan = ntohl (ats[c_a].value);
623          break;
624        case GNUNET_ATS_COST_WLAN:
625          if (p->ats_cost_wlan != ntohl (ats[c_a].value))
626              log = GNUNET_YES;
627          p->ats_cost_wlan = ntohl (ats[c_a].value);
628          break;
629        default:
630          break;
631      }
632    }
633   if (GNUNET_YES == log)
634     top->ats_perf_cb (cls, address, address_active, bandwidth_out, bandwidth_in,
635       ats, ats_count);
636   GNUNET_free(peer_id);
637 }
638
639
640 static void *
641 ats_perf_connect_adapter (void *cls,
642     const struct GNUNET_CONFIGURATION_Handle *cfg)
643 {
644   struct BenchmarkPeer *me = cls;
645
646   me->ats_perf_handle = GNUNET_ATS_performance_init (cfg, ats_performance_info_cb, me);
647   if (NULL == me->ats_perf_handle)
648     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
649         "Failed to create ATS performance handle \n");
650   return me->ats_perf_handle;
651 }
652
653 static void
654 ats_perf_disconnect_adapter (void *cls, void *op_result)
655 {
656   struct BenchmarkPeer *me = cls;
657
658   GNUNET_ATS_performance_done (me->ats_perf_handle);
659   me->ats_perf_handle = NULL;
660 }
661
662 static void
663 ats_connect_completion_cb (void *cls, struct GNUNET_TESTBED_Operation *op,
664     void *ca_result, const char *emsg)
665 {
666   static int op_done = 0;
667
668   if ((NULL != emsg) || (NULL == ca_result))
669   {
670     GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initialization failed, shutdown\n"));
671     GNUNET_break(0);
672     if (GNUNET_SCHEDULER_NO_TASK != top->shutdown_task)
673       GNUNET_SCHEDULER_cancel (top->shutdown_task);
674     top->shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL );
675     return;
676   }
677   op_done++;
678   if (op_done == (top->num_masters + top->num_slaves))
679   {
680     GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connected to all ATS services\n");
681     top->state.connected_ATS_service = GNUNET_YES;
682     GNUNET_SCHEDULER_add_now (&do_comm_connect, NULL );
683   }
684 }
685
686
687 static void
688 do_connect_ats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
689 {
690   int c_m;
691   int c_s;
692
693   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connecting to all ATS services\n");
694   for (c_m = 0; c_m < top->num_masters; c_m++)
695   {
696     top->mps[c_m].ats_perf_op = GNUNET_TESTBED_service_connect (NULL,
697         top->mps[c_m].peer,
698         "ats", ats_connect_completion_cb, NULL,
699         &ats_perf_connect_adapter,
700         &ats_perf_disconnect_adapter, &top->mps[c_m]);
701   }
702
703   for (c_s = 0; c_s < top->num_slaves; c_s++)
704   {
705     top->sps[c_s].ats_perf_op = GNUNET_TESTBED_service_connect (NULL, top->sps[c_s].peer,
706         "ats", ats_connect_completion_cb, NULL, &ats_perf_connect_adapter,
707         &ats_perf_disconnect_adapter, &top->sps[c_s]);
708   }
709 }
710
711
712
713 static void
714 peerinformation_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op,
715     const struct GNUNET_TESTBED_PeerInformation*pinfo, const char *emsg)
716 {
717   struct BenchmarkPeer *p = cb_cls;
718   static int done = 0;
719
720   GNUNET_assert(pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY);
721
722   p->id = *pinfo->result.id;
723   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "%s [%u] has peer id `%s'\n",
724       (p->master == GNUNET_YES) ? "Master" : "Slave", p->no,
725       GNUNET_i2s (&p->id));
726
727   GNUNET_TESTBED_operation_done (op);
728   p->peer_id_op = NULL;
729   done++;
730
731   if (done == top->num_slaves + top->num_masters)
732   {
733     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
734         "Retrieved all peer ID, connect to ATS\n");
735     GNUNET_SCHEDULER_add_now (&do_connect_ats, NULL );
736   }
737 }
738
739 /**
740  * Signature of a main function for a testcase.
741  *
742  * @param cls closure
743  * @param num_peers number of peers in 'peers'
744  * @param peers_ handle to peers run in the testbed
745  * @param links_succeeded the number of overlay link connection attempts that
746  *          succeeded
747  * @param links_failed the number of overlay link connection attempts that
748  *          failed
749  */
750 static void
751 main_run (void *cls, struct GNUNET_TESTBED_RunHandle *h,
752           unsigned int num_peers,
753           struct GNUNET_TESTBED_Peer **peers_,
754           unsigned int links_succeeded,
755           unsigned int links_failed)
756 {
757   int c_m;
758   int c_s;
759   GNUNET_assert(NULL == cls);
760   GNUNET_assert(top->num_masters + top->num_slaves == num_peers);
761   GNUNET_assert(NULL != peers_);
762
763   top->shutdown_task = GNUNET_SCHEDULER_add_delayed (
764       GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, top);
765
766   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up %u masters and %u slaves\n",
767       top->num_masters, top->num_slaves);
768
769   /* Setup master peers */
770   for (c_m = 0; c_m < top->num_masters; c_m++)
771   {
772     GNUNET_assert(NULL != peers_[c_m]);
773     top->mps[c_m].peer = peers_[c_m];
774     top->mps[c_m].no = c_m;
775     top->mps[c_m].master = GNUNET_YES;
776     top->mps[c_m].pref_partner = &top->sps[c_m];
777     top->mps[c_m].pref_value = TEST_ATS_PREFERENCE_DEFAULT;
778     top->mps[c_m].partners =
779         GNUNET_malloc (top->num_slaves * sizeof (struct BenchmarkPartner));
780     top->mps[c_m].num_partners = top->num_slaves;
781     /* Initialize partners */
782     for (c_s = 0; c_s < top->num_slaves; c_s++)
783     {
784       top->mps[c_m].partners[c_s].me = &top->mps[c_m];
785       top->mps[c_m].partners[c_s].dest = &top->sps[c_s];
786     }
787     /* Get configuration */
788     top->mps[c_m].peer_id_op = GNUNET_TESTBED_peer_get_information (top->mps[c_m].peer,
789         GNUNET_TESTBED_PIT_IDENTITY, &peerinformation_cb, &top->mps[c_m]);
790   }
791
792   /* Setup slave peers */
793   for (c_s = 0; c_s < top->num_slaves; c_s++)
794   {
795     GNUNET_assert(NULL != peers_[c_s + top->num_masters]);
796     top->sps[c_s].peer = peers_[c_s + top->num_masters];
797     top->sps[c_s].no = c_s + top->num_masters;
798     top->sps[c_s].master = GNUNET_NO;
799     top->sps[c_s].partners =
800         GNUNET_malloc (top->num_masters * sizeof (struct BenchmarkPartner));
801     top->sps[c_s].num_partners = top->num_masters;
802     /* Initialize partners */
803     for (c_m = 0; c_m < top->num_masters; c_m++)
804     {
805       top->sps[c_s].partners[c_m].me = &top->sps[c_s];
806       top->sps[c_s].partners[c_m].dest = &top->mps[c_m];
807     }
808     /* Get configuration */
809     top->sps[c_s].peer_id_op = GNUNET_TESTBED_peer_get_information (top->sps[c_s].peer,
810         GNUNET_TESTBED_PIT_IDENTITY, &peerinformation_cb, &top->sps[c_s]);
811   }
812 }
813
814 /**
815  * Controller event callback
816  *
817  * @param cls NULL
818  * @param event the controller event
819  */
820 static void
821 controller_event_cb (void *cls,
822     const struct GNUNET_TESTBED_EventInformation *event)
823 {
824   struct GNUNET_ATS_TEST_Topology *top = cls;
825   switch (event->type)
826   {
827   case GNUNET_TESTBED_ET_CONNECT:
828     break;
829   case GNUNET_TESTBED_ET_OPERATION_FINISHED:
830     break;
831   default:
832     GNUNET_break(0);
833     GNUNET_SCHEDULER_cancel (top->shutdown_task);
834     top->shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL );
835   }
836 }
837
838
839 void
840 GNUNET_ATS_TEST_create_topology (char *name, char *cfg_file,
841     unsigned int num_slaves,
842     unsigned int num_masters,
843     int test_core,
844     GNUNET_ATS_TEST_TopologySetupDoneCallback done_cb,
845     void *done_cb_cls,
846     GNUNET_TRANSPORT_ReceiveCallback transport_recv_cb,
847     GNUNET_ATS_AddressInformationCallback log_request_cb)
848 {
849
850   static struct GNUNET_CORE_MessageHandler handlers[] = {
851       {&comm_handle_ping, TEST_MESSAGE_TYPE_PING, 0 },
852       {&comm_handle_pong, TEST_MESSAGE_TYPE_PONG, 0 },
853       { NULL, 0, 0 } };
854
855   top = GNUNET_new (struct GNUNET_ATS_TEST_Topology);
856   top->num_masters = num_masters;
857   top->num_slaves = num_slaves;
858   top->handlers = handlers;
859   top->done_cb = done_cb;
860   top->done_cb_cls = done_cb_cls;
861   top->test_core = test_core;
862   top->transport_recv_cb = transport_recv_cb;
863   top->ats_perf_cb = log_request_cb;
864
865   top->mps = GNUNET_malloc (num_masters * sizeof (struct BenchmarkPeer));
866   top->sps = GNUNET_malloc (num_slaves * sizeof (struct BenchmarkPeer));
867
868   /* Start topology */
869   uint64_t event_mask;
870   event_mask = 0;
871   event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
872   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
873   (void) GNUNET_TESTBED_test_run (name, cfg_file,
874       num_slaves + num_masters, event_mask, &controller_event_cb, NULL,
875       &main_run, NULL);
876 }
877
878 void
879 GNUNET_ATS_TEST_shutdown_topology (void)
880 {
881   if (NULL == top)
882     return;
883
884   GNUNET_SCHEDULER_shutdown();
885 }
886
887
888
889
890
891 /* end of file ats-testing.c */