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