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