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