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