1 //----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2007 by the FRESCOR consortium:
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
11 // Thales Communication S.A. FRANCE
12 // Visual Tools S.A. SPAIN
13 // Rapita Systems Ltd UK
16 // See http://www.frescor.org
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
24 // based on previous work (FSF) done in the FIRST project
26 // Copyright (C) 2005 Mälardalen University, SWEDEN
27 // Scuola Superiore S.Anna, ITALY
28 // Universidad de Cantabria, SPAIN
29 // University of York, UK
31 // This file is part of FNA (Frescor Network Adaptation)
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.
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 // -----------------------------------------------------------------------
53 //==============================================
54 // ******** **** ** **
55 // **///// /**/** /** ****
56 // ** /**//** /** **//**
57 // ******* /** //** /** ** //**
58 // **//// /** //**/** **********
59 // ** /** //****/**//////**
60 // ** /** //***/** /**
63 // FNA(Frescor Network Adaptation layer), pronounced "efe ene a"
64 //==============================================================
65 #include <malloc.h> // for malloc and free
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"
74 #define DEBUG(x,args...) printf("%s: " x, __func__ , ##args)
76 #define DEBUG(x,args...)
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;
83 //////////////////////////////////////////////////////////////////////
85 //////////////////////////////////////////////////////////////////////
90 * This function will be hooked to the frsh_init function and it is
91 * intented to initialize the protocol and its structures.
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)
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
104 int rtep_fna_init(const frsh_resource_id_t resource_id)
108 DEBUG("calling rtep_adainit\n");
113 DEBUG("calling freelist_init\n");
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;
119 DEBUG("calling rtep_bwres_init\n");
121 return rtep_bwres_init();
124 ///////////////////////////////////////////////////////////////////
126 ///////////////////////////////////////////////////////////////////
129 * rtep_fna_contract_negotiate()
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.
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.
141 * This is a potentially blocking operation, it returns when the
142 * system has either rejected the contract, or admitted it and made it
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
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
161 int rtep_fna_contract_negotiate
162 (const frsh_resource_id_t resource_id,
163 const frsh_contract_t *contract,
166 rtep_bwres_contract_t rtep_contract;
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;
179 // allocate a free internal vres.
180 pos = fadt_freelist_alloc(&rtep_vres_freelist);
183 DEBUG("not enough resources\n");
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]);
192 // if accepted assign the vres, if not deallocate the rtep_vres
194 DEBUG("contract accepted\n");
195 *vres = (fna_vres_id_t)pos;
197 DEBUG("contract not accepted\n");
198 fadt_freelist_free(&rtep_vres_freelist, pos);
205 * rtep_fna_contract_renegotiate_sync()
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
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
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
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)
239 rtep_bwres_contract_t rtep_contract;
241 int pos = (int) vres;
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;
252 // renegotiate the contract
253 accepted = rtep_bwres_contract_renegotiate_sync
254 (&rtep_vres_list[pos], &rtep_contract);
260 * rtep_fna_contract_renegotiate_async()
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.
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.
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.
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
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)
311 * rtep_fna_vres_get_renegotiation_status()
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
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
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)
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
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)
347 * rtep_fna_vres_destroy()
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.
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
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
367 int rtep_fna_vres_destroy
368 (const frsh_resource_id_t resource_id,
369 const fna_vres_id_t vres)
372 int pos = (int) vres;
374 // cancel de negotiated contract (the function spread results
376 err = rtep_bwres_vres_destroy (&rtep_vres_list[pos]);
377 if (err != 0) return -1;
379 // free the element in the rtep_vres list
380 err = fadt_freelist_free(&rtep_vres_freelist, pos);
381 if (err != 0) return -1;
387 * rtep_fna_vres_get_contract()
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.
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
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
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)
416 * rtep_fna_vres_get_usage()
418 * This function gets the execution time spent by all messages that have been
419 * sent through the specified vres.
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
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
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)
444 * rtep_fna_vres_get_remaining_budget()
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.
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
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
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)
473 * rtep_fna_vres_get_budget_and_period()
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.
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
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
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)
505 ///////////////////////////////////////////////////////////////////
506 // SPARE CAPACITY FUNCIONS
507 ///////////////////////////////////////////////////////////////////
510 * @defgroup fnaspare FNA Spare Capacity
513 * The following functions are used to get spare capacity data
519 * rtep_fna_resource_get_capacity()
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.
525 * The following is typically in stdint.h: \n
526 * - typedef unsigned int uint32_t; \n
527 * - # define UINT32_MAX (4294967295U) \n
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
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
542 int rtep_fna_resource_get_capacity
543 (const frsh_resource_id_t resource_id,
544 const int importance,
551 * rtep_fna_resource_get_total_weight()
553 * This function gets the sum of the weight parameters for all vres in a
554 * network of an importance level.
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
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
569 int rtep_fna_resource_get_total_weight
570 (const frsh_resource_id_t resource_id,
571 const int importance,
578 * rtep_fna_vres_decrease_capacity()
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.
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
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
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)
611 ///////////////////////////////////////////////////////////////////
612 // SEND RECEIVE OPERATIONS
613 ///////////////////////////////////////////////////////////////////
616 * rtep_fna_send_sync()
618 * Similar to previous function but now the sending thread gets blocked
619 * until the message is already sent to the network.
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
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
638 int rtep_fna_send_sync
639 (const fna_endpoint_data_t *endpoint,
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);
647 // TODO: check errors
648 rtep_server_send_info
649 ((rtep_station_id_t) endpoint->destination,
650 (rtep_channel_t) endpoint->stream_id,
653 rtep_vres_list[endpoint->vres].server_id,
659 * rtep_fna_send_async()
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.
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
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
682 int rtep_fna_send_async
683 (const fna_endpoint_data_t *endpoint,
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);
691 // TODO: check errors
692 rtep_server_send_info
693 ((rtep_station_id_t) endpoint->destination,
694 (rtep_channel_t) endpoint->stream_id,
697 rtep_vres_list[endpoint->vres].server_id,
703 * rtep_fna_receive_sync()
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).
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).
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
718 * Messages arriving at a receiver buffer that is full will be handled
719 * according to the queueing policy of the endpoint (overwrite oldest,
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
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
739 int rtep_fna_receive_sync
740 (const fna_endpoint_data_t *endpoint,
742 const size_t buffer_size,
743 size_t *received_bytes,
744 frsh_network_address_t *from)
746 rtep_priority_t prio;
747 rtep_station_id_t rtep_from;
748 rtep_channel_t chan = (rtep_channel_t) endpoint->stream_id;
750 // TODO: checks for errors
761 DEBUG(" %u bytes, from %u, prio %u\n",
762 *received_bytes, rtep_from, prio);
768 * rtep_fna_receive_async()
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.
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
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
792 int rtep_fna_receive_async
793 (const fna_endpoint_data_t *endpoint,
795 const size_t buffer_size,
796 size_t *received_bytes,
797 frsh_network_address_t *from)
803 * rtep_fna_send_endpoint_get_status()
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.
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
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
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)
832 * rtep_fna_receive_endpoint_created()
834 * This operation is a called from frsh_receive_endpoint_create with a
835 * receive_endpoint structure already filled.
837 * Receiving endpoints are not bound to any network vres, this is
838 * because don't originate any traffic.
840 * @param[in] endpoint the endpoint object.
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
849 int rtep_fna_receive_endpoint_created
850 (fna_endpoint_data_t *endpoint)
856 * rtep_fna_receive_endpoint_get_pending_messages
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.
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
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
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)
884 //////////////////////////////////////////////////////////////////////
885 // NETWORK CONFIGURATION FUNCTIONS
886 //////////////////////////////////////////////////////////////////////
889 * rtep_fna_network_get_max_message_size()
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'.
895 * If the application needs to send bigger messages it will have to
898 * Some protocols, like IP, are capable of sending large messages
899 * (and use fragmentation internally) but other protocols don't.
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
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
915 int rtep_fna_network_get_max_message_size
916 (const frsh_resource_id_t resource_id,
917 const frsh_network_address_t destination,
922 if (max_size == NULL) {
926 is_multicast = rtep_valid_multicast_id((rtep_station_id_t) destination);
928 *max_size = MULTICAST_MTU;
930 *max_size = MAX_RTEP_MTU;
936 * rtep_fna_network_bytes_to_budget()
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.
942 * @param[in] resource_id The network
943 * @param[in] nbytes Number of bytes
944 * @param[out] budget The network budget for nbytes
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
956 int rtep_fna_network_bytes_to_budget
957 (const frsh_resource_id_t resource_id,
959 struct timespec *budget)
961 int number_of_packets;
963 if (budget == NULL || nbytes < 0) {
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);
977 * rtep_fna_network_budget_to_bytes()
979 * This operation converts a temporal budget into a number of bytes for
980 * a specific network. Network overheads are not included.
982 * @param[in] resource_id The network
983 * @param[in] budget The network budget for nbytes
984 * @param[out] nbytes Number of bytes
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
996 int rtep_fna_network_budget_to_bytes
997 (const frsh_resource_id_t resource_id,
998 const struct timespec *budget,
1001 int number_of_packets;
1003 if (budget == NULL || nbytes == NULL) {
1006 number_of_packets = budget->tv_sec;
1007 *nbytes = number_of_packets * MAX_RTEP_MTU;
1012 * rtep_fna_network_get_min_eff_budget()
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.
1018 * A negotiated contract, for N bytes in a period T, means that there is a
1019 * virtual resource that reserves for the user:
1021 * Ceiling ((N bytes) / budget_to_bytes (min_effective_budget)) "CHUNKS"
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.
1027 * @param[in] resource_id The network
1028 * @param[out] budget The network budget
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
1039 int rtep_fna_network_get_min_eff_budget
1040 (const frsh_resource_id_t resource_id,
1041 struct timespec *budget)
1043 if (budget == NULL) {
1050 // GLOBAL variable to install the network protocol in FRESCOR
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,
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