test_ats_simplistic_pref_aging.c 13 KB

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