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_servers.h"
73 #include "frescan_data.h"
74 #include "frescan_config.h"
75 #include "frescan_debug.h"
76 #include "frsh_distributed.h"
78 #define FRESCAN_BWRES_MX_MSG_SIZE 5000 // TODO: adjust to the accurate value
81 * frescan_messages_init()
84 static frescan_send_params_t send_params[FRESCAN_MX_NETWORKS];
85 static frescan_recv_params_t recv_params[FRESCAN_MX_NETWORKS];
87 int frescan_messages_init(frescan_network_t net)
89 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "initialization\n");
91 send_params[net].net = net;
92 send_params[net].channel = FRESCAN_BWRES_NEG_MSG_CHAN;
93 send_params[net].flags = FRESCAN_SS | FRESCAN_ASYNC;
94 send_params[net].ss = frescan_data[net].neg_messages_ss_id;
95 send_params[net].to = FRESCAN_BWRES_MASTER_NODE;
97 recv_params[net].net = net;
98 recv_params[net].channel = FRESCAN_BWRES_NEG_MSG_CHAN;
99 recv_params[net].flags = FRESCAN_SYNC;
105 * FRESCAN_BWRES_REQ_GN
106 * ====================
107 * This message is sent from a SLAVE to the MASTER when the slave wants
108 * to make a negotiation (including creating new vres, renegotiations and
112 static int frescan_request_to_gn_message
113 (const frescan_bwres_request_data_t *data,
118 uint8_t *msg_begin, *msg_tmp;
119 size_t bytes_written;
123 // type: FRESCAN_GN_MESSAGE
124 *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REQ_GN;
125 bytes_written = sizeof(uint8_t);
126 msg = msg + bytes_written;
129 *((frescan_bwres_request_id_t *)msg) = data->req;
130 bytes_written = sizeof(frescan_bwres_request_id_t);
131 msg = msg + bytes_written;
133 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
134 "GN message req:%u\n", data->req);
137 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
138 "NEG-GROUP num contracts:%d\n", data->contracts_to_neg->size);
140 *((uint8_t *)msg) = (uint8_t)data->contracts_to_neg->size;
141 bytes_written = sizeof(uint8_t);
142 msg = msg + bytes_written;
144 for (i=0; i<data->contracts_to_neg->size; i++) {
145 // reserve 2 bytes for the size of the marshalled contract
147 msg = msg + sizeof(uint16_t);
148 // marshal the contract
149 ret = frsh_contract_marshal
150 (&data->contracts_to_neg->contracts[i],
152 FRESCAN_BWRES_MX_MSG_SIZE - (msg - msg_begin),
155 FRESCAN_ERROR("frsh_contract_marshal return -1\n");
158 // write the size and update the message pointer msg
159 *((uint16_t *)msg_tmp) = (uint16_t)bytes_written;
160 msg = msg + bytes_written;
162 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
163 "contract[%d].size:%u\n", i, bytes_written);
167 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
168 "RENEG-GROUP num contracts:%d\n",data->contracts_to_reneg->size);
170 *((uint8_t *)msg) = (uint8_t)data->contracts_to_reneg->size;
171 bytes_written = sizeof(uint8_t);
172 msg = msg + bytes_written;
174 for (i=0; i<data->contracts_to_reneg->size; i++) {
176 *((uint16_t *)msg) = (uint16_t)data->ss_to_reneg->ss[i];
177 bytes_written = sizeof(uint16_t);
178 msg = msg + bytes_written;
179 // reserve 2 bytes for the size of the marshalled contract
181 msg = msg + sizeof(uint16_t);
182 // marshal the contract
183 ret = frsh_contract_marshal
184 (&data->contracts_to_reneg->contracts[i],
186 FRESCAN_BWRES_MX_MSG_SIZE - (msg - msg_begin),
189 FRESCAN_ERROR("frsh_contract_marshal return -1\n");
192 // write the size and update the message pointer msg
193 *((uint16_t *)msg_tmp) = (uint16_t)bytes_written;
194 msg = msg + bytes_written;
196 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
197 "contract[%d].size:%u ss[%d]:%u\n",
198 i, bytes_written, i, data->ss_to_reneg->ss[i]);
202 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "CANCEL-GROUP num ss:%d\n",
203 data->ss_to_cancel->size);
205 *((uint8_t *)msg) = (uint8_t)data->ss_to_cancel->size;
206 bytes_written = sizeof(uint8_t);
207 msg = msg + bytes_written;
209 for (i=0; i<data->ss_to_cancel->size; i++) {
211 *((uint16_t *)msg) = (uint16_t)data->ss_to_cancel->ss[i];
212 bytes_written = sizeof(uint16_t);
213 msg = msg + bytes_written;
215 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
216 "ss[%d]:%u\n", i, data->ss_to_cancel->ss[i]);
219 *size = msg - msg_begin;
221 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size);
226 static int frescan_gn_message_to_request(const uint8_t *msg_to_parse,
227 frescan_bwres_request_data_t *data,
232 size_t bytes_read, contract_size;
234 msg = (uint8_t *)msg_to_parse;
236 data->contracts_to_neg = &data->contracts_to_neg_data;
237 data->contracts_to_reneg = &data->contracts_to_reneg_data;
238 data->ss_to_reneg = &data->ss_to_reneg_data;
239 data->ss_to_cancel = &data->ss_to_cancel_data;
240 data->ss_new = &data->ss_new_data;
243 data->req = *((frescan_bwres_request_id_t *)msg);
244 bytes_read = sizeof(frescan_bwres_request_id_t);
245 msg = msg + bytes_read;
247 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
248 "GN message req:%u\n", data->req);
251 data->contracts_to_neg->size = *((uint8_t *)msg);
252 bytes_read = sizeof(uint8_t);
253 msg = msg + bytes_read;
255 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
256 "NEG-GROUP num contracts:%u\n", data->contracts_to_neg->size);
258 for (i=0; i<data->contracts_to_neg->size; i++) {
259 contract_size = *((uint16_t *)msg);
260 bytes_read = sizeof(uint16_t);
261 msg = msg + bytes_read;
263 // unmarshal the contract
264 ret = frsh_contract_unmarshal
265 (&data->contracts_to_neg->contracts[i],
269 FRESCAN_ERROR("frsh_contract_unmarshal return -1\n");
273 bytes_read = contract_size;
274 msg = msg + bytes_read;
276 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
277 "contract[%d].size:%u\n", i, contract_size);
281 data->contracts_to_reneg->size = *((uint8_t *)msg);
282 bytes_read = sizeof(uint8_t);
283 msg = msg + bytes_read;
285 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
286 "RENEG-GROUP num contracts:%u\n",data->contracts_to_reneg->size);
288 for (i=0; i<data->contracts_to_reneg->size; i++) {
289 data->ss_to_reneg->ss[i] = *((uint16_t *)msg);
290 bytes_read = sizeof(uint16_t);
291 msg = msg + bytes_read;
293 contract_size = *((uint16_t *)msg);
294 bytes_read = sizeof(uint16_t);
295 msg = msg + bytes_read;
297 // unmarshal the contract
298 ret = frsh_contract_unmarshal
299 (&data->contracts_to_reneg->contracts[i],
303 FRESCAN_ERROR("frsh_contract_unmarshal return -1\n");
307 bytes_read = contract_size;
308 msg = msg + bytes_read;
310 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
311 "contract[%d].size:%u ss[%d]:%u\n",
312 i, contract_size, i, data->ss_to_reneg->ss[i]);
316 data->ss_to_cancel->size = *((uint8_t *)msg);
317 bytes_read = sizeof(uint8_t);
318 msg = msg + bytes_read;
320 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
321 "CANCEL-GROUP num ss:%u\n", data->ss_to_cancel->size);
323 for (i=0; i<data->ss_to_cancel->size; i++) {
325 data->ss_to_cancel->ss[i] = *((uint16_t *)msg);
326 bytes_read = sizeof(uint16_t);
327 msg = msg + bytes_read;
329 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
330 "ss[%d]:%u\n", i, data->ss_to_cancel->ss[i]);
337 * FRESCAN_BWRES_REQ_MC
338 * ====================
339 * This message is sent from the MASTER to a slave when there is a change
340 * in the budget value assigned by the spare capacity algorithm.
343 static int frescan_request_to_mc_message
344 (const frescan_bwres_request_data_t *data,
348 frescan_bwres_vres_t *vres;
350 size_t bytes_written;
354 // type: FRESCAN_GN_MESSAGE
355 *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REQ_MC;
356 bytes_written = sizeof(uint8_t);
357 msg = msg + bytes_written;
359 // write the SS-mode_change_type-values fields
360 list_for_each_entry(vres,
361 &frescan_data[data->net].mode_change_list
362 [data->request_node],
365 if ((vres->mode_change_type & data->mode_change_type) !=
366 data->mode_change_type) continue;
368 *((frescan_ss_t *)msg) = vres->ss;
369 bytes_written = sizeof(frescan_ss_t);
370 msg = msg + bytes_written;
372 *((uint8_t *)msg) = (uint8_t)data->mode_change_type;
373 bytes_written = sizeof(uint8_t);
374 msg = msg + bytes_written;
376 if (data->mode_change_type & (FRESCAN_BWRES_MC_BUDGET_INC |
377 FRESCAN_BWRES_MC_BUDGET_DEC)) {
378 *((frsh_sa_time_t *)msg) = vres->old_c;
379 bytes_written = sizeof(frsh_sa_time_t);
380 msg = msg + bytes_written;
383 if (data->mode_change_type & (FRESCAN_BWRES_MC_PERIOD_INC |
384 FRESCAN_BWRES_MC_PERIOD_DEC)) {
385 *((frsh_sa_time_t *)msg) = vres->old_t;
386 bytes_written = sizeof(frsh_sa_time_t);
387 msg = msg + bytes_written;
390 if (data->mode_change_type & (FRESCAN_BWRES_MC_PRIO_INC |
391 FRESCAN_BWRES_MC_PRIO_DEC)) {
392 *((frsh_sa_prio_t *)msg) = vres->old_p;
393 bytes_written = sizeof(frsh_sa_prio_t);
394 msg = msg + bytes_written;
398 *size = msg - msg_begin;
400 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size);
405 static int frescan_mc_message_to_request(const uint8_t *msg_to_parse,
406 frescan_bwres_request_data_t *data,
412 frescan_bwres_vres_t *vres;
415 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "MC message\n");
417 msg = (uint8_t *)msg_to_parse;
418 me = frescan_data[data->net].local_node;
419 data->mode_change_type = 0;
421 while(msg < msg_to_parse + size) {
422 ss = *((frescan_ss_t *)msg);
423 bytes_read = sizeof(frescan_ss_t);
424 msg = msg + bytes_read;
426 vres = &frescan_data[data->net].scenario.vres_pool[me][ss];
428 vres->mode_change_type = *((uint8_t *)msg);
429 bytes_read = sizeof(uint8_t);
430 msg = msg + bytes_read;
432 if (vres->mode_change_type & (FRESCAN_BWRES_MC_BUDGET_INC |
433 FRESCAN_BWRES_MC_BUDGET_DEC)) {
434 vres->old_c = *((frsh_sa_time_t *)msg);
435 bytes_read = sizeof(frsh_sa_time_t);
436 msg = msg + bytes_read;
439 if (data->mode_change_type & (FRESCAN_BWRES_MC_PERIOD_INC |
440 FRESCAN_BWRES_MC_PERIOD_DEC)) {
441 vres->old_t = *((frsh_sa_time_t *)msg);
442 bytes_read = sizeof(frsh_sa_time_t);
443 msg = msg + bytes_read;
446 if (data->mode_change_type & (FRESCAN_BWRES_MC_PRIO_INC |
447 FRESCAN_BWRES_MC_PRIO_DEC)) {
448 vres->old_p = *((frsh_sa_prio_t *)msg);
449 bytes_read = sizeof(frsh_sa_prio_t);
450 msg = msg + bytes_read;
453 if (vres->mode_change_type != 0) {
454 list_add_tail(&(vres->mode_change_list),
455 &(frescan_data[data->net].
456 mode_change_list[me]));
459 data->mode_change_type |= vres->mode_change_type;
466 * FRESCAN_BWRES_REP_GN
467 * ====================
468 * This message is sent from the MASTER to a slave as a reply to a
469 * FRESCAN_BWRES_REQ_GN message
472 static int frescan_request_to_rep_gn_message
473 (const frescan_bwres_request_data_t *data,
479 size_t bytes_written;
480 frescan_bwres_vres_t *vres;
485 *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REP_GN;
486 bytes_written = sizeof(uint8_t);
487 msg = msg + bytes_written;
490 *((frescan_bwres_request_id_t *)msg) = data->req;
491 bytes_written = sizeof(frescan_bwres_request_id_t);
492 msg = msg + bytes_written;
495 *((uint8_t *)msg) = data->return_value;
496 bytes_written = sizeof(uint8_t);
497 msg = msg + bytes_written;
499 if (data->return_value == FRESCAN_BWRES_REQ_ACCEPTED) {
501 for(i=0; i<data->contracts_to_neg->size; i++) {
503 *((uint16_t *)msg) = data->ss_new->ss[i];
504 bytes_written = sizeof(uint16_t);
505 msg = msg + bytes_written;
508 vres = &frescan_data[data->net].scenario.
509 vres_pool[data->request_node]
510 [data->ss_new->ss[i]];
512 *((frsh_sa_time_t *)msg) = vres->old_c;
513 bytes_written = sizeof(frsh_sa_time_t);
514 msg = msg + bytes_written;
516 *((frsh_sa_time_t *)msg) = vres->old_t;
517 bytes_written = sizeof(frsh_sa_time_t);
518 msg = msg + bytes_written;
520 *((frsh_sa_prio_t *)msg) = vres->old_p;
521 bytes_written = sizeof(frsh_sa_prio_t);
522 msg = msg + bytes_written;
524 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
525 "ss[%d]:%u\n", i, data->ss_new->ss[i]);
529 *size = msg - msg_begin;
531 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size);
536 static int frescan_rep_gn_message_to_request
537 (const uint8_t *msg_to_parse,
538 frescan_bwres_request_data_t *data,
545 frescan_server_params_t server_params;
547 msg = (uint8_t *)msg_to_parse;
550 data->req = *((frescan_bwres_request_id_t *)msg);
551 bytes_read = sizeof(frescan_bwres_request_id_t);
552 msg = msg + bytes_read;
555 data->return_value = *((uint8_t *)msg);
556 bytes_read = sizeof(uint8_t);
557 msg = msg + bytes_read;
559 // create the new sporadic servers
560 data->ss_new->size = 0;
562 while(msg < msg_to_parse + size) {
564 data->ss_new->ss[data->ss_new->size] = *((uint16_t *)msg);
565 bytes_read = sizeof(uint16_t);
566 msg = msg + bytes_read;
569 server_params.budget =
570 frsh_rel_time_to_usec
571 (frsh_sa_time_to_rel_time(*((frsh_sa_time_t *)msg))) /
572 FRESCAN_FRAME_TX_TIME_US;
573 bytes_read = sizeof(frsh_sa_time_t);
574 msg = msg + bytes_read;
577 server_params.period = frsh_sa_time_to_rel_time
578 (*((frsh_sa_time_t *)msg));
579 bytes_read = sizeof(frsh_sa_time_t);
580 msg = msg + bytes_read;
583 server_params.prio = *((frsh_sa_prio_t *)msg);
584 bytes_read = sizeof(frsh_sa_prio_t);
585 msg = msg + bytes_read;
588 ret = frescan_servers_create(data->net, &server_params, &ss);
589 if (ret != 0) return ret;
591 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
592 "ss_master[%d]:%u ss_created[%d]:%u\n",
593 data->ss_new->size, data->ss_new->ss[data->ss_new->size],
594 data->ss_new->size, ss);
596 if (ss != data->ss_new->ss[data->ss_new->size]) {
597 FRESCAN_ERROR("ss from master != ss created\n");
601 data->ss_new->size++;
604 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
605 "data->ss_new->size:%u\n", data->ss_new->size);
611 * frescan_messages_send_request()
613 * this function converts a request with the necessary data into a message
616 * @req_data: the request to be sent (NOTE: the network is in req_data)
620 int frescan_messages_send_request(const frescan_bwres_request_data_t *req_data)
623 uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
626 switch(req_data->type) {
627 case FRESCAN_BWRES_REQ_GN:
628 ret = frescan_request_to_gn_message
629 (req_data, msg, &size);
630 if (ret != 0) return ret;
631 send_params[req_data->net].to =
632 FRESCAN_BWRES_MASTER_NODE;
634 case FRESCAN_BWRES_REQ_MC:
635 ret = frescan_request_to_mc_message
636 (req_data, msg, &size);
637 if (ret != 0) return ret;
638 send_params[req_data->net].to = req_data->request_node;
640 case FRESCAN_BWRES_REP_GN:
641 ret = frescan_request_to_rep_gn_message
642 (req_data, msg, &size);
643 if (ret != 0) return ret;
644 send_params[req_data->net].to = req_data->request_node;
646 case FRESCAN_BWRES_REQ_RES:
647 case FRESCAN_BWRES_REQ_RES_GET:
648 case FRESCAN_BWRES_REP_RES_GET:
649 case FRESCAN_BWRES_REQ_RES_SET:
650 case FRESCAN_BWRES_REQ_RES_COMMIT:
651 case FRESCAN_BWRES_REQ_RES_CANCEL:
653 FRESCAN_ERROR("request type not supported\n");
657 ret = frescan_send(&send_params[req_data->net], msg, size);
658 if (ret != 0) return ret;
660 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
661 "sent request, type:%X size:%u\n",
662 req_data->type, size);
668 * frescan_messages_recv_request()
670 * this function BLOCKS the calling thread until receives a message
671 * and transforms it into a request.
673 * @req_data: the request data to fill from the message bytes (out)
677 int frescan_messages_recv_request(frescan_network_t net,
678 frescan_bwres_request_id_t *req)
681 uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
682 uint8_t *msg_to_parse;
686 frescan_bwres_request_data_t *req_data;
688 ret = frescan_bwres_requests_alloc(req);
689 if (ret != 0) return ret;
691 ret = frescan_bwres_requests_get_data(*req, &req_data);
692 if (ret != 0) return ret;
694 ret = frescan_recv(&recv_params[net],
700 if (ret != 0) return ret;
702 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
703 "msg received! from:%u size:%u prio:%u chan:%u flags:%X\n",
704 from, recv_bytes, prio, recv_params[net].channel,
705 recv_params[net].flags);
707 req_data->request_node = from;
709 req_data->type = *((uint8_t *)msg);
711 msg_to_parse = msg + sizeof(uint8_t);
712 recv_bytes = recv_bytes - sizeof(uint8_t);
714 switch(req_data->type) {
715 case FRESCAN_BWRES_REQ_GN:
716 return frescan_gn_message_to_request(msg_to_parse,
719 case FRESCAN_BWRES_REQ_MC:
720 return frescan_mc_message_to_request(msg_to_parse,
723 case FRESCAN_BWRES_REP_GN:
724 return frescan_rep_gn_message_to_request(msg_to_parse,
727 case FRESCAN_BWRES_REQ_RES:
728 case FRESCAN_BWRES_REQ_RES_GET:
729 case FRESCAN_BWRES_REP_RES_GET:
730 case FRESCAN_BWRES_REQ_RES_SET:
731 case FRESCAN_BWRES_REQ_RES_COMMIT:
732 case FRESCAN_BWRES_REQ_RES_CANCEL:
734 FRESCAN_ERROR("request type %d not supported\n",