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