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_INC_BUDGET / FRESCAN_REP_DEC_BUDGET
320 * ===============================================
321 * This message is sent from the MASTER to a slave when there is a change
322 * in the budget value assigned by the spare capacity algorithm.
324 * +---------------------------------------------------+
325 * | 'INC/DEC' | SS | NEW_B | SS | NEW_B | SS | NEW_B |
326 * +---------------------------------------------------+
330 static int frescan_request_to_repchange_message
331 (const frescan_request_data_t *data, uint8_t *msg)
334 struct list_head *the_mode_change_list;
335 frescan_sa_vres_t *vres;
338 if (data->type == FRESCAN_REP_INC_BUDGET) {
339 the_mode_change_list = &the_networks[data->net].
340 mode_change_budget_inc_list_head
341 [data->request_node];
343 the_mode_change_list = &the_networks[data->net].
344 mode_change_budget_dec_list_head
345 [data->request_node];
348 if (list_empty(the_mode_change_list)) {
349 return 0; // nothing to send
354 *((frescan_request_type_t *)msg) = data->type;
355 bytes_written = sizeof(frescan_request_type_t);
356 msg = msg + bytes_written;
358 list_for_each_entry(vres,
359 the_mode_change_list,
362 *((frescan_ss_t *)msg) = vres->ss;
363 bytes_written = sizeof(frescan_ss_t);
364 msg = msg + bytes_written;
366 *((frsh_sa_time_t *)msg) = vres->old_c;
367 bytes_written = sizeof(frsh_sa_time_t);
368 msg = msg + bytes_written;
371 return (msg - msg_begin);
374 static int frescan_repchange_message_to_request(const uint8_t *msg,
375 frescan_request_data_t *data,
378 struct list_head *the_mode_change_list;
379 frescan_node_t me = the_networks[data->net].local_node;
380 frescan_sa_vres_t *vres;
382 uint8_t *msg_pointer;
385 data->type = *((frescan_request_type_t *)msg);
387 if (data->type == FRESCAN_REP_INC_BUDGET) {
388 the_mode_change_list = &the_networks[data->net].
389 mode_change_budget_inc_list_head[me];
391 the_mode_change_list = &the_networks[data->net].
392 mode_change_budget_dec_list_head[me];
395 INIT_LIST_HEAD(the_mode_change_list);
397 msg_pointer = (uint8_t *)msg;
399 while(msg_pointer < msg + size) {
400 ss = *((frescan_ss_t *)msg_pointer);
401 bytes_read = sizeof(frescan_ss_t);
402 msg_pointer = msg_pointer + bytes_read;
404 vres = &the_networks[data->net].scenario.vres_pool[me][ss];
406 vres->old_c = *((frsh_sa_time_t *)msg_pointer);
407 bytes_read = sizeof(frsh_sa_time_t);
408 msg_pointer = msg_pointer + bytes_read;
416 * FRESCAN_REP_NEG MESSAGE
417 * =======================
418 * This message is sent from the MASTER to a slave as a reply to a
419 * FRESCAN_REQ_NEG or a FRESCAN_REQ_RENEG, to say if they were admited.
420 * It contains the type 'REPNEG', the request ID of the slave, a
421 * return value to say if the contract is admited or not, and the final
422 * values if it was admited
424 * +-------------------------------------------+
425 * | 'REPNEG' | REQ | RET_VALUE | FINAL_VALUES | + FRESCAN_REP_INC/DEC_BUDGET
426 * +-------------------------------------------+
430 struct frescan_rep_neg_message_t {
431 frescan_request_type_t type;
432 frescan_request_id_t req;
433 frescan_request_retval_t return_value;
434 frescan_server_params_t final_values;
435 } __attribute__ ((packed));
437 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
440 struct frescan_rep_neg_message_t *repneg_msg;
442 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
444 repneg_msg->type = FRESCAN_REP_NEG;
445 repneg_msg->req = data->req;
446 repneg_msg->return_value = data->return_value;
447 repneg_msg->final_values = data->final_values;
449 if (data->return_value == FRESCAN_REQ_ACCEPTED) {
453 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
454 repneg_msg->type, repneg_msg->req, repneg_msg->return_value);
456 return sizeof(struct frescan_rep_neg_message_t);
459 static int frescan_repneg_message_to_request(const uint8_t *msg,
460 frescan_request_data_t *data)
462 struct frescan_rep_neg_message_t *repneg_msg;
464 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
466 data->type = FRESCAN_REP_NEG;
467 data->req = repneg_msg->req;
468 data->return_value = repneg_msg->return_value;
469 // TODO: use final values only if it was accepted!
470 data->final_values = repneg_msg->final_values;
472 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "type:%d req:%d ret:%d\n",
473 data->type, data->req, data->return_value);
479 * frescan_messages_send_request()
481 * this function converts a request with the necessary data into a message
484 * @req_data: the request to be sent (NOTE: the network is in req_data)
488 int frescan_messages_send_request(const frescan_request_data_t *req_data)
491 uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
494 switch(req_data->type) {
495 case FRESCAN_REQ_NEG:
496 size = frescan_request_to_neg_message(req_data, msg);
497 send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
499 case FRESCAN_REQ_RENEG:
500 size = frescan_request_to_reneg_message(req_data, msg);
501 send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
503 case FRESCAN_REQ_CANCEL:
504 size = frescan_request_to_cancel_message(req_data, msg);
505 send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
507 case FRESCAN_REP_DEC_BUDGET:
508 case FRESCAN_REP_INC_BUDGET:
509 size = frescan_request_to_repchange_message
511 send_params[req_data->net].to = req_data->request_node;
513 case FRESCAN_REP_NEG:
514 size = frescan_request_to_repneg_message(req_data, msg);
515 send_params[req_data->net].to = req_data->request_node;
518 FRESCAN_ERROR("request type not supported\n");
522 ret = frescan_send(&send_params[req_data->net], msg, size);
523 if (ret != 0) return ret;
525 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "sent request, type:%X size:%d\n",
526 *(frescan_request_type_t *)msg, size);
532 * frescan_messages_recv_request()
534 * this function BLOCKS the calling thread until receives a message
535 * and transforms it into a request.
537 * @req_data: the request data to fill from the message bytes (out)
541 int frescan_messages_recv_request(frescan_network_t net,
542 frescan_request_id_t *req)
545 uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
549 frescan_request_data_t *req_data;
551 ret = frescan_requests_alloc(req);
552 if (ret != 0) return ret;
554 ret = frescan_requests_get_data(*req, &req_data);
555 if (ret != 0) return ret;
557 ret = frescan_recv(&recv_params[net],
563 if (ret != 0) return ret;
565 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG,
566 "msg received! from:%u size:%u prio:%u chan:%u flags:%X\n",
567 from, recv_bytes, prio, recv_params[net].channel,
568 recv_params[net].flags);
570 req_data->request_node = from;
573 switch(*((frescan_request_type_t *)msg)) {
574 case FRESCAN_REQ_NEG:
575 return frescan_neg_message_to_request(msg,
578 case FRESCAN_REQ_RENEG:
579 return frescan_reneg_message_to_request(msg,
582 case FRESCAN_REQ_CANCEL:
583 return frescan_cancel_message_to_request(msg, req_data);
584 case FRESCAN_REP_DEC_BUDGET:
585 case FRESCAN_REP_INC_BUDGET:
586 return frescan_repchange_message_to_request(msg,
589 case FRESCAN_REP_NEG:
590 return frescan_repneg_message_to_request(msg, req_data);
592 FRESCAN_ERROR("request type %X not supported\n",
593 *(frescan_request_type_t *)msg);