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_data.h"
73 #include "frescan_config.h"
74 #include "frescan_debug.h"
75 #include "frsh_distributed.h"
77 #define FRESCAN_BWRES_MX_MSG_SIZE 5000 // TODO: adjust to the accurate value
80 * frescan_messages_init()
83 static frescan_send_params_t send_params[FRESCAN_MX_NETWORKS];
84 static frescan_recv_params_t recv_params[FRESCAN_MX_NETWORKS];
86 int frescan_messages_init(frescan_network_t net)
88 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "initialization\n");
90 send_params[net].net = net;
91 send_params[net].channel = FRESCAN_BWRES_NEG_CHANNEL;
92 send_params[net].flags = FRESCAN_SS | FRESCAN_ASYNC;
93 send_params[net].ss = frescan_data[net].neg_messages_ss_id;
94 send_params[net].to = FRESCAN_BWRES_MASTER_NODE;
96 recv_params[net].net = net;
97 recv_params[net].channel = FRESCAN_BWRES_NEG_CHANNEL;
98 recv_params[net].flags = FRESCAN_SYNC;
104 * FRESCAN_BWRES_REQ_GN
105 * ====================
106 * This message is sent from a SLAVE to the MASTER when the slave wants
107 * to make a negotiation (including creating new vres, renegotiations and
111 static int frescan_request_to_gn_message
112 (const frescan_bwres_request_data_t *data,
117 uint8_t *msg_begin, *msg_tmp;
118 size_t bytes_written;
122 // type: FRESCAN_GN_MESSAGE
123 *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REQ_GN;
124 bytes_written = sizeof(uint8_t);
125 msg = msg + bytes_written;
128 *((frescan_bwres_request_id_t *)msg) = data->req;
129 bytes_written = sizeof(frescan_bwres_request_id_t);
130 msg = msg + bytes_written;
132 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
133 "GN message req:%u\n", data->req);
136 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
137 "NEG-GROUP num contracts:%u\n", data->contracts_to_neg->size);
139 *((uint8_t *)msg) = (uint8_t)data->contracts_to_neg->size;
140 bytes_written = sizeof(uint8_t);
141 msg = msg + bytes_written;
143 for (i=0; i<data->contracts_to_neg->size; i++) {
144 // reserve 2 bytes for the size of the marshalled contract
146 msg = msg + sizeof(uint16_t);
147 // marshal the contract
148 ret = frsh_contract_marshal
149 (&data->contracts_to_neg->contracts[i],
151 FRESCAN_BWRES_MX_MSG_SIZE - (msg - msg_begin),
154 FRESCAN_ERROR("frsh_contract_marshal return -1\n");
157 // write the size and update the message pointer msg
158 *((uint16_t *)msg_tmp) = (uint16_t)bytes_written;
159 msg = msg + bytes_written;
161 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
162 "contract[%d].size:%u\n", i, bytes_written);
166 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
167 "RENEG-GROUP num contracts:%u\n",data->contracts_to_reneg->size);
169 *((uint8_t *)msg) = (uint8_t)data->contracts_to_reneg->size;
170 bytes_written = sizeof(uint8_t);
171 msg = msg + bytes_written;
173 for (i=0; i<data->contracts_to_reneg->size; i++) {
175 *((uint16_t *)msg) = (uint16_t)data->ss_to_reneg->ss[i];
176 bytes_written = sizeof(uint16_t);
177 msg = msg + bytes_written;
178 // reserve 2 bytes for the size of the marshalled contract
180 msg = msg + sizeof(uint16_t);
181 // marshal the contract
182 ret = frsh_contract_marshal
183 (&data->contracts_to_reneg->contracts[i],
185 FRESCAN_BWRES_MX_MSG_SIZE - (msg - msg_begin),
188 FRESCAN_ERROR("frsh_contract_marshal return -1\n");
191 // write the size and update the message pointer msg
192 *((uint16_t *)msg_tmp) = (uint16_t)bytes_written;
193 msg = msg + bytes_written;
195 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
196 "contract[%d].size:%u ss[%d]:%u\n",
197 i, bytes_written, i, data->ss_to_reneg->ss[i]);
201 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "CANCEL-GROUP num ss:%u\n",
202 data->ss_to_cancel->size);
204 *((uint8_t *)msg) = (uint8_t)data->ss_to_cancel->size;
205 bytes_written = sizeof(uint8_t);
206 msg = msg + bytes_written;
208 for (i=0; i<data->ss_to_cancel->size; i++) {
210 *((uint16_t *)msg) = (uint16_t)data->ss_to_cancel->ss[i];
211 bytes_written = sizeof(uint16_t);
212 msg = msg + bytes_written;
214 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
215 "ss[%d]:%u\n", data->ss_to_cancel->ss[i]);
218 *size = msg - msg_begin;
220 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size);
225 static int frescan_gn_message_to_request(const uint8_t *msg_to_parse,
226 frescan_bwres_request_data_t *data,
231 size_t bytes_read, contract_size;
233 msg = (uint8_t *)msg_to_parse;
235 data->contracts_to_neg = &data->contracts_to_neg_data;
236 data->contracts_to_reneg = &data->contracts_to_reneg_data;
237 data->ss_to_reneg = &data->ss_to_reneg_data;
238 data->ss_to_cancel = &data->ss_to_cancel_data;
239 data->ss_new = &data->ss_new_data;
242 data->req = *((frescan_bwres_request_id_t *)msg);
243 bytes_read = sizeof(frescan_bwres_request_id_t);
244 msg = msg + bytes_read;
246 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
247 "GN message req:%u\n", data->req);
250 data->contracts_to_neg->size = *((uint8_t *)msg);
251 bytes_read = sizeof(uint8_t);
252 msg = msg + bytes_read;
254 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
255 "NEG-GROUP num contracts:%u\n", data->contracts_to_neg->size);
257 for (i=0; i<data->contracts_to_neg->size; i++) {
258 contract_size = *((uint16_t *)msg);
259 bytes_read = sizeof(uint16_t);
260 msg = msg + bytes_read;
262 // unmarshal the contract
263 ret = frsh_contract_unmarshal
264 (&data->contracts_to_neg->contracts[i],
268 FRESCAN_ERROR("frsh_contract_unmarshal return -1\n");
272 bytes_read = contract_size;
273 msg = msg + bytes_read;
275 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
276 "contract[%d].size:%u\n", i, contract_size);
280 data->contracts_to_reneg->size = *((uint8_t *)msg);
281 bytes_read = sizeof(uint8_t);
282 msg = msg + bytes_read;
284 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
285 "RENEG-GROUP num contracts:%u\n",data->contracts_to_reneg->size);
287 for (i=0; i<data->contracts_to_reneg->size; i++) {
288 data->ss_to_reneg->ss[i] = *((uint16_t *)msg);
289 bytes_read = sizeof(uint16_t);
290 msg = msg + bytes_read;
292 contract_size = *((uint16_t *)msg);
293 bytes_read = sizeof(uint16_t);
294 msg = msg + bytes_read;
296 // unmarshal the contract
297 ret = frsh_contract_unmarshal
298 (&data->contracts_to_reneg->contracts[i],
302 FRESCAN_ERROR("frsh_contract_unmarshal return -1\n");
306 bytes_read = contract_size;
307 msg = msg + bytes_read;
309 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
310 "contract[%d].size:%u ss[%d]:%u\n",
311 i, contract_size, i, data->ss_to_reneg->ss[i]);
315 data->ss_to_cancel->size = *((uint8_t *)msg);
316 bytes_read = sizeof(uint8_t);
317 msg = msg + bytes_read;
319 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
320 "CANCEL-GROUP num ss:%u\n", data->ss_to_cancel->size);
322 for (i=0; i<data->ss_to_cancel->size; i++) {
324 data->ss_to_cancel->ss[i] = *((uint16_t *)msg);
325 bytes_read = sizeof(uint16_t);
326 msg = msg + bytes_read;
328 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
329 "ss[%d]:%u\n", data->ss_to_cancel->ss[i]);
336 * FRESCAN_BWRES_REQ_MC
337 * ====================
338 * This message is sent from the MASTER to a slave when there is a change
339 * in the budget value assigned by the spare capacity algorithm.
342 static int frescan_request_to_mc_message
343 (const frescan_bwres_request_data_t *data,
347 frescan_bwres_vres_t *vres;
349 size_t bytes_written;
353 // type: FRESCAN_GN_MESSAGE
354 *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REQ_MC;
355 bytes_written = sizeof(uint8_t);
356 msg = msg + bytes_written;
358 // write the SS-mode_change_type-values fields
359 list_for_each_entry(vres,
360 &frescan_data[data->net].mode_change_list
361 [data->request_node],
364 if ((vres->mode_change_type & data->mode_change_type) !=
365 data->mode_change_type) continue;
367 *((frescan_ss_t *)msg) = vres->ss;
368 bytes_written = sizeof(frescan_ss_t);
369 msg = msg + bytes_written;
371 *((uint8_t *)msg) = (uint8_t)data->mode_change_type;
372 bytes_written = sizeof(uint8_t);
373 msg = msg + bytes_written;
375 if (data->mode_change_type & (FRESCAN_BWRES_MC_BUDGET_INC |
376 FRESCAN_BWRES_MC_BUDGET_DEC)) {
377 *((frsh_sa_time_t *)msg) = vres->old_c;
378 bytes_written = sizeof(frsh_sa_time_t);
379 msg = msg + bytes_written;
382 if (data->mode_change_type & (FRESCAN_BWRES_MC_PERIOD_INC |
383 FRESCAN_BWRES_MC_PERIOD_DEC)) {
384 *((frsh_sa_time_t *)msg) = vres->old_t;
385 bytes_written = sizeof(frsh_sa_time_t);
386 msg = msg + bytes_written;
389 if (data->mode_change_type & (FRESCAN_BWRES_MC_PRIO_INC |
390 FRESCAN_BWRES_MC_PRIO_DEC)) {
391 *((frsh_sa_prio_t *)msg) = vres->old_p;
392 bytes_written = sizeof(frsh_sa_prio_t);
393 msg = msg + bytes_written;
397 *size = msg - msg_begin;
399 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size);
404 static int frescan_mc_message_to_request(const uint8_t *msg_to_parse,
405 frescan_bwres_request_data_t *data,
411 frescan_bwres_vres_t *vres;
414 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "MC message\n");
416 msg = (uint8_t *)msg_to_parse;
417 me = frescan_data[data->net].local_node;
418 data->mode_change_type = 0;
420 while(msg < msg_to_parse + size) {
421 ss = *((frescan_ss_t *)msg);
422 bytes_read = sizeof(frescan_ss_t);
423 msg = msg + bytes_read;
425 vres = &frescan_data[data->net].scenario.vres_pool[me][ss];
427 vres->mode_change_type = *((uint8_t *)msg);
428 bytes_read = sizeof(uint8_t);
429 msg = msg + bytes_read;
431 if (vres->mode_change_type & (FRESCAN_BWRES_MC_BUDGET_INC |
432 FRESCAN_BWRES_MC_BUDGET_DEC)) {
433 vres->old_c = *((frsh_sa_time_t *)msg);
434 bytes_read = sizeof(frsh_sa_time_t);
435 msg = msg + bytes_read;
438 if (data->mode_change_type & (FRESCAN_BWRES_MC_PERIOD_INC |
439 FRESCAN_BWRES_MC_PERIOD_DEC)) {
440 vres->old_t = *((frsh_sa_time_t *)msg);
441 bytes_read = sizeof(frsh_sa_time_t);
442 msg = msg + bytes_read;
445 if (data->mode_change_type & (FRESCAN_BWRES_MC_PRIO_INC |
446 FRESCAN_BWRES_MC_PRIO_DEC)) {
447 vres->old_p = *((frsh_sa_prio_t *)msg);
448 bytes_read = sizeof(frsh_sa_prio_t);
449 msg = msg + bytes_read;
452 if (vres->mode_change_type != 0) {
453 list_add_tail(&(vres->mode_change_list),
454 &(frescan_data[data->net].
455 mode_change_list[me]));
458 data->mode_change_type |= vres->mode_change_type;
465 * FRESCAN_BWRES_REP_GN
466 * ====================
467 * This message is sent from the MASTER to a slave as a reply to a
468 * FRESCAN_BWRES_REQ_GN message
471 static int frescan_request_to_rep_gn_message
472 (const frescan_bwres_request_data_t *data,
477 size_t bytes_written;
482 *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REP_GN;
483 bytes_written = sizeof(uint8_t);
484 msg = msg + bytes_written;
487 *((frescan_bwres_request_id_t *)msg) = data->req;
488 bytes_written = sizeof(frescan_bwres_request_id_t);
489 msg = msg + bytes_written;
492 *((uint8_t *)msg) = data->return_value;
493 bytes_written = sizeof(uint8_t);
494 msg = msg + bytes_written;
496 *size = msg - msg_begin;
498 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size);
503 static int frescan_rep_gn_message_to_request
504 (const uint8_t *msg_to_parse,
505 frescan_bwres_request_data_t *data,
511 msg = (uint8_t *)msg_to_parse;
514 data->req = *((frescan_bwres_request_id_t *)msg);
515 bytes_read = sizeof(frescan_bwres_request_id_t);
516 msg = msg + bytes_read;
519 data->return_value = *((uint8_t *)msg);
520 bytes_read = sizeof(uint8_t);
521 msg = msg + bytes_read;
527 * frescan_messages_send_request()
529 * this function converts a request with the necessary data into a message
532 * @req_data: the request to be sent (NOTE: the network is in req_data)
536 int frescan_messages_send_request(const frescan_bwres_request_data_t *req_data)
539 uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
542 switch(req_data->type) {
543 case FRESCAN_BWRES_REQ_GN:
544 ret = frescan_request_to_gn_message
545 (req_data, msg, &size);
546 if (ret != 0) return ret;
547 send_params[req_data->net].to =
548 FRESCAN_BWRES_MASTER_NODE;
550 case FRESCAN_BWRES_REQ_MC:
551 ret = frescan_request_to_mc_message
552 (req_data, msg, &size);
553 if (ret != 0) return ret;
554 send_params[req_data->net].to = req_data->request_node;
556 case FRESCAN_BWRES_REP_GN:
557 ret = frescan_request_to_rep_gn_message
558 (req_data, msg, &size);
559 if (ret != 0) return ret;
560 send_params[req_data->net].to = req_data->request_node;
562 case FRESCAN_BWRES_REQ_RES:
563 case FRESCAN_BWRES_REQ_RES_GET:
564 case FRESCAN_BWRES_REP_RES_GET:
565 case FRESCAN_BWRES_REQ_RES_SET:
566 case FRESCAN_BWRES_REQ_RES_COMMIT:
567 case FRESCAN_BWRES_REQ_RES_CANCEL:
569 FRESCAN_ERROR("request type not supported\n");
573 ret = frescan_send(&send_params[req_data->net], msg, size);
574 if (ret != 0) return ret;
576 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "sent request, type:%X size:%u\n",
577 *(frescan_bwres_request_type_t *)msg, size);
583 * frescan_messages_recv_request()
585 * this function BLOCKS the calling thread until receives a message
586 * and transforms it into a request.
588 * @req_data: the request data to fill from the message bytes (out)
592 int frescan_messages_recv_request(frescan_network_t net,
593 frescan_bwres_request_id_t *req)
596 uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
597 uint8_t *msg_to_parse;
601 frescan_bwres_request_data_t *req_data;
603 ret = frescan_bwres_requests_alloc(req);
604 if (ret != 0) return ret;
606 ret = frescan_bwres_requests_get_data(*req, &req_data);
607 if (ret != 0) return ret;
609 ret = frescan_recv(&recv_params[net],
615 if (ret != 0) return ret;
617 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
618 "msg received! from:%u size:%u prio:%u chan:%u flags:%X\n",
619 from, recv_bytes, prio, recv_params[net].channel,
620 recv_params[net].flags);
622 req_data->request_node = from;
624 req_data->type = *((uint8_t *)msg);
626 msg_to_parse = msg + sizeof(uint8_t);
627 recv_bytes = recv_bytes - sizeof(uint8_t);
629 switch(req_data->type) {
630 case FRESCAN_BWRES_REQ_GN:
631 return frescan_gn_message_to_request(msg_to_parse,
634 case FRESCAN_BWRES_REQ_MC:
635 return frescan_mc_message_to_request(msg_to_parse,
638 case FRESCAN_BWRES_REP_GN:
639 return frescan_rep_gn_message_to_request(msg_to_parse,
642 case FRESCAN_BWRES_REQ_RES:
643 case FRESCAN_BWRES_REQ_RES_GET:
644 case FRESCAN_BWRES_REP_RES_GET:
645 case FRESCAN_BWRES_REQ_RES_SET:
646 case FRESCAN_BWRES_REQ_RES_COMMIT:
647 case FRESCAN_BWRES_REQ_RES_CANCEL:
649 FRESCAN_ERROR("request type %d not supported\n",