2 This file is part of GNUnet.
3 Copyright (C) 2010-2013, 2016 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
16 * @file ats-tests/ats-testing-traffic.c
17 * @brief ats benchmark: traffic generator
18 * @author Christian Grothoff
19 * @author Matthias Wachs
22 #include "gnunet_util_lib.h"
23 #include "ats-testing.h"
25 static struct TrafficGenerator *tg_head;
26 static struct TrafficGenerator *tg_tail;
28 extern struct GNUNET_ATS_TEST_Topology *top;
30 static struct GNUNET_TIME_Relative
31 get_delay (struct TrafficGenerator *tg)
33 struct GNUNET_TIME_Relative delay;
34 struct GNUNET_TIME_Relative time_delta;
35 long long int cur_rate;
36 long long int delta_rate;
38 delay.rel_value_us = 0;
40 /* Calculate the current transmission rate based on the type of traffic */
42 case GNUNET_ATS_TEST_TG_CONSTANT:
43 if (UINT32_MAX == tg->base_rate)
44 return GNUNET_TIME_UNIT_ZERO;
45 cur_rate = tg->base_rate;
47 case GNUNET_ATS_TEST_TG_LINEAR:
48 time_delta = GNUNET_TIME_absolute_get_duration(tg->time_start);
49 /* Calculate point of time in the current period */
50 time_delta.rel_value_us = time_delta.rel_value_us % tg->duration_period.rel_value_us;
51 delta_rate = ((double) time_delta.rel_value_us / tg->duration_period.rel_value_us) *
52 (tg->max_rate - tg->base_rate);
53 if ((tg->max_rate < tg->base_rate) && ((tg->max_rate - tg->base_rate) > tg->base_rate))
55 /* This will cause an underflow */
58 cur_rate = tg->base_rate + delta_rate;
60 case GNUNET_ATS_TEST_TG_RANDOM:
61 cur_rate = tg->base_rate + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
62 tg->max_rate - tg->base_rate);
64 case GNUNET_ATS_TEST_TG_SINUS:
65 time_delta = GNUNET_TIME_absolute_get_duration(tg->time_start);
66 /* Calculate point of time in the current period */
67 time_delta.rel_value_us = time_delta.rel_value_us % tg->duration_period.rel_value_us;
68 if ((tg->max_rate - tg->base_rate) > tg->base_rate)
70 /* This will cause an underflow for second half of sinus period,
71 * will be detected in general when experiments are loaded */
74 delta_rate = (tg->max_rate - tg->base_rate) *
75 sin ( (2 * M_PI) / ((double) tg->duration_period.rel_value_us) * time_delta.rel_value_us);
76 cur_rate = tg->base_rate + delta_rate;
87 /* Calculate the delay for the next message based on the current delay */
88 delay.rel_value_us = GNUNET_TIME_UNIT_SECONDS.rel_value_us * TEST_MESSAGE_SIZE / cur_rate;
90 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
91 "Current rate is %lld, calculated delay is %llu\n",
93 (unsigned long long) delay.rel_value_us);
99 update_ping_data (void *cls)
101 struct BenchmarkPartner *p = cls;
102 struct GNUNET_TIME_Relative delay;
105 p->bytes_sent += TEST_MESSAGE_SIZE;
106 p->me->total_messages_sent++;
107 p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
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,
119 p->tg->next_ping_transmission
120 = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
126 comm_schedule_send (void *cls)
128 struct BenchmarkPartner *p = cls;
129 struct TestMessage *msg;
130 struct GNUNET_MQ_Envelope *env;
132 p->tg->send_task = NULL;
133 p->last_message_sent = GNUNET_TIME_absolute_get();
134 env = GNUNET_MQ_msg (msg,
135 TEST_MESSAGE_TYPE_PING);
136 memset (msg->padding,
138 sizeof (msg->padding));
139 GNUNET_MQ_notify_sent (env,
142 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
143 "Master [%u]: Sending PING to [%u]\n",
146 GNUNET_MQ_send (p->mq,
152 update_pong_data (void *cls)
154 struct BenchmarkPartner *p = cls;
157 p->bytes_sent += TEST_MESSAGE_SIZE;
158 p->me->total_messages_sent++;
159 p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
164 GNUNET_ATS_TEST_traffic_handle_ping (struct BenchmarkPartner *p)
166 struct TestMessage *msg;
167 struct GNUNET_MQ_Envelope *env;
169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
170 "Slave [%u]: Received PING from [%u], sending PONG\n",
173 p->messages_received++;
174 p->bytes_received += TEST_MESSAGE_SIZE;
175 p->me->total_messages_received++;
176 p->me->total_bytes_received += TEST_MESSAGE_SIZE;
179 env = GNUNET_MQ_msg (msg,
180 TEST_MESSAGE_TYPE_PING);
181 memset (msg->padding,
183 sizeof (msg->padding));
184 GNUNET_MQ_notify_sent (env,
187 GNUNET_MQ_send (p->mq,
193 GNUNET_ATS_TEST_traffic_handle_pong (struct BenchmarkPartner *p)
195 struct GNUNET_TIME_Relative left;
196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
197 "Master [%u]: Received PONG from [%u], next message\n",
201 p->messages_received++;
202 p->bytes_received += TEST_MESSAGE_SIZE;
203 p->me->total_messages_received++;
204 p->me->total_bytes_received += TEST_MESSAGE_SIZE;
205 p->total_app_rtt += GNUNET_TIME_absolute_get_difference(p->last_message_sent,
206 GNUNET_TIME_absolute_get()).rel_value_us;
208 /* Schedule next send event */
212 left = GNUNET_TIME_absolute_get_remaining(p->tg->next_ping_transmission);
213 if (UINT32_MAX == p->tg->base_rate)
215 p->tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, p);
217 else if (0 == left.rel_value_us)
219 p->tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, p);
223 /* Enforce minimum transmission rate 1 msg / sec */
224 if (GNUNET_TIME_UNIT_SECONDS.rel_value_us == (left = GNUNET_TIME_relative_min (left, GNUNET_TIME_UNIT_SECONDS)).rel_value_us)
225 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
226 "Enforcing minimum send rate between master [%u] and slave [%u]\n",
227 p->me->no, p->dest->no);
228 p->tg->send_task = GNUNET_SCHEDULER_add_delayed (left,
229 &comm_schedule_send, p);
235 * Generate between the source master and the partner and send traffic with a
238 * @param src traffic source
239 * @param dest traffic partner
240 * @param type type of traffic to generate
241 * @param base_rate traffic base rate to send data with
242 * @param max_rate traffic maximum rate to send data with
243 * @param period duration of a period of traffic generation (~ 1/frequency)
244 * @param duration how long to generate traffic
245 * @return the traffic generator
247 struct TrafficGenerator *
248 GNUNET_ATS_TEST_generate_traffic_start (struct BenchmarkPeer *src,
249 struct BenchmarkPartner *dest,
250 enum GeneratorType type,
251 unsigned int base_rate,
252 unsigned int max_rate,
253 struct GNUNET_TIME_Relative period,
254 struct GNUNET_TIME_Relative duration)
256 struct TrafficGenerator *tg;
258 if (NULL != dest->tg)
264 tg = GNUNET_new (struct TrafficGenerator);
265 GNUNET_CONTAINER_DLL_insert (tg_head,
271 tg->base_rate = base_rate;
272 tg->max_rate = max_rate;
273 tg->duration_period = period;
274 tg->time_start = GNUNET_TIME_absolute_get();
275 tg->next_ping_transmission = GNUNET_TIME_UNIT_FOREVER_ABS;
278 case GNUNET_ATS_TEST_TG_CONSTANT:
279 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
280 "Setting up constant traffic generator master[%u] `%s' and slave [%u] `%s' max %u Bips\n",
282 GNUNET_i2s (&dest->me->id),
284 GNUNET_i2s (&dest->dest->id),
287 case GNUNET_ATS_TEST_TG_LINEAR:
288 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
289 "Setting up linear traffic generator master[%u] `%s' and slave [%u] `%s' min %u Bips max %u Bips\n",
291 GNUNET_i2s (&dest->me->id),
293 GNUNET_i2s (&dest->dest->id),
297 case GNUNET_ATS_TEST_TG_SINUS:
298 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
299 "Setting up sinus traffic generator master[%u] `%s' and slave [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
301 GNUNET_i2s (&dest->me->id),
303 GNUNET_i2s (&dest->dest->id),
307 case GNUNET_ATS_TEST_TG_RANDOM:
308 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
309 "Setting up random traffic generator master[%u] `%s' and slave [%u] `%s' min %u Bips max %u Bps\n",
311 GNUNET_i2s (&dest->me->id),
313 GNUNET_i2s (&dest->dest->id),
323 = GNUNET_SCHEDULER_add_now (&comm_schedule_send,
330 GNUNET_ATS_TEST_generate_traffic_stop (struct TrafficGenerator *tg)
332 GNUNET_CONTAINER_DLL_remove (tg_head,
336 if (NULL != tg->send_task)
338 GNUNET_SCHEDULER_cancel (tg->send_task);
339 tg->send_task = NULL;
346 * Stop all traffic generators
349 GNUNET_ATS_TEST_generate_traffic_stop_all ()
351 struct TrafficGenerator *cur;
352 struct TrafficGenerator *next;
355 for (cur = next; NULL != cur; cur = next)
358 GNUNET_ATS_TEST_generate_traffic_stop(cur);
362 /* end of file ats-testing-traffic.c */