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