]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_rtep/rtep_fna_c.c
renegotiate_sync
[frescor/fna.git] / src_rtep / rtep_fna_c.c
1 // -----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2007 FRESCOR consortium partners:
3 //
4 //    Universidad de Cantabria,              SPAIN
5 //    University of York,                    UK
6 //    Scuola Superiore Sant'Anna,            ITALY
7 //    Kaiserslautern University,             GERMANY
8 //    Univ. Politécnica  Valencia,           SPAIN
9 //    Czech Technical University in Prague,  CZECH REPUBLIC
10 //    ENEA                                   SWEDEN
11 //    Thales Communication S.A.              FRANCE
12 //    Visual Tools S.A.                      SPAIN
13 //    Rapita Systems Ltd                     UK
14 //    Evidence                               ITALY
15 //
16 //    See http://www.frescor.org for a link to partners' websites
17 //
18 //           FRESCOR project (FP6/2005/IST/5-034026) is funded
19 //        in part by the European Union Sixth Framework Programme
20 //        The European Union is not liable of any use that may be
21 //        made of this code.
22 //
23 //
24 //  based on previous work (FSF) done in the FIRST project
25 //
26 //   Copyright (C) 2005  Mälardalen University, SWEDEN
27 //                       Scuola Superiore S.Anna, ITALY
28 //                       Universidad de Cantabria, SPAIN
29 //                       University of York, UK
30 //
31 //   FSF API web pages: http://marte.unican.es/fsf/docs
32 //                      http://shark.sssup.it/contrib/first/docs/
33 //
34 //  This file is part of FRSH API
35 //
36 //  FRSH API is free software; you can  redistribute it and/or  modify
37 //  it under the terms of  the GNU General Public License as published by
38 //  the Free Software Foundation;  either  version 2, or (at  your option)
39 //  any later version.
40 //
41 //  FRSH API  is distributed  in  the hope  that  it  will  be useful,  but
42 //  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
43 //  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
44 //  General Public License for more details.
45 //
46 //  You should have  received a  copy of  the  GNU  General Public License
47 //  distributed  with  FRSH API;  see file COPYING.   If not,  write to the
48 //  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
49 //  02111-1307, USA.
50 //
51 //  As a special exception, if you include this header file into source
52 //  files to be compiled, this header file does not by itself cause
53 //  the resulting executable to be covered by the GNU General Public
54 //  License.  This exception does not however invalidate any other
55 //  reasons why the executable file might be covered by the GNU General
56 //  Public License.
57 // -----------------------------------------------------------------------
58
59 //==============================================
60 //  ******** ****     **     **
61 //  **///// /**/**   /**    ****
62 //  **      /**//**  /**   **//**
63 //  ******* /** //** /**  **  //**
64 //  **////  /**  //**/** **********
65 //  **      /**   //****/**//////**
66 //  **      /**    //***/**     /**
67 //  /       //      /// //      //
68 //
69 // FNA(Frescor Network Adaptation layer), pronounced "efe ene a"
70 //==============================================================
71 #include <malloc.h> // for malloc and free
72
73 #include "rtep.h" // for rtep_adainit, rtep_valid_multicast_id, ..
74 #include "rtep_bandwith_reservation.h" // for rtep_bwres_*
75 #include "rtep_fna.h" // function prototypes
76
77 #include "frsh_freelist.h"
78
79 #if 1
80 #include <stdio.h>
81 #define DEBUG(x,args...) printf("%s: " x, __func__ , ##args)
82 #else
83 #define DEBUG(x,args...)
84 #endif
85
86 // TODO: add a mutex for concurrent access if necessary
87 static rtep_bwres_vres_t rtep_vres_list[MAX_N_RTEP_BWRES_VRES];
88 static frsh_freelist_t rtep_vres_freelist;
89
90 //////////////////////////////////////////////////////////////////////
91 //           INITIALIZATION
92 //////////////////////////////////////////////////////////////////////
93
94 /**
95  * rtep_fna_init()
96  *
97  * This function will be hooked to the frsh_init function and it is
98  * intented to initialize the protocol and its structures.
99  *
100  * @param[in]  resource_id The network we are referring to (a protocol
101  * could be able to handle several networks at the same time)
102  *
103  * @return
104  *   0 if there are no errors \n
105  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
106  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
107  *   FNA_ERR_ALREADY_INITIALIZED:
108  *      if the function has already been called before (with success) \n
109  *
110  **/
111 int rtep_fna_init(const frsh_resource_id_t resource_id)
112 {
113     int err = 0;
114
115     DEBUG("starting rtep\n");
116
117     // init Ada bindings
118     rtep_adainit();
119
120     // initialize the freelist to handle the rtep_vres
121     err = frsh_freelist_init(&rtep_vres_freelist, MAX_N_RTEP_BWRES_VRES);
122     if (err != 0) return -1;
123
124     return rtep_bwres_init();
125 }
126
127 ///////////////////////////////////////////////////////////////////
128 //           VIRTUAL RESOURCES
129 ///////////////////////////////////////////////////////////////////
130
131 /**
132  * rtep_fna_contract_negotiate()
133  *
134  * The operation negotiates a contract and if accepted it will return
135  * a fna_vres_id_t. It will also check that the given contract_id is unique
136  * within the network.
137  *
138  * If the on-line admission test is enabled, it determines whether the
139  * contract can be admitted or not based on the current contracts
140  * established in the network. Then it creates the vres and
141  * recalculates all necessary parameters for the contracts already
142  * present in the system.
143  *
144  * This is a potentially blocking operation, it returns when the
145  * system has either rejected the contract, or admitted it and made it
146  * effective.
147  *
148  * @param[in] resource_id The network we are referring to (a protocol
149  * could be able to handle several networks at the same time)
150  * @param[in] contract  The contract parameters to negotiate
151  * @param[out] vres The internal virtual resource id
152  *
153  * @return
154  *   0 if there are no errors (in this case it also means contract accepted) \n
155  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
156  *   FNA_ERR_TOO_MANY_VRES: if there is no space for more vres \n
157  *   FNA_ERR_CONTRACT_ID_ALREADY_EXISTS: contract_id is not unique \n
158  *   FNA_ERR_CONTRACT_REJECTED: if the contract is not accepted \n
159  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
160  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
161  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
162  *
163  **/
164 int rtep_fna_contract_negotiate
165       (const frsh_resource_id_t resource_id,
166        const frsh_contract_t *contract,
167        fna_vres_id_t *vres)
168 {
169     rtep_bwres_contract_t rtep_contract;
170     int accepted;
171     int pos;
172
173     // convert FRSH contract to RTEP BWRES contract
174     rtep_contract.period_max = contract->period_max;
175     rtep_contract.deadline = contract->deadline;
176     rtep_contract.prio = contract->preemption_level;
177     // in RTEP BWRES, budget is given in number of packets. We do a little trick
178     // in the function bytes_to_network_budget to use a the field tv_sec from
179     // the timespec in frsh_contract to store the budget in bytes directly
180     rtep_contract.budget_min = contract->budget_min.tv_sec;
181
182     // allocate a free internal vres.
183     pos = frsh_freelist_alloc(&rtep_vres_freelist);
184
185     if (pos < 0) {
186         return -1;
187     }
188
189     DEBUG("calling rtep_bwres_contract_negotiate\n");
190     // negotiate the contract
191     accepted = rtep_bwres_contract_negotiate
192                     (&rtep_contract, &rtep_vres_list[pos]);
193
194     // if accepted assign the vres, if not deallocate the rtep_vres
195     if (accepted == 0) {
196         *vres = (fna_vres_id_t)pos;
197     } else {
198         frsh_freelist_free(&rtep_vres_freelist, pos);
199     }
200
201     return accepted;
202 }
203
204 /**
205  * rtep_fna_contract_renegotiate_sync()
206  *
207  * The operation renegotiates a contract for an existing vres. If
208  * the on-line admission test is enabled it determines whether the
209  * contract can be admitted or not based on the current contracts
210  * established in the system. If it cannot be admitted, the old
211  * contract remains in effect and an error is returned. If it can be
212  * admitted, it recalculates all necessary parameters for the
213  * contracts already present in the system and returns zero. This is a
214  * potentially blocking operation; it returns when the system has
215  * either rejected the new contract, or admitted it and made it
216  * effective.
217  *
218  * @param[in] resource_id The network we are referring to (a protocol
219  * could be able to handle several networks at the same time)
220  * @param[in] vres The internal virtual resource id to renegotiate
221  * @param[in] new_contract The new contract
222  *
223  *  @return
224  *   0 if there are no errors (in this case it also means contract accepted) \n
225  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
226  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
227  *   FNA_ERR_CONTRACT_ID_ALREADY_EXISTS: contract_id is not unique \n
228  *   FNA_ERR_CONTRACT_REJECTED: if the contract is not accepted \n
229  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
230  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
231  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
232  *
233  **/
234 int rtep_fna_contract_renegotiate_sync
235       (const frsh_resource_id_t resource_id,
236        const fna_vres_id_t vres,
237        const frsh_contract_t *new_contract)
238 {
239     rtep_bwres_contract_t rtep_contract;
240     int accepted;
241     int pos = (int) vres;
242
243     // convert FRSH contract to RTEP BWRES contract
244     rtep_contract.period_max = new_contract->period_max;
245     rtep_contract.deadline = new_contract->deadline;
246     rtep_contract.prio = new_contract->preemption_level;
247     // in RTEP BWRES, budget is given in number of packets. We do a little trick
248     // in the function bytes_to_network_budget to use a the field tv_sec from
249     // the timespec in frsh_contract to store the budget in bytes directly
250     rtep_contract.budget_min = new_contract->budget_min.tv_sec;
251
252     // renegotiate the contract
253     accepted = rtep_bwres_contract_renegotiate_sync
254             (&rtep_vres_list[pos], &rtep_contract);
255
256     return accepted;
257 }
258
259 /**
260  * rtep_fna_contract_renegotiate_async()
261  *
262  * The operation enqueues a renegotiate operation for an existing
263  * vres, and returns immediately. The renegotiate operation is
264  * performed asynchronously, as soon as it is practical; meanwhile the
265  * system operation will continue normally. When the renegotiation is
266  * made, if the on-line admission test is enabled it determines
267  * whether the contract can be admitted or not based on the current
268  * contracts established in the system. If it cannot be admitted, the
269  * old contract remains in effect. If it can be admitted, it
270  * recalculates all necessary parameters for the contracts already
271  * present in the system.
272  *
273  * When the operation is completed, notification is made to the
274  * caller, if requested, via a signal. The status of the operation (in
275  * progress, admitted, rejected) can be checked with the
276  * frsh_vres_get_renegotiation_status() operation.  The argument
277  * sig_notify can be FRSH_NULL_SIGNAL (no notification), or any FRSH
278  * signal value and in this case signal_info is to be sent with the signal.
279  *
280  * @param[in] resource_id The network we are referring to (a protocol
281  * could be able to handle several networks at the same time)
282  * @param[in] vres The internal virtual resource id to renegotiate
283  * @param[in] new_contract The new contract
284  * @param[in] signal_to_notify  Signal number to use to notify vres of
285  * the negotiation result. If FRSH_NULL_SIGNAL,  no signal will be raised.
286  * @param[in] signal_info: Associated info that will come with the signal.
287  * This parameter will be ignored if signal_to_notify == FRSH_NULL_SIGNAL.
288  *
289  * @return
290  *   0 if there are no errors \n
291  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
292  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
293  *   FNA_ERR_CONTRACT_ID_ALREADY_EXISTS: contract_id is not unique \n
294  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
295  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
296  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL, or sig_notify is neither
297  *      NULL nor a valid POSIX signal \n
298  *
299  **/
300 int rtep_fna_contract_renegotiate_async
301       (const frsh_resource_id_t resource_id,
302        const fna_vres_id_t vres,
303        const frsh_contract_t *new_contract,
304        frsh_signal_t signal_to_notify,
305        frsh_signal_info_t signal_info)
306 {
307    return 0;
308 }
309
310 /**
311  * rtep_fna_vres_get_renegotiation_status()
312  *
313  * The operation reports on the status of the last renegotiation
314  * operation enqueued for the specified vres. It is callable even
315  * after notification of the completion of such operation, if
316  * requested.
317  *
318  * If the vres is not and has not been involved in any of the
319  * frsh_contract_renegotiate_async() or frsh_group_change_mode_async()
320  * operations, the status returned is FNA_NOT_REQUESTED
321  *
322  * @param[in] resource_id The network we are referring to (a protocol
323  * could be able to handle several networks at the same time)
324  * @param[in] vres The internal virtual resource id we want the status from
325  * @param[in] renegotiation_status The status of the last renegotiation on
326  * vres (FRSH_RS_IN_PROGRESS, FRSH_RS_REJECTED, FRSH_RS_ADMITTED,
327  * FRSH_RS_NOT_REQUESTED)
328  *
329  * @return
330  *   0 if there are no errors \n
331  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
332  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
333  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
334  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
335  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
336  *
337  **/
338 int rtep_fna_vres_get_renegotiation_status
339       (const frsh_resource_id_t resource_id,
340        const fna_vres_id_t vres,
341        frsh_renegotiation_status_t *renegotiation_status)
342 {
343    return 0;
344 }
345
346 /**
347  * rtep_fna_vres_destroy()
348  *
349  * The operation eliminates the specified vres
350  * and recalculates all necessary parameters for the contracts
351  * remaining in the system. This is a potentially blocking operation;
352  * it returns when the system has made the changes effective.
353  *
354  * @param[in] resource_id The network we are referring to (a protocol
355  * could be able to handle several networks at the same time)
356  * @param[in] vres The internal virtual resource id to destroy
357  *
358  * @return
359  *   0 if there are no errors \n
360  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
361  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
362  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
363  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
364  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
365  *
366  **/
367 int rtep_fna_vres_destroy
368       (const frsh_resource_id_t resource_id,
369        const fna_vres_id_t vres)
370 {
371     int err = 0;
372     int pos = (int) vres;
373
374     // cancel de negotiated contract (the function spread results among nodes)
375     err = rtep_bwres_vres_destroy (&rtep_vres_list[pos]);
376     if (err != 0) return -1;
377
378     // free the element in the rtep_vres list
379     err = frsh_freelist_free(&rtep_vres_freelist, pos);
380     if (err != 0) return -1;
381
382     return 0;
383 }
384
385 /**
386  * rtep_fna_vres_get_contract()
387  *
388  * This operation stores the contract parameters currently associated
389  * with the specified vres in the variable pointed to by
390  * contract. It returns an error if the vres_id is not recognised.
391  *
392  * @param[in] resource_id The network we are referring to (a protocol
393  * could be able to handle several networks at the same time)
394  * @param[in] vres The internal virtual resource id
395  * @param[out] contract  The contract parameters that we want
396  *
397  * @return
398  *   0 if there are no errors \n
399  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
400  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
401  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
402  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
403  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
404  *
405  **/
406 int rtep_fna_vres_get_contract
407       (const frsh_resource_id_t resource_id,
408        const fna_vres_id_t vres,
409        frsh_contract_t *contract)
410 {
411    return 0;
412 }
413
414 /**
415  * rtep_fna_vres_get_usage()
416  *
417  * This function gets the execution time spent by all messages that have been
418  * sent through the specified vres.
419  *
420  * @param[in] resource_id The network we are referring to (a protocol
421  * could be able to handle several networks at the same time)
422  * @param[in] vres The internal virtual resource id
423  * @param[out] usage  Execution time spent by this vres
424  *
425  * @return
426  *   0 if there are no errors \n
427  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
428  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
429  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
430  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
431  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
432  *
433  **/
434 int rtep_fna_vres_get_usage
435       (const frsh_resource_id_t resource_id,
436        const fna_vres_id_t vres,
437        struct timespec *usage)
438 {
439    return 0;
440 }
441
442 /**
443  * rtep_fna_vres_get_remaining_budget()
444  *
445  * This function stores in the variable pointed to by budget the
446  * remaining execution-time budget associated with the specified
447  * vres in the present period.
448  *
449  * @param[in] resource_id The network we are referring to (a protocol
450  * could be able to handle several networks at the same time)
451  * @param[in] vres The internal virtual resource id
452  * @param[out] remaining_budget  The remaining budget for this period
453  *
454  *  @return
455  *   0 if there are no errors \n
456  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
457  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
458  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
459  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
460  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
461  *
462  **/
463 int rtep_fna_vres_get_remaining_budget
464       (const frsh_resource_id_t resource_id,
465        const fna_vres_id_t vres,
466        struct timespec *remaining_budget)
467 {
468    return 0;
469 }
470
471 /**
472  * rtep_fna_vres_get_budget_and_period()
473  *
474  * This function gets the budget and period associated with the specified vres
475  * for each period. If one of these pointers is NULL, the corresponding
476  * information is not stored.
477  *
478  * @param[in] resource_id The network we are referring to (a protocol
479  * could be able to handle several networks at the same time)
480  * @param[in] vres The internal virtual resource id
481  * @param[out] budget The budget associated to vres
482  * @param[out] period  The period associated to vres
483  *
484  * @return
485  *   0 if there are no errors \n
486  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
487  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
488  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
489  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
490  *   FNA_ERR_BAD_ARGUMENT: if both pointers are NULL \n
491  *
492  **/
493 int rtep_fna_vres_get_budget_and_period
494       (const frsh_resource_id_t resource_id,
495        const fna_vres_id_t vres,
496        struct timespec *budget,
497        struct timespec *period)
498 {
499    return 0;
500 }
501
502 /*@}*/
503
504 ///////////////////////////////////////////////////////////////////
505 //           SPARE CAPACITY FUNCIONS
506 ///////////////////////////////////////////////////////////////////
507
508 /**
509  * @defgroup fnaspare FNA Spare Capacity
510  * @ingroup fna
511  *
512  * The following functions are used to get spare capacity data
513  *
514  * @{
515  **/
516
517 /**
518  * rtep_fna_resource_get_capacity()
519  *
520  * This operation gets the spare capacity currently assigned to a importance
521  * level. If we divide this value by UINT32_MAX we will get the network
522  * utilization associated to the spare capacity of a importance level.
523  *
524  * The following is typically in stdint.h: \n
525  *  - typedef unsigned int uint32_t;  \n
526  *  - # define UINT32_MAX  (4294967295U)  \n
527  *
528  * @param[in] resource_id The network we are referring to (a protocol
529  * could be able to handle several networks at the same time)
530  * @param[in] importance The importance we want the capacity of
531  * @param[out] capacity The spare capacity for that importance level
532  *
533  * @return
534  *   0 if there are no errors \n
535  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
536  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
537  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
538  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
539  *
540  **/
541 int rtep_fna_resource_get_capacity
542       (const frsh_resource_id_t resource_id,
543        const int importance,
544        uint32_t *capacity)
545 {
546    return 0;
547 }
548
549 /**
550  * rtep_fna_resource_get_total_weight()
551  *
552  * This function gets the sum of the weight parameters for all vres in a
553  * network of an importance level.
554  *
555  * @param[in] resource_id The network we are referring to (a protocol
556  * could be able to handle several networks at the same time)
557  * @param[in] importance The importance we want the total weight of
558  * @param[out] total_weight The total weight for that importance level
559  *
560  * @return
561  *   0 if there are no errors \n
562  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
563  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
564  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
565  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
566  *
567  **/
568 int rtep_fna_resource_get_total_weight
569       (const frsh_resource_id_t resource_id,
570        const int importance,
571        int *total_weight)
572 {
573    return 0;
574 }
575
576 /**
577  * rtep_fna_vres_decrease_capacity()
578  *
579  * This function allows to ask for less budget and period than what we
580  * received. The request must be compatible with the rest of contract
581  * parameters of the vres. If we want to recover the released capacity
582  * we will need to renegotiate.
583  *
584  * @param[in] resource_id The network we are referring to (a protocol
585  * could be able to handle several networks at the same time)
586  * @param[in] vres The internal virtual resource id
587  * @param[in] new_budget The new_budget
588  * @param[in] new_period The new Period
589  *
590  * @return
591  *   0 if there are no errors \n
592  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
593  *   FNA_ERR_NOT_CONTRACTED_VRES: if the vres is not contracted \n
594  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
595  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
596  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
597  *   FNA_ERR_CONTRACT_REJECTED: if it is incompatible with the current
598  *      contract \n
599  *
600  **/
601 int rtep_fna_vres_decrease_capacity
602       (const frsh_resource_id_t resource_id,
603        const fna_vres_id_t vres,
604        const struct timespec new_budget,
605        const struct timespec new_period)
606 {
607    return 0;
608 }
609
610 ///////////////////////////////////////////////////////////////////
611 //           SEND RECEIVE OPERATIONS
612 ///////////////////////////////////////////////////////////////////
613
614 /**
615  * rtep_fna_send_sync()
616  *
617  * Similar to previous function but now the sending thread gets blocked
618  * until the message is already sent to the network.
619  *
620  * @param[in] endpoint The send endpoint we are sending through. It must
621  *    be bound to a virtual resource (resource_id is in the endpoint).
622  * @param[in] msg The message we want to send
623  * @param[in] size The size in bytes of the message
624  *
625  * @returns
626  *   0 if there are no errors \n
627  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
628  *   FNA_ERR_NOT_BOUND: if endpoint is not bound to a valid vres \n
629  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
630  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
631  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
632  *   FNA_ERR_TOO_LARGE: if the message is too large for the network protocol \n
633  *   FNA_ERR_BUFFER_FULL: if the message has been discarded because
634  *   the queue is full (and does not have the policy FNA_QP_OLDEST) \n
635  *
636  **/
637 int rtep_fna_send_sync
638    (const fna_endpoint_data_t *endpoint,
639     const void *msg,
640     const size_t size)
641 {
642    return 0;
643 }
644
645 /**
646  * rtep_fna_send_async()
647  *
648  * This operation sends a message stored in msg and of length size
649  * through the given send endpoint. The operation is non-blocking and
650  * returns immediately.
651  *
652  * @param[in] endpoint The send endpoint we are sending through. It must
653  *    be bound to a virtual resource (resource_id is in the endpoint).
654  * @param[in] msg The message we want to send
655  * @param[in] size The size in bytes of the message
656  *
657  * @returns
658  *   0 if there are no errors \n
659  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
660  *   FNA_ERR_NOT_BOUND: if endpoint is not bound to a valid vres \n
661  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
662  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
663  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
664  *   FNA_ERR_TOO_LARGE: if the message is too large for the network protocol \n
665  *   FNA_ERR_BUFFER_FULL: if the message has been discarded because
666  *   the queue is full (and does not have the policy FNA_QP_OLDEST) \n
667  *
668  **/
669 int rtep_fna_send_async
670    (const fna_endpoint_data_t *endpoint,
671     const void *msg,
672     const size_t size)
673 {
674     DEBUG("dest: %d, chan: %d, size: %d, server: %d\n",
675           endpoint->destination, endpoint->stream_id, size,
676           rtep_vres_list[endpoint->vres].server_id);
677
678     // TODO: check errors
679     rtep_server_send_info
680             ((rtep_station_id_t) endpoint->destination,
681              (rtep_channel_t) endpoint->stream_id,
682              (uint8_t *) msg,
683              size,
684              rtep_vres_list[endpoint->vres].server_id,
685              0); // not blocking
686     return 0;
687 }
688
689 /**
690  * rtep_fna_receive_sync()
691  *
692  * This operation is used to receive messages from the network with a
693  * blocking behavior (if there are no messages this operation blocks
694  * the calling thread).
695  *
696  * When a message is available, it is copied to buffer (up to its size).
697  * The number of bytes copied is returned in received_bytes. The rest
698  * of the bytes of that message will be lost or not depending on the
699  * protocol (FNA_ERR_NO_SPACE will be returned if it is).
700  *
701  * The function fails with FNA_ERR_NO_SPACE if the buffersize is
702  * too small for the message received.  In this case the message is
703  * lost.
704  *
705  * Messages arriving at a receiver buffer that is full will be handled
706  * according to the queueing policy of the endpoint (overwrite oldest,
707  * discard it,etc).
708  *
709  * @param[in] endpoint The receive endpoint we are receiving from.
710  *    (resource_id is in the endpoint).
711  * @param[out] buffer Buffer for storing the received message
712  * @param[in] buffer_size The size in bytes of this buffer
713  * @param[out] received_bytes The actual number of received bytes
714  * @param[out] from Address of the sender node
715  *
716  * @return
717  *   0 if there are no errors \n
718  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
719  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
720  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
721  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
722  *   FNA_ERR_NO_SPACE: if the message size is bigger than the
723  *      provided buffer. \n
724  *
725  **/
726 int rtep_fna_receive_sync
727       (const fna_endpoint_data_t *endpoint,
728        void *buffer,
729        const size_t buffer_size,
730        size_t *received_bytes,
731        frsh_network_address_t *from)
732 {
733     rtep_priority_t prio;
734     rtep_station_id_t rtep_from;
735
736     // TODO: checks for errors
737     rtep_recv_info
738             (&rtep_from,
739              (rtep_channel_t) endpoint->stream_id,
740              (uint8_t *) buffer,
741              buffer_size,
742              received_bytes,
743              &prio);
744
745     *from = rtep_from;
746
747     DEBUG(" %u bytes, from %u, prio %u\n", *received_bytes, rtep_from, prio);
748
749     return 0;
750 }
751
752 /**
753  * rtep_fna_receive_async()
754  *
755  * This operation is similar to the previous one but it works in a non
756  * blocking (asynchronous) fashion.  If no message is available it
757  * returns with error FNA_NO_MESSAGE.
758  *
759  * @param[in] endpoint The receive endpoint we are receiving from.
760  *    (resource_id is in the endpoint).
761  * @param[out] buffer Buffer for storing the received message
762  * @param[in] buffer_size The size in bytes of this buffer
763  * @param[out] received_bytes The actual number of received bytes
764  * @param[out] from Address of the sender node
765  *
766  * @return
767  *   0 if there are no errors \n
768  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
769  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
770  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
771  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
772  *   FNA_ERR_NO_SPACE: if the message size is bigger than the
773  *      provided buffer. \n
774  *   FNA_NO_MESSAGE: if no messages are available in the queue. \n
775  *
776  **/
777 int rtep_fna_receive_async
778       (const fna_endpoint_data_t *endpoint,
779        void *buffer,
780        const size_t buffer_size,
781        size_t *received_bytes,
782        frsh_network_address_t *from)
783 {
784    return 0;
785 }
786
787 /**
788  * rtep_fna_send_endpoint_get_status()
789  *
790  * This function tells the number of messages still pending in the
791  * endpoint queue, whether the network is up or down with some
792  * optional information which is protocol_dependent.
793  *
794  * @param[in] endpoint The send endpoint (resource_id is in the endpoint).
795  * @param[out] number_of_pending_messages The number of pending messages
796  * @param[out] network_status How is the network (up, down..)
797  * @param[out] protocol_status Protocol dependent status info
798  *
799  * @return
800  *   0 if there are no errors \n
801  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
802  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
803  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
804  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
805  *
806  **/
807 int rtep_fna_send_endpoint_get_status
808    (const fna_endpoint_data_t *endpoint,
809     int *number_of_pending_messages,
810     frsh_endpoint_network_status_t *network_status,
811     frsh_protocol_status_t *protocol_status)
812 {
813    return 0;
814 }
815
816 /**
817  * rtep_fna_receive_endpoint_created()
818  *
819  * This operation is a called from frsh_receive_endpoint_create with a
820  * receive_endpoint structure already filled.
821  *
822  * Receiving endpoints are not bound to any network vres, this is
823  * because don't originate any traffic.
824  *
825  * @param[in] endpoint the endpoint object.
826  *
827  * @return
828  *   0 if there are no errors \n
829  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
830  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
831  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
832  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
833  **/
834 int rtep_fna_receive_endpoint_created
835       (const fna_endpoint_data_t *endpoint)
836 {
837    return 0;
838 }
839
840 /**
841  * rtep_fna_receive_endpoint_get_pending_messages
842  *
843  * This function tells the number of messages still pending in the
844  * endpoint queue, whether the network is up or down and some optional
845  * information which is protocol dependent.
846  *
847  * @param[in] endpoint The receive endpoint (resource_id is in the endpoint).
848  * @param[out] number_of_pending_messages The number of pending messages
849  * @param[out] network_status How is the network (up, down..)
850  * @param[out] protocol_status Protocol dependent status info
851  *
852  * @return
853  *   0 if there are no errors \n
854  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
855  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
856  *   FNA_ERR_RESOURCE_ID_INVALID: if we are not in charge of resource_id \n
857  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
858  *
859  **/
860 int rtep_fna_receive_endpoint_get_status
861       (const fna_endpoint_data_t *endpoint,
862        int *number_of_pending_messages,
863        frsh_endpoint_network_status_t *network_status,
864        frsh_protocol_status_t *protocol_status)
865 {
866    return 0;
867 }
868
869 //////////////////////////////////////////////////////////////////////
870 //           NETWORK CONFIGURATION FUNCTIONS
871 //////////////////////////////////////////////////////////////////////
872
873 /**
874  * rtep_fna_network_get_max_message_size()
875  *
876  * This operation gives the maximum number of bytes that can be sent
877  * at a time through the send function when using the network designated by
878  * 'resource_id' and sending it to 'destination'.
879  *
880  * If the application needs to send bigger messages it will have to
881  * split them.
882  *
883  * Some protocols, like IP, are capable of sending large messages
884  * (and use fragmentation internally) but other protocols don't.
885  *
886  * @param[in] resource_id The network we want the tx time from.
887  * @param[in] destination The destination address
888  * @param[out] max_size The maximum number of bytes for each message
889  *
890  * @return
891  *   0 if there are no errors \n
892  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
893  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
894  *   FNA_ERR_RESOURCE_ID_INVALID: if resource id does not represent
895  *   a network accessible from the current processing node \n
896  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL or destination is
897  *   invalid \n
898  *
899  **/
900 int rtep_fna_network_get_max_message_size
901       (const frsh_resource_id_t resource_id,
902        const frsh_network_address_t destination,
903        size_t *max_size)
904 {
905     int is_multicast;
906
907     if (max_size == NULL) {
908         return -1;
909     }
910
911     is_multicast = rtep_valid_multicast_id ((rtep_station_id_t) destination);
912     if (is_multicast) {
913         *max_size = MULTICAST_MTU;
914     } else {
915         *max_size = MAX_RTEP_MTU;
916     }
917     return 0;
918 }
919
920 /**
921  * rtep_fna_network_bytes_to_budget()
922  *
923  * This operation converts a number of bytes into a temporal budget for
924  * a specific network. Network overheads are not included here but are
925  * considered internally when negotiating a specific contract.
926  *
927  * @param[in] resource_id The network
928  * @param[in] nbytes Number of bytes
929  * @param[out] budget The network budget for nbytes
930  *
931  * @return
932  *   0 if there are no errors \n
933  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
934  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
935  *   FNA_ERR_RESOURCE_ID_INVALID: if resource id does not represent
936  *   a network accessible from the current processing node \n
937  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL or nbytes is less
938  *   than zero \n
939  *
940  **/
941 int rtep_fna_network_bytes_to_budget
942       (const frsh_resource_id_t resource_id,
943        const size_t nbytes,
944        struct timespec *budget)
945 {
946     int number_of_packets;
947
948     if (budget == NULL || nbytes < 0) {
949         return -1;
950     }
951
952    // we measure the budget in number of RTEP packets of maximum size
953     number_of_packets = nbytes / MAX_RTEP_MTU + 1;
954    // we store the budget in number of packets instead of in time. We
955    // use a field in the timespec structure.
956     budget->tv_sec = number_of_packets;
957     DEBUG("bytes: %d -> budget: %d\n", nbytes, budget->tv_sec);
958     return 0;
959 }
960
961 /**
962  * rtep_fna_network_budget_to_bytes()
963  *
964  * This operation converts a temporal budget into a number of bytes for
965  * a specific network. Network overheads are not included.
966  *
967  * @param[in] resource_id The network
968  * @param[in] budget The network budget for nbytes
969  * @param[out] nbytes Number of bytes
970  *
971  * @return
972  *   0 if there are no errors \n
973  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
974  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
975  *   FNA_ERR_RESOURCE_ID_INVALID: if resource id does not represent
976  *   a network accessible from the current processing node \n
977  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL or budget refers to
978  *   an invalid time value \n
979  *
980  **/
981 int rtep_fna_network_budget_to_bytes
982       (const frsh_resource_id_t resource_id,
983        const struct timespec *budget,
984        size_t *nbytes)
985 {
986     int number_of_packets;
987
988     if (budget == NULL || nbytes == NULL) {
989         return -1;
990     }
991     number_of_packets = budget->tv_sec;
992     *nbytes = number_of_packets * MAX_RTEP_MTU;
993     return 0;
994 }
995
996 /**
997  * rtep_fna_network_get_min_eff_budget()
998  *
999  * This operation gets the minimum effective budget for a network. Each message
1000  * consumes a contracted budget in "chunks" (i.e: packets) that we call
1001  * minimum effective budget.
1002  *
1003  * A negotiated contract, for N bytes in a period T, means that there is a
1004  * virtual resource that reserves for the user:
1005  *
1006  *   Ceiling ((N bytes) / budget_to_bytes (min_effective_budget)) "CHUNKS"
1007  *
1008  * Note that if the user decides not to send these N bytes at once but, say,
1009  * one byte at a time, it will consume one "CHUNK" at a time and the reserved
1010  * budget will become exhausted before sending all the bytes.
1011  *
1012  * @param[in] resource_id The network
1013  * @param[out] budget The network budget
1014  *
1015  * @return
1016  *   0 if there are no errors \n
1017  *   FNA_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
1018  *   FNA_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
1019  *   FNA_ERR_RESOURCE_ID_INVALID: if resource id does not represent
1020  *   a network accessible from the current processing node \n
1021  *   FNA_ERR_BAD_ARGUMENT: if pointers are NULL \n
1022  *
1023  **/
1024 int rtep_fna_network_get_min_eff_budget
1025       (const frsh_resource_id_t resource_id,
1026        struct timespec *budget)
1027 {
1028    if (budget == NULL) {
1029       return -1;
1030    }
1031    budget->tv_sec = 1;
1032    return 0;
1033 }
1034
1035 // GLOBAL variable to install the network protocol in FRESCOR
1036
1037 fna_operations_t rtep_fna_operations = {
1038     .fna_init = rtep_fna_init,
1039     .fna_contract_negotiate = rtep_fna_contract_negotiate,
1040     .fna_contract_renegotiate_sync = rtep_fna_contract_renegotiate_sync,
1041     .fna_contract_renegotiate_async = rtep_fna_contract_renegotiate_async,
1042     .fna_vres_get_renegotiation_status = rtep_fna_vres_get_renegotiation_status,
1043     .fna_vres_destroy = rtep_fna_vres_destroy,
1044     .fna_vres_get_contract = rtep_fna_vres_get_contract,
1045     .fna_vres_get_usage = rtep_fna_vres_get_usage,
1046     .fna_vres_get_remaining_budget = rtep_fna_vres_get_remaining_budget,
1047     .fna_vres_get_budget_and_period = rtep_fna_vres_get_budget_and_period,
1048     .fna_resource_get_capacity = rtep_fna_resource_get_capacity,
1049     .fna_resource_get_total_weight = rtep_fna_resource_get_total_weight,
1050     .fna_vres_decrease_capacity = rtep_fna_vres_decrease_capacity,
1051     .fna_send_sync = rtep_fna_send_sync,
1052     .fna_send_async = rtep_fna_send_async,
1053     .fna_receive_sync = rtep_fna_receive_sync,
1054     .fna_receive_async = rtep_fna_receive_async,
1055     .fna_send_endpoint_get_status = rtep_fna_send_endpoint_get_status,
1056     .fna_receive_endpoint_created = rtep_fna_receive_endpoint_created,
1057     .fna_receive_endpoint_get_status = rtep_fna_receive_endpoint_get_status,
1058     .fna_network_get_max_message_size = rtep_fna_network_get_max_message_size,
1059     .fna_network_bytes_to_budget = rtep_fna_network_bytes_to_budget,
1060     .fna_network_budget_to_bytes = rtep_fna_network_budget_to_bytes,
1061     .fna_network_get_min_eff_budget = rtep_fna_network_get_min_eff_budget
1062 };
1063
1064 // TODO: move this out of here
1065
1066 #include "fna_configuration.h"
1067
1068 fna_operations_t  *fna_operations[FNA_MAX_NETWORKS] = {
1069     &rtep_fna_operations, // resource_id 0 (default) --> RTEP
1070     NULL, // resource_id 1
1071     NULL, // resource_id 2
1072     NULL  // resource_id 3
1073 };