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