]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_messages.c
changes to use the FRSH FSA module to do the analysis and spare capacity. TODO: finis...
[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 #define FRESCAN_BWRES_MX_MSG_SIZE 3000  // TODO: adjust to the minimum
76
77 /**
78  * frescan_messages_init()
79  */
80
81 static frescan_send_params_t send_params[FRESCAN_MX_NETWORKS];
82 static frescan_recv_params_t recv_params[FRESCAN_MX_NETWORKS];
83
84 int frescan_messages_init(frescan_network_t net)
85 {
86         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "initialization\n");
87
88         send_params[net].net     = net;
89         send_params[net].channel = FRESCAN_NEG_CHANNEL;
90         send_params[net].flags   = FRESCAN_SS | FRESCAN_ASYNC;
91         send_params[net].ss      = the_networks[net].neg_messages_ss_id;
92         send_params[net].to      = FRESCAN_NEG_MASTER_NODE;
93
94         recv_params[net].net     = net;
95         recv_params[net].channel = FRESCAN_NEG_CHANNEL;
96         recv_params[net].flags   = FRESCAN_SYNC;
97
98         return 0;
99 }
100
101 /**
102  *
103  *  FRESCAN_REQ_NEG MESSAGE
104  *  =======================
105  *  This message is sent from a SLAVE to the MASTER when the slave wants
106  *  to negotiate a new contract. It contains the type (a negotiation 'NEG'
107  *  request), the LOCAL request id (so the MASTER can use it in the reply
108  *  to identify to which request is replying), a preallocated sporadic
109  *  server id (the MASTER will store it in its table together with the
110  *  node so we can perform renegotiations and spare capacity distribution
111  *  in the future) and the contract.
112  *
113  *      1     2     2      N
114  *  +-----------------------------+
115  *  | 'NEG' | REQ | SS | CONTRACT |
116  *  +-----------------------------+
117  *
118  */
119
120 struct frescan_req_neg_message_t {
121         frescan_request_type_t   type;
122         frescan_request_id_t     req;
123         frescan_ss_t             ss;
124 }  __attribute__ ((packed));
125
126 static int frescan_request_to_neg_message(const frescan_request_data_t *data,
127                                           uint8_t *msg)
128 {
129         int ret;
130         struct frescan_req_neg_message_t *neg_msg;
131         size_t req_size, contract_size;
132
133         neg_msg = (struct frescan_req_neg_message_t *)msg;
134         req_size = sizeof(struct frescan_req_neg_message_t);
135
136         neg_msg->type     = FRESCAN_REQ_NEG;
137         neg_msg->req      = data->req;
138         neg_msg->ss       = data->ss;
139
140         ret = frsh_contract_marshal(data->contract,
141                                     msg + req_size,
142                                     FRESCAN_BWRES_MX_MSG_SIZE - req_size,
143                                     &contract_size);
144         if (ret != 0) {
145                 FRESCAN_ERROR("frsh_contract_marshal return -1\n");
146                 return -1;
147         }
148
149         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d csize:%u\n",
150               neg_msg->type, neg_msg->req, neg_msg->ss, contract_size);
151
152         return req_size + contract_size;
153 }
154
155 static int frescan_neg_message_to_request(const uint8_t *msg,
156                                           frescan_request_data_t *data,
157                                           size_t size)
158 {
159         int ret;
160         struct frescan_req_neg_message_t *neg_msg;
161         size_t req_size;
162
163         neg_msg = (struct frescan_req_neg_message_t *)msg;
164         req_size = sizeof(struct frescan_req_neg_message_t);
165
166         data->type        = FRESCAN_REQ_NEG;
167         data->req         = neg_msg->req;
168         data->ss          = neg_msg->ss;
169
170         ret = frsh_contract_unmarshal(data->contract,
171                                       msg  + req_size,  // pointer to contract
172                                       size - req_size); // size marshal '   '
173         if (ret != 0) {
174                 FRESCAN_ERROR("frsh_contract_unmarshal return -1\n");
175                 return -1;
176         }
177
178         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d\n",
179               data->type, data->req, data->ss);
180
181         return 0;
182 }
183
184 /**
185  *
186  *  FRESCAN_REQ_RENEG MESSAGE
187  *  =========================
188  *  This message is sent from a SLAVE to the MASTER when the slave wants
189  *  to renegotiate a contract. It contains the type (a renegotiation 'RENEG'
190  *  request), the LOCAL request id (so the MASTER can use it in the reply
191  *  to identify to which request is replying), the sporadic server id
192  *  (the MASTER will look up its table together with the node to find the
193  *  appropiate entry) and the contract.
194  *
195  *      1       2     2      N
196  *  +-------------------------------+
197  *  | 'RENEG' | REQ | SS | CONTRACT |
198  *  +-------------------------------+
199  *
200  */
201
202 struct frescan_req_reneg_message_t {
203         frescan_request_type_t   type;
204         frescan_request_id_t     req;
205         frescan_ss_t             ss;
206 }  __attribute__ ((packed));
207
208 static int frescan_request_to_reneg_message(const frescan_request_data_t *data,
209                                             uint8_t *msg)
210 {
211         int ret;
212         size_t req_size, contract_size;
213         struct frescan_req_reneg_message_t *reneg_msg;
214
215         reneg_msg = (struct frescan_req_reneg_message_t *)msg;
216         req_size = sizeof(struct frescan_req_reneg_message_t);
217
218         reneg_msg->type     = FRESCAN_REQ_RENEG;
219         reneg_msg->req      = data->req;
220         reneg_msg->ss       = data->ss;
221
222         ret = frsh_contract_marshal(data->contract,
223                                     msg + req_size,
224                                     FRESCAN_BWRES_MX_MSG_SIZE - req_size,
225                                     &contract_size);
226         if (ret != 0) {
227                 FRESCAN_ERROR("frsh_contract_marshal return -1\n");
228                 return -1;
229         }
230
231         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d csize:%u\n",
232               reneg_msg->type, reneg_msg->req, reneg_msg->ss, contract_size);
233
234         return req_size + contract_size;
235 }
236
237 static int frescan_reneg_message_to_request(const uint8_t *msg,
238                                             frescan_request_data_t *data,
239                                             size_t size)
240 {
241         int ret;
242         struct frescan_req_reneg_message_t *reneg_msg;
243         size_t req_size;
244
245         reneg_msg = (struct frescan_req_reneg_message_t *)msg;
246         req_size = sizeof(struct frescan_req_neg_message_t);
247
248         data->type        = FRESCAN_REQ_RENEG;
249         data->req         = reneg_msg->req;
250         data->ss          = reneg_msg->ss;
251
252         ret = frsh_contract_unmarshal(data->contract,
253                                       msg  + req_size,
254                                       size - req_size);
255         if (ret != 0) {
256                 FRESCAN_ERROR("frsh_contract_unmarshal return -1\n");
257                 return -1;
258         }
259
260         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d\n",
261               data->type, data->req, data->ss);
262
263         return 0;
264 }
265
266 /**
267  *  FRESCAN_REQ_CANCEL MESSAGE
268  *  ==========================
269  *  This message is sent from a SLAVE to the MASTER to cancel a contract.
270  *  It contains the type, 'CANCEL' and the sporadic server id (the MASTER will
271  *  have to look it up in the table). The MASTER doesnt need to reply this
272  *  message.
273  *
274  *  +---------------+
275  *  | 'CANCEL' | SS |
276  *  +---------------+
277  *
278  */
279
280 struct frescan_req_cancel_message_t {
281         frescan_request_type_t   type;
282         frescan_ss_t             ss;
283 }  __attribute__ ((packed));
284
285 static int frescan_request_to_cancel_message(const frescan_request_data_t *data,
286                                              uint8_t *msg)
287 {
288         struct frescan_req_cancel_message_t *cancel_msg;
289
290         cancel_msg = (struct frescan_req_cancel_message_t *)msg;
291
292         cancel_msg->type     = FRESCAN_REQ_CANCEL;
293         cancel_msg->ss       = data->ss;
294
295         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d ss:%d\n",
296               cancel_msg->type, cancel_msg->ss);
297
298         return sizeof(struct frescan_req_cancel_message_t);
299 }
300
301 static int frescan_cancel_message_to_request(const uint8_t *msg,
302                                              frescan_request_data_t *data)
303 {
304         struct frescan_req_cancel_message_t *cancel_msg;
305
306         cancel_msg = (struct frescan_req_cancel_message_t *)msg;
307
308         data->type        = FRESCAN_REQ_CANCEL;
309         data->ss          = cancel_msg->ss;
310
311         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d ss:%d\n",
312               data->type, data->ss);
313
314         return 0;
315 }
316
317 /**
318  *
319  *  FRESCAN_REP_CHANGE MESSAGE
320  *  ==========================
321  *  This message is sent from the MASTER to a slave as a reply to a
322  *  FRESCAN_REQ_NEG or a FRESCAN_REQ_RENEG, to say if they were admited.
323  *  It contains the type 'REPNEG', the request ID of the slave, a
324  *  return value to say if the contract is admited or not, and the final
325  *  values if it was admited
326  *
327  *  +----------------------------------------------+
328  *  | 'REPNEG' | REQ | RETURN_VALUE | FINAL_VALUES |
329  *  +----------------------------------------------+
330  *
331  */
332
333 struct frescan_rep_neg_message_t {
334         frescan_request_type_t    type;
335         frescan_request_id_t      req;
336         frescan_request_retval_t  return_value;
337         frescan_server_params_t   final_values;
338 }  __attribute__ ((packed));
339
340 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
341                                              uint8_t *msg)
342 {
343         struct frescan_rep_neg_message_t *repneg_msg;
344
345         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
346
347         repneg_msg->type         = FRESCAN_REP_NEG;
348         repneg_msg->req          = data->req;
349         repneg_msg->return_value = data->return_value;
350         repneg_msg->final_values = data->final_values;
351
352         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
353               repneg_msg->type, repneg_msg->req, repneg_msg->return_value);
354
355         return sizeof(struct frescan_rep_neg_message_t);
356 }
357
358 static int frescan_repneg_message_to_request(const uint8_t *msg,
359                                              frescan_request_data_t *data)
360 {
361         struct frescan_rep_neg_message_t *repneg_msg;
362
363         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
364
365         data->type         = FRESCAN_REP_NEG;
366         data->req          = repneg_msg->req;
367         data->return_value = repneg_msg->return_value;
368         data->final_values = repneg_msg->final_values;
369
370         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
371               data->type, data->req, data->return_value);
372
373         return 0;
374 }
375
376 /**
377  *
378  *  FRESCAN_REP_NEG MESSAGE
379  *  =======================
380  *  This message is sent from the MASTER to a slave as a reply to a
381  *  FRESCAN_REQ_NEG or a FRESCAN_REQ_RENEG, to say if they were admited.
382  *  It contains the type 'REPNEG', the request ID of the slave, a
383  *  return value to say if the contract is admited or not, and the final
384  *  values if it was admited
385  *
386  *  +----------------------------------------------+
387  *  | 'REPNEG' | REQ | RETURN_VALUE | FINAL_VALUES |
388  *  +----------------------------------------------+
389  *
390  */
391
392 struct frescan_rep_neg_message_t {
393         frescan_request_type_t    type;
394         frescan_request_id_t      req;
395         frescan_request_retval_t  return_value;
396         frescan_server_params_t   final_values;
397 }  __attribute__ ((packed));
398
399 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
400                                              uint8_t *msg)
401 {
402         struct frescan_rep_neg_message_t *repneg_msg;
403
404         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
405
406         repneg_msg->type         = FRESCAN_REP_NEG;
407         repneg_msg->req          = data->req;
408         repneg_msg->return_value = data->return_value;
409         // TODO: use final values only if it was accepted!
410         repneg_msg->final_values = data->final_values;
411
412         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
413               repneg_msg->type, repneg_msg->req, repneg_msg->return_value);
414
415         return sizeof(struct frescan_rep_neg_message_t);
416 }
417
418 static int frescan_repneg_message_to_request(const uint8_t *msg,
419                                              frescan_request_data_t *data)
420 {
421         struct frescan_rep_neg_message_t *repneg_msg;
422
423         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
424
425         data->type         = FRESCAN_REP_NEG;
426         data->req          = repneg_msg->req;
427         data->return_value = repneg_msg->return_value;
428         // TODO: use final values only if it was accepted!
429         data->final_values = repneg_msg->final_values;
430
431         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
432               data->type, data->req, data->return_value);
433
434         return 0;
435 }
436
437 /**
438  * frescan_messages_send_request()
439  *
440  * this function converts a request with the necessary data into a message
441  * and sends it.
442  *
443  * @req_data: the request to be sent (NOTE: the network is in req_data)
444  *
445  */
446
447 int frescan_messages_send_request(const frescan_request_data_t *req_data)
448 {
449         int ret;
450         uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
451         size_t size;
452
453         switch(req_data->type) {
454                 case FRESCAN_REQ_NEG:
455                         size = frescan_request_to_neg_message(req_data, msg);
456                         send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
457                         break;
458                 case FRESCAN_REQ_RENEG:
459                         size = frescan_request_to_reneg_message(req_data, msg);
460                         send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
461                         break;
462                 case FRESCAN_REQ_CANCEL:
463                         size = frescan_request_to_cancel_message(req_data, msg);
464                         send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
465                         break;
466                 case FRESCAN_REP_CHANGE:
467                         size = frescan_request_to_repchange_message(req_data, msg);
468                         send_params[req_data->net].to = req_data->request_node;
469                         break;
470                 case FRESCAN_REP_NEG:
471                         size = frescan_request_to_repneg_message(req_data, msg);
472                         send_params[req_data->net].to = req_data->request_node;
473                         break;
474                 default:
475                         FRESCAN_ERROR("request type not supported\n");
476                         return -1;
477         }
478
479         ret = frescan_send(&send_params[req_data->net], msg, size);
480         if (ret != 0) return ret;
481
482         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "sent request, type:%X size:%d\n",
483               *(frescan_request_type_t *)msg, size);
484
485         return 0;
486 }
487
488 /**
489  * frescan_messages_recv_request()
490  *
491  * this function BLOCKS the calling thread until receives a message
492  * and transforms it into a request.
493  *
494  * @req_data: the request data to fill from the message bytes (out)
495  *
496  */
497
498 int frescan_messages_recv_request(frescan_network_t    net,
499                                   frescan_request_id_t *req)
500 {
501         int ret;
502         uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
503         size_t recv_bytes;
504         frescan_node_t from;
505         frescan_prio_t prio;
506         frescan_request_data_t *req_data;
507
508         ret = frescan_requests_alloc(req);
509         if (ret != 0) return ret;
510
511         ret = frescan_requests_get_data(*req, &req_data);
512         if (ret != 0) return ret;
513
514         ret = frescan_recv(&recv_params[net],
515                             msg,
516                             sizeof(msg),
517                             &recv_bytes,
518                             &from,
519                             &prio);
520         if (ret != 0) return ret;
521
522         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG,
523               "msg received! from:%u size:%u prio:%u chan:%u flags:%X\n",
524               from, recv_bytes, prio, recv_params[net].channel,
525               recv_params[net].flags);
526
527         req_data->request_node = from;
528         req_data->net = net;
529
530         switch(*((frescan_request_type_t *)msg)) {
531                 case FRESCAN_REQ_NEG:
532                         return frescan_neg_message_to_request(msg,
533                                                               req_data,
534                                                               recv_bytes);
535                 case FRESCAN_REQ_RENEG:
536                         return frescan_reneg_message_to_request(msg,
537                                                                 req_data,
538                                                                 recv_bytes);
539                 case FRESCAN_REQ_CANCEL:
540                         return frescan_cancel_message_to_request(msg, req_data);
541                 case FRESCAN_REP_CHANGE:
542                         return frescan_repchange_message_to_request(msg, req_data);
543                 case FRESCAN_REP_NEG:
544                         return frescan_repneg_message_to_request(msg, req_data);
545                 default:
546                         FRESCAN_ERROR("request type %X not supported\n",
547                               *(frescan_request_type_t *)msg);
548                         return -1;
549         }
550 }