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