ats-testing.c 24 KB

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