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, a
212 * return value to say if the contract is admited or not, and the final
213 * values if it was admited
215 * +----------------------------------------------+
216 * | 'REPNEG' | REQ | RETURN_VALUE | FINAL_VALUES |
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 frescan_sa_final_values_t final_values;
226 } __attribute__ ((packed));
228 static int frescan_request_to_repneg_message(const frescan_request_data_t *data,
231 struct frescan_rep_neg_message_t *repneg_msg;
233 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
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;
240 return sizeof(struct frescan_rep_neg_message_t);
243 static int frescan_repneg_message_to_request(const uint8_t *msg,
244 frescan_request_data_t *data)
246 struct frescan_rep_neg_message_t *repneg_msg;
248 repneg_msg = (struct frescan_rep_neg_message_t *)msg;
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;
259 * frescan_messages_send_request()
261 * this function converts a request with the necessary data into a message
264 * @req_data: the request to be sent (NOTE: the network is in req_data)
268 int frescan_messages_send_request(const frescan_request_data_t *req_data)
271 uint8_t msg[2000]; // TODO: use a constant for max neg message size
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;
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;
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;
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;
292 ERROR("request type not supported\n");
296 ret = frescan_send(&send_params[req_data->net], msg, size);
297 if (ret != 0) return ret;
303 * frescan_messages_recv_request()
305 * this function BLOCKS the calling thread until receives a message
306 * and transforms it into a request.
308 * @req_data: the request data to fill from the message bytes (out)
312 int frescan_messages_recv_request(frescan_network_t net,
313 frescan_request_id_t *req)
316 uint8_t msg[2000]; // TODO: use a constant with the max neg message size
320 frescan_request_data_t *req_data;
322 ret = frescan_requests_alloc(req);
323 if (ret != 0) return ret;
325 ret = frescan_requests_get_data(*req, &req_data);
326 if (ret != 0) return ret;
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);
332 ret = frescan_recv(&recv_params[net],
338 if (ret != 0) return ret;
340 DEBUG(FRESCAN_MESSAGES_ENABLE_DEBUG,
341 "msg received, from:%u size:%u prio:%u\n",
342 from, recv_bytes, prio);
344 req_data->request_node = from;
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);
357 ERROR("request type not supported\n");