ats-testing-traffic.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2010-2013, 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 ats-tests/ats-testing-traffic.c
  18. * @brief ats benchmark: traffic generator
  19. * @author Christian Grothoff
  20. * @author Matthias Wachs
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "ats-testing.h"
  25. static struct TrafficGenerator *tg_head;
  26. static struct TrafficGenerator *tg_tail;
  27. extern struct GNUNET_ATS_TEST_Topology *top;
  28. static struct GNUNET_TIME_Relative
  29. get_delay (struct TrafficGenerator *tg)
  30. {
  31. struct GNUNET_TIME_Relative delay;
  32. struct GNUNET_TIME_Relative time_delta;
  33. long long int cur_rate;
  34. long long int delta_rate;
  35. delay.rel_value_us = 0;
  36. /* Calculate the current transmission rate based on the type of traffic */
  37. switch (tg->type)
  38. {
  39. case GNUNET_ATS_TEST_TG_CONSTANT:
  40. if (UINT32_MAX == tg->base_rate)
  41. return GNUNET_TIME_UNIT_ZERO;
  42. cur_rate = tg->base_rate;
  43. break;
  44. case GNUNET_ATS_TEST_TG_LINEAR:
  45. time_delta = GNUNET_TIME_absolute_get_duration (tg->time_start);
  46. /* Calculate point of time in the current period */
  47. time_delta.rel_value_us = time_delta.rel_value_us
  48. % tg->duration_period.rel_value_us;
  49. delta_rate = ((double) time_delta.rel_value_us
  50. / tg->duration_period.rel_value_us)
  51. * (tg->max_rate - tg->base_rate);
  52. if ((tg->max_rate < tg->base_rate) && ((tg->max_rate - tg->base_rate) >
  53. tg->base_rate))
  54. {
  55. /* This will cause an underflow */
  56. GNUNET_break (0);
  57. }
  58. cur_rate = tg->base_rate + delta_rate;
  59. break;
  60. case GNUNET_ATS_TEST_TG_RANDOM:
  61. cur_rate = tg->base_rate + GNUNET_CRYPTO_random_u32 (
  62. GNUNET_CRYPTO_QUALITY_WEAK,
  63. tg->max_rate
  64. - tg->base_rate);
  65. break;
  66. case GNUNET_ATS_TEST_TG_SINUS:
  67. time_delta = GNUNET_TIME_absolute_get_duration (tg->time_start);
  68. /* Calculate point of time in the current period */
  69. time_delta.rel_value_us = time_delta.rel_value_us
  70. % tg->duration_period.rel_value_us;
  71. if ((tg->max_rate - tg->base_rate) > tg->base_rate)
  72. {
  73. /* This will cause an underflow for second half of sinus period,
  74. * will be detected in general when experiments are loaded */
  75. GNUNET_break (0);
  76. }
  77. delta_rate = (tg->max_rate - tg->base_rate)
  78. * sin ((2 * M_PI)
  79. / ((double) tg->duration_period.rel_value_us)
  80. * time_delta.rel_value_us);
  81. cur_rate = tg->base_rate + delta_rate;
  82. break;
  83. default:
  84. return delay;
  85. break;
  86. }
  87. if (cur_rate < 0)
  88. {
  89. cur_rate = 1;
  90. }
  91. /* Calculate the delay for the next message based on the current delay */
  92. delay.rel_value_us = GNUNET_TIME_UNIT_SECONDS.rel_value_us
  93. * TEST_MESSAGE_SIZE / cur_rate;
  94. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  95. "Current rate is %lld, calculated delay is %llu\n",
  96. cur_rate,
  97. (unsigned long long) delay.rel_value_us);
  98. return delay;
  99. }
  100. static void
  101. update_ping_data (void *cls)
  102. {
  103. struct BenchmarkPartner *p = cls;
  104. struct GNUNET_TIME_Relative delay;
  105. p->messages_sent++;
  106. p->bytes_sent += TEST_MESSAGE_SIZE;
  107. p->me->total_messages_sent++;
  108. p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
  109. if (NULL == p->tg)
  110. {
  111. GNUNET_break (0);
  112. return;
  113. }
  114. delay = get_delay (p->tg);
  115. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  116. "Delay for next transmission %s\n",
  117. GNUNET_STRINGS_relative_time_to_string (delay,
  118. GNUNET_YES));
  119. p->tg->next_ping_transmission
  120. = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
  121. delay);
  122. }
  123. static void
  124. comm_schedule_send (void *cls)
  125. {
  126. struct BenchmarkPartner *p = cls;
  127. struct TestMessage *msg;
  128. struct GNUNET_MQ_Envelope *env;
  129. p->tg->send_task = NULL;
  130. p->last_message_sent = GNUNET_TIME_absolute_get ();
  131. env = GNUNET_MQ_msg (msg,
  132. TEST_MESSAGE_TYPE_PING);
  133. memset (msg->padding,
  134. 'a',
  135. sizeof(msg->padding));
  136. GNUNET_MQ_notify_sent (env,
  137. &update_ping_data,
  138. p);
  139. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  140. "Master [%u]: Sending PING to [%u]\n",
  141. p->me->no,
  142. p->dest->no);
  143. GNUNET_MQ_send (p->mq,
  144. env);
  145. }
  146. static void
  147. update_pong_data (void *cls)
  148. {
  149. struct BenchmarkPartner *p = cls;
  150. p->messages_sent++;
  151. p->bytes_sent += TEST_MESSAGE_SIZE;
  152. p->me->total_messages_sent++;
  153. p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
  154. }
  155. void
  156. GNUNET_ATS_TEST_traffic_handle_ping (struct BenchmarkPartner *p)
  157. {
  158. struct TestMessage *msg;
  159. struct GNUNET_MQ_Envelope *env;
  160. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  161. "Slave [%u]: Received PING from [%u], sending PONG\n",
  162. p->me->no,
  163. p->dest->no);
  164. p->messages_received++;
  165. p->bytes_received += TEST_MESSAGE_SIZE;
  166. p->me->total_messages_received++;
  167. p->me->total_bytes_received += TEST_MESSAGE_SIZE;
  168. env = GNUNET_MQ_msg (msg,
  169. TEST_MESSAGE_TYPE_PING);
  170. memset (msg->padding,
  171. 'a',
  172. sizeof(msg->padding));
  173. GNUNET_MQ_notify_sent (env,
  174. &update_pong_data,
  175. p);
  176. GNUNET_MQ_send (p->mq,
  177. env);
  178. }
  179. void
  180. GNUNET_ATS_TEST_traffic_handle_pong (struct BenchmarkPartner *p)
  181. {
  182. struct GNUNET_TIME_Relative left;
  183. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  184. "Master [%u]: Received PONG from [%u], next message\n",
  185. p->me->no,
  186. p->dest->no);
  187. p->messages_received++;
  188. p->bytes_received += TEST_MESSAGE_SIZE;
  189. p->me->total_messages_received++;
  190. p->me->total_bytes_received += TEST_MESSAGE_SIZE;
  191. p->total_app_rtt += GNUNET_TIME_absolute_get_difference (p->last_message_sent,
  192. GNUNET_TIME_absolute_get ())
  193. .rel_value_us;
  194. /* Schedule next send event */
  195. if (NULL == p->tg)
  196. return;
  197. left = GNUNET_TIME_absolute_get_remaining (p->tg->next_ping_transmission);
  198. if (UINT32_MAX == p->tg->base_rate)
  199. {
  200. p->tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, p);
  201. }
  202. else if (0 == left.rel_value_us)
  203. {
  204. p->tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, p);
  205. }
  206. else
  207. {
  208. /* Enforce minimum transmission rate 1 msg / sec */
  209. if (GNUNET_TIME_UNIT_SECONDS.rel_value_us == (left =
  210. GNUNET_TIME_relative_min (
  211. left,
  212. GNUNET_TIME_UNIT_SECONDS))
  213. .rel_value_us)
  214. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  215. "Enforcing minimum send rate between master [%u] and slave [%u]\n",
  216. p->me->no, p->dest->no);
  217. p->tg->send_task = GNUNET_SCHEDULER_add_delayed (left,
  218. &comm_schedule_send, p);
  219. }
  220. }
  221. /**
  222. * Generate between the source master and the partner and send traffic with a
  223. * maximum rate.
  224. *
  225. * @param src traffic source
  226. * @param dest traffic partner
  227. * @param type type of traffic to generate
  228. * @param base_rate traffic base rate to send data with
  229. * @param max_rate traffic maximum rate to send data with
  230. * @param period duration of a period of traffic generation (~ 1/frequency)
  231. * @param duration how long to generate traffic
  232. * @return the traffic generator
  233. */
  234. struct TrafficGenerator *
  235. GNUNET_ATS_TEST_generate_traffic_start (struct BenchmarkPeer *src,
  236. struct BenchmarkPartner *dest,
  237. enum GeneratorType type,
  238. unsigned int base_rate,
  239. unsigned int max_rate,
  240. struct GNUNET_TIME_Relative period,
  241. struct GNUNET_TIME_Relative duration)
  242. {
  243. struct TrafficGenerator *tg;
  244. if (NULL != dest->tg)
  245. {
  246. GNUNET_break (0);
  247. return NULL;
  248. }
  249. tg = GNUNET_new (struct TrafficGenerator);
  250. GNUNET_CONTAINER_DLL_insert (tg_head,
  251. tg_tail,
  252. tg);
  253. tg->type = type;
  254. tg->src = src;
  255. tg->dest = dest;
  256. tg->base_rate = base_rate;
  257. tg->max_rate = max_rate;
  258. tg->duration_period = period;
  259. tg->time_start = GNUNET_TIME_absolute_get ();
  260. tg->next_ping_transmission = GNUNET_TIME_UNIT_FOREVER_ABS;
  261. switch (type)
  262. {
  263. case GNUNET_ATS_TEST_TG_CONSTANT:
  264. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  265. "Setting up constant traffic generator master[%u] `%s' and slave [%u] `%s' max %u Bips\n",
  266. dest->me->no,
  267. GNUNET_i2s (&dest->me->id),
  268. dest->dest->no,
  269. GNUNET_i2s (&dest->dest->id),
  270. base_rate);
  271. break;
  272. case GNUNET_ATS_TEST_TG_LINEAR:
  273. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  274. "Setting up linear traffic generator master[%u] `%s' and slave [%u] `%s' min %u Bips max %u Bips\n",
  275. dest->me->no,
  276. GNUNET_i2s (&dest->me->id),
  277. dest->dest->no,
  278. GNUNET_i2s (&dest->dest->id),
  279. base_rate,
  280. max_rate);
  281. break;
  282. case GNUNET_ATS_TEST_TG_SINUS:
  283. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  284. "Setting up sinus traffic generator master[%u] `%s' and slave [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
  285. dest->me->no,
  286. GNUNET_i2s (&dest->me->id),
  287. dest->dest->no,
  288. GNUNET_i2s (&dest->dest->id),
  289. base_rate,
  290. max_rate);
  291. break;
  292. case GNUNET_ATS_TEST_TG_RANDOM:
  293. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  294. "Setting up random traffic generator master[%u] `%s' and slave [%u] `%s' min %u Bips max %u Bps\n",
  295. dest->me->no,
  296. GNUNET_i2s (&dest->me->id),
  297. dest->dest->no,
  298. GNUNET_i2s (&dest->dest->id),
  299. base_rate,
  300. max_rate);
  301. break;
  302. default:
  303. break;
  304. }
  305. dest->tg = tg;
  306. tg->send_task
  307. = GNUNET_SCHEDULER_add_now (&comm_schedule_send,
  308. dest);
  309. return tg;
  310. }
  311. void
  312. GNUNET_ATS_TEST_generate_traffic_stop (struct TrafficGenerator *tg)
  313. {
  314. GNUNET_CONTAINER_DLL_remove (tg_head,
  315. tg_tail,
  316. tg);
  317. tg->dest->tg = NULL;
  318. if (NULL != tg->send_task)
  319. {
  320. GNUNET_SCHEDULER_cancel (tg->send_task);
  321. tg->send_task = NULL;
  322. }
  323. GNUNET_free (tg);
  324. }
  325. /**
  326. * Stop all traffic generators
  327. */
  328. void
  329. GNUNET_ATS_TEST_generate_traffic_stop_all ()
  330. {
  331. struct TrafficGenerator *cur;
  332. struct TrafficGenerator *next;
  333. next = tg_head;
  334. for (cur = next; NULL != cur; cur = next)
  335. {
  336. next = cur->next;
  337. GNUNET_ATS_TEST_generate_traffic_stop (cur);
  338. }
  339. }
  340. /* end of file ats-testing-traffic.c */