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", 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", 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;
526 *size = msg - msg_begin;
528 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size);
533 static int frescan_rep_gn_message_to_request
534 (const uint8_t *msg_to_parse,
535 frescan_bwres_request_data_t *data,
542 frescan_server_params_t server_params;
544 msg = (uint8_t *)msg_to_parse;
547 data->req = *((frescan_bwres_request_id_t *)msg);
548 bytes_read = sizeof(frescan_bwres_request_id_t);
549 msg = msg + bytes_read;
552 data->return_value = *((uint8_t *)msg);
553 bytes_read = sizeof(uint8_t);
554 msg = msg + bytes_read;
556 // create the new sporadic servers
557 data->ss_new->size = 0;
559 while(msg < msg_to_parse + size) {
561 data->ss_new->ss[data->ss_new->size] = *((uint16_t *)msg);
562 bytes_read = sizeof(uint16_t);
563 msg = msg + bytes_read;
566 server_params.budget =
567 frsh_rel_time_to_usec
568 (frsh_sa_time_to_rel_time(*((frsh_sa_time_t *)msg))) /
569 FRESCAN_FRAME_TX_TIME_US;
570 bytes_read = sizeof(frsh_sa_time_t);
571 msg = msg + bytes_read;
574 server_params.period = frsh_sa_time_to_rel_time
575 (*((frsh_sa_time_t *)msg));
576 bytes_read = sizeof(frsh_sa_time_t);
577 msg = msg + bytes_read;
580 server_params.prio = *((frsh_sa_prio_t *)msg);
581 bytes_read = sizeof(frsh_sa_prio_t);
582 msg = msg + bytes_read;
585 ret = frescan_servers_create(data->net, &server_params, &ss);
586 if (ret != 0) return ret;
588 if (ss != data->ss_new->ss[data->ss_new->size]) {
589 FRESCAN_ERROR("ss from master != ss created\n");
593 data->ss_new->size++;
600 * frescan_messages_send_request()
602 * this function converts a request with the necessary data into a message
605 * @req_data: the request to be sent (NOTE: the network is in req_data)
609 int frescan_messages_send_request(const frescan_bwres_request_data_t *req_data)
612 uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
615 switch(req_data->type) {
616 case FRESCAN_BWRES_REQ_GN:
617 ret = frescan_request_to_gn_message
618 (req_data, msg, &size);
619 if (ret != 0) return ret;
620 send_params[req_data->net].to =
621 FRESCAN_BWRES_MASTER_NODE;
623 case FRESCAN_BWRES_REQ_MC:
624 ret = frescan_request_to_mc_message
625 (req_data, msg, &size);
626 if (ret != 0) return ret;
627 send_params[req_data->net].to = req_data->request_node;
629 case FRESCAN_BWRES_REP_GN:
630 ret = frescan_request_to_rep_gn_message
631 (req_data, msg, &size);
632 if (ret != 0) return ret;
633 send_params[req_data->net].to = req_data->request_node;
635 case FRESCAN_BWRES_REQ_RES:
636 case FRESCAN_BWRES_REQ_RES_GET:
637 case FRESCAN_BWRES_REP_RES_GET:
638 case FRESCAN_BWRES_REQ_RES_SET:
639 case FRESCAN_BWRES_REQ_RES_COMMIT:
640 case FRESCAN_BWRES_REQ_RES_CANCEL:
642 FRESCAN_ERROR("request type not supported\n");
646 ret = frescan_send(&send_params[req_data->net], msg, size);
647 if (ret != 0) return ret;
649 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "sent request, type:%X size:%u\n",
650 *(frescan_bwres_request_type_t *)msg, size);
656 * frescan_messages_recv_request()
658 * this function BLOCKS the calling thread until receives a message
659 * and transforms it into a request.
661 * @req_data: the request data to fill from the message bytes (out)
665 int frescan_messages_recv_request(frescan_network_t net,
666 frescan_bwres_request_id_t *req)
669 uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
670 uint8_t *msg_to_parse;
674 frescan_bwres_request_data_t *req_data;
676 ret = frescan_bwres_requests_alloc(req);
677 if (ret != 0) return ret;
679 ret = frescan_bwres_requests_get_data(*req, &req_data);
680 if (ret != 0) return ret;
682 ret = frescan_recv(&recv_params[net],
688 if (ret != 0) return ret;
690 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
691 "msg received! from:%u size:%u prio:%u chan:%u flags:%X\n",
692 from, recv_bytes, prio, recv_params[net].channel,
693 recv_params[net].flags);
695 req_data->request_node = from;
697 req_data->type = *((uint8_t *)msg);
699 msg_to_parse = msg + sizeof(uint8_t);
700 recv_bytes = recv_bytes - sizeof(uint8_t);
702 switch(req_data->type) {
703 case FRESCAN_BWRES_REQ_GN:
704 return frescan_gn_message_to_request(msg_to_parse,
707 case FRESCAN_BWRES_REQ_MC:
708 return frescan_mc_message_to_request(msg_to_parse,
711 case FRESCAN_BWRES_REP_GN:
712 return frescan_rep_gn_message_to_request(msg_to_parse,
715 case FRESCAN_BWRES_REQ_RES:
716 case FRESCAN_BWRES_REQ_RES_GET:
717 case FRESCAN_BWRES_REP_RES_GET:
718 case FRESCAN_BWRES_REQ_RES_SET:
719 case FRESCAN_BWRES_REQ_RES_COMMIT:
720 case FRESCAN_BWRES_REQ_RES_CANCEL:
722 FRESCAN_ERROR("request type %d not supported\n",