glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / ats-tests / ats-testing-preferences.c
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2010-2013 GNUnet e.V.
4
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.
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  Affero General Public License for more details.
14  */
15 /**
16  * @file ats-tests/ats-testing-preferences.c
17  * @brief ats benchmark: preference generator
18  * @author Christian Grothoff
19  * @author Matthias Wachs
20  */
21 #include "platform.h"
22 #include "gnunet_util_lib.h"
23 #include "ats-testing.h"
24
25 static struct PreferenceGenerator *pg_head;
26 static struct PreferenceGenerator *pg_tail;
27
28 extern struct GNUNET_ATS_TEST_Topology *top;
29
30 static double
31 get_preference (struct PreferenceGenerator *pg)
32 {
33   struct GNUNET_TIME_Relative time_delta;
34   double delta_value;
35   double pref_value;
36
37   /* Calculate the current preference value */
38   switch (pg->type) {
39     case GNUNET_ATS_TEST_TG_CONSTANT:
40       pref_value = pg->base_value;
41       break;
42     case GNUNET_ATS_TEST_TG_LINEAR:
43       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
44       /* Calculate point of time in the current period */
45       time_delta.rel_value_us = time_delta.rel_value_us %
46           pg->duration_period.rel_value_us;
47       delta_value = ((double) time_delta.rel_value_us  /
48           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
49       if ((pg->max_value < pg->base_value) &&
50           ((pg->max_value - pg->base_value) > pg->base_value))
51       {
52         /* This will cause an underflow */
53         GNUNET_break (0);
54       }
55       pref_value = pg->base_value + delta_value;
56       break;
57     case GNUNET_ATS_TEST_TG_RANDOM:
58       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
59           10000 * (pg->max_value - pg->base_value)) / 10000;
60       pref_value = pg->base_value + delta_value;
61       break;
62     case GNUNET_ATS_TEST_TG_SINUS:
63       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
64       /* Calculate point of time in the current period */
65       time_delta.rel_value_us = time_delta.rel_value_us %
66           pg->duration_period.rel_value_us;
67       if ((pg->max_value - pg->base_value) > pg->base_value)
68       {
69         /* This will cause an underflow for second half of sinus period,
70          * will be detected in general when experiments are loaded */
71         GNUNET_break (0);
72       }
73       delta_value = (pg->max_value - pg->base_value) *
74           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
75               time_delta.rel_value_us);
76       pref_value = pg->base_value + delta_value;
77       break;
78     default:
79       pref_value = 0.0;
80       break;
81   }
82   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current preference value is %f\n",
83       pref_value);
84   return pref_value;
85 }
86
87
88 static void
89 set_pref_task (void *cls)
90 {
91   struct BenchmarkPartner *p = cls;
92   double pref_value;
93   p->pg->set_task = NULL;
94
95   pref_value = get_preference (p->pg);
96
97   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
98       "Setting preference for master [%u] and slave [%u] for %s to %f\n",
99       p->me->no, p->dest->no,
100       GNUNET_ATS_print_preference_type (p->pg->kind), pref_value);
101
102   GNUNET_ATS_performance_change_preference(p->me->ats_perf_handle,
103                                            &p->dest->id,
104                                            p->pg->kind,
105                                            pref_value,
106                                            GNUNET_ATS_PREFERENCE_END);
107
108   switch (p->pg->kind) {
109     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
110       p->pref_bandwidth = pref_value;
111       break;
112     case GNUNET_ATS_PREFERENCE_LATENCY:
113       p->pref_delay = pref_value;
114       break;
115     default:
116       break;
117   }
118
119   p->pg->set_task = GNUNET_SCHEDULER_add_delayed (p->pg->frequency,
120       set_pref_task, p);
121
122 }
123
124
125 /**
126  * Generate between the source master and the partner and set preferences with a
127  * value depending on the generator.
128  *
129  * @param src source
130  * @param dest partner
131  * @param type type of preferences to generate
132  * @param base_value traffic base rate to send data with
133  * @param value_rate  traffic maximum rate to send data with
134  * @param period duration of a period of preferences generation (~ 1/frequency)
135  * @param frequency how long to generate preferences
136  * @param kind ATS preference to generate
137  * @return the preference generator
138  */
139 struct PreferenceGenerator *
140 GNUNET_ATS_TEST_generate_preferences_start (struct BenchmarkPeer *src,
141                                             struct BenchmarkPartner *dest,
142                                             enum GeneratorType type,
143                                             unsigned int base_value,
144                                             unsigned int value_rate,
145                                             struct GNUNET_TIME_Relative period,
146                                             struct GNUNET_TIME_Relative frequency,
147                                             enum GNUNET_ATS_PreferenceKind kind)
148 {
149   struct PreferenceGenerator *pg;
150
151   if (NULL != dest->pg)
152   {
153     GNUNET_break (0);
154     return NULL;
155   }
156
157   pg = GNUNET_new (struct PreferenceGenerator);
158   GNUNET_CONTAINER_DLL_insert (pg_head, pg_tail, pg);
159   pg->type = type;
160   pg->src = src;
161   pg->dest = dest;
162   pg->kind = kind;
163   pg->base_value = base_value;
164   pg->max_value = value_rate;
165   pg->duration_period = period;
166   pg->frequency = frequency;
167   pg->time_start = GNUNET_TIME_absolute_get();
168
169   switch (type) {
170     case GNUNET_ATS_TEST_TG_CONSTANT:
171       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
172                   "Setting up constant preference generator master[%u] `%s' and slave [%u] `%s' max %u Bips\n",
173                   dest->me->no, GNUNET_i2s (&dest->me->id),
174                   dest->dest->no, GNUNET_i2s (&dest->dest->id),
175                   base_value);
176       break;
177     case GNUNET_ATS_TEST_TG_LINEAR:
178       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
179                   "Setting up linear preference generator master[%u] `%s' and slave [%u] `%s' min %u Bips max %u Bips\n",
180                   dest->me->no, GNUNET_i2s (&dest->me->id),
181                   dest->dest->no, GNUNET_i2s (&dest->dest->id),
182                   base_value, value_rate);
183       break;
184     case GNUNET_ATS_TEST_TG_SINUS:
185       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
186                   "Setting up sinus preference generator master[%u] `%s' and slave [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
187                   dest->me->no, GNUNET_i2s (&dest->me->id),
188                   dest->dest->no, GNUNET_i2s (&dest->dest->id),
189                   base_value, value_rate);
190       break;
191     case GNUNET_ATS_TEST_TG_RANDOM:
192       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
193                   "Setting up random preference generator master[%u] `%s' and slave [%u] `%s' min %u Bips max %u Bps\n",
194                   dest->me->no, GNUNET_i2s (&dest->me->id),
195                   dest->dest->no, GNUNET_i2s (&dest->dest->id),
196                   base_value, value_rate);
197       break;
198     default:
199       break;
200   }
201
202   dest->pg = pg;
203   pg->set_task = GNUNET_SCHEDULER_add_now (&set_pref_task, dest);
204   return pg;
205 }
206
207
208 void
209 GNUNET_ATS_TEST_generate_preferences_stop (struct PreferenceGenerator *pg)
210 {
211   GNUNET_CONTAINER_DLL_remove (pg_head, pg_tail, pg);
212   pg->dest->pg = NULL;
213
214   if (NULL != pg->set_task)
215   {
216     GNUNET_SCHEDULER_cancel (pg->set_task);
217     pg->set_task = NULL;
218   }
219
220   GNUNET_free (pg);
221 }
222
223
224 /**
225  * Stop all preferences generators
226  */
227 void
228 GNUNET_ATS_TEST_generate_preferences_stop_all ()
229 {
230   struct PreferenceGenerator *cur;
231   struct PreferenceGenerator *next;
232   next = pg_head;
233   for (cur = next; NULL != cur; cur = next)
234   {
235       next = cur->next;
236       GNUNET_ATS_TEST_generate_preferences_stop(cur);
237   }
238 }
239
240 /* end of file ats-testing-preferences.c */