]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_fna.c
renaming
[frescor/fna.git] / src_frescan / frescan_bwres_fna.c
1 /*!
2  * @file frescan_bwres_fna.c
3  *
4  * @brief FRESCAN bandwidth reservation layer: FNA hooks
5  *
6  * This module contains hooks to integrate the FRESCAN protocol in FRSH
7  *
8  * @version 0.01
9  *
10  * @date 1-Apr-2008
11  *
12  * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
13  *
14  */
15
16 #include "frsh.h" /* frsh_resource_id_t, .. */
17 #include "frescan.h" /* frescan_init, ... */
18 #include "frescan_data.h" /* frescan_contract_t, ... */
19 #include "frescan_bwres.h" /* frescan_bwres_init, ... */
20 #include "fna.h" /* fna_vres_id_t, fna_endpoint_data_t */
21
22 #undef ERROR
23 #include "frescan_debug.h" /* DEBUG, ERROR */
24
25 //////////////////////////////////////////////////////////////////////
26 //           INITIALIZATION
27 //////////////////////////////////////////////////////////////////////
28
29 /**
30  * frescan_fna_init()
31  *
32  * This function will be hooked to the frsh_init function and it is
33  * intented to initialize the protocol and its structures.
34  *
35  * @param[in]  resource_id The network we are referring to (a protocol
36  * could be able to handle several networks at the same time)
37  *
38  * @return
39  *   0 if there are no errors \n
40  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
41  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
42  *   FNA_ERR_ALREADY_INITIALIZED:
43  *      if the function has already been called before (with success) \n
44  *
45  **/
46 int frescan_fna_init(const frsh_resource_id_t resource_id)
47 {
48         int ret;
49         frescan_init_params_t init_params;
50
51         // TODO: resource_id must be relative or sth
52         // TODO: init_params must be configurable
53         init_params.net = (frescan_network_t)resource_id;
54         init_params.node = (frescan_node_t)FRSH_CPU_ID_DEFAULT;
55         init_params.tx_fp_max_prio = 10;
56         init_params.rx_num_of_channels = 10;
57         init_params.rx_channel_max_prio = NULL;
58
59         DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "Initializing FRESCAN\n");
60
61         ret = frescan_init(&init_params);
62         if (ret != 0) ERROR ("could not init FRESCAN");
63
64         DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "Initializing BWRES\n");
65
66         ret = frescan_bwres_init(init_params.net);
67         if (ret != 0) ERROR ("could not init BWRES");
68
69         return 0;
70 }
71
72 ///////////////////////////////////////////////////////////////////
73 //           VIRTUAL RESOURCES
74 ///////////////////////////////////////////////////////////////////
75
76 /**
77  * frescan_fna_contract_negotiate()
78  *
79  * The operation negotiates a contract and if accepted it will return
80  * a fna_vres_id_t. It will also check that the given contract_id is unique
81  * within the network.
82  *
83  * If the on-line admission test is enabled, it determines whether the
84  * contract can be admitted or not based on the current contracts
85  * established in the network. Then it creates the vres and
86  * recalculates all necessary parameters for the contracts already
87  * present in the system.
88  *
89  * This is a potentially blocking operation, it returns when the
90  * system has either rejected the contract, or admitted it and made it
91  * effective.
92  *
93  * @param[in] resource_id The network we are referring to (a protocol
94  * could be able to handle several networks at the same time)
95  * @param[in] contract  The contract parameters to negotiate
96  * @param[out] vres The internal virtual resource id
97  *
98  * @return
99  *   0 if there are no errors (in this case it also means contract accepted) \n
100  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
101  *   FNA_ERR_TOO_MANY_VRES: if there is no space for more vres \n
102  *   FNA_ERR_CONTRACT_ID_ALREADY_EXISTS: contract_id is not unique \n
103  *   FNA_ERR_CONTRACT_REJECTED: if the contract is not accepted \n
104  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
105  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
106  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
107  *
108  **/
109 int frescan_fna_contract_negotiate
110                 (const frsh_resource_id_t resource_id,
111                  const frsh_contract_t *contract,
112                  fna_vres_id_t *vres)
113 {
114         int accepted;
115         frescan_ss_t ss;
116         frescan_contract_t frescan_contract;
117
118         DEBUG(FRESCAN_FNA_ENABLE_DEBUG,
119               "frsh contract->frescan contract\n");
120
121         // TODO: budget is stored as number of can frames in tv_sec
122         frescan_contract.min_values.budget = contract->budget_min.tv_sec;
123         frescan_contract.min_values.period = contract->period_max;
124
125         frescan_contract.max_values.budget = contract->budget_max.tv_sec;
126         frescan_contract.max_values.period = contract->period_min;
127
128         frescan_contract.prio = contract->preemption_level;
129
130         DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "calling frescan_bwres_negotiate\n");
131         accepted = frescan_bwres_negotiate((frescan_network_t)resource_id,
132                                            &frescan_contract,
133                                            &ss); // TODO: associate the contract with the ss
134
135         if (accepted == 0) {
136                 DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "contract accepted\n");
137                 *vres = (fna_vres_id_t)ss;
138         } else {
139                 DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "contract not accepted\n");
140         }
141
142         return accepted;
143 }
144
145 /**
146  * frescan_fna_contract_renegotiate_sync()
147  *
148  * The operation renegotiates a contract for an existing vres. If
149  * the on-line admission test is enabled it determines whether the
150  * contract can be admitted or not based on the current contracts
151  * established in the system. If it cannot be admitted, the old
152  * contract remains in effect and an error is returned. If it can be
153  * admitted, it recalculates all necessary parameters for the
154  * contracts already present in the system and returns zero. This is a
155  * potentially blocking operation; it returns when the system has
156  * either rejected the new contract, or admitted it and made it
157  * effective.
158  *
159  * @param[in] resource_id The network we are referring to (a protocol
160  * could be able to handle several networks at the same time)
161  * @param[in] vres The internal virtual resource id to renegotiate
162  * @param[in] new_contract The new contract
163  *
164  *  @return
165  *   0 if there are no errors (in this case it also means contract accepted) \n
166  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
167  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
168  *   FNA_ERR_CONTRACT_ID_ALREADY_EXISTS: contract_id is not unique \n
169  *   FNA_ERR_CONTRACT_REJECTED: if the contract is not accepted \n
170  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
171  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
172  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
173  *
174  **/
175 int frescan_fna_contract_renegotiate_sync
176                 (const frsh_resource_id_t resource_id,
177                  const fna_vres_id_t vres,
178                  const frsh_contract_t *new_contract)
179 {
180         ERROR("not implemented\n");
181         return -1;
182 }
183
184 /**
185  * frescan_fna_contract_renegotiate_async()
186  *
187  * The operation enqueues a renegotiate operation for an existing
188  * vres, and returns immediately. The renegotiate operation is
189  * performed asynchronously, as soon as it is practical; meanwhile the
190  * system operation will continue normally. When the renegotiation is
191  * made, if the on-line admission test is enabled it determines
192  * whether the contract can be admitted or not based on the current
193  * contracts established in the system. If it cannot be admitted, the
194  * old contract remains in effect. If it can be admitted, it
195  * recalculates all necessary parameters for the contracts already
196  * present in the system.
197  *
198  * When the operation is completed, notification is made to the
199  * caller, if requested, via a signal. The status of the operation (in
200  * progress, admitted, rejected) can be checked with the
201  * frsh_vres_get_renegotiation_status() operation.  The argument
202  * sig_notify can be FRSH_NULL_SIGNAL (no notification), or any FRSH
203  * signal value and in this case signal_info is to be sent with the signal.
204  *
205  * @param[in] resource_id The network we are referring to (a protocol
206  * could be able to handle several networks at the same time)
207  * @param[in] vres The internal virtual resource id to renegotiate
208  * @param[in] new_contract The new contract
209  * @param[in] signal_to_notify  Signal number to use to notify vres of
210  * the negotiation result. If FRSH_NULL_SIGNAL,  no signal will be raised.
211  * @param[in] signal_info: Associated info that will come with the signal.
212  * This parameter will be ignored if signal_to_notify == FRSH_NULL_SIGNAL.
213  *
214  * @return
215  *   0 if there are no errors \n
216  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
217  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
218  *   FNA_ERR_CONTRACT_ID_ALREADY_EXISTS: contract_id is not unique \n
219  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
220  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
221  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL, or sig_notify is neither
222  *      NULL nor a valid POSIX signal \n
223  *
224  **/
225 int frescan_fna_contract_renegotiate_async
226                 (const frsh_resource_id_t resource_id,
227                  const fna_vres_id_t vres,
228                  const frsh_contract_t *new_contract,
229                  frsh_signal_t signal_to_notify,
230                  frsh_signal_info_t signal_info)
231 {
232         ERROR("not implemented\n");
233         return -1;
234 }
235
236 /**
237  * frescan_fna_vres_get_renegotiation_status()
238  *
239  * The operation reports on the status of the last renegotiation
240  * operation enqueued for the specified vres. It is callable even
241  * after notification of the completion of such operation, if
242  * requested.
243  *
244  * If the vres is not and has not been involved in any of the
245  * frsh_contract_renegotiate_async() or frsh_group_change_mode_async()
246  * operations, the status returned is FNA_NOT_REQUESTED
247  *
248  * @param[in] resource_id The network we are referring to (a protocol
249  * could be able to handle several networks at the same time)
250  * @param[in] vres The internal virtual resource id we want the status from
251  * @param[in] renegotiation_status The status of the last renegotiation on
252  * vres (FRSH_RS_IN_PROGRESS, FRSH_RS_REJECTED, FRSH_RS_ADMITTED,
253  * FRSH_RS_NOT_REQUESTED)
254  *
255  * @return
256  *   0 if there are no errors \n
257  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
258  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
259  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
260  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
261  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
262  *
263  **/
264 int frescan_fna_vres_get_renegotiation_status
265                 (const frsh_resource_id_t resource_id,
266                  const fna_vres_id_t vres,
267                  frsh_renegotiation_status_t *renegotiation_status)
268 {
269         ERROR("not implemented\n");
270         return -1;
271 }
272
273 /**
274  * frescan_fna_vres_destroy()
275  *
276  * The operation eliminates the specified vres
277  * and recalculates all necessary parameters for the contracts
278  * remaining in the system. This is a potentially blocking operation;
279  * it returns when the system has made the changes effective.
280  *
281  * @param[in] resource_id The network we are referring to (a protocol
282  * could be able to handle several networks at the same time)
283  * @param[in] vres The internal virtual resource id to destroy
284  *
285  * @return
286  *   0 if there are no errors \n
287  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
288  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
289  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
290  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
291  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
292  *
293  **/
294 int frescan_fna_vres_destroy
295                 (const frsh_resource_id_t resource_id,
296                  const fna_vres_id_t vres)
297 {
298         ERROR("not implemented\n");
299         return -1;
300 }
301
302 /**
303  * frescan_fna_vres_get_contract()
304  *
305  * This operation stores the contract parameters currently associated
306  * with the specified vres in the variable pointed to by
307  * contract. It returns an error if the vres_id is not recognised.
308  *
309  * @param[in] resource_id The network we are referring to (a protocol
310  * could be able to handle several networks at the same time)
311  * @param[in] vres The internal virtual resource id
312  * @param[out] contract  The contract parameters that we want
313  *
314  * @return
315  *   0 if there are no errors \n
316  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
317  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
318  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
319  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
320  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
321  *
322  **/
323 int frescan_fna_vres_get_contract
324                 (const frsh_resource_id_t resource_id,
325                  const fna_vres_id_t vres,
326                  frsh_contract_t *contract)
327 {
328         ERROR("not implemented\n");
329         return -1;
330 }
331
332 /**
333  * frescan_fna_vres_get_usage()
334  *
335  * This function gets the execution time spent by all messages that have been
336  * sent through the specified vres.
337  *
338  * @param[in] resource_id The network we are referring to (a protocol
339  * could be able to handle several networks at the same time)
340  * @param[in] vres The internal virtual resource id
341  * @param[out] usage  Execution time spent by this vres
342  *
343  * @return
344  *   0 if there are no errors \n
345  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
346  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
347  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
348  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
349  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
350  *
351  **/
352 int frescan_fna_vres_get_usage
353                 (const frsh_resource_id_t resource_id,
354                  const fna_vres_id_t vres,
355                  struct timespec *usage)
356 {
357         ERROR("not implemented\n");
358         return -1;
359 }
360
361 /**
362  * frescan_fna_vres_get_remaining_budget()
363  *
364  * This function stores in the variable pointed to by budget the
365  * remaining execution-time budget associated with the specified
366  * vres in the present period.
367  *
368  * @param[in] resource_id The network we are referring to (a protocol
369  * could be able to handle several networks at the same time)
370  * @param[in] vres The internal virtual resource id
371  * @param[out] remaining_budget  The remaining budget for this period
372  *
373  *  @return
374  *   0 if there are no errors \n
375  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
376  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
377  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
378  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
379  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
380  *
381  **/
382 int frescan_fna_vres_get_remaining_budget
383                 (const frsh_resource_id_t resource_id,
384                  const fna_vres_id_t vres,
385                  struct timespec *remaining_budget)
386 {
387         ERROR("not implemented\n");
388         return -1;
389 }
390
391 /**
392  * frescan_fna_vres_get_budget_and_period()
393  *
394  * This function gets the budget and period associated with the specified vres
395  * for each period. If one of these pointers is NULL, the corresponding
396  * information is not stored.
397  *
398  * @param[in] resource_id The network we are referring to (a protocol
399  * could be able to handle several networks at the same time)
400  * @param[in] vres The internal virtual resource id
401  * @param[out] budget The budget associated to vres
402  * @param[out] period  The period associated to vres
403  *
404  * @return
405  *   0 if there are no errors \n
406  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
407  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
408  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
409  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
410  *   FNA_ERR_BAD_ARGUMENT: if both pointers are NULL \n
411  *
412  **/
413 int frescan_fna_vres_get_budget_and_period
414                 (const frsh_resource_id_t resource_id,
415                  const fna_vres_id_t vres,
416                  struct timespec *budget,
417                  struct timespec *period)
418 {
419         ERROR("not implemented\n");
420         return -1;
421 }
422
423 /*@}*/
424
425 ///////////////////////////////////////////////////////////////////
426 //           SPARE CAPACITY FUNCIONS
427 ///////////////////////////////////////////////////////////////////
428
429 /**
430  * @defgroup fnaspare FNA Spare Capacity
431  * @ingroup fna
432  *
433  * The following functions are used to get spare capacity data
434  *
435  * @{
436  **/
437
438 /**
439  * frescan_fna_resource_get_capacity()
440  *
441  * This operation gets the spare capacity currently assigned to a importance
442  * level. If we divide this value by UINT32_MAX we will get the network
443  * utilization associated to the spare capacity of a importance level.
444  *
445  * The following is typically in stdint.h: \n
446  *  - typedef unsigned int uint32_t;  \n
447  *  - # define UINT32_MAX  (4294967295U)  \n
448  *
449  * @param[in] resource_id The network we are referring to (a protocol
450  * could be able to handle several networks at the same time)
451  * @param[in] importance The importance we want the capacity of
452  * @param[out] capacity The spare capacity for that importance level
453  *
454  * @return
455  *   0 if there are no errors \n
456  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
457  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
458  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
459  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
460  *
461  **/
462 int frescan_fna_resource_get_capacity
463                 (const frsh_resource_id_t resource_id,
464                  const int importance,
465                  uint32_t *capacity)
466 {
467         ERROR("not implemented\n");
468         return -1;
469 }
470
471 /**
472  * frescan_fna_resource_get_total_weight()
473  *
474  * This function gets the sum of the weight parameters for all vres in a
475  * network of an importance level.
476  *
477  * @param[in] resource_id The network we are referring to (a protocol
478  * could be able to handle several networks at the same time)
479  * @param[in] importance The importance we want the total weight of
480  * @param[out] total_weight The total weight for that importance level
481  *
482  * @return
483  *   0 if there are no errors \n
484  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
485  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
486  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
487  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
488  *
489  **/
490 int frescan_fna_resource_get_total_weight
491                 (const frsh_resource_id_t resource_id,
492                  const int importance,
493                  int *total_weight)
494 {
495         ERROR("not implemented\n");
496         return -1;
497 }
498
499 /**
500  * frescan_fna_vres_decrease_capacity()
501  *
502  * This function allows to ask for less budget and period than what we
503  * received. The request must be compatible with the rest of contract
504  * parameters of the vres. If we want to recover the released capacity
505  * we will need to renegotiate.
506  *
507  * @param[in] resource_id The network we are referring to (a protocol
508  * could be able to handle several networks at the same time)
509  * @param[in] vres The internal virtual resource id
510  * @param[in] new_budget The new_budget
511  * @param[in] new_period The new Period
512  *
513  * @return
514  *   0 if there are no errors \n
515  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
516  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
517  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
518  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
519  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
520  *   FNA_ERR_CONTRACT_REJECTED: if it is incompatible with the current
521  *      contract \n
522  *
523  **/
524 int frescan_fna_vres_decrease_capacity
525                 (const frsh_resource_id_t resource_id,
526                  const fna_vres_id_t vres,
527                  const struct timespec new_budget,
528                  const struct timespec new_period)
529 {
530         ERROR("not implemented\n");
531         return -1;
532 }
533
534 ///////////////////////////////////////////////////////////////////
535 //           SEND RECEIVE OPERATIONS
536 ///////////////////////////////////////////////////////////////////
537
538 /**
539  * frescan_fna_send_sync()
540  *
541  * Similar to previous function but now the sending thread gets blocked
542  * until the message is already sent to the network.
543  *
544  * @param[in] endpoint The send endpoint we are sending through. It must
545  *    be bound to a virtual resource (resource_id is in the endpoint).
546  * @param[in] msg The message we want to send
547  * @param[in] size The size in bytes of the message
548  *
549  * @returns
550  *   0 if there are no errors \n
551  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
552  *   FNA_ERR_NOT_BOUND: if endpoint is not bound to a valid vres \n
553  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
554  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
555  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
556  *   FNA_ERR_TOO_LARGE: if the message is too large for the network protocol \n
557  *   FNA_ERR_BUFFER_FULL: if the message has been discarded because
558  *   the queue is full (and does not have the policy FNA_QP_OLDEST) \n
559  *
560  **/
561 int frescan_fna_send_sync
562                 (const fna_endpoint_data_t *endpoint,
563                  const void *msg,
564                  const size_t size)
565 {
566         ERROR("not implemented\n");
567         return -1;
568 }
569
570 /**
571  * frescan_fna_send_async()
572  *
573  * This operation sends a message stored in msg and of length size
574  * through the given send endpoint. The operation is non-blocking and
575  * returns immediately.
576  *
577  * @param[in] endpoint The send endpoint we are sending through. It must
578  *    be bound to a virtual resource (resource_id is in the endpoint).
579  * @param[in] msg The message we want to send
580  * @param[in] size The size in bytes of the message
581  *
582  * @returns
583  *   0 if there are no errors \n
584  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
585  *   FNA_ERR_NOT_BOUND: if endpoint is not bound to a valid vres \n
586  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
587  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
588  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
589  *   FNA_ERR_TOO_LARGE: if the message is too large for the network protocol \n
590  *   FNA_ERR_BUFFER_FULL: if the message has been discarded because
591  *   the queue is full (and does not have the policy FNA_QP_OLDEST) \n
592  *
593  **/
594 int frescan_fna_send_async
595                 (const fna_endpoint_data_t *endpoint,
596                  const void *msg,
597                  const size_t size)
598 {
599         int ret;
600         frescan_send_params_t params;
601
602         DEBUG(FRESCAN_FNA_ENABLE_DEBUG,
603               "net:%u dest:%u chan:%u size:%u ss:%u\n",
604               endpoint->resource_id, endpoint->destination,
605               endpoint->stream_id, size, endpoint->vres);
606
607         params.net      = (frescan_network_t)endpoint->resource_id;
608         params.to       = (frescan_node_t)endpoint->destination;
609         params.channel  = (frescan_channel_t)endpoint->stream_id;
610         params.flags    = FRESCAN_SS | FRESCAN_ASYNC;
611         params.ss       = endpoint->vres;
612
613         ret = frescan_send(&params, (uint8_t *)msg, size);
614         if (ret != 0) {
615                 ERROR ("could not send message\n");
616                 return -1;
617         }
618
619         return 0;
620 }
621
622 /**
623  * frescan_fna_receive_sync()
624  *
625  * This operation is used to receive messages from the network with a
626  * blocking behavior (if there are no messages this operation blocks
627  * the calling thread).
628  *
629  * When a message is available, it is copied to buffer (up to its size).
630  * The number of bytes copied is returned in received_bytes. The rest
631  * of the bytes of that message will be lost or not depending on the
632  * protocol (FNA_ERR_NO_SPACE will be returned if it is).
633  *
634  * The function fails with FNA_ERR_NO_SPACE if the buffersize is
635  * too small for the message received.  In this case the message is
636  * lost.
637  *
638  * Messages arriving at a receiver buffer that is full will be handled
639  * according to the queueing policy of the endpoint (overwrite oldest,
640  * discard it,etc).
641  *
642  * @param[in] endpoint The receive endpoint we are receiving from.
643  *    (resource_id is in the endpoint).
644  * @param[out] buffer Buffer for storing the received message
645  * @param[in] buffer_size The size in bytes of this buffer
646  * @param[out] received_bytes The actual number of received bytes
647  * @param[out] from Address of the sender node
648  *
649  * @return
650  *   0 if there are no errors \n
651  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
652  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
653  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
654  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
655  *   FNA_ERR_NO_SPACE: if the message size is bigger than the
656  *      provided buffer. \n
657  *
658  **/
659 int frescan_fna_receive_sync
660                 (const fna_endpoint_data_t *endpoint,
661                  void *buffer,
662                  const size_t buffer_size,
663                  size_t *received_bytes,
664                  frsh_network_address_t *from)
665 {
666         int ret;
667         frescan_recv_params_t params;
668         frescan_node_t frescan_from;
669         frescan_prio_t prio;
670
671         params.net      = (frescan_network_t)endpoint->resource_id;
672         params.channel  = (frescan_channel_t)endpoint->stream_id;
673         params.flags    = FRESCAN_SYNC;
674
675         DEBUG(FRESCAN_FNA_ENABLE_DEBUG,
676               "net:%u chan:%u size:%u\n",
677               endpoint->resource_id, endpoint->stream_id, buffer_size);
678
679         ret = frescan_recv(&params, (uint8_t *)buffer, buffer_size,
680                            received_bytes, &frescan_from, &prio);
681
682         if (ret != 0) {
683                 ERROR ("error while receiving message");
684                 return -1;
685         }
686
687         *from = (frsh_network_address_t)frescan_from;
688
689         DEBUG(FRESCAN_FNA_ENABLE_DEBUG,
690               "msg received, from:%u bytes:%u prio:%u\n",
691               *from, *received_bytes, prio);
692
693         return 0;
694 }
695
696 /**
697  * frescan_fna_receive_async()
698  *
699  * This operation is similar to the previous one but it works in a non
700  * blocking (asynchronous) fashion.  If no message is available it
701  * returns with error FNA_NO_MESSAGE.
702  *
703  * @param[in] endpoint The receive endpoint we are receiving from.
704  *    (resource_id is in the endpoint).
705  * @param[out] buffer Buffer for storing the received message
706  * @param[in] buffer_size The size in bytes of this buffer
707  * @param[out] received_bytes The actual number of received bytes
708  * @param[out] from Address of the sender node
709  *
710  * @return
711  *   0 if there are no errors \n
712  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
713  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
714  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
715  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
716  *   FNA_ERR_NO_SPACE: if the message size is bigger than the
717  *      provided buffer. \n
718  *   FNA_NO_MESSAGE: if no messages are available in the queue. \n
719  *
720  **/
721 int frescan_fna_receive_async
722                 (const fna_endpoint_data_t *endpoint,
723                  void *buffer,
724                  const size_t buffer_size,
725                  size_t *received_bytes,
726                  frsh_network_address_t *from)
727 {
728         ERROR("not implemented\n");
729         return -1;
730 }
731
732 /**
733  * frescan_fna_send_endpoint_get_status()
734  *
735  * This function tells the number of messages still pending in the
736  * endpoint queue, whether the network is up or down with some
737  * optional information which is protocol_dependent.
738  *
739  * @param[in] endpoint The send endpoint (resource_id is in the endpoint).
740  * @param[out] number_of_pending_messages The number of pending messages
741  * @param[out] network_status How is the network (up, down..)
742  * @param[out] protocol_status Protocol dependent status info
743  *
744  * @return
745  *   0 if there are no errors \n
746  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
747  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
748  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
749  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
750  *
751  **/
752 int frescan_fna_send_endpoint_get_status
753                 (const fna_endpoint_data_t *endpoint,
754                  int *number_of_pending_messages,
755                  frsh_endpoint_network_status_t *network_status,
756                  frsh_protocol_status_t *protocol_status)
757 {
758         ERROR("not implemented\n");
759         return -1;
760 }
761
762 /**
763  * frescan_fna_receive_endpoint_created()
764  *
765  * This operation is a called from frsh_receive_endpoint_create with a
766  * receive_endpoint structure already filled.
767  *
768  * Receiving endpoints are not bound to any network vres, this is
769  * because don't originate any traffic.
770  *
771  * @param[in] endpoint the endpoint object.
772  *
773  * @return
774  *   0 if there are no errors \n
775  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
776  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
777  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
778  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
779  **/
780 int frescan_fna_receive_endpoint_created
781                 (fna_endpoint_data_t *endpoint)
782 {
783         DEBUG(FRESCAN_FNA_ENABLE_DEBUG, "receive endpoint created\n");
784         return 0;
785 }
786
787 /**
788  * frescan_fna_receive_endpoint_get_pending_messages
789  *
790  * This function tells the number of messages still pending in the
791  * endpoint queue, whether the network is up or down and some optional
792  * information which is protocol dependent.
793  *
794  * @param[in] endpoint The receive endpoint (resource_id is in the endpoint).
795  * @param[out] number_of_pending_messages The number of pending messages
796  * @param[out] network_status How is the network (up, down..)
797  * @param[out] protocol_status Protocol dependent status info
798  *
799  * @return
800  *   0 if there are no errors \n
801  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
802  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
803  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
804  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
805  *
806  **/
807 int frescan_fna_receive_endpoint_get_status
808                 (const fna_endpoint_data_t *endpoint,
809                  int *number_of_pending_messages,
810                  frsh_endpoint_network_status_t *network_status,
811                  frsh_protocol_status_t *protocol_status)
812 {
813         ERROR("not implemented\n");
814         return -1;
815 }
816
817 //////////////////////////////////////////////////////////////////////
818 //           NETWORK CONFIGURATION FUNCTIONS
819 //////////////////////////////////////////////////////////////////////
820
821 /**
822  * frescan_fna_network_get_max_message_size()
823  *
824  * This operation gives the maximum number of bytes that can be sent
825  * at a time through the send function when using the network designated by
826  * 'resource_id' and sending it to 'destination'.
827  *
828  * If the application needs to send bigger messages it will have to
829  * split them.
830  *
831  * Some protocols, like IP, are capable of sending large messages
832  * (and use fragmentation internally) but other protocols don't.
833  *
834  * @param[in] resource_id The network we want the tx time from.
835  * @param[in] destination The destination address
836  * @param[out] max_size The maximum number of bytes for each message
837  *
838  * @return
839  *   0 if there are no errors \n
840  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
841  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
842  *   FNA_ERR_RESOURCE_ID_INVALID: if resource id does not represent
843  *   a network accessible from the current processing node \n
844  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL or destination is
845  *   invalid \n
846  *
847  **/
848 int frescan_fna_network_get_max_message_size
849                 (const frsh_resource_id_t resource_id,
850                  const frsh_network_address_t destination,
851                  size_t *max_size)
852 {
853         ERROR("not implemented\n");
854         return -1;
855 }
856
857 /**
858  * frescan_fna_network_bytes_to_budget()
859  *
860  * This operation converts a number of bytes into a temporal budget for
861  * a specific network. Network overheads are not included here but are
862  * considered internally when negotiating a specific contract.
863  *
864  * @param[in] resource_id The network
865  * @param[in] nbytes Number of bytes
866  * @param[out] budget The network budget for nbytes
867  *
868  * @return
869  *   0 if there are no errors \n
870  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
871  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
872  *   FNA_ERR_RESOURCE_ID_INVALID: if resource id does not represent
873  *   a network accessible from the current processing node \n
874  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL or nbytes is less
875  *   than zero \n
876  *
877  **/
878 int frescan_fna_network_bytes_to_budget
879                 (const frsh_resource_id_t resource_id,
880                  const size_t nbytes,
881                  struct timespec *budget)
882 {
883         int number_of_packets;
884
885         if (budget == NULL || nbytes < 0) {
886                 return -1;
887         }
888
889         // we measure the budget in number of FRESCAN frames (8 bytes)
890         number_of_packets = nbytes / 8 + 1;
891
892         // we store the budget in number of packets instead of in time. We
893         // use a field in the timespec structure.
894         budget->tv_sec = number_of_packets;
895
896         DEBUG(FRESCAN_FNA_ENABLE_DEBUG,
897               "bytes: %d -> budget: %d\n", nbytes, budget->tv_sec);
898
899         return 0;
900 }
901
902 /**
903  * frescan_fna_network_budget_to_bytes()
904  *
905  * This operation converts a temporal budget into a number of bytes for
906  * a specific network. Network overheads are not included.
907  *
908  * @param[in] resource_id The network
909  * @param[in] budget The network budget for nbytes
910  * @param[out] nbytes Number of bytes
911  *
912  * @return
913  *   0 if there are no errors \n
914  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
915  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
916  *   FNA_ERR_RESOURCE_ID_INVALID: if resource id does not represent
917  *   a network accessible from the current processing node \n
918  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL or budget refers to
919  *   an invalid time value \n
920  *
921  **/
922 int frescan_fna_network_budget_to_bytes
923                 (const frsh_resource_id_t resource_id,
924                  const struct timespec *budget,
925                  size_t *nbytes)
926 {
927         int number_of_packets;
928
929         if (budget == NULL || nbytes == NULL) {
930                 return -1;
931         }
932
933         number_of_packets = budget->tv_sec;
934
935         *nbytes = number_of_packets * 8;
936
937         return 0;
938 }
939
940 /**
941  * frescan_fna_network_get_min_eff_budget()
942  *
943  * This operation gets the minimum effective budget for a network. Each message
944  * consumes a contracted budget in "chunks" (i.e: packets) that we call
945  * minimum effective budget.
946  *
947  * A negotiated contract, for N bytes in a period T, means that there is a
948  * virtual resource that reserves for the user:
949  *
950  *   Ceiling ((N bytes) / budget_to_bytes (min_effective_budget)) "CHUNKS"
951  *
952  * Note that if the user decides not to send these N bytes at once but, say,
953  * one byte at a time, it will consume one "CHUNK" at a time and the reserved
954  * budget will become exhausted before sending all the bytes.
955  *
956  * @param[in] resource_id The network
957  * @param[out] budget The network budget
958  *
959  * @return
960  *   0 if there are no errors \n
961  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
962  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
963  *   FNA_ERR_RESOURCE_ID_INVALID: if resource id does not represent
964  *   a network accessible from the current processing node \n
965  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
966  *
967  **/
968 int frescan_fna_network_get_min_eff_budget
969                 (const frsh_resource_id_t resource_id,
970                  struct timespec *budget)
971 {
972         if (budget == NULL) {
973                 return -1;
974         }
975
976         budget->tv_sec = 1;
977
978         return 0;
979 }
980
981 // GLOBAL variable to install the network protocol in FRESCOR
982
983 fna_operations_t frescan_fna_operations = {
984         .fna_init = frescan_fna_init,
985         .fna_contract_negotiate = frescan_fna_contract_negotiate,
986         .fna_contract_renegotiate_sync = frescan_fna_contract_renegotiate_sync,
987         .fna_contract_renegotiate_async = frescan_fna_contract_renegotiate_async,
988         .fna_vres_get_renegotiation_status = frescan_fna_vres_get_renegotiation_status,
989         .fna_vres_destroy = frescan_fna_vres_destroy,
990         .fna_vres_get_contract = frescan_fna_vres_get_contract,
991         .fna_vres_get_usage = frescan_fna_vres_get_usage,
992         .fna_vres_get_remaining_budget = frescan_fna_vres_get_remaining_budget,
993         .fna_vres_get_budget_and_period = frescan_fna_vres_get_budget_and_period,
994         .fna_resource_get_capacity = frescan_fna_resource_get_capacity,
995         .fna_resource_get_total_weight = frescan_fna_resource_get_total_weight,
996         .fna_vres_decrease_capacity = frescan_fna_vres_decrease_capacity,
997         .fna_send_sync = frescan_fna_send_sync,
998         .fna_send_async = frescan_fna_send_async,
999         .fna_receive_sync = frescan_fna_receive_sync,
1000         .fna_receive_async = frescan_fna_receive_async,
1001         .fna_send_endpoint_get_status = frescan_fna_send_endpoint_get_status,
1002         .fna_receive_endpoint_created = frescan_fna_receive_endpoint_created,
1003         .fna_receive_endpoint_get_status = frescan_fna_receive_endpoint_get_status,
1004         .fna_network_get_max_message_size = frescan_fna_network_get_max_message_size,
1005         .fna_network_bytes_to_budget = frescan_fna_network_bytes_to_budget,
1006         .fna_network_budget_to_bytes = frescan_fna_network_budget_to_bytes,
1007         .fna_network_get_min_eff_budget = frescan_fna_network_get_min_eff_budget
1008 };