2 * @file frescan_bwres_messages.c
4 * @brief FRESCAN bandwidth reservation layer: negotiation messages formating
6 * This module contains the data types that define the FRESCAN negotiation
7 * message format and operations to convert them into or from negotiation
14 * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
18 * -----------------------------------------------------------------------
19 * Copyright (C) 2006 - 2008 FRESCOR consortium partners:
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
28 * Thales Communication S.A. FRANCE
29 * Visual Tools S.A. SPAIN
30 * Rapita Systems Ltd UK
33 * See http://www.frescor.org for a link to partners' websites
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
40 * This file is part of FRESCAN
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)
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.
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
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 * -----------------------------------------------------------------------
69 #include "frescan_bwres_messages.h"
70 #include "frescan_bwres_requests.h"
72 #include "frescan_config.h"
73 #include "frescan_debug.h"
75 #define FRESCAN_BWRES_MX_MSG_SIZE 3000 // TODO: adjust to the minimum
78 * frescan_messages_init()
81 static frescan_send_params_t send_params[FRESCAN_MX_NETWORKS];
82 static frescan_recv_params_t recv_params[FRESCAN_MX_NETWORKS];
84 int frescan_messages_init(frescan_network_t net)
86 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "initialization\n");
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;
94 recv_params[net].net = net;
95 recv_params[net].channel = FRESCAN_NEG_CHANNEL;
96 recv_params[net].flags = FRESCAN_SYNC;
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.
114 * +-----------------------------+
115 * | 'NEG' | REQ | SS | CONTRACT |
116 * +-----------------------------+
120 struct frescan_req_neg_message_t {
121 frescan_request_type_t type;
122 frescan_request_id_t req;
124 } __attribute__ ((packed));
126 static int frescan_request_to_neg_message(const frescan_request_data_t *data,
130 struct frescan_req_neg_message_t *neg_msg;
131 size_t req_size, contract_size;
133 neg_msg = (struct frescan_req_neg_message_t *)msg;
134 req_size = sizeof(struct frescan_req_neg_message_t);
136 neg_msg->type = FRESCAN_REQ_NEG;
137 neg_msg->req = data->req;
138 neg_msg->ss = data->ss;
140 ret = frsh_contract_marshal(data->contract,
142 FRESCAN_BWRES_MX_MSG_SIZE - req_size,
145 FRESCAN_ERROR("frsh_contract_marshal return -1\n");
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);
152 return req_size + contract_size;
155 static int frescan_neg_message_to_request(const uint8_t *msg,
156 frescan_request_data_t *data,
160 struct frescan_req_neg_message_t *neg_msg;
163 neg_msg = (struct frescan_req_neg_message_t *)msg;
164 req_size = sizeof(struct frescan_req_neg_message_t);
166 data->type = FRESCAN_REQ_NEG;
167 data->req = neg_msg->req;
168 data->ss = neg_msg->ss;
170 ret = frsh_contract_unmarshal(data->contract,
171 msg + req_size, // pointer to contract
172 size - req_size); // size marshal ' '
174 FRESCAN_ERROR("frsh_contract_unmarshal return -1\n");
178 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d\n",
179 data->type, data->req, data->ss);
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.
196 * +-------------------------------+
197 * | 'RENEG' | REQ | SS | CONTRACT |
198 * +-------------------------------+
202 struct frescan_req_reneg_message_t {
203 frescan_request_type_t type;
204 frescan_request_id_t req;
206 } __attribute__ ((packed));
208 static int frescan_request_to_reneg_message(const frescan_request_data_t *data,
212 size_t req_size, contract_size;
213 struct frescan_req_reneg_message_t *reneg_msg;
215 reneg_msg = (struct frescan_req_reneg_message_t *)msg;
216 req_size = sizeof(struct frescan_req_reneg_message_t);
218 reneg_msg->type = FRESCAN_REQ_RENEG;
219 reneg_msg->req = data->req;
220 reneg_msg->ss = data->ss;
222 ret = frsh_contract_marshal(data->contract,
224 FRESCAN_BWRES_MX_MSG_SIZE - req_size,
227 FRESCAN_ERROR("frsh_contract_marshal return -1\n");
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);
234 return req_size + contract_size;
237 static int frescan_reneg_message_to_request(const uint8_t *msg,
238 frescan_request_data_t *data,
242 struct frescan_req_reneg_message_t *reneg_msg;
245 reneg_msg = (struct frescan_req_reneg_message_t *)msg;
246 req_size = sizeof(struct frescan_req_neg_message_t);
248 data->type = FRESCAN_REQ_RENEG;
249 data->req = reneg_msg->req;
250 data->ss = reneg_msg->ss;
252 ret = frsh_contract_unmarshal(data->contract,
256 FRESCAN_ERROR("frsh_contract_unmarshal return -1\n");
260 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ss:%d\n",
261 data->type, data->req, data->ss);
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
280 struct frescan_req_cancel_message_t {
281 frescan_request_type_t type;
283 } __attribute__ ((packed));
285 static int frescan_request_to_cancel_message(const frescan_request_data_t *data,
288 struct frescan_req_cancel_message_t *cancel_msg;
290 cancel_msg = (struct frescan_req_cancel_message_t *)msg;
292 cancel_msg->type = FRESCAN_REQ_CANCEL;
293 cancel_msg->ss = data->ss;
295 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d ss:%d\n",
296 cancel_msg->type, cancel_msg->ss);
298 return sizeof(struct frescan_req_cancel_message_t);
301 static int frescan_cancel_message_to_request(const uint8_t *msg,
302 frescan_request_data_t *data)
304 struct frescan_req_cancel_message_t *cancel_msg;
306 cancel_msg = (struct frescan_req_cancel_message_t *)msg;
308 data->type = FRESCAN_REQ_CANCEL;
309 data->ss = cancel_msg->ss;
311 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d ss:%d\n",
312 data->type, data->ss);
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
327 * +----------------------------------------------+
328 * | 'REPNEG' | REQ | RETURN_VALUE | FINAL_VALUES |
329 * +----------------------------------------------+
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));
340 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
343 struct frescan_rep_neg_message_t *repneg_msg;
345 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
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;
352 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
353 repneg_msg->type, repneg_msg->req, repneg_msg->return_value);
355 return sizeof(struct frescan_rep_neg_message_t);
358 static int frescan_repneg_message_to_request(const uint8_t *msg,
359 frescan_request_data_t *data)
361 struct frescan_rep_neg_message_t *repneg_msg;
363 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
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;
370 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
371 data->type, data->req, data->return_value);
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
386 * +----------------------------------------------+
387 * | 'REPNEG' | REQ | RETURN_VALUE | FINAL_VALUES |
388 * +----------------------------------------------+
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));
399 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
402 struct frescan_rep_neg_message_t *repneg_msg;
404 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
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;
412 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
413 repneg_msg->type, repneg_msg->req, repneg_msg->return_value);
415 return sizeof(struct frescan_rep_neg_message_t);
418 static int frescan_repneg_message_to_request(const uint8_t *msg,
419 frescan_request_data_t *data)
421 struct frescan_rep_neg_message_t *repneg_msg;
423 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
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;
431 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
432 data->type, data->req, data->return_value);
438 * frescan_messages_send_request()
440 * this function converts a request with the necessary data into a message
443 * @req_data: the request to be sent (NOTE: the network is in req_data)
447 int frescan_messages_send_request(const frescan_request_data_t *req_data)
450 uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
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;
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;
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;
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;
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;
475 FRESCAN_ERROR("request type not supported\n");
479 ret = frescan_send(&send_params[req_data->net], msg, size);
480 if (ret != 0) return ret;
482 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "sent request, type:%X size:%d\n",
483 *(frescan_request_type_t *)msg, size);
489 * frescan_messages_recv_request()
491 * this function BLOCKS the calling thread until receives a message
492 * and transforms it into a request.
494 * @req_data: the request data to fill from the message bytes (out)
498 int frescan_messages_recv_request(frescan_network_t net,
499 frescan_request_id_t *req)
502 uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
506 frescan_request_data_t *req_data;
508 ret = frescan_requests_alloc(req);
509 if (ret != 0) return ret;
511 ret = frescan_requests_get_data(*req, &req_data);
512 if (ret != 0) return ret;
514 ret = frescan_recv(&recv_params[net],
520 if (ret != 0) return ret;
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);
527 req_data->request_node = from;
530 switch(*((frescan_request_type_t *)msg)) {
531 case FRESCAN_REQ_NEG:
532 return frescan_neg_message_to_request(msg,
535 case FRESCAN_REQ_RENEG:
536 return frescan_reneg_message_to_request(msg,
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);
546 FRESCAN_ERROR("request type %X not supported\n",
547 *(frescan_request_type_t *)msg);