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