2 This file is part of GNUnet.
3 (C) 2010-2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file ats-tests/ats-testing-traffic.c
22 * @brief ats benchmark: traffic generator
23 * @author Christian Grothoff
24 * @author Matthias Wachs
27 #include "gnunet_util_lib.h"
28 #include "ats-testing.h"
30 static struct TrafficGenerator *tg_head;
31 static struct TrafficGenerator *tg_tail;
33 extern struct GNUNET_ATS_TEST_Topology *top;
35 static struct GNUNET_TIME_Relative
36 get_delay (struct TrafficGenerator *tg)
38 struct GNUNET_TIME_Relative delay;
39 struct GNUNET_TIME_Relative time_delta;
40 long long int cur_rate;
41 long long int delta_rate;
43 delay.rel_value_us = 0;
45 /* Calculate the current transmission rate based on the type of traffic */
47 case GNUNET_ATS_TEST_TG_CONSTANT:
48 if (UINT32_MAX == tg->base_rate)
49 return GNUNET_TIME_UNIT_ZERO;
50 cur_rate = tg->base_rate;
53 case GNUNET_ATS_TEST_TG_LINEAR:
54 time_delta = GNUNET_TIME_absolute_get_duration(tg->time_start);
55 /* Calculate point of time in the current period */
56 time_delta.rel_value_us = time_delta.rel_value_us % tg->duration_period.rel_value_us;
57 delta_rate = ((double) time_delta.rel_value_us / tg->duration_period.rel_value_us) *
58 (tg->max_rate - tg->base_rate);
59 if ((tg->max_rate - tg->base_rate) > tg->base_rate)
61 /* This will cause an underflow */
64 cur_rate = tg->base_rate + delta_rate;
66 case GNUNET_ATS_TEST_TG_RANDOM:
67 cur_rate = tg->base_rate + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
68 tg->max_rate - tg->base_rate);
70 case GNUNET_ATS_TEST_TG_SINUS:
71 time_delta = GNUNET_TIME_absolute_get_duration(tg->time_start);
72 /* Calculate point of time in the current period */
73 time_delta.rel_value_us = time_delta.rel_value_us % tg->duration_period.rel_value_us;
74 if ((tg->max_rate - tg->base_rate) > tg->base_rate)
76 /* This will cause an underflow for second half of sinus period,
77 * will be detected in general when experiments are loaded */
80 delta_rate = (tg->max_rate - tg->base_rate) *
81 sin ( (2 * M_PI) / ((double) tg->duration_period.rel_value_us) * time_delta.rel_value_us);
82 cur_rate = tg->base_rate + delta_rate;
94 /* Calculate the delay for the next message based on the current delay */
95 delay.rel_value_us = GNUNET_TIME_UNIT_SECONDS.rel_value_us * TEST_MESSAGE_SIZE / cur_rate;
97 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
98 "Current rate is %u, calculated delay is %u \n",
99 cur_rate, delay.rel_value_us);
105 send_ping_ready_cb (void *cls, size_t size, void *buf)
107 struct BenchmarkPartner *p = cls;
108 static char msgbuf[TEST_MESSAGE_SIZE];
109 struct GNUNET_MessageHeader *msg;
110 struct GNUNET_TIME_Relative delay;
117 if (size < TEST_MESSAGE_SIZE)
123 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
124 "Master [%u]: Sending PING to [%u]\n",
125 p->me->no, p->dest->no);
143 msg = (struct GNUNET_MessageHeader *) &msgbuf;
144 memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
145 msg->type = htons (TEST_MESSAGE_TYPE_PING);
146 msg->size = htons (TEST_MESSAGE_SIZE);
147 memcpy (buf, msg, TEST_MESSAGE_SIZE);
150 p->bytes_sent += TEST_MESSAGE_SIZE;
151 p->me->total_messages_sent++;
152 p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
157 return TEST_MESSAGE_SIZE;
159 delay = get_delay (p->tg);
161 fprintf (stderr, "Delay for next transmission %llu ms\n",
162 (long long unsigned int) delay.rel_value_us / 1000);*/
163 p->tg->next_ping_transmission = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(),
166 return TEST_MESSAGE_SIZE;
171 comm_schedule_send (void *cls,
172 const struct GNUNET_SCHEDULER_TaskContext *tc)
174 struct BenchmarkPartner *p = cls;
176 p->tg->send_task = GNUNET_SCHEDULER_NO_TASK;
177 p->last_message_sent = GNUNET_TIME_absolute_get();
178 if (GNUNET_YES == top->test_core)
180 p->cth = GNUNET_CORE_notify_transmit_ready (p->me->ch, GNUNET_NO,
181 GNUNET_CORE_PRIO_BEST_EFFORT,
182 GNUNET_TIME_UNIT_MINUTES,
185 &send_ping_ready_cb, p);
189 p->tth = GNUNET_TRANSPORT_notify_transmit_ready (p->me->th,
192 GNUNET_TIME_UNIT_MINUTES,
193 &send_ping_ready_cb, p);
199 comm_send_pong_ready (void *cls, size_t size, void *buf)
201 static char msgbuf[TEST_MESSAGE_SIZE];
202 struct BenchmarkPartner *p = cls;
203 struct GNUNET_MessageHeader *msg;
205 if (GNUNET_YES == top->test_core)
211 p->bytes_sent += TEST_MESSAGE_SIZE;
212 p->me->total_messages_sent++;
213 p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
215 msg = (struct GNUNET_MessageHeader *) &msgbuf;
216 memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
217 msg->type = htons (TEST_MESSAGE_TYPE_PONG);
218 msg->size = htons (TEST_MESSAGE_SIZE);
219 memcpy (buf, msg, TEST_MESSAGE_SIZE);
221 return TEST_MESSAGE_SIZE;
226 GNUNET_ATS_TEST_traffic_handle_ping (struct BenchmarkPartner *p)
228 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
229 "Slave [%u]: Received PING from [%u], sending PONG\n", p->me->no,
232 p->messages_received++;
233 p->bytes_received += TEST_MESSAGE_SIZE;
234 p->me->total_messages_received++;
235 p->me->total_bytes_received += TEST_MESSAGE_SIZE;
237 if (GNUNET_YES == top->test_core)
239 GNUNET_assert (NULL == p->cth);
242 = GNUNET_CORE_notify_transmit_ready (p->me->ch, GNUNET_NO,
243 GNUNET_CORE_PRIO_BEST_EFFORT,
244 GNUNET_TIME_UNIT_MINUTES,
245 &p->dest->id, TEST_MESSAGE_SIZE,
246 &comm_send_pong_ready, p);
250 GNUNET_assert (NULL == p->tth);
251 p->tth = GNUNET_TRANSPORT_notify_transmit_ready (p->me->th, &p->dest->id,
252 TEST_MESSAGE_SIZE, GNUNET_TIME_UNIT_MINUTES, &comm_send_pong_ready,
259 GNUNET_ATS_TEST_traffic_handle_pong (struct BenchmarkPartner *p)
261 struct GNUNET_TIME_Relative left;
262 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
263 "Master [%u]: Received PONG from [%u], next message\n", p->me->no,
266 p->messages_received++;
267 p->bytes_received += TEST_MESSAGE_SIZE;
268 p->me->total_messages_received++;
269 p->me->total_bytes_received += TEST_MESSAGE_SIZE;
270 p->total_app_rtt += GNUNET_TIME_absolute_get_difference(p->last_message_sent,
271 GNUNET_TIME_absolute_get()).rel_value_us;
273 /* Schedule next send event */
274 left = GNUNET_TIME_absolute_get_remaining(p->tg->next_ping_transmission);
275 if (UINT32_MAX == p->tg->base_rate)
277 p->tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, p);
279 else if (0 == left.rel_value_us)
281 p->tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, p);
285 p->tg->send_task = GNUNET_SCHEDULER_add_delayed (left,
286 &comm_schedule_send, p);
292 * Generate between the source master and the partner and send traffic with a
295 * @param src traffic source
296 * @param dest traffic partner
297 * @param type type of traffic to generate
298 * @param base_rate traffic base rate to send data with
299 * @param max_rate traffic maximum rate to send data with
300 * @param period duration of a period of traffic generation (~ 1/frequency)
301 * @param duration how long to generate traffic
302 * @return the traffic generator
304 struct TrafficGenerator *
305 GNUNET_ATS_TEST_generate_traffic_start (struct BenchmarkPeer *src,
306 struct BenchmarkPartner *dest,
307 enum TrafficGeneratorType type,
310 struct GNUNET_TIME_Relative period,
311 struct GNUNET_TIME_Relative duration)
313 struct TrafficGenerator *tg;
315 if (NULL != dest->tg)
321 tg = GNUNET_new (struct TrafficGenerator);
322 GNUNET_CONTAINER_DLL_insert (tg_head, tg_tail, tg);
326 tg->base_rate = base_rate;
327 tg->max_rate = max_rate;
328 tg->duration_period = period;
329 tg->time_start = GNUNET_TIME_absolute_get();
330 tg->next_ping_transmission = GNUNET_TIME_UNIT_FOREVER_ABS;
332 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
333 "Setting up traffic generator master[%u] `%s' and slave [%u] `%s' max %u Bips\n",
334 dest->me->no, GNUNET_i2s (&dest->me->id),
335 dest->dest->no, GNUNET_i2s (&dest->dest->id),
338 if ( ((GNUNET_YES == top->test_core) && (NULL != dest->cth)) ||
339 ((GNUNET_NO == top->test_core) && (NULL != dest->tth)) )
342 GNUNET_CONTAINER_DLL_remove (tg_head, tg_tail, tg);
348 tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, dest);
354 GNUNET_ATS_TEST_generate_traffic_stop (struct TrafficGenerator *tg)
356 GNUNET_CONTAINER_DLL_remove (tg_head, tg_tail, tg);
359 if (GNUNET_SCHEDULER_NO_TASK != tg->send_task)
361 GNUNET_SCHEDULER_cancel (tg->send_task);
362 tg->send_task = GNUNET_SCHEDULER_NO_TASK;
366 if (NULL != tg->dest->cth)
368 GNUNET_CORE_notify_transmit_ready_cancel (tg->dest->cth);
369 tg->dest->cth = NULL;
374 if (NULL != tg->dest->tth)
376 GNUNET_TRANSPORT_notify_transmit_ready_cancel (tg->dest->tth);
377 tg->dest->tth = NULL;
385 * Stop all traffic generators
388 GNUNET_ATS_TEST_generate_traffic_stop_all ()
390 struct TrafficGenerator *cur;
391 struct TrafficGenerator *next;
393 for (cur = next; NULL != cur; cur = next)
396 GNUNET_ATS_TEST_generate_traffic_stop(cur);
400 /* end of file ats-testing-traffic.c */