test_ats_simplistic_pref_aging.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2010,2011 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/test_ats_mlp.c
  19. * @brief test for the MLP solver
  20. * @author Christian Grothoff
  21. * @author Matthias Wachs
  22. */
  23. /**
  24. * @file ats/test_ats_api_scheduling_add_address.c
  25. * @brief test for ats proportional solver preference aging:
  26. * Add 2 addresses and set high preference for one. Expect higher bw for this
  27. * address, wait. Preferences should age and so bw assigned should decrease.
  28. * @author Christian Grothoff
  29. * @author Matthias Wachs
  30. */
  31. #include "platform.h"
  32. #include "gnunet_ats_service.h"
  33. #include "gnunet_testing_lib.h"
  34. #include "ats.h"
  35. #include "test_ats_api_common.h"
  36. #define DEBUG_ATS_INFO GNUNET_NO
  37. static struct GNUNET_SCHEDULER_Task * die_task;
  38. /**
  39. * Scheduling handle
  40. */
  41. static struct GNUNET_ATS_SchedulingHandle *sched_ats;
  42. /**
  43. * Connectivity handle
  44. */
  45. static struct GNUNET_ATS_ConnectivityHandle *connect_ats;
  46. /**
  47. * Performance handle
  48. */
  49. static struct GNUNET_ATS_PerformanceHandle *perf_ats;
  50. /**
  51. * Return value
  52. */
  53. static int ret;
  54. /**
  55. * Test address
  56. */
  57. static struct Test_Address test_addr[2];
  58. /**
  59. * Test peer
  60. */
  61. static struct PeerContext p[2];
  62. /**
  63. * Connectivity suggestion handles.
  64. */
  65. static struct GNUNET_ATS_ConnectivitySuggestHandle *sh[2];
  66. /**
  67. * HELLO address
  68. */
  69. static struct GNUNET_HELLO_Address test_hello_address[2];
  70. /**
  71. * Session
  72. */
  73. static void *test_session[2];
  74. /**
  75. * Test ats info
  76. */
  77. static struct GNUNET_ATS_Information test_ats_info[2];
  78. /**
  79. * Test ats count
  80. */
  81. static uint32_t test_ats_count;
  82. /**
  83. * Configured WAN out quota
  84. */
  85. static unsigned long long wan_quota_out;
  86. /**
  87. * Configured WAN in quota
  88. */
  89. static unsigned long long wan_quota_in;
  90. static void
  91. end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  92. {
  93. die_task = NULL;
  94. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error! Shutting down\n");
  95. if (sched_ats != NULL)
  96. {
  97. GNUNET_ATS_scheduling_done (sched_ats);
  98. sched_ats = NULL;
  99. }
  100. if (NULL != connect_ats)
  101. {
  102. GNUNET_ATS_connectivity_done (connect_ats);
  103. connect_ats = NULL;
  104. }
  105. if (perf_ats != NULL)
  106. {
  107. GNUNET_ATS_performance_done (perf_ats);
  108. perf_ats = NULL;
  109. }
  110. free_test_address (&test_addr[0]);
  111. ret = GNUNET_SYSERR;
  112. }
  113. static void
  114. end ()
  115. {
  116. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n");
  117. if (die_task != NULL)
  118. {
  119. GNUNET_SCHEDULER_cancel (die_task);
  120. die_task = NULL;
  121. }
  122. GNUNET_ATS_connectivity_suggest_cancel (sh[0]);
  123. GNUNET_ATS_connectivity_suggest_cancel (sh[1]);
  124. if (NULL != sched_ats)
  125. GNUNET_ATS_scheduling_done (sched_ats);
  126. if (NULL != perf_ats)
  127. GNUNET_ATS_performance_done (perf_ats);
  128. sched_ats = NULL;
  129. perf_ats = NULL;
  130. free_test_address (&test_addr[0]);
  131. free_test_address (&test_addr[1]);
  132. }
  133. static void
  134. address_suggest_cb (void *cls,
  135. const struct GNUNET_PeerIdentity *peer,
  136. const struct GNUNET_HELLO_Address *address,
  137. struct Session *session,
  138. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
  139. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
  140. const struct GNUNET_ATS_Information *atsi,
  141. uint32_t ats_count)
  142. {
  143. static int stage = 0;
  144. static int sug_p0 = GNUNET_NO;
  145. static int sug_p1 = GNUNET_NO;
  146. static uint32_t p0_last_bandwidth_out;
  147. static uint32_t p0_last_bandwidth_in;
  148. static uint32_t p1_last_bandwidth_out;
  149. static uint32_t p1_last_bandwidth_in;
  150. uint32_t cur_bandwidth_out = ntohl (bandwidth_out.value__);
  151. uint32_t cur_bandwidth_in = ntohl (bandwidth_in.value__);
  152. if (0 == stage)
  153. {
  154. /* Callback for initial suggestion */
  155. if (0 == memcmp (&address->peer, &p[0].id, sizeof (p[0].id)))
  156. {
  157. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  158. "Stage %u: Callback for peer 0 `%s': (in/out) %u/%u\n",
  159. stage,
  160. GNUNET_i2s (&address->peer),
  161. (unsigned int) ntohl (bandwidth_in.value__),
  162. (unsigned int) ntohl (bandwidth_out.value__));
  163. sug_p0 = GNUNET_YES;
  164. p0_last_bandwidth_out = ntohl(bandwidth_out.value__);
  165. p0_last_bandwidth_in = ntohl(bandwidth_in.value__);
  166. }
  167. if (0 == memcmp (&address->peer, &p[1].id, sizeof (p[1].id)))
  168. {
  169. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  170. "Stage %u: Callback for peer 1 `%s': (in/out) %u/%u\n",
  171. stage,
  172. GNUNET_i2s (&address->peer),
  173. (unsigned int) ntohl (bandwidth_in.value__),
  174. (unsigned int) ntohl (bandwidth_out.value__));
  175. sug_p1 = GNUNET_YES;
  176. p1_last_bandwidth_out = ntohl(bandwidth_out.value__);
  177. p1_last_bandwidth_in = ntohl(bandwidth_in.value__);
  178. }
  179. if ((GNUNET_YES == sug_p0) && (GNUNET_YES == sug_p1))
  180. {
  181. /* Changing preference for peer 0 */
  182. stage ++;
  183. GNUNET_ATS_performance_change_preference (perf_ats, &p[0].id, GNUNET_ATS_PREFERENCE_BANDWIDTH,(double) 1000, GNUNET_ATS_PREFERENCE_END);
  184. sug_p0 = GNUNET_NO;
  185. sug_p1 = GNUNET_NO;
  186. return;
  187. }
  188. }
  189. if (1 == stage)
  190. {
  191. /* Callback due to preference change */
  192. if (0 == memcmp (&address->peer, &p[0].id, sizeof (p[0].id)))
  193. {
  194. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  195. "Stage %u: Callback for peer 0 `%s': (in/out) %u/%u\n",
  196. stage,
  197. GNUNET_i2s (&address->peer),
  198. (unsigned int) ntohl (bandwidth_in.value__),
  199. (unsigned int) ntohl (bandwidth_out.value__));
  200. sug_p0 = GNUNET_YES;
  201. /* Peer 0 should get more bandwidth */
  202. if (cur_bandwidth_out <= p0_last_bandwidth_out)
  203. GNUNET_break (0);
  204. if (cur_bandwidth_in <= p0_last_bandwidth_in)
  205. GNUNET_break (0);
  206. p0_last_bandwidth_out = ntohl(bandwidth_out.value__);
  207. p0_last_bandwidth_in = ntohl(bandwidth_in.value__);
  208. }
  209. if (0 == memcmp (&address->peer, &p[1].id, sizeof (p[1].id)))
  210. {
  211. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  212. "Stage %u: Callback for peer 1 `%s': (in/out) %u/%u\n",
  213. stage,
  214. GNUNET_i2s (&address->peer),
  215. (unsigned int) ntohl (bandwidth_in.value__),
  216. (unsigned int) ntohl (bandwidth_out.value__));
  217. sug_p1 = GNUNET_YES;
  218. /* Peer 1 should get less bandwidth */
  219. if (cur_bandwidth_out >= p1_last_bandwidth_out)
  220. {
  221. GNUNET_break (0);
  222. goto error;
  223. }
  224. if (cur_bandwidth_in >= p1_last_bandwidth_in)
  225. {
  226. GNUNET_break (0);
  227. goto error;
  228. }
  229. p1_last_bandwidth_out = ntohl(bandwidth_out.value__);
  230. p1_last_bandwidth_in = ntohl(bandwidth_in.value__);
  231. }
  232. if ((GNUNET_YES == sug_p0) && (GNUNET_YES == sug_p1))
  233. {
  234. stage ++;
  235. sug_p0 = GNUNET_NO;
  236. sug_p1 = GNUNET_NO;
  237. return;
  238. }
  239. }
  240. if (2 == stage)
  241. {
  242. /* Callback due to preference aging */
  243. if (0 == memcmp (&address->peer, &p[0].id, sizeof (p[0].id)))
  244. {
  245. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  246. "Stage %u: Callback for peer 0 `%s': (in/out) %u/%u\n",
  247. stage,
  248. GNUNET_i2s (&address->peer),
  249. (unsigned int) ntohl (bandwidth_in.value__),
  250. (unsigned int) ntohl (bandwidth_out.value__));
  251. sug_p0 = GNUNET_YES;
  252. /* Peer 0 should get less bandwidth */
  253. if (cur_bandwidth_out <= p0_last_bandwidth_out)
  254. GNUNET_break (0);
  255. if (cur_bandwidth_in <= p0_last_bandwidth_in)
  256. GNUNET_break (0);
  257. p0_last_bandwidth_out = ntohl(bandwidth_out.value__);
  258. p0_last_bandwidth_in = ntohl(bandwidth_in.value__);
  259. }
  260. if (0 == memcmp (&address->peer, &p[1].id, sizeof (p[1].id)))
  261. {
  262. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  263. "Stage %u: Callback for peer 1 `%s': (in/out) %u/%u\n",
  264. stage,
  265. GNUNET_i2s (&address->peer),
  266. (unsigned int) ntohl (bandwidth_in.value__),
  267. (unsigned int) ntohl (bandwidth_out.value__));
  268. sug_p1 = GNUNET_YES;
  269. /* Peer 1 should get more bandwidth */
  270. if (cur_bandwidth_out <= p1_last_bandwidth_out)
  271. {
  272. GNUNET_break (0);
  273. goto error;
  274. }
  275. if (cur_bandwidth_in <= p1_last_bandwidth_in)
  276. {
  277. GNUNET_break (0);
  278. goto error;
  279. }
  280. p0_last_bandwidth_out = ntohl(bandwidth_out.value__);
  281. p0_last_bandwidth_in = ntohl(bandwidth_in.value__);
  282. }
  283. if ((GNUNET_YES == sug_p0) && (GNUNET_YES == sug_p1))
  284. {
  285. /* Done ! */
  286. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n");
  287. stage ++;
  288. ret = 0;
  289. GNUNET_SCHEDULER_add_now (&end,NULL);
  290. return;
  291. }
  292. }
  293. return;
  294. error:
  295. /* Error ! */
  296. ret = 1;
  297. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Error!\n");
  298. GNUNET_SCHEDULER_add_now (&end,NULL);
  299. }
  300. static void
  301. run (void *cls,
  302. const struct GNUNET_CONFIGURATION_Handle *cfg,
  303. struct GNUNET_TESTING_Peer *peer)
  304. {
  305. char *quota_str;
  306. if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_OUT", &quota_str))
  307. {
  308. fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n");
  309. ret = 1;
  310. return;
  311. }
  312. if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_out))
  313. {
  314. fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n");
  315. ret = 1;
  316. GNUNET_free (quota_str);
  317. return;
  318. }
  319. GNUNET_free (quota_str);
  320. quota_str = NULL;
  321. if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_IN", &quota_str))
  322. {
  323. fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n");
  324. ret = 1;
  325. return;
  326. }
  327. if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_in))
  328. {
  329. fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n");
  330. GNUNET_free (quota_str);
  331. ret = 1;
  332. return;
  333. }
  334. GNUNET_free (quota_str);
  335. quota_str = NULL;
  336. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN inbound quota: %llu\n", wan_quota_in);
  337. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN outbound quota: %llu\n", wan_quota_out);
  338. die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
  339. /* Connect to ATS scheduling */
  340. connect_ats = GNUNET_ATS_connectivity_init (mycfg);
  341. sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL);
  342. if (sched_ats == NULL)
  343. {
  344. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n");
  345. ret = 1;
  346. end ();
  347. return;
  348. }
  349. /* Connect to ATS performance */
  350. perf_ats = GNUNET_ATS_performance_init(cfg, NULL, NULL);
  351. if (sched_ats == NULL)
  352. {
  353. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n");
  354. ret = 1;
  355. end ();
  356. return;
  357. }
  358. /* Set up peer 0 */
  359. if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID0, &p[0].id.hashPubKey))
  360. {
  361. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n");
  362. ret = GNUNET_SYSERR;
  363. end ();
  364. return;
  365. }
  366. GNUNET_assert (0 == strcmp (PEERID0, GNUNET_i2s_full (&p[0].id)));
  367. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n",
  368. GNUNET_i2s(&p[0].id));
  369. /* Set up peer 1*/
  370. if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID1, &p[1].id.hashPubKey))
  371. {
  372. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n");
  373. ret = GNUNET_SYSERR;
  374. end ();
  375. return;
  376. }
  377. GNUNET_assert (0 == strcmp (PEERID1, GNUNET_i2s_full (&p[1].id)));
  378. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n",
  379. GNUNET_i2s(&p[1].id));
  380. /* Prepare ATS Information */
  381. test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
  382. test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN);
  383. test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
  384. test_ats_info[1].value = htonl(1);
  385. test_ats_count = 2;
  386. /* Peer 0: Adding address with session */
  387. test_session[0] = &test_addr[0];
  388. create_test_address (&test_addr[0], "test0", test_session[0], "test0", strlen ("test0") + 1);
  389. test_hello_address[0].peer = p[0].id;
  390. test_hello_address[0].transport_name = test_addr[0].plugin;
  391. test_hello_address[0].address = test_addr[0].addr;
  392. test_hello_address[0].address_length = test_addr[0].addr_len;
  393. GNUNET_ATS_address_add (sched_ats, &test_hello_address[0], test_session[0], test_ats_info, test_ats_count);
  394. /* Peer 1: Adding address with session */
  395. test_session[1] = &test_addr[1];
  396. create_test_address (&test_addr[1], "test1", test_session[1], "test1", strlen ("test1") + 1);
  397. test_hello_address[1].peer = p[1].id;
  398. test_hello_address[1].transport_name = test_addr[1].plugin;
  399. test_hello_address[1].address = test_addr[1].addr;
  400. test_hello_address[1].address_length = test_addr[1].addr_len;
  401. GNUNET_ATS_address_add (sched_ats, &test_hello_address[1], test_session[1], test_ats_info, test_ats_count);
  402. sh[0] = GNUNET_ATS_connectivity_suggest (connect_ats, &p[0].id);
  403. sh[1] = GNUNET_ATS_connectivity_suggest (connect_ats, &p[1].id);
  404. }
  405. int
  406. main (int argc, char *argv[])
  407. {
  408. if (0 != GNUNET_TESTING_peer_run ("test_ats_proportional_pref_aging",
  409. "test_ats_api.conf",
  410. &run, NULL))
  411. return 1;
  412. return ret;
  413. }
  414. /* end of file test_ats_simplistic_pref_aging.c */