ats-testing.c 26 KB

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