]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres.c
add test measuring using the parallel port with a logic analyzer
[frescor/fna.git] / src_frescan / frescan_bwres.c
1 /*!
2  * @file frescan_bwres.c
3  *
4  * @brief FRESCAN bandwidth reservation layer
5  *
6  * This module contains function to negotiate contracts and get the
7  * corresponding frescan sporadic servers.
8  *
9  * @version 0.01
10  *
11  * @date 1-Apr-2008
12  *
13  * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
14  *
15  * @license
16  *
17  * -----------------------------------------------------------------------
18  *  Copyright (C) 2006 - 2008 FRESCOR consortium partners:
19  *
20  *    Universidad de Cantabria,              SPAIN
21  *    University of York,                    UK
22  *    Scuola Superiore Sant'Anna,            ITALY
23  *    Kaiserslautern University,             GERMANY
24  *    Univ. Politécnica  Valencia,           SPAIN
25  *    Czech Technical University in Prague,  CZECH REPUBLIC
26  *    ENEA                                   SWEDEN
27  *    Thales Communication S.A.              FRANCE
28  *    Visual Tools S.A.                      SPAIN
29  *    Rapita Systems Ltd                     UK
30  *    Evidence                               ITALY
31  *
32  *    See http://www.frescor.org for a link to partners' websites
33  *
34  *           FRESCOR project (FP6/2005/IST/5-034026) is funded
35  *        in part by the European Union Sixth Framework Programme
36  *        The European Union is not liable of any use that may be
37  *        made of this code.
38  *
39  *  This file is part of FRESCAN
40  *
41  *  FRESCAN is free software; you can  redistribute it and/or  modify
42  *  it under the terms of  the GNU General Public License as published by
43  *  the Free Software Foundation;  either  version 2, or (at  your option)
44  *  any later version.
45  *
46  *  FRESCAN  is distributed  in  the hope  that  it  will  be useful,  but
47  *  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
48  *  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
49  *  General Public License for more details.
50  *
51  *  You should have  received a  copy of  the  GNU  General Public License
52  *  distributed  with  FRESCAN;  see file COPYING.   If not,  write to the
53  *  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
54  *  02111-1307, USA.
55  *
56  * As a special exception, including FRESCAN header files in a file,
57  * instantiating FRESCAN generics or templates, or linking other files
58  * with FRESCAN objects to produce an executable application, does not
59  * by itself cause the resulting executable application to be covered
60  * by the GNU General Public License. This exception does not
61  * however invalidate any other reasons why the executable file might be
62  * covered by the GNU Public License.
63  * -----------------------------------------------------------------------
64  *
65  */
66
67 #include "frsh.h"
68 #include "frescan_bwres.h"
69 #include "frescan_bwres_requests.h"
70 #include "frescan_bwres_robjs.h"
71 #include "frescan_bwres_messages.h"
72 #include "frescan_bwres_threads.h"
73 #include "frescan_bwres_analysis.h"
74 #include "frescan_data.h"
75 #include "frescan_debug.h"
76 #include "frescan_config.h"
77 #include "frescan_servers.h"
78
79 /**
80  * frescan_bwres_init()
81  *
82  * Init the frescan bandwidth reservation layer
83  */
84
85 int frescan_bwres_init(frescan_network_t net)
86 {
87         int ret;
88         frescan_node_t node;
89         frescan_ss_t neg_msg_ss_id;
90         frescan_server_params_t server_params;
91         frescan_bwres_sa_init_params_t init_params;
92         frsh_contract_t neg_msgs_contract;
93         frsh_rel_time_t neg_msgs_budget;
94         frsh_rel_time_t neg_msgs_period;
95
96         init_params.min_prio = FRESCAN_BWRES_SS_MIN_PRIO;
97         init_params.max_prio = FRESCAN_BWRES_SS_MAX_PRIO;
98
99         if (frescan_data[net].local_node == FRESCAN_BWRES_MASTER_NODE) {
100             ret = frescan_bwres_sa_init(&frescan_data[net].scenario,
101                                         &init_params);
102             if (ret != 0) return ret;
103
104             // Add contracts for the negotiation messages
105             ret = frsh_contract_init(&neg_msgs_contract);
106             if (ret != 0) return ret;
107
108             neg_msgs_budget = frsh_usec_to_rel_time(
109                                         (long)FRESCAN_FRAME_TX_TIME_US *
110                                               FRESCAN_BWRES_NEG_MSG_BUDGET);
111
112             neg_msgs_period = frsh_usec_to_rel_time(
113                                         (long)FRESCAN_BWRES_NEG_MSG_PERIOD);
114
115             ret = frsh_contract_set_basic_params(&neg_msgs_contract,
116                                                  &neg_msgs_budget,
117                                                  &neg_msgs_period,
118                                                  FRSH_WT_INDETERMINATE,
119                                                  FRSH_CT_REGULAR);
120             if (ret != 0) return ret;
121
122             ret = frsh_contract_set_preemption_level
123                             (&neg_msgs_contract, FRESCAN_BWRES_NEG_MSG_PRIO);
124             if (ret != 0) return ret;
125
126             for(node=0; node<FRESCAN_MX_NODES; node++) {
127                     ret = freelist_init(&frescan_data[net].scenario.
128                                                         ss_id_freelist[node],
129                                                         FRESCAN_MX_IDS);
130                     if (ret != 0) return ret;
131
132                     ret = freelist_alloc(&frescan_data[net].scenario.
133                                                         ss_id_freelist[node]);
134                     if (ret < 0) return -1;
135
136                     neg_msg_ss_id = (frescan_ss_t)ret;
137
138                     DEBUG(FRESCAN_BWRES_ENABLE_DEBUG,
139                           "manager node:%u b:(%d,%d) t:(%d,%d) p:%u ss:%u\n",
140                           node,
141                           neg_msgs_budget.tv_sec, neg_msgs_budget.tv_nsec,
142                           neg_msgs_period.tv_sec, neg_msgs_period.tv_nsec,
143                           FRESCAN_BWRES_NEG_MSG_PRIO,
144                           neg_msg_ss_id);
145
146                     ret = frescan_bwres_sa_add_contract
147                                     (&frescan_data[net].scenario,
148                                      neg_msg_ss_id,
149                                      node,
150                                      &neg_msgs_contract);
151                     if (ret != 0) return ret;
152             }
153         }
154
155         server_params.budget = FRESCAN_BWRES_NEG_MSG_BUDGET;
156         server_params.period = frsh_rel_time_to_timespec(
157                                         frsh_usec_to_rel_time(
158                                         (long)FRESCAN_BWRES_NEG_MSG_PERIOD));
159         server_params.prio   = FRESCAN_BWRES_NEG_MSG_PRIO;
160
161         ret = frescan_servers_create(net, &server_params,
162                                      &frescan_data[net].neg_messages_ss_id);
163         if (ret != 0) return ret;
164
165         DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "neg_msg_ss_id: %u\n",
166               frescan_data[net].neg_messages_ss_id);
167
168         ret = frescan_bwres_robjs_init(FRESCAN_BWRES_ROBJS_MX_CEILING);
169         if (ret != 0) return ret;
170
171         ret = frescan_bwres_requests_init(FRESCAN_BWRES_REQ_MX_CEILING);
172         if (ret != 0) return ret;
173
174         ret = frescan_messages_init(net);
175         if (ret != 0) return ret;
176
177         ret = frescan_manager_thread_create(net);
178         if (ret != 0) return ret;
179
180         ret = frescan_acceptor_thread_create(net);
181         if (ret != 0) return ret;
182
183         return 0;
184 }
185
186 /**
187  * frescan_bwres_group_change_mode_sync()
188  *
189  * 1.- allocate and prepare the GN request
190  * 2.- enqueue the request
191  * 3.- wait in the reply object for a reply
192  *     (unless there are only cancellations)
193  * 4.- free the request
194  */
195
196 int frescan_bwres_group_change_mode_sync
197                 (frescan_network_t            net,
198                  const frsh_contracts_group_t *contracts_to_neg,
199                  const frsh_contracts_group_t *contracts_to_reneg,
200                  const frescan_ss_group_t     *ss_to_reneg,
201                  const frescan_ss_group_t     *ss_to_cancel,
202                  frescan_ss_group_t           *ss_new,
203                  bool                         *accepted)
204 {
205         int ret;
206         frescan_bwres_request_id_t req;
207         frescan_bwres_request_data_t *req_data;
208
209         DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "preparing a GN request\n");
210
211         ret = frescan_bwres_requests_alloc(&req);
212         if (ret != 0) return ret;
213
214         ret = frescan_bwres_requests_get_data(req, &req_data);
215         if (ret != 0) return ret;
216
217         req_data->net          = net;
218         req_data->type         = FRESCAN_BWRES_REQ_GN;
219         req_data->req          = req;
220         req_data->request_node = frescan_data[net].local_node;
221
222         if (contracts_to_neg == NULL) {
223                 req_data->contracts_to_neg = &req_data->contracts_to_neg_data;
224                 req_data->contracts_to_neg->size = 0;
225         } else {
226                 req_data->contracts_to_neg =
227                                 (frsh_contracts_group_t *)contracts_to_neg;
228         }
229
230         if (contracts_to_reneg == NULL) {
231                 req_data->contracts_to_reneg = &req_data->
232                                                        contracts_to_reneg_data;
233                 req_data->contracts_to_reneg->size = 0;
234         } else {
235                 req_data->contracts_to_reneg = (frsh_contracts_group_t *)
236                                 contracts_to_reneg;
237         }
238
239         if (ss_to_reneg == NULL) {
240                 req_data->ss_to_reneg = &req_data->ss_to_reneg_data;
241                 req_data->ss_to_reneg->size = 0;
242         } else {
243                 req_data->ss_to_reneg = (frescan_ss_group_t *)ss_to_reneg;
244         }
245
246         if (ss_to_cancel == NULL) {
247                 req_data->ss_to_cancel = &req_data->ss_to_cancel_data;
248                 req_data->ss_to_cancel->size = 0;
249         } else {
250                 req_data->ss_to_cancel = (frescan_ss_group_t *)ss_to_cancel;
251
252         }
253
254         if (ss_new == NULL) {
255                 req_data->ss_new = &req_data->ss_new_data;
256                 req_data->ss_new->size = 0;
257         } else {
258                 req_data->ss_new = ss_new;
259         }
260
261         ret = frescan_bwres_robjs_alloc(&req_data->robj, FRESCAN_BWRES_MX_PRIO);
262         if (ret != 0) return ret;
263
264         DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "enqueue the negotiation request\n");
265
266         ret = frescan_bwres_requests_enqueue(req);
267         if (ret != 0) return ret;
268
269         DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "wait for a reply\n");
270
271         ret = frescan_bwres_robjs_wait(req_data->robj);
272         if (ret != 0) return ret;
273
274         ret = frescan_bwres_robjs_free(req_data->robj);
275         if (ret != 0) return ret;
276
277         switch (req_data->return_value) {
278                 case FRESCAN_BWRES_REQ_ACCEPTED:
279                         DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "negotiation OK\n");
280                         *accepted = true;
281                         break;
282
283                 case FRESCAN_BWRES_REQ_NOT_ACCEPTED:
284                         DEBUG(FRESCAN_BWRES_ENABLE_DEBUG, "negotiation FAIL\n");
285                         *accepted = false;
286                         break;
287
288                 default:
289                         FRESCAN_ERROR("return_value unknown\n");
290                         return -1;
291         }
292
293         ret = frescan_bwres_requests_free(req);
294         if (ret != 0) return ret;
295
296         return 0;
297 }
298
299 /**
300  * frescan_bwres_negotiate()
301  */
302
303 int frescan_bwres_negotiate(frescan_network_t net,
304                             const frsh_contract_t *contract,
305                             frescan_ss_t *ss,
306                             bool *accepted)
307 {
308         int ret;
309         frsh_contracts_group_t contracts_to_neg;
310         frescan_ss_group_t ss_new;
311
312         contracts_to_neg.size = 1;
313         contracts_to_neg.contracts[0] = *contract;
314
315         ret = frescan_bwres_group_change_mode_sync
316                         (net, &contracts_to_neg, NULL, NULL,
317                          NULL, &ss_new, accepted);
318         if (ret != 0) return ret;
319
320         if (*accepted) {
321                 *ss = ss_new.ss[0];
322         }
323
324         return 0;
325 }
326
327 /**
328  * frescan_bwres_renegotiate()
329  */
330
331 int frescan_bwres_renegotiate(frescan_network_t net,
332                               const frsh_contract_t *contract,
333                               frescan_ss_t ss,
334                               bool *accepted)
335 {
336         frsh_contracts_group_t contracts_to_reneg;
337         frescan_ss_group_t ss_to_reneg;
338
339         contracts_to_reneg.size = 1;
340         contracts_to_reneg.contracts[0] = *contract;
341
342         ss_to_reneg.size = 1;
343         ss_to_reneg.ss[0] = ss;
344
345         return frescan_bwres_group_change_mode_sync
346                 (net, NULL, &contracts_to_reneg, &ss_to_reneg,
347                  NULL, NULL, accepted);
348 }
349
350 /**
351  * frescan_bwres_cancel()
352  */
353
354 int frescan_bwres_cancel(frescan_network_t net,
355                          frescan_ss_t      ss)
356 {
357         frescan_ss_group_t ss_to_cancel;
358
359         ss_to_cancel.size = 1;
360         ss_to_cancel.ss[0] = ss;
361
362         return frescan_bwres_group_change_mode_sync
363                         (net, NULL, NULL, NULL, &ss_to_cancel, NULL, NULL);
364 }