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