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