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"
27 * FRESCAN_REQ_NEG MESSAGE
28 * =======================
29 * This message is sent from a SLAVE to the MASTER when the slave wants
30 * to negotiate a new contract. It contains the type (a negotiation 'NEG'
31 * request), the LOCAL request id (so the MASTER can use it in the reply
32 * to identify to which request is replying), a preallocated sporadic
33 * server id (the MASTER will store it in its table together with the
34 * node so we can perform renegotiations and spare capacity distribution
35 * in the future) and the contract.
38 * +-----------------------------+
39 * | 'NEG' | REQ | SS | CONTRACT |
40 * +-----------------------------+
44 struct frescan_req_neg_message_t {
45 frescan_request_type_t type;
46 frescan_request_id_t req;
48 frescan_contract_t contract;
49 } __attribute__ ((packed));
51 static int frescan_request_to_neg_message(const frescan_request_data_t *data,
54 struct frescan_req_neg_message_t *neg_msg;
56 neg_msg = (struct frescan_req_neg_message_t *)msg;
58 neg_msg->type = FRESCAN_REQ_NEG;
59 neg_msg->req = data->req;
60 neg_msg->ss = data->ss;
61 neg_msg->contract = *(data->contract);
66 static int frescan_neg_message_to_request(const uint8_t *msg,
67 frescan_request_data_t *data)
69 struct frescan_req_neg_message_t *neg_msg;
71 neg_msg = (struct frescan_req_neg_message_t *)msg;
73 data->type = FRESCAN_REQ_NEG;
74 data->req = neg_msg->req;
75 data->ss = neg_msg->ss;
76 *(data->contract) = neg_msg->contract;
83 * FRESCAN_REQ_RENEG MESSAGE
84 * =========================
85 * This message is sent from a SLAVE to the MASTER when the slave wants
86 * to renegotiate a contract. It contains the type (a renegotiation 'RENEG'
87 * request), the LOCAL request id (so the MASTER can use it in the reply
88 * to identify to which request is replying), the sporadic server id
89 * (the MASTER will look up its table together with the node to find the
90 * appropiate entry) and the contract.
93 * +-------------------------------+
94 * | 'RENEG' | REQ | SS | CONTRACT |
95 * +-------------------------------+
99 struct frescan_req_reneg_message_t {
100 frescan_request_type_t type;
101 frescan_request_id_t req;
103 frescan_contract_t contract;
104 } __attribute__ ((packed));
106 static int frescan_request_to_reneg_message(const frescan_request_data_t *data,
109 struct frescan_req_reneg_message_t *reneg_msg;
111 reneg_msg = (struct frescan_req_reneg_message_t *)msg;
113 reneg_msg->type = FRESCAN_REQ_RENEG;
114 reneg_msg->req = data->req;
115 reneg_msg->ss = data->ss;
116 reneg_msg->contract = *(data->contract);
121 static int frescan_reneg_message_to_request(const uint8_t *msg,
122 frescan_request_data_t *data)
124 struct frescan_req_reneg_message_t *reneg_msg;
126 reneg_msg = (struct frescan_req_reneg_message_t *)msg;
128 data->type = FRESCAN_REQ_RENEG;
129 data->req = reneg_msg->req;
130 data->ss = reneg_msg->ss;
131 *(data->contract) = reneg_msg->contract;
137 * FRESCAN_REQ_CANCEL MESSAGE
138 * ==========================
139 * This message is sent from a SLAVE to the MASTER to cancel a contract.
140 * It contains the type, 'CANCEL' and the sporadic server id (the MASTER will
141 * have to look it up in the table). The MASTER doesnt need to reply this
150 struct frescan_req_cancel_message_t {
151 frescan_request_type_t type;
153 } __attribute__ ((packed));
155 static int frescan_request_to_cancel_message(const frescan_request_data_t *data,
158 struct frescan_req_cancel_message_t *cancel_msg;
160 cancel_msg = (struct frescan_req_cancel_message_t *)msg;
162 cancel_msg->type = FRESCAN_REQ_CANCEL;
163 cancel_msg->ss = data->ss;
168 static int frescan_cancel_message_to_request(const uint8_t *msg,
169 frescan_request_data_t *data)
171 struct frescan_req_cancel_message_t *cancel_msg;
173 cancel_msg = (struct frescan_req_cancel_message_t *)msg;
175 data->type = FRESCAN_REQ_CANCEL;
176 data->ss = cancel_msg->ss;
183 * FRESCAN_REP_NEG MESSAGE
184 * =======================
185 * This message is sent from the MASTER to a slave as a reply to a
186 * FRESCAN_REQ_NEG or a FRESCAN_REQ_RENEG, to say if they were admited.
187 * It contains the type 'REPNEG', the request ID of the slave and a
188 * return value to say if the contract is admited, not admited or if
189 * there was an error.
191 * +-------------------------------+
192 * | 'REPNEG' | REQ | RETURN_VALUE |
193 * +-------------------------------+
197 struct frescan_rep_neg_message_t {
198 frescan_request_type_t type;
199 frescan_request_id_t req;
200 frescan_request_retval_t return_value;
201 } __attribute__ ((packed));
203 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
206 struct frescan_rep_neg_message_t *repneg_msg;
208 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
210 repneg_msg->type = FRESCAN_REP_NEG;
211 repneg_msg->req = data->req;
212 repneg_msg->return_value = data->return_value;
217 static int frescan_repneg_message_to_request(const uint8_t *msg,
218 frescan_request_data_t *data)
220 struct frescan_rep_neg_message_t *repneg_msg;
222 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
224 data->type = FRESCAN_REP_NEG;
225 data->req = repneg_msg->req;
226 data->return_value = repneg_msg->return_value;
232 * frescan_request_to_message() - converts a request into a network message
234 * this function converts a request with the necessary data into a message
235 * that can be sent through the network.
237 * @req_data: the request data to fill the message bytes (in)
238 * @msg: buffer with the bytes that will be sent to the network (out)
242 int frescan_request_to_message(const frescan_request_data_t *req_data,
245 switch(req_data->type) {
246 case FRESCAN_REQ_NEG:
247 return frescan_request_to_neg_message(req_data, msg);
248 case FRESCAN_REQ_RENEG:
249 return frescan_request_to_reneg_message(req_data, msg);
250 case FRESCAN_REQ_CANCEL:
251 return frescan_request_to_cancel_message(req_data, msg);
252 case FRESCAN_REP_NEG:
253 return frescan_request_to_repneg_message(req_data, msg);
255 ERROR("request type not supported\n");
261 * frescan_message_to_request() - converts a network message into a request
263 * this function is the opposite to the previous one. It will be used by
264 * the acceptor threads to transform messages received from the network
267 * @msg: buffer with the bytes received from the network (in)
268 * @req_data: the request data to fill from the message bytes (out)
272 int frescan_message_to_request(const uint8_t *msg,
273 frescan_request_data_t *req_data)
275 switch(*((frescan_request_type_t *)msg)) {
276 case FRESCAN_REQ_NEG:
277 return frescan_neg_message_to_request(msg, req_data);
278 case FRESCAN_REQ_RENEG:
279 return frescan_reneg_message_to_request(msg, req_data);
280 case FRESCAN_REQ_CANCEL:
281 return frescan_cancel_message_to_request(msg, req_data);
282 case FRESCAN_REP_NEG:
283 return frescan_repneg_message_to_request(msg, req_data);
285 ERROR("request type not supported\n");
292 int frescan_message_parse(frescan_network_t net,
298 frescan_msg_type_t type;
301 frescan_contract_t contract;
302 frescan_request_id_t request_id;
303 frescan_robj_id_t reply;
304 uint8_t reply_msg[200];
306 frescan_neg_return_info_t *neg_return_info;
308 frescan_send_params_t params;
309 frescan_server_params_t server_params;
312 params.channel = FRESCAN_NEG_CHANNEL;
313 params.flags = FRESCAN_SS | FRESCAN_ASYNC;
314 params.ss = the_networks[net].neg_messages_ss_id;
317 tmp = (uint8_t *)msg;
318 type = (frescan_msg_type_t)*msg;
321 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
322 "parsing message, type:%u, size:%u\n", type, size);
325 case FRESCAN_MSG_TYPE_NEG:
326 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
327 "FRESCAN_MSG_TYPE_NEG\n");
330 memcpy(&request_id, tmp, num);
332 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
333 "request id: %d (2 bytes)\n", request_id);
335 num = sizeof(frescan_contract_t);
336 memcpy(&contract, tmp, num);
339 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
340 "contract (%d bytes)\n", num);
342 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
343 "min_budget:%u max_period:(%u,%u)\n",
344 contract.min_values.budget,
345 contract.min_values.period.tv_sec,
346 contract.min_values.period.tv_nsec);
348 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
349 "max_budget:%u min_period:(%u,%u)\n",
350 contract.max_values.budget,
351 contract.max_values.period.tv_sec,
352 contract.max_values.period.tv_nsec);
354 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
355 "prio:%u\n", contract.prio);
357 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
358 "TODO: sched test and add contract to table\n");
360 // server_params.values.budget = contract.min_values.budget;
361 // server_params.values.period = contract.min_values.period;
362 // server_params.prio = contract.prio;
363 FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
365 FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
367 server_params.values.budget = 69;
368 server_params.values.period.tv_sec = 33;
369 server_params.values.period.tv_nsec = 666;
370 server_params.prio = 2;
372 DEBUG(FRESCAN_BWRES_ENABLE_DEBUG,
373 "accepted:%u send results, net:%u to:%u ss:%u\n",
374 accepted, params.net, params.to, params.ss);
376 bytes_to_send = frescan_repneg_message_create
382 DEBUG(FRESCAN_BWRES_ENABLE_DEBUG,
383 "bytes_to_send:%u\n", bytes_to_send);
385 if (bytes_to_send <= 0) {
386 ERROR("creating reply_msg to neg\n");
390 ret = frescan_send(¶ms, reply_msg, bytes_to_send);
392 ERROR("error while sending neg request to master\n");
397 case FRESCAN_MSG_TYPE_REP_NEG:
398 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
399 "FRESCAN_MSG_TYPE_REP_NEG\n");
402 memcpy(&request_id, tmp, num);
404 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
405 "request id: %d (2 bytes)\n", request_id);
407 ret = frescan_request_get_return_info
409 (void *)&neg_return_info);
411 ERROR("error getting final_values_ref\n");
415 accepted = (int)*tmp;
419 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
420 "contract accepted:%d\n", accepted);
421 neg_return_info->error = 0;
423 num = sizeof(frescan_budget_period_t);
424 memcpy(&server_params.values, tmp, num);
427 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
428 "final budget:%u period:(%u,%u)\n",
429 server_params.values.budget,
430 server_params.values.period.tv_sec,
431 server_params.values.period.tv_nsec);
434 memcpy(&server_params.prio, tmp, num);
437 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
438 "server prio:%u\n", server_params.prio);
440 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
441 "create sporadic server with results\n");
443 ret = frescan_servers_create(net,
445 &neg_return_info->id);
447 ERROR("error creating server\n");
451 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
452 "contract not accepted:%d\n", accepted);
453 neg_return_info->error = -1;
456 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
457 "signal the request id with the results\n");
459 ret = frescan_request_get_reply(request_id, &reply);
461 ERROR("error getting reply object\n");
465 ret = frescan_replyobject_signal(reply);
467 ERROR("error while sending neg request to master\n");
473 ERROR("type not known %u\n", type);