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