]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_messages.c
29d1d0dd1b51b336348be5fe1048fbea56c097eb
[frescor/fna.git] / src_frescan / frescan_bwres_messages.c
1 /*!
2  * @file frescan_bwres_messages.c
3  *
4  * @brief FRESCAN bandwidth reservation layer: negotiation messages formating
5  *
6  * This module contains the data types that define the FRESCAN negotiation
7  * message format and operations to convert them into or from negotiation
8  * requests
9  *
10  * @version 0.01
11  *
12  * @date 2-Apr-2008
13  *
14  * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
15  *
16  */
17
18 #include <string.h>
19 #include "frescan_bwres_messages.h"
20 #include "frescan_bwres_requests.h"
21 #include "frescan.h"
22 #include "frescan_config.h"
23 #include "frescan_debug.h"
24
25 /**
26  * frescan_messages_init()
27  */
28
29 static frescan_send_params_t send_params[FRESCAN_MX_NETWORKS];
30 static frescan_recv_params_t recv_params[FRESCAN_MX_NETWORKS];
31
32 int frescan_messages_init(frescan_network_t net)
33 {
34         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG, "initialization\n");
35
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;
41
42         recv_params[net].net     = net;
43         recv_params[net].channel = FRESCAN_NEG_CHANNEL;
44         recv_params[net].flags   = FRESCAN_SYNC;
45
46         return 0;
47 }
48
49 /**
50  *
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.
60  *
61  *      1     2     2      N
62  *  +-----------------------------+
63  *  | 'NEG' | REQ | SS | CONTRACT |
64  *  +-----------------------------+
65  *
66  */
67
68 struct frescan_req_neg_message_t {
69         frescan_request_type_t   type;
70         frescan_request_id_t     req;
71         frescan_ss_t             ss;
72         frescan_contract_t       contract;
73 }  __attribute__ ((packed));
74
75 static int frescan_request_to_neg_message(const frescan_request_data_t *data,
76                                           uint8_t *msg)
77 {
78         struct frescan_req_neg_message_t *neg_msg;
79
80         neg_msg = (struct frescan_req_neg_message_t *)msg;
81
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);
86
87         return sizeof(struct frescan_req_neg_message_t);
88 }
89
90 static int frescan_neg_message_to_request(const uint8_t *msg,
91                                           frescan_request_data_t *data)
92 {
93         struct frescan_req_neg_message_t *neg_msg;
94
95         neg_msg = (struct frescan_req_neg_message_t *)msg;
96
97         data->type        = FRESCAN_REQ_NEG;
98         data->req         = neg_msg->req;
99         data->ss          = neg_msg->ss;
100         *(data->contract) = neg_msg->contract;
101
102         return 0;
103 }
104
105 /**
106  *
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.
115  *
116  *      1       2     2      N
117  *  +-------------------------------+
118  *  | 'RENEG' | REQ | SS | CONTRACT |
119  *  +-------------------------------+
120  *
121  */
122
123 struct frescan_req_reneg_message_t {
124         frescan_request_type_t   type;
125         frescan_request_id_t     req;
126         frescan_ss_t             ss;
127         frescan_contract_t       contract;
128 }  __attribute__ ((packed));
129
130 static int frescan_request_to_reneg_message(const frescan_request_data_t *data,
131                                             uint8_t *msg)
132 {
133         struct frescan_req_reneg_message_t *reneg_msg;
134
135         reneg_msg = (struct frescan_req_reneg_message_t *)msg;
136
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);
141
142         return sizeof(struct frescan_req_reneg_message_t);
143 }
144
145 static int frescan_reneg_message_to_request(const uint8_t *msg,
146                                             frescan_request_data_t *data)
147 {
148         struct frescan_req_reneg_message_t *reneg_msg;
149
150         reneg_msg = (struct frescan_req_reneg_message_t *)msg;
151
152         data->type        = FRESCAN_REQ_RENEG;
153         data->req         = reneg_msg->req;
154         data->ss          = reneg_msg->ss;
155         *(data->contract) = reneg_msg->contract;
156
157         return 0;
158 }
159
160 /**
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
166  *  message.
167  *
168  *  +---------------+
169  *  | 'CANCEL' | SS |
170  *  +---------------+
171  *
172  */
173
174 struct frescan_req_cancel_message_t {
175         frescan_request_type_t   type;
176         frescan_ss_t             ss;
177 }  __attribute__ ((packed));
178
179 static int frescan_request_to_cancel_message(const frescan_request_data_t *data,
180                                              uint8_t *msg)
181 {
182         struct frescan_req_cancel_message_t *cancel_msg;
183
184         cancel_msg = (struct frescan_req_cancel_message_t *)msg;
185
186         cancel_msg->type     = FRESCAN_REQ_CANCEL;
187         cancel_msg->ss       = data->ss;
188
189         return sizeof(struct frescan_req_cancel_message_t);
190 }
191
192 static int frescan_cancel_message_to_request(const uint8_t *msg,
193                                              frescan_request_data_t *data)
194 {
195         struct frescan_req_cancel_message_t *cancel_msg;
196
197         cancel_msg = (struct frescan_req_cancel_message_t *)msg;
198
199         data->type        = FRESCAN_REQ_CANCEL;
200         data->ss          = cancel_msg->ss;
201
202         return 0;
203 }
204
205 /**
206  *
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.
214  *
215  *  +-------------------------------+
216  *  | 'REPNEG' | REQ | RETURN_VALUE |
217  *  +-------------------------------+
218  *
219  */
220
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));
226
227 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
228                                              uint8_t *msg)
229 {
230         struct frescan_rep_neg_message_t *repneg_msg;
231
232         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
233
234         repneg_msg->type         = FRESCAN_REP_NEG;
235         repneg_msg->req          = data->req;
236         repneg_msg->return_value = data->return_value;
237
238         return sizeof(struct frescan_rep_neg_message_t);
239 }
240
241 static int frescan_repneg_message_to_request(const uint8_t *msg,
242                                              frescan_request_data_t *data)
243 {
244         struct frescan_rep_neg_message_t *repneg_msg;
245
246         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
247
248         data->type         = FRESCAN_REP_NEG;
249         data->req          = repneg_msg->req;
250         data->return_value = repneg_msg->return_value;
251
252         return 0;
253 }
254
255 /**
256  * frescan_messages_send_request()
257  *
258  * this function converts a request with the necessary data into a message
259  * and sends it.
260  *
261  * @req_data: the request to be sent (NOTE: the network is in req_data)
262  *
263  */
264
265 int frescan_messages_send_request(const frescan_request_data_t *req_data)
266 {
267         int ret;
268         uint8_t msg[2000]; // TODO: use a constant for max neg message size
269         size_t size;
270
271         switch(req_data->type) {
272                 case FRESCAN_REQ_NEG:
273                         size = frescan_request_to_neg_message(req_data, msg);
274                         break;
275                 case FRESCAN_REQ_RENEG:
276                         size = frescan_request_to_reneg_message(req_data, msg);
277                         break;
278                 case FRESCAN_REQ_CANCEL:
279                         size = frescan_request_to_cancel_message(req_data, msg);
280                         break;
281                 case FRESCAN_REP_NEG:
282                         size = frescan_request_to_repneg_message(req_data, msg);
283                         break;
284                 default:
285                         ERROR("request type not supported\n");
286                         return -1;
287         }
288
289         ret = frescan_send(&send_params[req_data->net], msg, size);
290         if (ret != 0) return ret;
291
292         return 0;
293 }
294
295 /**
296  * frescan_messages_recv_request()
297  *
298  * this function BLOCKS the calling thread until receives a message
299  * and transforms it into a request.
300  *
301  * @req_data: the request data to fill from the message bytes (out)
302  *
303  */
304
305 int frescan_messages_recv_request(frescan_network_t    net,
306                                   frescan_request_id_t *req)
307 {
308         int ret;
309         uint8_t msg[2000]; // TODO: use a constant with the max neg message size
310         size_t recv_bytes;
311         frescan_node_t from;
312         frescan_prio_t prio;
313         frescan_request_data_t *req_data;
314
315         ret = frescan_requests_alloc(req);
316         if (ret != 0) return ret;
317
318         ret = frescan_requests_get_data(*req, &req_data);
319         if (ret != 0) return ret;
320
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);
324
325         ret = frescan_recv(&recv_params[net],
326                             msg,
327                             sizeof(msg),
328                             &recv_bytes,
329                             &from,
330                             &prio);
331         if (ret != 0) return ret;
332
333         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG,
334               "msg received, from:%u size:%u prio:%u\n",
335               from, recv_bytes, prio);
336
337         req_data->request_node = from;
338         req_data->net = net;
339
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);
349                 default:
350                         ERROR("request type not supported\n");
351                         return -1;
352         }
353 }
354
355 /*
356
357 int frescan_message_parse(frescan_network_t net,
358                           const uint8_t *msg,
359                           size_t size,
360                           frescan_node_t from)
361 {
362         int ret;
363         frescan_msg_type_t type;
364         size_t num;
365         uint8_t *tmp;
366         frescan_contract_t contract;
367         frescan_request_id_t request_id;
368         frescan_robj_id_t reply;
369         uint8_t reply_msg[200];
370         int accepted;
371         frescan_neg_return_info_t *neg_return_info;
372         int bytes_to_send;
373         frescan_send_params_t params;
374         frescan_server_params_t server_params;
375
376         params.net = net;
377         params.channel = FRESCAN_NEG_CHANNEL;
378         params.flags = FRESCAN_SS | FRESCAN_ASYNC;
379         params.ss = the_networks[net].neg_messages_ss_id;
380         params.to  = from;
381
382         tmp = (uint8_t *)msg;
383         type = (frescan_msg_type_t)*msg;
384         tmp++;
385
386         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
387               "parsing message, type:%u, size:%u\n", type, size);
388
389         switch (type) {
390                 case FRESCAN_MSG_TYPE_NEG:
391                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
392                               "FRESCAN_MSG_TYPE_NEG\n");
393
394                         num = 2;
395                         memcpy(&request_id, tmp, num);
396                         tmp = tmp + num;
397                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
398                               "request id: %d (2 bytes)\n", request_id);
399
400                         num = sizeof(frescan_contract_t);
401                         memcpy(&contract, tmp, num);
402                         tmp = tmp + num;
403
404                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
405                               "contract (%d bytes)\n", num);
406
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);
412
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);
418
419                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
420                               "prio:%u\n", contract.prio);
421
422                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
423                               "TODO: sched test and add contract to table\n");
424 //                         accepted = 1;
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);
429                         accepted = 1;
430                         FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
431
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;
436
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);
440
441                         bytes_to_send = frescan_repneg_message_create
442                                                 (reply_msg,
443                                                 request_id,
444                                                 accepted,
445                                                 &server_params);
446
447                         DEBUG(FRESCAN_BWRES_ENABLE_DEBUG,
448                                 "bytes_to_send:%u\n", bytes_to_send);
449
450                         if (bytes_to_send <= 0) {
451                                 ERROR("creating reply_msg to neg\n");
452                                 return -1;
453                         }
454
455                         ret = frescan_send(&params, reply_msg, bytes_to_send);
456                         if (ret != 0) {
457                                 ERROR("error while sending neg request to master\n");
458                                 return ret;
459                         }
460                         break;
461
462                 case FRESCAN_MSG_TYPE_REP_NEG:
463                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
464                               "FRESCAN_MSG_TYPE_REP_NEG\n");
465
466                         num = 2;
467                         memcpy(&request_id, tmp, num);
468                         tmp = tmp + num;
469                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
470                               "request id: %d (2 bytes)\n", request_id);
471
472                         ret = frescan_request_get_return_info
473                                         (request_id,
474                                         (void *)&neg_return_info);
475                         if (ret != 0) {
476                                 ERROR("error getting final_values_ref\n");
477                                 return ret;
478                         }
479
480                         accepted = (int)*tmp;
481                         tmp++;
482
483                         if (accepted) {
484                                 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
485                                       "contract accepted:%d\n", accepted);
486                                 neg_return_info->error = 0;
487
488                                 num = sizeof(frescan_budget_period_t);
489                                 memcpy(&server_params.values, tmp, num);
490                                 tmp = tmp + num;
491
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);
497
498                                 num = 1;
499                                 memcpy(&server_params.prio, tmp, num);
500                                 tmp = tmp + num;
501
502                                 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
503                                       "server prio:%u\n", server_params.prio);
504
505                                 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
506                                       "create sporadic server with results\n");
507
508                                 ret = frescan_servers_create(net,
509                                                 &server_params,
510                                                 &neg_return_info->id);
511                                 if (ret != 0) {
512                                         ERROR("error creating server\n");
513                                         return ret;
514                                 }
515                         } else {
516                                 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
517                                       "contract not accepted:%d\n", accepted);
518                                 neg_return_info->error = -1;
519                         }
520
521                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
522                               "signal the request id with the results\n");
523
524                         ret = frescan_request_get_reply(request_id, &reply);
525                         if (ret != 0) {
526                                 ERROR("error getting reply object\n");
527                                 return ret;
528                         }
529
530                         ret = frescan_replyobject_signal(reply);
531                         if (ret != 0) {
532                                 ERROR("error while sending neg request to master\n");
533                                 return ret;
534                         }
535                         break;
536
537                 default:
538                         ERROR("type not known %u\n", type);
539                         return -1;
540         }
541
542         return 0;
543 }*/