]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_messages.c
renamings... redo the request and messages part... also now there will be two threads...
[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  *
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.
36  *
37  *      1     2     2      N
38  *  +-----------------------------+
39  *  | 'NEG' | REQ | SS | CONTRACT |
40  *  +-----------------------------+
41  *
42  */
43
44 struct frescan_req_neg_message_t {
45         frescan_request_type_t   type;
46         frescan_request_id_t     req;
47         frescan_ss_t             ss;
48         frescan_contract_t       contract;
49 }  __attribute__ ((packed));
50
51 static int frescan_request_to_neg_message(const frescan_request_data_t *data,
52                                           uint8_t *msg)
53 {
54         struct frescan_req_neg_message_t *neg_msg;
55
56         neg_msg = (struct frescan_req_neg_message_t *)msg;
57
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);
62
63         return 0;
64 }
65
66 static int frescan_neg_message_to_request(const uint8_t *msg,
67                                           frescan_request_data_t *data)
68 {
69         struct frescan_req_neg_message_t *neg_msg;
70
71         neg_msg = (struct frescan_req_neg_message_t *)msg;
72
73         data->type        = FRESCAN_REQ_NEG;
74         data->req         = neg_msg->req;
75         data->ss          = neg_msg->ss;
76         *(data->contract) = neg_msg->contract;
77
78         return 0;
79 }
80
81 /**
82  *
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.
91  *
92  *      1       2     2      N
93  *  +-------------------------------+
94  *  | 'RENEG' | REQ | SS | CONTRACT |
95  *  +-------------------------------+
96  *
97  */
98
99 struct frescan_req_reneg_message_t {
100         frescan_request_type_t   type;
101         frescan_request_id_t     req;
102         frescan_ss_t             ss;
103         frescan_contract_t       contract;
104 }  __attribute__ ((packed));
105
106 static int frescan_request_to_reneg_message(const frescan_request_data_t *data,
107                                             uint8_t *msg)
108 {
109         struct frescan_req_reneg_message_t *reneg_msg;
110
111         reneg_msg = (struct frescan_req_reneg_message_t *)msg;
112
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);
117
118         return 0;
119 }
120
121 static int frescan_reneg_message_to_request(const uint8_t *msg,
122                                             frescan_request_data_t *data)
123 {
124         struct frescan_req_reneg_message_t *reneg_msg;
125
126         reneg_msg = (struct frescan_req_reneg_message_t *)msg;
127
128         data->type        = FRESCAN_REQ_RENEG;
129         data->req         = reneg_msg->req;
130         data->ss          = reneg_msg->ss;
131         *(data->contract) = reneg_msg->contract;
132
133         return 0;
134 }
135
136 /**
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
142  *  message.
143  *
144  *  +---------------+
145  *  | 'CANCEL' | SS |
146  *  +---------------+
147  *
148  */
149
150 struct frescan_req_cancel_message_t {
151         frescan_request_type_t   type;
152         frescan_ss_t             ss;
153 }  __attribute__ ((packed));
154
155 static int frescan_request_to_cancel_message(const frescan_request_data_t *data,
156                                              uint8_t *msg)
157 {
158         struct frescan_req_cancel_message_t *cancel_msg;
159
160         cancel_msg = (struct frescan_req_cancel_message_t *)msg;
161
162         cancel_msg->type     = FRESCAN_REQ_CANCEL;
163         cancel_msg->ss       = data->ss;
164
165         return 0;
166 }
167
168 static int frescan_cancel_message_to_request(const uint8_t *msg,
169                                              frescan_request_data_t *data)
170 {
171         struct frescan_req_cancel_message_t *cancel_msg;
172
173         cancel_msg = (struct frescan_req_cancel_message_t *)msg;
174
175         data->type        = FRESCAN_REQ_CANCEL;
176         data->ss          = cancel_msg->ss;
177
178         return 0;
179 }
180
181 /**
182  *
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.
190  *
191  *  +-------------------------------+
192  *  | 'REPNEG' | REQ | RETURN_VALUE |
193  *  +-------------------------------+
194  *
195  */
196
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));
202
203 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
204                                              uint8_t *msg)
205 {
206         struct frescan_rep_neg_message_t *repneg_msg;
207
208         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
209
210         repneg_msg->type         = FRESCAN_REP_NEG;
211         repneg_msg->req          = data->req;
212         repneg_msg->return_value = data->return_value;
213
214         return 0;
215 }
216
217 static int frescan_repneg_message_to_request(const uint8_t *msg,
218                                              frescan_request_data_t *data)
219 {
220         struct frescan_rep_neg_message_t *repneg_msg;
221
222         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
223
224         data->type         = FRESCAN_REP_NEG;
225         data->req          = repneg_msg->req;
226         data->return_value = repneg_msg->return_value;
227
228         return 0;
229 }
230
231 /**
232  * frescan_request_to_message() - converts a request into a network message
233  *
234  * this function converts a request with the necessary data into a message
235  * that can be sent through the network.
236  *
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)
239  *
240  */
241
242 int frescan_request_to_message(const frescan_request_data_t *req_data,
243                                uint8_t *msg)
244 {
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);
254                 default:
255                         ERROR("request type not supported\n");
256                         return -1;
257         }
258 }
259
260 /**
261  * frescan_message_to_request() - converts a network message into a request
262  *
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
265  * into requests.
266  *
267  * @msg: buffer with the bytes received from the network (in)
268  * @req_data: the request data to fill from the message bytes (out)
269  *
270  */
271
272 int frescan_message_to_request(const uint8_t *msg,
273                                frescan_request_data_t *req_data)
274 {
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);
284                 default:
285                         ERROR("request type not supported\n");
286                         return -1;
287         }
288 }
289
290 /*
291
292 int frescan_message_parse(frescan_network_t net,
293                           const uint8_t *msg,
294                           size_t size,
295                           frescan_node_t from)
296 {
297         int ret;
298         frescan_msg_type_t type;
299         size_t num;
300         uint8_t *tmp;
301         frescan_contract_t contract;
302         frescan_request_id_t request_id;
303         frescan_robj_id_t reply;
304         uint8_t reply_msg[200];
305         int accepted;
306         frescan_neg_return_info_t *neg_return_info;
307         int bytes_to_send;
308         frescan_send_params_t params;
309         frescan_server_params_t server_params;
310
311         params.net = net;
312         params.channel = FRESCAN_NEG_CHANNEL;
313         params.flags = FRESCAN_SS | FRESCAN_ASYNC;
314         params.ss = the_networks[net].neg_messages_ss_id;
315         params.to  = from;
316
317         tmp = (uint8_t *)msg;
318         type = (frescan_msg_type_t)*msg;
319         tmp++;
320
321         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
322               "parsing message, type:%u, size:%u\n", type, size);
323
324         switch (type) {
325                 case FRESCAN_MSG_TYPE_NEG:
326                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
327                               "FRESCAN_MSG_TYPE_NEG\n");
328
329                         num = 2;
330                         memcpy(&request_id, tmp, num);
331                         tmp = tmp + num;
332                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
333                               "request id: %d (2 bytes)\n", request_id);
334
335                         num = sizeof(frescan_contract_t);
336                         memcpy(&contract, tmp, num);
337                         tmp = tmp + num;
338
339                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
340                               "contract (%d bytes)\n", num);
341
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);
347
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);
353
354                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
355                               "prio:%u\n", contract.prio);
356
357                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
358                               "TODO: sched test and add contract to table\n");
359 //                         accepted = 1;
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);
364                         accepted = 1;
365                         FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
366
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;
371
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);
375
376                         bytes_to_send = frescan_repneg_message_create
377                                                 (reply_msg,
378                                                 request_id,
379                                                 accepted,
380                                                 &server_params);
381
382                         DEBUG(FRESCAN_BWRES_ENABLE_DEBUG,
383                                 "bytes_to_send:%u\n", bytes_to_send);
384
385                         if (bytes_to_send <= 0) {
386                                 ERROR("creating reply_msg to neg\n");
387                                 return -1;
388                         }
389
390                         ret = frescan_send(&params, reply_msg, bytes_to_send);
391                         if (ret != 0) {
392                                 ERROR("error while sending neg request to master\n");
393                                 return ret;
394                         }
395                         break;
396
397                 case FRESCAN_MSG_TYPE_REP_NEG:
398                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
399                               "FRESCAN_MSG_TYPE_REP_NEG\n");
400
401                         num = 2;
402                         memcpy(&request_id, tmp, num);
403                         tmp = tmp + num;
404                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
405                               "request id: %d (2 bytes)\n", request_id);
406
407                         ret = frescan_request_get_return_info
408                                         (request_id,
409                                         (void *)&neg_return_info);
410                         if (ret != 0) {
411                                 ERROR("error getting final_values_ref\n");
412                                 return ret;
413                         }
414
415                         accepted = (int)*tmp;
416                         tmp++;
417
418                         if (accepted) {
419                                 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
420                                       "contract accepted:%d\n", accepted);
421                                 neg_return_info->error = 0;
422
423                                 num = sizeof(frescan_budget_period_t);
424                                 memcpy(&server_params.values, tmp, num);
425                                 tmp = tmp + num;
426
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);
432
433                                 num = 1;
434                                 memcpy(&server_params.prio, tmp, num);
435                                 tmp = tmp + num;
436
437                                 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
438                                       "server prio:%u\n", server_params.prio);
439
440                                 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
441                                       "create sporadic server with results\n");
442
443                                 ret = frescan_servers_create(net,
444                                                 &server_params,
445                                                 &neg_return_info->id);
446                                 if (ret != 0) {
447                                         ERROR("error creating server\n");
448                                         return ret;
449                                 }
450                         } else {
451                                 DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
452                                       "contract not accepted:%d\n", accepted);
453                                 neg_return_info->error = -1;
454                         }
455
456                         DEBUG(FRESCAN_NEG_MESSAGES_ENABLE_DEBUG,
457                               "signal the request id with the results\n");
458
459                         ret = frescan_request_get_reply(request_id, &reply);
460                         if (ret != 0) {
461                                 ERROR("error getting reply object\n");
462                                 return ret;
463                         }
464
465                         ret = frescan_replyobject_signal(reply);
466                         if (ret != 0) {
467                                 ERROR("error while sending neg request to master\n");
468                                 return ret;
469                         }
470                         break;
471
472                 default:
473                         ERROR("type not known %u\n", type);
474                         return -1;
475         }
476
477         return 0;
478 }*/