]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_messages.c
add the infraestructure for storing the negotiated contracts and performing the analy...
[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, a
212  *  return value to say if the contract is admited or not, and the final
213  *  values if it was admited
214  *
215  *  +----------------------------------------------+
216  *  | 'REPNEG' | REQ | RETURN_VALUE | FINAL_VALUES |
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         frescan_sa_final_values_t final_values;
226 }  __attribute__ ((packed));
227
228 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
229                                              uint8_t *msg)
230 {
231         struct frescan_rep_neg_message_t *repneg_msg;
232
233         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
234
235         repneg_msg->type         = FRESCAN_REP_NEG;
236         repneg_msg->req          = data->req;
237         repneg_msg->return_value = data->return_value;
238         repneg_msg->final_values = data->final_values;
239
240         return sizeof(struct frescan_rep_neg_message_t);
241 }
242
243 static int frescan_repneg_message_to_request(const uint8_t *msg,
244                                              frescan_request_data_t *data)
245 {
246         struct frescan_rep_neg_message_t *repneg_msg;
247
248         repneg_msg = (struct frescan_rep_neg_message_t *)msg;
249
250         data->type         = FRESCAN_REP_NEG;
251         data->req          = repneg_msg->req;
252         data->return_value = repneg_msg->return_value;
253         data->final_values = repneg_msg->final_values;
254
255         return 0;
256 }
257
258 /**
259  * frescan_messages_send_request()
260  *
261  * this function converts a request with the necessary data into a message
262  * and sends it.
263  *
264  * @req_data: the request to be sent (NOTE: the network is in req_data)
265  *
266  */
267
268 int frescan_messages_send_request(const frescan_request_data_t *req_data)
269 {
270         int ret;
271         uint8_t msg[2000]; // TODO: use a constant for max neg message size
272         size_t size;
273
274         switch(req_data->type) {
275                 case FRESCAN_REQ_NEG:
276                         size = frescan_request_to_neg_message(req_data, msg);
277                         send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
278                         break;
279                 case FRESCAN_REQ_RENEG:
280                         size = frescan_request_to_reneg_message(req_data, msg);
281                         send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
282                         break;
283                 case FRESCAN_REQ_CANCEL:
284                         size = frescan_request_to_cancel_message(req_data, msg);
285                         send_params[req_data->net].to = FRESCAN_NEG_MASTER_NODE;
286                         break;
287                 case FRESCAN_REP_NEG:
288                         size = frescan_request_to_repneg_message(req_data, msg);
289                         send_params[req_data->net].to = req_data->request_node;
290                         break;
291                 default:
292                         ERROR("request type not supported\n");
293                         return -1;
294         }
295
296         ret = frescan_send(&send_params[req_data->net], msg, size);
297         if (ret != 0) return ret;
298
299         return 0;
300 }
301
302 /**
303  * frescan_messages_recv_request()
304  *
305  * this function BLOCKS the calling thread until receives a message
306  * and transforms it into a request.
307  *
308  * @req_data: the request data to fill from the message bytes (out)
309  *
310  */
311
312 int frescan_messages_recv_request(frescan_network_t    net,
313                                   frescan_request_id_t *req)
314 {
315         int ret;
316         uint8_t msg[2000]; // TODO: use a constant with the max neg message size
317         size_t recv_bytes;
318         frescan_node_t from;
319         frescan_prio_t prio;
320         frescan_request_data_t *req_data;
321
322         ret = frescan_requests_alloc(req);
323         if (ret != 0) return ret;
324
325         ret = frescan_requests_get_data(*req, &req_data);
326         if (ret != 0) return ret;
327
328         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG,
329               "wait for a msg, net:%u chan:%u flags:%u\n",
330               net, recv_params[net].channel, recv_params[net].flags);
331
332         ret = frescan_recv(&recv_params[net],
333                             msg,
334                             sizeof(msg),
335                             &recv_bytes,
336                             &from,
337                             &prio);
338         if (ret != 0) return ret;
339
340         DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG,
341               "msg received, from:%u size:%u prio:%u\n",
342               from, recv_bytes, prio);
343
344         req_data->request_node = from;
345         req_data->net = net;
346
347         switch(*((frescan_request_type_t *)msg)) {
348                 case FRESCAN_REQ_NEG:
349                         return frescan_neg_message_to_request(msg, req_data);
350                 case FRESCAN_REQ_RENEG:
351                         return frescan_reneg_message_to_request(msg, req_data);
352                 case FRESCAN_REQ_CANCEL:
353                         return frescan_cancel_message_to_request(msg, req_data);
354                 case FRESCAN_REP_NEG:
355                         return frescan_repneg_message_to_request(msg, req_data);
356                 default:
357                         ERROR("request type not supported\n");
358                         return -1;
359         }
360 }