renaming types
[oweals/gnunet.git] / src / ats-tests / ats-testing-traffic.c
1 /*
2  This file is part of GNUnet.
3  (C) 2010-2013 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19  */
20 /**
21  * @file ats-tests/ats-testing-traffic.c
22  * @brief ats benchmark: traffic generator
23  * @author Christian Grothoff
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "ats-testing.h"
29
30 static struct TrafficGenerator *tg_head;
31 static struct TrafficGenerator *tg_tail;
32
33 extern struct GNUNET_ATS_TEST_Topology *top;
34
35 static struct GNUNET_TIME_Relative
36 get_delay (struct TrafficGenerator *tg)
37 {
38   struct GNUNET_TIME_Relative delay;
39   delay.rel_value_us = 0;
40
41   switch (tg->type) {
42     case GNUNET_ATS_TEST_TG_CONSTANT:
43       if (UINT32_MAX == tg->rate)
44         delay.rel_value_us = 0;
45       else if (tg->rate <= TEST_MESSAGE_SIZE)
46         delay.rel_value_us = (GNUNET_TIME_UNIT_SECONDS.rel_value_us);
47       else
48         delay.rel_value_us = (GNUNET_TIME_UNIT_SECONDS.rel_value_us / (tg->rate / TEST_MESSAGE_SIZE));
49       break;
50     case GNUNET_ATS_TEST_TG_LINEAR:
51       GNUNET_break (0);
52       break;
53     case GNUNET_ATS_TEST_TG_RANDOM:
54       GNUNET_break (0);
55       break;
56     case GNUNET_ATS_TEST_TG_SINUS:
57       GNUNET_break (0);
58       break;
59     default:
60       return delay;
61       break;
62   }
63   return delay;
64 }
65
66 static size_t
67 send_ping_ready_cb (void *cls, size_t size, void *buf)
68 {
69   struct BenchmarkPartner *p = cls;
70   static char msgbuf[TEST_MESSAGE_SIZE];
71   struct GNUNET_MessageHeader *msg;
72
73   if (NULL == buf)
74   {
75     GNUNET_break (0);
76     return 0;
77   }
78   if (size < TEST_MESSAGE_SIZE)
79   {
80     GNUNET_break (0);
81     return 0;
82   }
83
84   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Master [%u]: Sending PING to [%u]\n",
85       p->me->no, p->dest->no);
86
87   if (top->test_core)
88   {
89       if (NULL == p->cth)
90       {
91         GNUNET_break (0);
92       }
93       p->cth = NULL;
94   }
95   else
96   {
97       if (NULL == p->tth)
98       {
99         GNUNET_break (0);
100       }
101       p->tth = NULL;
102   }
103
104   msg = (struct GNUNET_MessageHeader *) &msgbuf;
105   memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
106   msg->type = htons (TEST_MESSAGE_TYPE_PING);
107   msg->size = htons (TEST_MESSAGE_SIZE);
108   memcpy (buf, msg, TEST_MESSAGE_SIZE);
109
110   p->messages_sent++;
111   p->bytes_sent += TEST_MESSAGE_SIZE;
112   p->me->total_messages_sent++;
113   p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
114
115   if (NULL == p->tg)
116   {
117     GNUNET_break (0);
118     return TEST_MESSAGE_SIZE;
119   }
120   p->tg->next_ping_transmission = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(),
121       get_delay (p->tg));
122
123   return TEST_MESSAGE_SIZE;
124 }
125
126
127 static void
128 comm_schedule_send (void *cls,
129     const struct GNUNET_SCHEDULER_TaskContext* tc)
130 {
131   struct BenchmarkPartner *p = cls;
132
133   p->tg->send_task = GNUNET_SCHEDULER_NO_TASK;
134
135   p->last_message_sent = GNUNET_TIME_absolute_get();
136   if (GNUNET_YES == top->test_core)
137   {
138     p->cth = GNUNET_CORE_notify_transmit_ready (
139       p->me->ch, GNUNET_NO,
140       GNUNET_CORE_PRIO_BEST_EFFORT,
141       GNUNET_TIME_UNIT_MINUTES, &p->dest->id,
142       TEST_MESSAGE_SIZE, &send_ping_ready_cb, p);
143   }
144   else
145   {
146     p->tth = GNUNET_TRANSPORT_notify_transmit_ready (
147       p->me->th, &p->dest->id, TEST_MESSAGE_SIZE, 0,GNUNET_TIME_UNIT_MINUTES,
148       &send_ping_ready_cb, p);
149   }
150
151 }
152
153 static size_t
154 comm_send_pong_ready (void *cls, size_t size, void *buf)
155 {
156   static char msgbuf[TEST_MESSAGE_SIZE];
157   struct BenchmarkPartner *p = cls;
158   struct GNUNET_MessageHeader *msg;
159
160   if (GNUNET_YES == top->test_core)
161     p->cth = NULL;
162   else
163     p->tth = NULL;
164
165   p->messages_sent++;
166   p->bytes_sent += TEST_MESSAGE_SIZE;
167   p->me->total_messages_sent++;
168   p->me->total_bytes_sent += TEST_MESSAGE_SIZE;
169
170   msg = (struct GNUNET_MessageHeader *) &msgbuf;
171   memset (&msgbuf, 'a', TEST_MESSAGE_SIZE);
172   msg->type = htons (TEST_MESSAGE_TYPE_PONG);
173   msg->size = htons (TEST_MESSAGE_SIZE);
174   memcpy (buf, msg, TEST_MESSAGE_SIZE);
175
176   return TEST_MESSAGE_SIZE;
177 }
178
179
180 void
181 GNUNET_ATS_TEST_traffic_handle_ping (struct BenchmarkPartner *p)
182 {
183   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
184       "Slave [%u]: Received PING from [%u], sending PONG\n", p->me->no,
185       p->dest->no);
186
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
192   if (GNUNET_YES == top->test_core)
193   {
194     GNUNET_assert (NULL == p->cth);
195
196     p->cth
197       = GNUNET_CORE_notify_transmit_ready (p->me->ch, GNUNET_NO,
198                                            GNUNET_CORE_PRIO_BEST_EFFORT,
199                                            GNUNET_TIME_UNIT_MINUTES,
200                                            &p->dest->id, TEST_MESSAGE_SIZE,
201                                            &comm_send_pong_ready, p);
202   }
203   else
204   {
205     GNUNET_assert (NULL == p->tth);
206     p->tth = GNUNET_TRANSPORT_notify_transmit_ready (p->me->th, &p->dest->id,
207         TEST_MESSAGE_SIZE, 0, GNUNET_TIME_UNIT_MINUTES, &comm_send_pong_ready,
208         p);
209   }
210 }
211
212 void
213 GNUNET_ATS_TEST_traffic_handle_pong (struct BenchmarkPartner *p)
214 {
215   struct GNUNET_TIME_Relative left;
216   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
217       "Master [%u]: Received PONG from [%u], next message\n", p->me->no,
218       p->dest->no);
219
220   p->messages_received++;
221   p->bytes_received += TEST_MESSAGE_SIZE;
222   p->me->total_messages_received++;
223   p->me->total_bytes_received += TEST_MESSAGE_SIZE;
224   p->total_app_rtt += GNUNET_TIME_absolute_get_difference(p->last_message_sent,
225       GNUNET_TIME_absolute_get()).rel_value_us;
226
227   /* Schedule next send event */
228   left = GNUNET_TIME_absolute_get_remaining(p->tg->next_ping_transmission);
229   if (UINT32_MAX == p->tg->rate)
230   {
231     p->tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, p);
232   }
233   else if (0 == left.rel_value_us)
234   {
235     p->tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, p);
236   }
237   else
238   {
239     p->tg->send_task = GNUNET_SCHEDULER_add_delayed (left,
240         &comm_schedule_send, p);
241   }
242 }
243
244
245 /**
246  * Generate between the source master and the partner and send traffic with a
247  * maximum rate.
248  *
249  */
250 struct TrafficGenerator *
251 GNUNET_ATS_TEST_generate_traffic_start (struct BenchmarkPeer *src,
252     struct BenchmarkPartner *dest,
253     enum TrafficGeneratorType type,
254     unsigned int rate,
255     struct GNUNET_TIME_Relative duration)
256 {
257   struct TrafficGenerator * tg;
258   tg = NULL;
259
260   if (NULL != dest->tg)
261   {
262     GNUNET_break (0);
263     return NULL;
264   }
265
266   tg = GNUNET_new (struct TrafficGenerator);
267   GNUNET_CONTAINER_DLL_insert (tg_head, tg_tail, tg);
268   tg->type = type;
269   tg->src = src;
270   tg->dest = dest;
271   tg->rate = rate;
272   tg->next_ping_transmission = GNUNET_TIME_UNIT_FOREVER_ABS;
273
274   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
275       "Setting up traffic generator master[%u] `%s' and slave [%u] `%s' max %u Bips\n",
276       dest->me->no, GNUNET_i2s (&dest->me->id),
277       dest->dest->no, GNUNET_i2s (&dest->dest->id),
278       rate);
279
280   if ( ((GNUNET_YES == top->test_core) && (NULL != dest->cth)) ||
281        ((GNUNET_NO == top->test_core) && (NULL != dest->tth)) )
282   {
283         GNUNET_break (0);
284         GNUNET_CONTAINER_DLL_remove (tg_head, tg_tail, tg);
285         GNUNET_free (tg);
286         return NULL;
287   }
288
289   dest->tg = tg;
290   tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, dest);
291   return tg;
292 }
293
294 void
295 GNUNET_ATS_TEST_generate_traffic_stop (struct TrafficGenerator *tg)
296 {
297
298   GNUNET_CONTAINER_DLL_remove (tg_head, tg_tail, tg);
299   tg->dest->tg = NULL;
300
301   if (GNUNET_SCHEDULER_NO_TASK != tg->send_task)
302   {
303     GNUNET_SCHEDULER_cancel (tg->send_task);
304     tg->send_task = GNUNET_SCHEDULER_NO_TASK;
305   }
306   if (top->test_core)
307   {
308       if (NULL != tg->dest->cth)
309       {
310           GNUNET_CORE_notify_transmit_ready_cancel (tg->dest->cth);
311           tg->dest->cth = NULL;
312       }
313   }
314   else
315   {
316       if (NULL != tg->dest->tth)
317       {
318           GNUNET_TRANSPORT_notify_transmit_ready_cancel (tg->dest->tth);
319           tg->dest->tth = NULL;
320       }
321   }
322   GNUNET_free (tg);
323 }
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
341 /* end of file ats-testing-traffic.c */
342