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