-fix config, shutdown issue
[oweals/gnunet.git] / src / ats / test_ats_simplistic_pref_aging.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2010,2011 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/test_ats_mlp.c
22  * @brief test for the MLP solver
23  * @author Christian Grothoff
24  * @author Matthias Wachs
25
26  */
27 /**
28  * @file ats/test_ats_api_scheduling_add_address.c
29  * @brief test for ats proportional solver preference aging:
30  *      Add 2 addresses and set high preference for one. Expect higher bw for this
31  *      address, wait. Preferences should age and so bw assigned should decrease.
32  * @author Christian Grothoff
33  * @author Matthias Wachs
34  */
35 #include "platform.h"
36 #include "gnunet_ats_service.h"
37 #include "gnunet_testing_lib.h"
38 #include "ats.h"
39 #include "test_ats_api_common.h"
40
41 #define DEBUG_ATS_INFO GNUNET_NO
42
43 static struct GNUNET_SCHEDULER_Task * die_task;
44
45 /**
46  * Scheduling handle
47  */
48 static struct GNUNET_ATS_SchedulingHandle *sched_ats;
49
50 /**
51  * Connectivity handle
52  */
53 static struct GNUNET_ATS_ConnectivityHandle *connect_ats;
54
55 /**
56  * Performance handle
57  */
58 static struct GNUNET_ATS_PerformanceHandle *perf_ats;
59
60 /**
61  * Return value
62  */
63 static int ret;
64
65 /**
66  * Test address
67  */
68 static struct Test_Address test_addr[2];
69
70 /**
71  * Test peer
72  */
73 static struct PeerContext p[2];
74
75 /**
76  * Connectivity suggestion handles.
77  */
78 static struct GNUNET_ATS_ConnectivitySuggestHandle *sh[2];
79
80 /**
81  * HELLO address
82  */
83 static struct GNUNET_HELLO_Address test_hello_address[2];
84
85 /**
86  * Session
87  */
88 static void *test_session[2];
89
90 /**
91  * Test ats info
92  */
93 static struct GNUNET_ATS_Information test_ats_info[2];
94
95 /**
96  * Test ats count
97  */
98 static uint32_t test_ats_count;
99
100 /**
101  * Configured WAN out quota
102  */
103 static unsigned long long wan_quota_out;
104
105 /**
106  * Configured WAN in quota
107  */
108 static unsigned long long wan_quota_in;
109
110
111 static void
112 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
113 {
114   die_task = NULL;
115   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error! Shutting down\n");
116   if (sched_ats != NULL)
117   {
118     GNUNET_ATS_scheduling_done (sched_ats);
119     sched_ats = NULL;
120   }
121   if (NULL != connect_ats)
122   {
123     GNUNET_ATS_connectivity_done (connect_ats);
124     connect_ats = NULL;
125   }
126   if (perf_ats != NULL)
127   {
128     GNUNET_ATS_performance_done (perf_ats);
129     perf_ats = NULL;
130   }
131   free_test_address (&test_addr[0]);
132   ret = GNUNET_SYSERR;
133 }
134
135
136 static void
137 end ()
138 {
139   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n");
140   if (die_task != NULL)
141   {
142     GNUNET_SCHEDULER_cancel (die_task);
143     die_task = NULL;
144   }
145
146   GNUNET_ATS_connectivity_suggest_cancel (sh[0]);
147   GNUNET_ATS_connectivity_suggest_cancel (sh[1]);
148
149   if (NULL != sched_ats)
150         GNUNET_ATS_scheduling_done (sched_ats);
151   if (NULL != perf_ats)
152   GNUNET_ATS_performance_done (perf_ats);
153   sched_ats = NULL;
154   perf_ats = NULL;
155   free_test_address (&test_addr[0]);
156   free_test_address (&test_addr[1]);
157 }
158
159
160 static void
161 address_suggest_cb (void *cls,
162                     const struct GNUNET_PeerIdentity *peer,
163                     const struct GNUNET_HELLO_Address *address,
164                     struct Session *session,
165                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
166                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
167                     const struct GNUNET_ATS_Information *atsi,
168                     uint32_t ats_count)
169 {
170   static int stage = 0;
171   static int sug_p0 = GNUNET_NO;
172   static int sug_p1 = GNUNET_NO;
173
174   static uint32_t p0_last_bandwidth_out;
175   static uint32_t p0_last_bandwidth_in;
176
177   static uint32_t p1_last_bandwidth_out;
178   static uint32_t p1_last_bandwidth_in;
179
180   uint32_t cur_bandwidth_out = ntohl (bandwidth_out.value__);
181   uint32_t cur_bandwidth_in = ntohl (bandwidth_in.value__);
182
183   if (0 == stage)
184   {
185     /* Callback for initial suggestion */
186     if (0 == memcmp (&address->peer, &p[0].id, sizeof (p[0].id)))
187     {
188       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
189                   "Stage %u: Callback for peer 0 `%s': (in/out) %u/%u\n",
190                   stage,
191                   GNUNET_i2s (&address->peer),
192                   (unsigned int) ntohl (bandwidth_in.value__),
193                   (unsigned int) ntohl (bandwidth_out.value__));
194       sug_p0 = GNUNET_YES;
195       p0_last_bandwidth_out = ntohl(bandwidth_out.value__);
196       p0_last_bandwidth_in = ntohl(bandwidth_in.value__);
197     }
198     if (0 == memcmp (&address->peer, &p[1].id, sizeof (p[1].id)))
199     {
200       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
201                   "Stage %u: Callback for peer 1 `%s': (in/out) %u/%u\n",
202                   stage,
203                   GNUNET_i2s (&address->peer),
204                   (unsigned int) ntohl (bandwidth_in.value__),
205                   (unsigned int) ntohl (bandwidth_out.value__));
206       sug_p1 = GNUNET_YES;
207       p1_last_bandwidth_out = ntohl(bandwidth_out.value__);
208       p1_last_bandwidth_in = ntohl(bandwidth_in.value__);
209     }
210     if ((GNUNET_YES == sug_p0) && (GNUNET_YES == sug_p1))
211     {
212       /* Changing preference for peer 0 */
213       stage ++;
214       GNUNET_ATS_performance_change_preference (perf_ats, &p[0].id, GNUNET_ATS_PREFERENCE_BANDWIDTH,(double) 1000, GNUNET_ATS_PREFERENCE_END);
215       sug_p0 = GNUNET_NO;
216       sug_p1 = GNUNET_NO;
217       return;
218     }
219   }
220   if (1 == stage)
221   {
222     /* Callback due to preference change */
223     if (0 == memcmp (&address->peer, &p[0].id, sizeof (p[0].id)))
224     {
225       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
226                   "Stage %u: Callback for peer 0 `%s': (in/out) %u/%u\n",
227                   stage,
228                   GNUNET_i2s (&address->peer),
229                   (unsigned int) ntohl (bandwidth_in.value__),
230                   (unsigned int) ntohl (bandwidth_out.value__));
231       sug_p0 = GNUNET_YES;
232
233       /* Peer 0 should get more bandwidth */
234       if (cur_bandwidth_out <= p0_last_bandwidth_out)
235         GNUNET_break (0);
236       if (cur_bandwidth_in <= p0_last_bandwidth_in)
237         GNUNET_break (0);
238       p0_last_bandwidth_out = ntohl(bandwidth_out.value__);
239       p0_last_bandwidth_in = ntohl(bandwidth_in.value__);
240     }
241     if (0 == memcmp (&address->peer, &p[1].id, sizeof (p[1].id)))
242     {
243       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
244                   "Stage %u: Callback for peer 1 `%s': (in/out) %u/%u\n",
245                   stage,
246                   GNUNET_i2s (&address->peer),
247                   (unsigned int) ntohl (bandwidth_in.value__),
248                   (unsigned int) ntohl (bandwidth_out.value__));
249       sug_p1 = GNUNET_YES;
250
251       /* Peer 1 should get less bandwidth */
252       if (cur_bandwidth_out >= p1_last_bandwidth_out)
253       {
254         GNUNET_break (0);
255         goto error;
256       }
257       if (cur_bandwidth_in >= p1_last_bandwidth_in)
258       {
259         GNUNET_break (0);
260         goto error;
261       }
262       p1_last_bandwidth_out = ntohl(bandwidth_out.value__);
263       p1_last_bandwidth_in = ntohl(bandwidth_in.value__);
264     }
265     if ((GNUNET_YES == sug_p0) && (GNUNET_YES == sug_p1))
266     {
267       stage ++;
268       sug_p0 = GNUNET_NO;
269       sug_p1 = GNUNET_NO;
270       return;
271     }
272   }
273   if (2 == stage)
274   {
275     /* Callback due to preference aging */
276     if (0 == memcmp (&address->peer, &p[0].id, sizeof (p[0].id)))
277     {
278       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
279                   "Stage %u: Callback for peer 0 `%s': (in/out) %u/%u\n",
280                   stage,
281                   GNUNET_i2s (&address->peer),
282                   (unsigned int) ntohl (bandwidth_in.value__),
283                   (unsigned int) ntohl (bandwidth_out.value__));
284       sug_p0 = GNUNET_YES;
285
286       /* Peer 0 should get less bandwidth */
287       if (cur_bandwidth_out <= p0_last_bandwidth_out)
288         GNUNET_break (0);
289       if (cur_bandwidth_in <= p0_last_bandwidth_in)
290         GNUNET_break (0);
291       p0_last_bandwidth_out = ntohl(bandwidth_out.value__);
292       p0_last_bandwidth_in = ntohl(bandwidth_in.value__);
293     }
294     if (0 == memcmp (&address->peer, &p[1].id, sizeof (p[1].id)))
295     {
296       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
297                   "Stage %u: Callback for peer 1 `%s': (in/out) %u/%u\n",
298                   stage,
299                   GNUNET_i2s (&address->peer),
300                   (unsigned int) ntohl (bandwidth_in.value__),
301                   (unsigned int) ntohl (bandwidth_out.value__));
302       sug_p1 = GNUNET_YES;
303       /* Peer 1 should get more bandwidth */
304       if (cur_bandwidth_out <= p1_last_bandwidth_out)
305       {
306         GNUNET_break (0);
307         goto error;
308       }
309       if (cur_bandwidth_in <= p1_last_bandwidth_in)
310       {
311         GNUNET_break (0);
312         goto error;
313       }
314       p0_last_bandwidth_out = ntohl(bandwidth_out.value__);
315       p0_last_bandwidth_in = ntohl(bandwidth_in.value__);
316     }
317
318     if ((GNUNET_YES == sug_p0) && (GNUNET_YES == sug_p1))
319     {
320       /* Done ! */
321       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n");
322       stage ++;
323       ret = 0;
324       GNUNET_SCHEDULER_add_now (&end,NULL);
325       return;
326     }
327   }
328   return;
329
330 error:
331   /* Error ! */
332   ret = 1;
333   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Error!\n");
334   GNUNET_SCHEDULER_add_now (&end,NULL);
335 }
336
337
338 static void
339 run (void *cls,
340      const struct GNUNET_CONFIGURATION_Handle *cfg,
341      struct GNUNET_TESTING_Peer *peer)
342 {
343   char *quota_str;
344
345   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_OUT", &quota_str))
346   {
347       fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n");
348       ret = 1;
349       return;
350   }
351   if  (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_out))
352   {
353       fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n");
354       ret = 1;
355       GNUNET_free (quota_str);
356       return;
357   }
358   GNUNET_free (quota_str);
359   quota_str = NULL;
360
361   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_IN", &quota_str))
362   {
363       fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n");
364       ret = 1;
365       return;
366   }
367   if  (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_in))
368   {
369       fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n");
370       GNUNET_free (quota_str);
371       ret = 1;
372       return;
373   }
374   GNUNET_free (quota_str);
375   quota_str = NULL;
376   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN inbound quota: %llu\n", wan_quota_in);
377   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN outbound quota: %llu\n", wan_quota_out);
378
379
380   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
381
382   /* Connect to ATS scheduling */
383   connect_ats = GNUNET_ATS_connectivity_init (mycfg);
384   sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL);
385   if (sched_ats == NULL)
386   {
387     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n");
388     ret = 1;
389     end ();
390     return;
391   }
392
393   /* Connect to ATS performance */
394   perf_ats = GNUNET_ATS_performance_init(cfg, NULL, NULL);
395   if (sched_ats == NULL)
396   {
397     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n");
398     ret = 1;
399     end ();
400     return;
401   }
402
403
404   /* Set up peer 0 */
405   if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID0, &p[0].id.hashPubKey))
406   {
407       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n");
408       ret = GNUNET_SYSERR;
409       end ();
410       return;
411   }
412
413   GNUNET_assert (0 == strcmp (PEERID0, GNUNET_i2s_full (&p[0].id)));
414
415   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n",
416               GNUNET_i2s(&p[0].id));
417
418   /* Set up peer 1*/
419   if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID1, &p[1].id.hashPubKey))
420   {
421       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n");
422       ret = GNUNET_SYSERR;
423       end ();
424       return;
425   }
426
427   GNUNET_assert (0 == strcmp (PEERID1, GNUNET_i2s_full (&p[1].id)));
428
429   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n",
430               GNUNET_i2s(&p[1].id));
431
432   /* Prepare ATS Information */
433   test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
434   test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN);
435   test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
436   test_ats_info[1].value = htonl(1);
437   test_ats_count = 2;
438
439   /* Peer 0: Adding address with session */
440   test_session[0] = &test_addr[0];
441   create_test_address (&test_addr[0], "test0", test_session[0], "test0", strlen ("test0") + 1);
442   test_hello_address[0].peer = p[0].id;
443   test_hello_address[0].transport_name = test_addr[0].plugin;
444   test_hello_address[0].address = test_addr[0].addr;
445   test_hello_address[0].address_length = test_addr[0].addr_len;
446   GNUNET_ATS_address_add (sched_ats, &test_hello_address[0], test_session[0], test_ats_info, test_ats_count);
447
448   /* Peer 1: Adding address with session */
449   test_session[1] = &test_addr[1];
450   create_test_address (&test_addr[1], "test1", test_session[1], "test1", strlen ("test1") + 1);
451   test_hello_address[1].peer = p[1].id;
452   test_hello_address[1].transport_name = test_addr[1].plugin;
453   test_hello_address[1].address = test_addr[1].addr;
454   test_hello_address[1].address_length = test_addr[1].addr_len;
455   GNUNET_ATS_address_add (sched_ats, &test_hello_address[1], test_session[1], test_ats_info, test_ats_count);
456
457   sh[0] = GNUNET_ATS_connectivity_suggest (connect_ats, &p[0].id);
458   sh[1] = GNUNET_ATS_connectivity_suggest (connect_ats, &p[1].id);
459 }
460
461
462 int
463 main (int argc, char *argv[])
464 {
465   if (0 != GNUNET_TESTING_peer_run ("test_ats_proportional_pref_aging",
466                                     "test_ats_api.conf",
467                                     &run, NULL))
468     return 1;
469   return ret;
470 }
471
472
473 /* end of file test_ats_simplistic_pref_aging.c */