]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_messages.c
4fea7a117fad9fb04a7a670a330bcd88dcd1defa
[frescor/fna.git] / src_frescan / frescan_bwres_messages.c
1 /*!
2  * @file frescan_bwres_messages.c
3  *
4  * @brief FRESCAN bandwidth reservation layer: negotiation messages formating
5  *
6  * This module contains the data types that define the FRESCAN negotiation
7  * message format and operations to convert them into or from negotiation
8  * requests
9  *
10  * @version 0.01
11  *
12  * @date 2-Apr-2008
13  *
14  * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
15  *
16  * @license
17  *
18  * -----------------------------------------------------------------------
19  *  Copyright (C) 2006 - 2008 FRESCOR consortium partners:
20  *
21  *    Universidad de Cantabria,              SPAIN
22  *    University of York,                    UK
23  *    Scuola Superiore Sant'Anna,            ITALY
24  *    Kaiserslautern University,             GERMANY
25  *    Univ. Politécnica  Valencia,           SPAIN
26  *    Czech Technical University in Prague,  CZECH REPUBLIC
27  *    ENEA                                   SWEDEN
28  *    Thales Communication S.A.              FRANCE
29  *    Visual Tools S.A.                      SPAIN
30  *    Rapita Systems Ltd                     UK
31  *    Evidence                               ITALY
32  *
33  *    See http://www.frescor.org for a link to partners' websites
34  *
35  *           FRESCOR project (FP6/2005/IST/5-034026) is funded
36  *        in part by the European Union Sixth Framework Programme
37  *        The European Union is not liable of any use that may be
38  *        made of this code.
39  *
40  *  This file is part of FRESCAN
41  *
42  *  FRESCAN is free software; you can  redistribute it and/or  modify
43  *  it under the terms of  the GNU General Public License as published by
44  *  the Free Software Foundation;  either  version 2, or (at  your option)
45  *  any later version.
46  *
47  *  FRESCAN  is distributed  in  the hope  that  it  will  be useful,  but
48  *  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
49  *  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
50  *  General Public License for more details.
51  *
52  *  You should have  received a  copy of  the  GNU  General Public License
53  *  distributed  with  FRESCAN;  see file COPYING.   If not,  write to the
54  *  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
55  *  02111-1307, USA.
56  *
57  * As a special exception, including FRESCAN header files in a file,
58  * instantiating FRESCAN generics or templates, or linking other files
59  * with FRESCAN objects to produce an executable application, does not
60  * by itself cause the resulting executable application to be covered
61  * by the GNU General Public License. This exception does not
62  * however invalidate any other reasons why the executable file might be
63  * covered by the GNU Public License.
64  * -----------------------------------------------------------------------
65  *
66  */
67
68 #include <string.h>
69 #include "frescan_bwres_messages.h"
70 #include "frescan_bwres_requests.h"
71 #include "frescan.h"
72 #include "frescan_config.h"
73 #include "frescan_debug.h"
74
75 /**
76  * frescan_messages_init()
77  */
78
79 static frescan_send_params_t send_params[FRESCAN_MX_NETWORKS];
80 static frescan_recv_params_t recv_params[FRESCAN_MX_NETWORKS];
81
82 int frescan_messages_init(frescan_network_t net)
83 {
84         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "initialization\n");
85
86         send_params[net].net     = net;
87         send_params[net].channel = FRESCAN_NEG_CHANNEL;
88         send_params[net].flags   = FRESCAN_SS | FRESCAN_ASYNC;
89         send_params[net].ss      = the_networks[net].neg_messages_ss_id;
90         send_params[net].to      = FRESCAN_NEG_MASTER_NODE;
91
92         recv_params[net].net     = net;
93         recv_params[net].channel = FRESCAN_NEG_CHANNEL;
94         recv_params[net].flags   = FRESCAN_SYNC;
95
96         return 0;
97 }
98
99 /**
100  *
101  *  FRESCAN_REQ_NEG MESSAGE
102  *  =======================
103  *  This message is sent from a SLAVE to the MASTER when the slave wants
104  *  to negotiate a new contract. It contains the type (a negotiation 'NEG'
105  *  request), the LOCAL request id (so the MASTER can use it in the reply
106  *  to identify to which request is replying), a preallocated sporadic
107  *  server id (the MASTER will store it in its table together with the
108  *  node so we can perform renegotiations and spare capacity distribution
109  *  in the future) and the contract.
110  *
111  *      1     2     2      N
112  *  +-----------------------------+
113  *  | 'NEG' | REQ | SS | CONTRACT |
114  *  +-----------------------------+
115  *
116  */
117
118 struct frescan_req_neg_message_t {
119         frescan_request_type_t   type;
120         frescan_request_id_t     req;
121         frescan_ss_t             ss;
122         frescan_contract_t       contract;
123 }  __attribute__ ((packed));
124
125 static int frescan_request_to_neg_message(const frescan_request_data_t *data,
126                                           uint8_t *msg)
127 {
128         struct frescan_req_neg_message_t *neg_msg;
129
130         neg_msg = (struct frescan_req_neg_message_t *)msg;
131
132         neg_msg->type     = FRESCAN_REQ_NEG;
133         neg_msg->req      = data->req;
134         neg_msg->ss       = data->ss;
135         neg_msg->contract = *(data->contract);
136
137         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d\n",
138               neg_msg->type, neg_msg->req, neg_msg->ss);
139
140         return sizeof(struct frescan_req_neg_message_t);
141 }
142
143 static int frescan_neg_message_to_request(const uint8_t *msg,
144                                           frescan_request_data_t *data)
145 {
146         struct frescan_req_neg_message_t *neg_msg;
147
148         neg_msg = (struct frescan_req_neg_message_t *)msg;
149
150         data->type        = FRESCAN_REQ_NEG;
151         data->req         = neg_msg->req;
152         data->ss          = neg_msg->ss;
153         *(data->contract) = neg_msg->contract;
154
155         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d\n",
156               data->type, data->req, data->ss);
157
158         return 0;
159 }
160
161 /**
162  *
163  *  FRESCAN_REQ_RENEG MESSAGE
164  *  =========================
165  *  This message is sent from a SLAVE to the MASTER when the slave wants
166  *  to renegotiate a contract. It contains the type (a renegotiation 'RENEG'
167  *  request), the LOCAL request id (so the MASTER can use it in the reply
168  *  to identify to which request is replying), the sporadic server id
169  *  (the MASTER will look up its table together with the node to find the
170  *  appropiate entry) and the contract.
171  *
172  *      1       2     2      N
173  *  +-------------------------------+
174  *  | 'RENEG' | REQ | SS | CONTRACT |
175  *  +-------------------------------+
176  *
177  */
178
179 struct frescan_req_reneg_message_t {
180         frescan_request_type_t   type;
181         frescan_request_id_t     req;
182         frescan_ss_t             ss;
183         frescan_contract_t       contract;
184 }  __attribute__ ((packed));
185
186 static int frescan_request_to_reneg_message(const frescan_request_data_t *data,
187                                             uint8_t *msg)
188 {
189         struct frescan_req_reneg_message_t *reneg_msg;
190
191         reneg_msg = (struct frescan_req_reneg_message_t *)msg;
192
193         reneg_msg->type     = FRESCAN_REQ_RENEG;
194         reneg_msg->req      = data->req;
195         reneg_msg->ss       = data->ss;
196         reneg_msg->contract = *(data->contract);
197
198         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d\n",
199               reneg_msg->type, reneg_msg->req, reneg_msg->ss);
200
201         return sizeof(struct frescan_req_reneg_message_t);
202 }
203
204 static int frescan_reneg_message_to_request(const uint8_t *msg,
205                                             frescan_request_data_t *data)
206 {
207         struct frescan_req_reneg_message_t *reneg_msg;
208
209         reneg_msg = (struct frescan_req_reneg_message_t *)msg;
210
211         data->type        = FRESCAN_REQ_RENEG;
212         data->req         = reneg_msg->req;
213         data->ss          = reneg_msg->ss;
214         *(data->contract) = reneg_msg->contract;
215
216         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d\n",
217               data->type, data->req, data->ss);
218
219         return 0;
220 }
221
222 /**
223  *  FRESCAN_REQ_CANCEL MESSAGE
224  *  ==========================
225  *  This message is sent from a SLAVE to the MASTER to cancel a contract.
226  *  It contains the type, 'CANCEL' and the sporadic server id (the MASTER will
227  *  have to look it up in the table). The MASTER doesnt need to reply this
228  *  message.
229  *
230  *  +---------------+
231  *  | 'CANCEL' | SS |
232  *  +---------------+
233  *
234  */
235
236 struct frescan_req_cancel_message_t {
237         frescan_request_type_t   type;
238         frescan_ss_t             ss;
239 }  __attribute__ ((packed));
240
241 static int frescan_request_to_cancel_message(const frescan_request_data_t *data,
242                                              uint8_t *msg)
243 {
244         struct frescan_req_cancel_message_t *cancel_msg;
245
246         cancel_msg = (struct frescan_req_cancel_message_t *)msg;
247
248         cancel_msg->type     = FRESCAN_REQ_CANCEL;
249         cancel_msg->ss       = data->ss;
250
251         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d ss:%d\n",
252               cancel_msg->type, cancel_msg->ss);
253
254         return sizeof(struct frescan_req_cancel_message_t);
255 }
256
257 static int frescan_cancel_message_to_request(const uint8_t *msg,
258                                              frescan_request_data_t *data)
259 {
260         struct frescan_req_cancel_message_t *cancel_msg;
261
262         cancel_msg = (struct frescan_req_cancel_message_t *)msg;
263
264         data->type        = FRESCAN_REQ_CANCEL;
265         data->ss          = cancel_msg->ss;
266
267         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d ss:%d\n",
268               data->type, data->ss);
269
270         return 0;
271 }
272
273 /**
274  *
275  *  FRESCAN_REP_NEG MESSAGE
276  *  =======================
277  *  This message is sent from the MASTER to a slave as a reply to a
278  *  FRESCAN_REQ_NEG or a FRESCAN_REQ_RENEG, to say if they were admited.
279  *  It contains the type 'REPNEG', the request ID of the slave, a
280  *  return value to say if the contract is admited or not, and the final
281  *  values if it was admited
282  *
283  *  +----------------------------------------------+
284  *  | 'REPNEG' | REQ | RETURN_VALUE | FINAL_VALUES |
285  *  +----------------------------------------------+
286  *
287  */
288
289 struct frescan_rep_neg_message_t {
290         frescan_request_type_t    type;
291         frescan_request_id_t      req;
292         frescan_request_retval_t  return_value;
293         frescan_sa_final_values_t final_values;
294 }  __attribute__ ((packed));
295
296 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
297                                              uint8_t *msg)
298 {
299         struct frescan_rep_neg_message_t *repneg_msg;
300
301         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
302
303         repneg_msg->type         = FRESCAN_REP_NEG;
304         repneg_msg->req          = data->req;
305         repneg_msg->return_value = data->return_value;
306         repneg_msg->final_values = data->final_values;
307
308         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
309               repneg_msg->type, repneg_msg->req, repneg_msg->return_value);
310
311         return sizeof(struct frescan_rep_neg_message_t);
312 }
313
314 static int frescan_repneg_message_to_request(const uint8_t *msg,
315                                              frescan_request_data_t *data)
316 {
317         struct frescan_rep_neg_message_t *repneg_msg;
318
319         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
320
321         data->type         = FRESCAN_REP_NEG;
322         data->req          = repneg_msg->req;
323         data->return_value = repneg_msg->return_value;
324         data->final_values = repneg_msg->final_values;
325
326         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
327               data->type, data->req, data->return_value);
328
329         return 0;
330 }
331
332 /**
333  * frescan_messages_send_request()
334  *
335  * this function converts a request with the necessary data into a message
336  * and sends it.
337  *
338  * @req_data: the request to be sent (NOTE: the network is in req_data)
339  *
340  */
341
342 int frescan_messages_send_request(const frescan_request_data_t *req_data)
343 {
344         int ret;
345         uint8_t msg[2000]; // TODO: use a constant for max neg message size
346         size_t size;
347
348         switch(req_data->type) {
349                 case FRESCAN_REQ_NEG:
350                         size = frescan_request_to_neg_message(req_data, msg);
351                         send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
352                         break;
353                 case FRESCAN_REQ_RENEG:
354                         size = frescan_request_to_reneg_message(req_data, msg);
355                         send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
356                         break;
357                 case FRESCAN_REQ_CANCEL:
358                         size = frescan_request_to_cancel_message(req_data, msg);
359                         send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
360                         break;
361                 case FRESCAN_REP_NEG:
362                         size = frescan_request_to_repneg_message(req_data, msg);
363                         send_params[req_data->net].to = req_data->request_node;
364                         break;
365                 default:
366                         ERROR("request type not supported\n");
367                         return -1;
368         }
369
370         ret = frescan_send(&send_params[req_data->net], msg, size);
371         if (ret != 0) return ret;
372
373         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "sent request, type:%X size:%d\n",
374               *(frescan_request_type_t *)msg, size);
375
376         return 0;
377 }
378
379 /**
380  * frescan_messages_recv_request()
381  *
382  * this function BLOCKS the calling thread until receives a message
383  * and transforms it into a request.
384  *
385  * @req_data: the request data to fill from the message bytes (out)
386  *
387  */
388
389 int frescan_messages_recv_request(frescan_network_t    net,
390                                   frescan_request_id_t *req)
391 {
392         int ret;
393         uint8_t msg[2000]; // TODO: use a constant with the max neg message size
394         size_t recv_bytes;
395         frescan_node_t from;
396         frescan_prio_t prio;
397         frescan_request_data_t *req_data;
398
399         ret = frescan_requests_alloc(req);
400         if (ret != 0) return ret;
401
402         ret = frescan_requests_get_data(*req, &req_data);
403         if (ret != 0) return ret;
404
405         ret = frescan_recv(&recv_params[net],
406                             msg,
407                             sizeof(msg),
408                             &recv_bytes,
409                             &from,
410                             &prio);
411         if (ret != 0) return ret;
412
413         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG,
414               "msg received! from:%u size:%u prio:%u chan:%u flags:%X\n",
415               from, recv_bytes, prio, recv_params[net].channel,
416               recv_params[net].flags);
417
418         req_data->request_node = from;
419         req_data->net = net;
420
421         switch(*((frescan_request_type_t *)msg)) {
422                 case FRESCAN_REQ_NEG:
423                         return frescan_neg_message_to_request(msg, req_data);
424                 case FRESCAN_REQ_RENEG:
425                         return frescan_reneg_message_to_request(msg, req_data);
426                 case FRESCAN_REQ_CANCEL:
427                         return frescan_cancel_message_to_request(msg, req_data);
428                 case FRESCAN_REP_NEG:
429                         return frescan_repneg_message_to_request(msg, req_data);
430                 default:
431                         ERROR("request type %X not supported\n",
432                               *(frescan_request_type_t *)msg);
433                         return -1;
434         }
435 }