5b0aa8c896396760d9638eb76dfb7f3050e66a05
[oweals/gnunet.git] / src / testbed / testbed_api_underlay.c
1 /*
2   This file is part of GNUnet.
3   Copyright (C) 2008--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   You should have received a copy of the GNU Affero General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20  * @file testbed/testbed_api_underlay.c
21  * @brief testbed underlay API implementation
22  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
23  */
24
25 #include "testbed_api_peers.h"
26
27
28 /**
29  * An underlay link
30  */
31 struct LinkProperty
32 {
33   /**
34    * next pointer for list
35    */
36   struct LinkProperty *next;
37
38   /**
39    * the peer whose link is defined by these properties
40    */
41   struct GNUNET_TESTBED_Peer *peer;
42
43   /**
44    * latency of the link in microseconds
45    */
46   uint32_t latency;
47
48   /**
49    * data loss on the link expressed as percentage
50    */
51   uint32_t loss;
52
53   /**
54    * bandwidth of the link in kilobytes per second
55    */
56   uint32_t bandwidth;
57 };
58
59
60 /**
61  * Container for holding a peer in whitelist/blacklist
62  */
63 struct ListEntry
64 {
65   /**
66    * the next pointer
67    */
68   struct ListEntry *next;
69
70   /**
71    * the peer
72    */
73   struct GNUNET_TESTBED_Peer *peer;
74 };
75
76
77 /**
78  * Model for configuring underlay links of a peer
79  * @ingroup underlay
80  */
81 struct GNUNET_TESTBED_UnderlayLinkModel
82 {
83   /**
84    * The peer associated with this model
85    */
86   struct GNUNET_TESTBED_Peer *peer;
87
88   /**
89    * List of peers in the list
90    */
91   struct ListEntry *entries;
92
93   /**
94    * list of link properties
95    */
96   struct LinkProperty *props;
97
98   /**
99    * the type of this model
100    */
101   enum GNUNET_TESTBED_UnderlayLinkModelType type;
102 }
103
104
105 /**
106  * Function to free resources of list entries
107  *
108  * @param model the model
109  */
110 static void
111 free_entries (struct GNUNET_TESTBED_UnderlayLinkModel *model)
112 {
113   struct ListEntry *e;
114
115   while (NULL != (e = model->entries))
116   {
117     model->entries = e->next;
118     GNUNET_free (e);
119   }
120 }
121
122
123 /**
124  * Function to free resources of link properties added to the given model
125  *
126  * @param model the model
127  */
128 static void
129 free_link_properties (struct GNUNET_TESTBED_UnderlayLinkModel *model)
130 {
131   struct LinkProperty *p;
132
133   while (NULL != (p = model->props))
134   {
135     model->props = p->next;
136     GNUNET_free (p);
137   }
138 }
139
140
141 /**
142  * Create a GNUNET_TESTBED_UnderlayLinkModel for the given peer.  A peer can
143  * have ONLY ONE model and it can be either a blacklist or whitelist based one.
144  *
145  * @ingroup underlay
146  * @param peer the peer for which the model has to be created
147  * @param type the type of the model
148  * @return the model
149  */
150 struct GNUNET_TESTBED_UnderlayLinkModel *
151 GNUNET_TESTBED_underlaylinkmodel_create (struct GNUNET_TESTBED_Peer *peer,
152                                          enum GNUNET_TESTBED_UnderlayLinkModelType type)
153 {
154   struct GNUNET_TESTBED_UnderlayLinkModel *m;
155
156   GNUNET_assert (0 == peer->underlay_model_exists);
157   m = GNUNET_new (struct GNUNET_TESTBED_UnderlayLinkModel);
158   peer->underlay_model_exists = 1;
159   m->type = type;
160   return m;
161 }
162
163
164 /**
165  * Add a peer to the given model.  Underlay connections to the given peer will
166  * be permitted if the model is whitelist based; otherwise they will not be
167  * permitted.
168  *
169  * @ingroup underlay
170  * @param model the model
171  * @param peer the peer to add
172  */
173 void
174 GNUNET_TESTBED_underlaylinkmodel_add_peer (struct GNUNET_TESTBED_UnderlayLinkModel *model,
175                                            struct GNUNET_TESTBED_Peer *peer)
176 {
177   struct ListEntry *entry;
178
179   entry = GNUNET_new (struct ListEntry);
180   entry->peer = peer;
181   entry->next = model->entries;
182   model->entries = entry;
183 }
184
185
186 /**
187  * Set the metrics for a link to the given peer in the underlay model.  The link
188  * SHOULD be permittable according to the given model.
189  *
190  * @ingroup underlay
191  * @param model the model
192  * @param peer the other end peer of the link
193  * @param latency latency of the link in microseconds
194  * @param loss data loss of the link expressed as a percentage
195  * @param bandwidth bandwidth of the link in kilobytes per second [kB/s]
196  */
197 void
198 GNUNET_TESTBED_underlaylinkmodel_set_link (struct GNUNET_TESTBED_UnderlayLinkModel *model,
199                                            struct GNUNET_TESTBED_Peer *peer,
200                                            uint32_t latency,
201                                            uint32_t loss,
202                                            uint32_t bandwidth)
203 {
204   struct LinkProperty *prop;
205
206   prop = GNUNET_new (struct LinkProperty);
207   prop->peer = peer;
208   prop->latency = latency;
209   prop->loss = loss;
210   prop->bandwidth = bandwidth;
211   prop->next = model->props;
212   model->props = prop;
213 }
214
215
216 /**
217  * Free the resources of the model.  Use this function only if the model has not
218  * be committed and has to be unallocated.  The peer can then have another model
219  * created.
220  *
221  * @ingroup underlay
222  * @param model the model to unallocate
223  */
224 void
225 GNUNET_TESTBED_underlaylinkmodel_free (struct GNUNET_TESTBED_UnderlayLinkModel *model)
226 {
227   model->peer->underlay_model_exists = 0;
228   free_entries (model);
229   free_link_properties (model);
230   gnunet_free (model);
231 }
232
233
234 /**
235  * Commit the model.  The model is freed in this function(!).
236  *
237  * @ingroup underlay
238  * @param model the model to commit
239  */
240 void
241 GNUNET_TESTBED_underlaylinkmodel_commit (struct GNUNET_TESTBED_UnderlayLinkModel *model)
242 {
243   /* FIXME: Marshal the model into a message */
244   GNUNET_break (0);
245   /* do not reset the value of model->peer->underlay_model_exists */
246   free_entries (model);
247   free_link_properties (model);
248   GNUNET_free (model);
249 }