test_quota_compliance.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2009, 2010, 2011, 2016 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 transport/test_quota_compliance.c
  18. * @brief base test case for transport implementations
  19. *
  20. * This test case tests quota compliance both on transport level
  21. */
  22. #include "platform.h"
  23. #include "gnunet_transport_service.h"
  24. #include "gnunet_ats_service.h"
  25. #include "gauger.h"
  26. #include "transport-testing.h"
  27. /**
  28. * Testcase timeout
  29. */
  30. #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 480)
  31. #define DURATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 80)
  32. static struct GNUNET_SCHEDULER_Task *measure_task;
  33. static char *gen_cfgs[2];
  34. static unsigned long long quota_in[] = { 10000, 10000 };
  35. static unsigned long long quota_out[] = { 10000, 10000 };
  36. static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
  37. /**
  38. * Note that this value must not significantly exceed
  39. * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise
  40. * messages may be dropped even for a reliable transport.
  41. */
  42. #define TOTAL_MSGS (1024 * 32)
  43. static unsigned long long total_bytes_recv;
  44. static struct GNUNET_TIME_Absolute start_time;
  45. static void
  46. report ()
  47. {
  48. unsigned long long delta;
  49. unsigned long long datarate;
  50. delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us;
  51. if (0 == delta)
  52. delta = 1;
  53. datarate = (total_bytes_recv * 1000 * 1000) / delta;
  54. fprintf (stderr,
  55. "Throughput was %llu b/s\n",
  56. datarate);
  57. ccc->global_ret = GNUNET_OK;
  58. if (datarate > 1.5 * quota_in[1])
  59. {
  60. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  61. "Datarate of %llu b/s significantly higher than allowed inbound quota of %llu b/s\n",
  62. datarate,
  63. quota_in[1]);
  64. ccc->global_ret = GNUNET_SYSERR;
  65. }
  66. if (datarate > 1.5 * quota_out[0])
  67. {
  68. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  69. "Datarate of %llu b/s significantly higher than allowed outbound quota of %llu b/s\n",
  70. datarate,
  71. quota_out[0]);
  72. ccc->global_ret = GNUNET_SYSERR;
  73. }
  74. if (GNUNET_OK == ccc->global_ret)
  75. {
  76. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  77. "Datarate of %llu b/s complied to allowed outbound quota of %llu b/s and inbound quota of %llu b/s\n",
  78. datarate,
  79. quota_out[0],
  80. quota_in[1]);
  81. }
  82. }
  83. static void
  84. custom_shutdown (void *cls)
  85. {
  86. if (NULL != measure_task)
  87. {
  88. GNUNET_SCHEDULER_cancel (measure_task);
  89. measure_task = NULL;
  90. }
  91. report ();
  92. }
  93. static size_t
  94. get_size (unsigned int iter)
  95. {
  96. size_t ret;
  97. ret = (iter * iter * iter) % 60000;
  98. ret += sizeof(struct GNUNET_TRANSPORT_TESTING_TestMessage);
  99. return ret;
  100. }
  101. static void
  102. notify_receive (void *cls,
  103. struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
  104. const struct GNUNET_PeerIdentity *sender,
  105. const struct GNUNET_TRANSPORT_TESTING_TestMessage *hdr)
  106. {
  107. if (GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE != ntohs (hdr->header.type))
  108. return;
  109. total_bytes_recv += ntohs (hdr->header.size);
  110. {
  111. char *ps = GNUNET_strdup (GNUNET_i2s (&receiver->id));
  112. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  113. "Peer %u (`%s') got message %u of size %u from peer (`%s')\n",
  114. receiver->no,
  115. ps,
  116. ntohl (hdr->num),
  117. ntohs (hdr->header.size),
  118. GNUNET_i2s (sender));
  119. GNUNET_free (ps);
  120. }
  121. }
  122. static void
  123. measure (void *cls)
  124. {
  125. static int counter;
  126. measure_task = NULL;
  127. counter++;
  128. if ((DURATION.rel_value_us / 1000 / 1000LL) < counter)
  129. {
  130. fprintf (stderr, "%s", ".\n");
  131. GNUNET_SCHEDULER_shutdown ();
  132. return;
  133. }
  134. fprintf (stderr, "%s", ".");
  135. measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
  136. &measure,
  137. NULL);
  138. }
  139. static void
  140. start_task (void *cls)
  141. {
  142. static struct GNUNET_TRANSPORT_TESTING_SendClosure sc = {
  143. .num_messages = TOTAL_MSGS,
  144. .get_size_cb = &get_size
  145. };
  146. sc.ccc = ccc;
  147. measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
  148. &measure,
  149. NULL);
  150. start_time = GNUNET_TIME_absolute_get ();
  151. GNUNET_SCHEDULER_add_now (&GNUNET_TRANSPORT_TESTING_simple_send,
  152. &sc);
  153. }
  154. static char *
  155. generate_config (const char *cfg_file,
  156. unsigned long long quota_in,
  157. unsigned long long quota_out)
  158. {
  159. char *in_name;
  160. char *out_name;
  161. char *fname = NULL;
  162. struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
  163. GNUNET_assert (GNUNET_OK ==
  164. GNUNET_CONFIGURATION_load (cfg,
  165. cfg_file));
  166. GNUNET_asprintf (&fname,
  167. "q_in_%llu_q_out_%llu_%s",
  168. quota_in,
  169. quota_out,
  170. cfg_file);
  171. GNUNET_CONFIGURATION_set_value_string (cfg,
  172. "PATHS",
  173. "DEFAULTCONFIG",
  174. fname);
  175. for (int c = 0; c < GNUNET_NT_COUNT; c++)
  176. {
  177. GNUNET_asprintf (&in_name,
  178. "%s_QUOTA_IN",
  179. GNUNET_NT_to_string (c));
  180. GNUNET_asprintf (&out_name,
  181. "%s_QUOTA_OUT",
  182. GNUNET_NT_to_string (c));
  183. GNUNET_CONFIGURATION_set_value_number (cfg,
  184. "ats",
  185. in_name,
  186. quota_in);
  187. GNUNET_CONFIGURATION_set_value_number (cfg,
  188. "ats",
  189. out_name,
  190. quota_out);
  191. GNUNET_free (in_name);
  192. GNUNET_free (out_name);
  193. }
  194. GNUNET_assert (GNUNET_OK ==
  195. GNUNET_CONFIGURATION_write (cfg,
  196. fname));
  197. GNUNET_CONFIGURATION_destroy (cfg);
  198. return fname;
  199. }
  200. static int
  201. check (void *cls,
  202. struct GNUNET_TRANSPORT_TESTING_Handle *tth_,
  203. const char *test_plugin_,
  204. const char *test_name_,
  205. unsigned int num_peers,
  206. char *cfg_files[])
  207. {
  208. struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc = {
  209. .connect_continuation = &start_task,
  210. .config_file = "test_quota_compliance_data.conf",
  211. .rec = &notify_receive,
  212. .nc = &GNUNET_TRANSPORT_TESTING_log_connect,
  213. .nd = &GNUNET_TRANSPORT_TESTING_log_disconnect,
  214. .shutdown_task = &custom_shutdown,
  215. .timeout = TIMEOUT
  216. };
  217. ccc = &my_ccc;
  218. if (NULL != strstr (test_name_,
  219. "asymmetric"))
  220. {
  221. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  222. "Running asymmetric test with sending peer unlimited, receiving peer (in/out): %llu/%llu b/s \n",
  223. quota_in[1],
  224. quota_out[1]);
  225. quota_out[0] = 1024 * 1024 * 1024;
  226. quota_in[0] = 1024 * 1024 * 1024;
  227. }
  228. else
  229. {
  230. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  231. "Running symmetric test with (in/out) %llu/%llu b/s \n",
  232. quota_in[1],
  233. quota_out[1]);
  234. }
  235. for (unsigned int i = 0; i < 2; i++)
  236. {
  237. gen_cfgs[i] = generate_config (cfg_files[i],
  238. quota_in[i],
  239. quota_out[i]);
  240. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  241. "Generated config file `%s'\n",
  242. gen_cfgs[i]);
  243. }
  244. return GNUNET_TRANSPORT_TESTING_connect_check (&my_ccc,
  245. tth_,
  246. test_plugin_,
  247. test_name_,
  248. num_peers,
  249. gen_cfgs);
  250. }
  251. int
  252. main (int argc,
  253. char *argv[])
  254. {
  255. if (GNUNET_OK !=
  256. GNUNET_TRANSPORT_TESTING_main (2,
  257. &check,
  258. NULL))
  259. {
  260. GNUNET_break (0);
  261. return 1;
  262. }
  263. for (unsigned int i = 0; i < 2; i++)
  264. {
  265. if ((NULL != gen_cfgs[i]) &&
  266. (GNUNET_YES == GNUNET_DISK_file_test (gen_cfgs[i])))
  267. {
  268. GNUNET_DISK_directory_remove (gen_cfgs[i]);
  269. GNUNET_free (gen_cfgs[i]);
  270. }
  271. }
  272. return 0;
  273. }
  274. /* end of test_quota_compliance.c */