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>
19 #include "frescan_bwres_messages.h"
20 #include "frescan_bwres_requests.h"
22 #include "frescan_config.h"
23 #include "frescan_debug.h"
26 * frescan_messages_init()
29 static frescan_send_params_t send_params[FRESCAN_MX_NETWORKS];
30 static frescan_recv_params_t recv_params[FRESCAN_MX_NETWORKS];
32 int frescan_messages_init(frescan_network_t net)
34 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "initialization\n");
36 send_params[net].net = net;
37 send_params[net].channel = FRESCAN_NEG_CHANNEL;
38 send_params[net].flags = FRESCAN_SS | FRESCAN_ASYNC;
39 send_params[net].ss = the_networks[net].neg_messages_ss_id;
40 send_params[net].to = FRESCAN_NEG_MASTER_NODE;
42 recv_params[net].net = net;
43 recv_params[net].channel = FRESCAN_NEG_CHANNEL;
44 recv_params[net].flags = FRESCAN_SYNC;
51 * FRESCAN_REQ_NEG MESSAGE
52 * =======================
53 * This message is sent from a SLAVE to the MASTER when the slave wants
54 * to negotiate a new contract. It contains the type (a negotiation 'NEG'
55 * request), the LOCAL request id (so the MASTER can use it in the reply
56 * to identify to which request is replying), a preallocated sporadic
57 * server id (the MASTER will store it in its table together with the
58 * node so we can perform renegotiations and spare capacity distribution
59 * in the future) and the contract.
62 * +-----------------------------+
63 * | 'NEG' | REQ | SS | CONTRACT |
64 * +-----------------------------+
68 struct frescan_req_neg_message_t {
69 frescan_request_type_t type;
70 frescan_request_id_t req;
72 frescan_contract_t contract;
73 } __attribute__ ((packed));
75 static int frescan_request_to_neg_message(const frescan_request_data_t *data,
78 struct frescan_req_neg_message_t *neg_msg;
80 neg_msg = (struct frescan_req_neg_message_t *)msg;
82 neg_msg->type = FRESCAN_REQ_NEG;
83 neg_msg->req = data->req;
84 neg_msg->ss = data->ss;
85 neg_msg->contract = *(data->contract);
87 return sizeof(struct frescan_req_neg_message_t);
90 static int frescan_neg_message_to_request(const uint8_t *msg,
91 frescan_request_data_t *data)
93 struct frescan_req_neg_message_t *neg_msg;
95 neg_msg = (struct frescan_req_neg_message_t *)msg;
97 data->type = FRESCAN_REQ_NEG;
98 data->req = neg_msg->req;
99 data->ss = neg_msg->ss;
100 *(data->contract) = neg_msg->contract;
107 * FRESCAN_REQ_RENEG MESSAGE
108 * =========================
109 * This message is sent from a SLAVE to the MASTER when the slave wants
110 * to renegotiate a contract. It contains the type (a renegotiation 'RENEG'
111 * request), the LOCAL request id (so the MASTER can use it in the reply
112 * to identify to which request is replying), the sporadic server id
113 * (the MASTER will look up its table together with the node to find the
114 * appropiate entry) and the contract.
117 * +-------------------------------+
118 * | 'RENEG' | REQ | SS | CONTRACT |
119 * +-------------------------------+
123 struct frescan_req_reneg_message_t {
124 frescan_request_type_t type;
125 frescan_request_id_t req;
127 frescan_contract_t contract;
128 } __attribute__ ((packed));
130 static int frescan_request_to_reneg_message(const frescan_request_data_t *data,
133 struct frescan_req_reneg_message_t *reneg_msg;
135 reneg_msg = (struct frescan_req_reneg_message_t *)msg;
137 reneg_msg->type = FRESCAN_REQ_RENEG;
138 reneg_msg->req = data->req;
139 reneg_msg->ss = data->ss;
140 reneg_msg->contract = *(data->contract);
142 return sizeof(struct frescan_req_reneg_message_t);
145 static int frescan_reneg_message_to_request(const uint8_t *msg,
146 frescan_request_data_t *data)
148 struct frescan_req_reneg_message_t *reneg_msg;
150 reneg_msg = (struct frescan_req_reneg_message_t *)msg;
152 data->type = FRESCAN_REQ_RENEG;
153 data->req = reneg_msg->req;
154 data->ss = reneg_msg->ss;
155 *(data->contract) = reneg_msg->contract;
161 * FRESCAN_REQ_CANCEL MESSAGE
162 * ==========================
163 * This message is sent from a SLAVE to the MASTER to cancel a contract.
164 * It contains the type, 'CANCEL' and the sporadic server id (the MASTER will
165 * have to look it up in the table). The MASTER doesnt need to reply this
174 struct frescan_req_cancel_message_t {
175 frescan_request_type_t type;
177 } __attribute__ ((packed));
179 static int frescan_request_to_cancel_message(const frescan_request_data_t *data,
182 struct frescan_req_cancel_message_t *cancel_msg;
184 cancel_msg = (struct frescan_req_cancel_message_t *)msg;
186 cancel_msg->type = FRESCAN_REQ_CANCEL;
187 cancel_msg->ss = data->ss;
189 return sizeof(struct frescan_req_cancel_message_t);
192 static int frescan_cancel_message_to_request(const uint8_t *msg,
193 frescan_request_data_t *data)
195 struct frescan_req_cancel_message_t *cancel_msg;
197 cancel_msg = (struct frescan_req_cancel_message_t *)msg;
199 data->type = FRESCAN_REQ_CANCEL;
200 data->ss = cancel_msg->ss;
207 * FRESCAN_REP_NEG MESSAGE
208 * =======================
209 * This message is sent from the MASTER to a slave as a reply to a
210 * FRESCAN_REQ_NEG or a FRESCAN_REQ_RENEG, to say if they were admited.
211 * It contains the type 'REPNEG', the request ID of the slave and a
212 * return value to say if the contract is admited, not admited or if
213 * there was an error.
215 * +-------------------------------+
216 * | 'REPNEG' | REQ | RETURN_VALUE |
217 * +-------------------------------+
221 struct frescan_rep_neg_message_t {
222 frescan_request_type_t type;
223 frescan_request_id_t req;
224 frescan_request_retval_t return_value;
225 } __attribute__ ((packed));
227 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
230 struct frescan_rep_neg_message_t *repneg_msg;
232 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
234 repneg_msg->type = FRESCAN_REP_NEG;
235 repneg_msg->req = data->req;
236 repneg_msg->return_value = data->return_value;
238 return sizeof(struct frescan_rep_neg_message_t);
241 static int frescan_repneg_message_to_request(const uint8_t *msg,
242 frescan_request_data_t *data)
244 struct frescan_rep_neg_message_t *repneg_msg;
246 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
248 data->type = FRESCAN_REP_NEG;
249 data->req = repneg_msg->req;
250 data->return_value = repneg_msg->return_value;
256 * frescan_messages_send_request()
258 * this function converts a request with the necessary data into a message
261 * @req_data: the request to be sent (NOTE: the network is in req_data)
265 int frescan_messages_send_request(const frescan_request_data_t *req_data)
268 uint8_t msg[2000]; // TODO: use a constant for max neg message size
271 switch(req_data->type) {
272 case FRESCAN_REQ_NEG:
273 size = frescan_request_to_neg_message(req_data, msg);
275 case FRESCAN_REQ_RENEG:
276 size = frescan_request_to_reneg_message(req_data, msg);
278 case FRESCAN_REQ_CANCEL:
279 size = frescan_request_to_cancel_message(req_data, msg);
281 case FRESCAN_REP_NEG:
282 size = frescan_request_to_repneg_message(req_data, msg);
285 ERROR("request type not supported\n");
289 ret = frescan_send(&send_params[req_data->net], msg, size);
290 if (ret != 0) return ret;
296 * frescan_messages_recv_request()
298 * this function BLOCKS the calling thread until receives a message
299 * and transforms it into a request.
301 * @req_data: the request data to fill from the message bytes (out)
305 int frescan_messages_recv_request(frescan_network_t net,
306 frescan_request_id_t *req)
309 uint8_t msg[2000]; // TODO: use a constant with the max neg message size
313 frescan_request_data_t *req_data;
315 ret = frescan_requests_alloc(req);
316 if (ret != 0) return ret;
318 ret = frescan_requests_get_data(*req, &req_data);
319 if (ret != 0) return ret;
321 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG,
322 "wait for a msg, net:%u chan:%u flags:%u\n",
323 net, recv_params[net].channel, recv_params[net].flags);
325 ret = frescan_recv(&recv_params[net],
331 if (ret != 0) return ret;
333 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG,
334 "msg received, from:%u size:%u prio:%u\n",
335 from, recv_bytes, prio);
337 req_data->request_node = from;
340 switch(*((frescan_request_type_t *)msg)) {
341 case FRESCAN_REQ_NEG:
342 return frescan_neg_message_to_request(msg, req_data);
343 case FRESCAN_REQ_RENEG:
344 return frescan_reneg_message_to_request(msg, req_data);
345 case FRESCAN_REQ_CANCEL:
346 return frescan_cancel_message_to_request(msg, req_data);
347 case FRESCAN_REP_NEG:
348 return frescan_repneg_message_to_request(msg, req_data);
350 ERROR("request type not supported\n");
357 int frescan_message_parse(frescan_network_t net,
363 frescan_msg_type_t type;
366 frescan_contract_t contract;
367 frescan_request_id_t request_id;
368 frescan_robj_id_t reply;
369 uint8_t reply_msg[200];
371 frescan_neg_return_info_t *neg_return_info;
373 frescan_send_params_t params;
374 frescan_server_params_t server_params;
377 params.channel = FRESCAN_NEG_CHANNEL;
378 params.flags = FRESCAN_SS | FRESCAN_ASYNC;
379 params.ss = the_networks[net].neg_messages_ss_id;
382 tmp = (uint8_t *)msg;
383 type = (frescan_msg_type_t)*msg;
386 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
387 "parsing message, type:%u, size:%u\n", type, size);
390 case FRESCAN_MSG_TYPE_NEG:
391 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
392 "FRESCAN_MSG_TYPE_NEG\n");
395 memcpy(&request_id, tmp, num);
397 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
398 "request id: %d (2 bytes)\n", request_id);
400 num = sizeof(frescan_contract_t);
401 memcpy(&contract, tmp, num);
404 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
405 "contract (%d bytes)\n", num);
407 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
408 "min_budget:%u max_period:(%u,%u)\n",
409 contract.min_values.budget,
410 contract.min_values.period.tv_sec,
411 contract.min_values.period.tv_nsec);
413 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
414 "max_budget:%u min_period:(%u,%u)\n",
415 contract.max_values.budget,
416 contract.max_values.period.tv_sec,
417 contract.max_values.period.tv_nsec);
419 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
420 "prio:%u\n", contract.prio);
422 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
423 "TODO: sched test and add contract to table\n");
425 // server_params.values.budget = contract.min_values.budget;
426 // server_params.values.period = contract.min_values.period;
427 // server_params.prio = contract.prio;
428 FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
430 FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
432 server_params.values.budget = 69;
433 server_params.values.period.tv_sec = 33;
434 server_params.values.period.tv_nsec = 666;
435 server_params.prio = 2;
437 DEBUG(FRESCAN_BWRES_ENABLE_DEBUG,
438 "accepted:%u send results, net:%u to:%u ss:%u\n",
439 accepted, params.net, params.to, params.ss);
441 bytes_to_send = frescan_repneg_message_create
447 DEBUG(FRESCAN_BWRES_ENABLE_DEBUG,
448 "bytes_to_send:%u\n", bytes_to_send);
450 if (bytes_to_send <= 0) {
451 ERROR("creating reply_msg to neg\n");
455 ret = frescan_send(¶ms, reply_msg, bytes_to_send);
457 ERROR("error while sending neg request to master\n");
462 case FRESCAN_MSG_TYPE_REP_NEG:
463 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
464 "FRESCAN_MSG_TYPE_REP_NEG\n");
467 memcpy(&request_id, tmp, num);
469 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
470 "request id: %d (2 bytes)\n", request_id);
472 ret = frescan_request_get_return_info
474 (void *)&neg_return_info);
476 ERROR("error getting final_values_ref\n");
480 accepted = (int)*tmp;
484 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
485 "contract accepted:%d\n", accepted);
486 neg_return_info->error = 0;
488 num = sizeof(frescan_budget_period_t);
489 memcpy(&server_params.values, tmp, num);
492 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
493 "final budget:%u period:(%u,%u)\n",
494 server_params.values.budget,
495 server_params.values.period.tv_sec,
496 server_params.values.period.tv_nsec);
499 memcpy(&server_params.prio, tmp, num);
502 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
503 "server prio:%u\n", server_params.prio);
505 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
506 "create sporadic server with results\n");
508 ret = frescan_servers_create(net,
510 &neg_return_info->id);
512 ERROR("error creating server\n");
516 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
517 "contract not accepted:%d\n", accepted);
518 neg_return_info->error = -1;
521 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
522 "signal the request id with the results\n");
524 ret = frescan_request_get_reply(request_id, &reply);
526 ERROR("error getting reply object\n");
530 ret = frescan_replyobject_signal(reply);
532 ERROR("error while sending neg request to master\n");
538 ERROR("type not known %u\n", type);