1 // -----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2009 FRESCOR consortium partners:
4 // Universidad de Cantabria, SPAIN
5 // University of York, UK
6 // Scuola Superiore Sant'Anna, ITALY
7 // Kaiserslautern University, GERMANY
8 // Univ. Politécnica Valencia, SPAIN
9 // Czech Technical University in Prague, CZECH REPUBLIC
11 // Thales Communication S.A. FRANCE
12 // Visual Tools S.A. SPAIN
13 // Rapita Systems Ltd UK
16 // See http://www.frescor.org for a link to partners' websites
18 // FRESCOR project (FP6/2005/IST/5-034026) is funded
19 // in part by the European Union Sixth Framework Programme
20 // The European Union is not liable of any use that may be
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 // FSF API web pages: http://marte.unican.es/fsf/docs
32 // http://shark.sssup.it/contrib/first/docs/
34 // This file is part of FRSH (FRescor ScHeduler)
36 // FRSH is free software; you can redistribute it and/or modify it
37 // under terms of the GNU General Public License as published by the
38 // Free Software Foundation; either version 2, or (at your option) any
39 // later version. FRSH is distributed in the hope that it will be
40 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
41 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 // General Public License for more details. You should have received a
43 // copy of the GNU General Public License along with FRSH; see file
44 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
45 // Cambridge, MA 02139, USA.
47 // As a special exception, including FRSH header files in a file,
48 // instantiating FRSH generics or templates, or linking other files
49 // with FRSH objects to produce an executable application, does not
50 // by itself cause the resulting executable application to be covered
51 // by the GNU General Public License. This exception does not
52 // however invalidate any other reasons why the executable file might be
53 // covered by the GNU Public License.
54 // -----------------------------------------------------------------------
56 //==============================================
57 // ******** ******* ******** ** **
58 // **///// /**////** **////// /** /**
59 // ** /** /** /** /** /**
60 // ******* /******* /********* /**********
61 // **//// /**///** ////////** /**//////**
62 // ** /** //** /** /** /**
63 // ** /** //** ******** /** /**
64 // // // // //////// // //
66 // FRSH(FRescor ScHeduler), pronounced "fresh"
67 //==============================================
68 #ifndef _FRSH_DISTRIBUTED_H_
69 #define _FRSH_DISTRIBUTED_H_
73 * @file frsh_distributed.h
77 #include "frsh_distributed_types.h"
78 #include "frsh_core_types.h"
82 // this global variable is assigned by frsh_distributed_init()
83 extern frsh_resource_id_t THE_FRSH_CPU_ID;
86 FRSH_NETPF_FRESCAN = 0,
90 FRSH_NETPF_CLUSTER_TREE = 4,
95 * @defgroup distributed Distributed module
97 * This module defines the functions and typedefs for use in
98 * distributed applications.
100 * Each network is identified by its resource_id and FRSH hides its
101 * characteristics completely. The type of network is implied with
102 * its ID via a configuration table defined at compile time.
104 * FRSH uses the "message" as the atomic unit for every exchange.
105 * Queue sizes are measured in number of pending messages.
107 * FRSH provides a function to calculate the transmision time needed
108 * for a certain message size in a network as well as the maximum
109 * message size that can admit.
111 * Note also that package delivery guarantee is protocol dependent.
112 * For protocols in which the order is no guaranteed, the application
113 * needs to add extra info to detect possible package disorder.
115 * Summary of typical steps.
117 * 1. Map (internally in FRSH implementation)
118 * - node--> network_addresses
119 * - network --> resource_id's
120 * - unidirectional communication channel --> stream_id
121 * - other config --> protocol_info.
123 * 2. In a sending node:
124 * 2.1. Negotiates a "network contract" per communication channel
125 * that is used in the application. In the contract it is
127 * - frsh_resource_type = FRSH_RT_NETWORK.
128 * - frsh_resource_id = <network id #>
129 * - budget: Time needed to send the required data per period.
130 * (you can use frsh_netinfo_*() functions for this).
131 * - period: Period of sendings.
132 * - Queueing info: How will sends be queued at sendEndpoint.
133 * - Other protocol dependent function in protocol_contract_info.
134 * 2.2. Create a send_endpoint per any unidirectional stream that will
136 * resource_id --> the network through which the stream will
137 * flow (this is extra info needed for coherency
139 * destinator --> network_address of the destination.
140 * stream_id --> the unidirectional communication channel.
141 * 2.3. Bind the send_endpoint to the network contract negotiated
143 * 2.4. The (processor) sending vres invokes frsh_send_(a)sync() to
144 * send the data through the corresponding stream.
146 * 3. In a receiving node:
147 * 3.1. Create a receive_endpoint per any unidirectional stream
148 * that will be used in receiving.
149 * 3.2. The processor expecting a reception of message invokes
150 * frsh_receive_(a)sync() to read the incoming data.
152 * 4. When all comunication is finished and the channel is no longer
153 * needed the nodes will destroy the send and receive endpoints
154 * and the network contract will be canceled.
158 * frsh_distributed_init(void)
160 * This operation initializes all the installed networks and the structures
161 * that are necessary for the distributed module. Currently it is called by
162 * frsh_init so it is not necessary that the user calls it again.
165 * FRSH_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
168 int frsh_distributed_init(void);
170 //////////////////////////////////////////////////////////////////////
172 //////////////////////////////////////////////////////////////////////
175 * @defgroup distcontract Contract Info for Distributed Systems
176 * @ingroup distributed
178 * These functions help you calculate the needed budget for network
179 * contracts and also to include protocol dependent info in contract
186 * frsh_network_get_max_message_size()
188 * This operation gives the maximum number of bytes that can be sent
189 * at a time through the send function when using the network designated by
190 * 'resource_id' and sending it to 'destination'.
192 * If the application needs to send bigger messages it will have to
195 * Some protocols, like IP, are capable of sending large messages
196 * (and use fragmentation internally) but other protocols don't.
198 * @param[in] resource_id The network we want the tx time from.
199 * @param[in] destination The destination address
200 * @param[out] max_size The maximum number of bytes for each message
204 * FRSH_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
205 * FRSH_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
206 * FRSH_ERR_RESOURCE_ID_INVALID: if resource id does not represent
207 * a network accessible from the current processing node \n
208 * FRSH_ERR_BAD_ARGUMENT: if pointers are NULL or destination is
212 int frsh_network_get_max_message_size
213 (const frsh_resource_id_t resource_id,
214 const frsh_network_address_t destination,
218 * frsh_network_bytes_to_budget()
220 * This operation converts a number of bytes into a temporal budget for
221 * a specific network. Network overheads are not included here but are
222 * considered internally when negotiating a specific contract.
224 * @param[in] resource_id The network
225 * @param[in] nbytes Number of bytes
226 * @param[out] budget The network budget for nbytes
230 * FRSH_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
231 * FRSH_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
232 * FRSH_ERR_RESOURCE_ID_INVALID: if resource id does not represent
233 * a network accessible from the current processing node \n
234 * FRSH_ERR_BAD_ARGUMENT: if pointers are NULL or nbytes is less
238 int frsh_network_bytes_to_budget
239 (const frsh_resource_id_t resource_id,
241 frsh_rel_time_t *budget);
244 * frsh_network_budget_to_bytes()
246 * This operation converts a temporal budget into a number of bytes for
247 * a specific network. Network overheads are not included.
249 * @param[in] resource_id The network
250 * @param[in] budget The network budget for nbytes
251 * @param[out] nbytes Number of bytes
255 * FRSH_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
256 * FRSH_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
257 * FRSH_ERR_RESOURCE_ID_INVALID: if resource id does not represent
258 * a network accessible from the current processing node \n
259 * FRSH_ERR_BAD_ARGUMENT: if pointers are NULL or budget refers to
260 * an invalid time value \n
263 int frsh_network_budget_to_bytes
264 (const frsh_resource_id_t resource_id,
265 const frsh_rel_time_t *budget,
269 * frsh_network_get_min_effective_budget()
271 * This operation gets the minimum effective budget for a network. Each message
272 * consumes a contracted budget in "chunks" (i.e: packets) that we call
273 * minimum effective budget.
275 * A negotiated contract, for N bytes in a period T, means that there is a
276 * virtual resource that reserves for the user:
278 * Ceiling ((N bytes) / budget_to_bytes (min_effective_budget)) "CHUNKS"
280 * Note that if the user decides not to send these N bytes at once but, say,
281 * one byte at a time, it will consume one "CHUNK" at a time and the reserved
282 * budget will become exhausted before sending all the bytes.
284 * @param[in] resource_id The network
285 * @param[out] budget The network budget
289 * FRSH_ERR_INTERNAL_ERROR: protocol dependent internal errors \n
290 * FRSH_ERR_NOT_INITIALIZED: if the protocol is not initialized \n
291 * FRSH_ERR_RESOURCE_ID_INVALID: if resource id does not represent
292 * a network accessible from the current processing node \n
293 * FRSH_ERR_BAD_ARGUMENT: if pointers are NULL \n
296 int frsh_network_get_min_effective_budget
297 (const frsh_resource_id_t resource_id,
298 frsh_rel_time_t *budget);
301 * frsh_contract_set_queueing_info()
303 * This function adds queueing parameters that will be used in the
304 * sendEndpoint when the sendEndpoint is bound to the vres.
306 int frsh_contract_set_queueing_info(frsh_endpoint_queueing_info_t queueing_info,
307 frsh_contract_t *contract);
310 * frsh_contract_get_queueing_info()
312 * This function gets the queueing parameters that were specified in
313 * the network contract.
315 int frsh_contract_get_queueing_info(const frsh_contract_t *contract,
316 frsh_endpoint_queueing_info_t *queueing_info);
319 * frsh_contract_set_protocol_info
321 * We add protocol info to the contract
323 int frsh_contract_set_protocol_info(frsh_protocol_info_t protocol_info,
324 frsh_contract_t *contract);
327 * frsh_contract_get_protocol_info
329 * We get protocol info from the contract
331 int frsh_contract_get_protocol_info(frsh_contract_t *contract,
332 frsh_protocol_info_t *protocol_info);
335 * frsh_contract_marshal
337 * Convert a contract to a sequence of bytes of minimum size so it can
338 * be sent through the network with the minimum amount of bytes.
342 int frsh_contract_marshal(const frsh_contract_t *contract,
343 unsigned char *buffer,
344 const size_t buffer_size,
348 * frsh_contract_unmarshal
350 * Convert a sequence of bytes generated by frsh_contract_marshal to a contract
354 int frsh_contract_unmarshal(frsh_contract_t *contract,
355 const unsigned char *marshal_bytes,
359 //////////////////////////////////////////////////////////////////////
360 // TWO STEP NEGOTIATION
361 //////////////////////////////////////////////////////////////////////
364 * @defgroup twostepnego Two Step Negotiation
365 * @ingroup distributed
367 * Using the core services of FRSH, contracts may be negotiated in a
370 * An alternative two-step negotiation process is introduced in the
371 * distribution module: the first step involves the reservation of the
372 * resources, but without the right to use them, and the second step
373 * is the commitment to use those resources.
375 * The rationale behind this approach is that in distributed systems,
376 * when a distributed transaction is being negotiated the system
377 * should only commit the virtual resources that were negotiated with
378 * various nodes in the system if the results of all negotiations
379 * match together. This approach enhances the efficiency since the
380 * actual temporal values of the virtual resources on distributed
381 * nodes are only changed if the initiator of the distributed
382 * transaction is satisfied with the results of the negotiations.
384 * After the reservation, it is not necessary to change the actual
385 * virtual resource attributes (and modifying the schedule) on each
386 * node before the initiator of the distributed transaction knows the
387 * amount of available virtual resources. A renegotiation of a
388 * reserved virtual resource is possible, to harmonize for the
389 * available virtual resources in other parts of the system, before a
390 * final commitment is made.
397 * frsh_contract_negotiate_reservation()
399 * Negotiate a service contract, obtaining a virtual resource id that
400 * represents a reservation of resources, but without the right to use
401 * those resources until the reservation is committed via
402 * frsh_vres_commit_reservation. In particular, this virtual resource
403 * cannot be bound until committed, but renegotiations are allowed for
406 int frsh_contract_negotiate_reservation
407 (const frsh_contract_t *contract,
408 frsh_vres_id_t *vres);
411 * frsh_vres_commit_reservation()
413 * Commit the resources reserved for a virtual resource through a
414 * frsh_contract_negotiate_reservation operation. The effects of
415 * subsequent calls to frsh_contract_negotiate_reservation and
416 * frsh_vres_commit_reservation are equivalent to a single call to
417 * frsh_contract_negotiate.
419 int frsh_vres_commit_reservation
420 (const frsh_vres_id_t vres);
426 //////////////////////////////////////////////////////////////////////
427 // TRANSMISSION SERVICES
428 //////////////////////////////////////////////////////////////////////
431 * @defgroup txservices Transmission services
432 * @ingroup distributed
434 * These functions allow to create and manage endpoints for sending
435 * and receiving and to perform send and receive operations both
436 * synchronously (blocking) and asynchronously (non-blocking).
443 * frsh_send_endpoint_create()
445 * This operation creates a unidirectional stream input endpoint
446 * through which, after the corresponding binding, it is possible to
447 * send data to a unicast or multicast destination.
449 * @param[in] resource_id Identifier of the network referred in the
450 * network contract as a resource_id.
451 * @param[in] destination FRSH abstraction of the protocol address for the
453 * @param[in] stream_id Identifier of the communication channel between
454 * the nodes. Multiplexing is achieved by using
455 * different streams between the same nodes and the
457 * @param[in] queueing_info Queueing params of the endpoint (size and
459 * @param[in] protocol_info Optional protocol-dependent info.
460 * @param[out] endpoint Placeholder for the endpoint object.
462 int frsh_send_endpoint_create
463 (frsh_resource_id_t resource_id,
464 frsh_network_address_t destination,
465 frsh_stream_id_t stream_id,
466 frsh_send_endpoint_protocol_info_t protocol_info,
467 frsh_send_endpoint_t *endpoint);
470 * frsh_send_endpoint_get_params()
472 * This operation returns in the variables associated to the
473 * endpoint at creation time.
475 int frsh_send_endpoint_get_params
476 (const frsh_send_endpoint_t endpoint,
477 frsh_resource_id_t *resource_id,
478 frsh_network_address_t *destination,
479 frsh_stream_id_t *stream,
480 frsh_send_endpoint_protocol_info_t *protocol_info);
483 * frsh_send_endpoint_destroy()
485 * This operation eliminates any resources reserved for the referenced
486 * endpoint. Pending messages will be discarded and processor-vres
487 * waiting in a synchronous operation will be awoken with an error
490 int frsh_send_endpoint_destroy
491 (frsh_send_endpoint_t endpoint);
494 * frsh_send_endpoint_bind()
496 * This operation associates a send endpoint with a network vres,
497 * which means that messages sent through this endpoint will consume
498 * the vres's reserved bandwidth and its packets will be sent
499 * according to the contract established for that vres.
501 * If the endpoint is already bound to another vres, it is effectively
502 * unbound from it and bound to the specified one. However if a vres
503 * is already bound to another endpoint an error is returned.
505 * A consistency check is done in which the resource_id specified at
506 * endpoint creation must correspond to the resource_id of the vres
509 * @return 0 if successful \n
510 * FRSH_ERR_BAD_ARGUMENT if the endpoint or the vres are not
512 * FRSH_ERR_ALREADY_BOUND if the vres is already bound to some
513 * other send endpoint \n
514 * FRSH_ERR_WRONG_NETWORK if the vres network id is not the same
515 * as the one in the endpoint \n
517 int frsh_send_endpoint_bind
518 (frsh_vres_id_t vres,
519 frsh_send_endpoint_t endpoint);
522 * frsh_send_endpoint_unbind()
524 * This operation unbinds a send endpoint from a vres. Endpoints with
525 * no vres associated cannot be used to send data, and they stay in
526 * that state until they are either eliminated or bound again.
528 * @return 0 if successful \n
529 * FRSH_ERR_NOT_BOUND if the endpoint was not bound \n
531 int frsh_send_endpoint_unbind
532 (frsh_send_endpoint_t endpoint);
535 * frsh_send_endpoint_get_vres_id()
537 * This operation copies the id of the vres that is bound to the
538 * specified send endpoint into the variable pointed to by vres.
540 * @return 0 if successful \n
541 * FRSH_ERR_NOT_BOUND if the endpoint was not bound \n
542 * FRSH_ERR_BAD_ARGUMENT if the endpoint is not valid or vres
545 int frsh_send_endpoint_get_vres_id
546 (const frsh_send_endpoint_t endpoint,
547 frsh_vres_id_t *vres);
552 * This operation sends a message stored in msg and of length size
553 * through the given endpoint. The operation is non-blocking and
554 * returns immediately.
556 * An internal frsh service will schedule the sending of messages and
557 * implement the communications sporadic vres corresponding to the
558 * network vres bound to the given endpoint.
560 * @returns 0 if successful \n
561 * FRSH_ERR_BAD_ARGUMENT if endpoint is not valid \n
562 * FRSH_ERR_NOT_BOUND if endpoint is not bound to a valid vres \n
563 * FRSH_ERR_TOO_LARGE if the message is too large for the
564 * network protocol \n
565 * FRSH_ERR_BUFFER_FULL if the message has been discarded
566 * because the queue is full (and does not
567 * have the policy FRSH_QP_OLDEST \n
570 (const frsh_send_endpoint_t endpoint,
577 * Similar to previous function but now the sending vres gets blocked
578 * until the message is processed.
581 (const frsh_send_endpoint_t endpoint,
586 * frsh_send_endpoint_get_status()
588 * This function tells the number of messages still pending in the
589 * endpoint queue, whether the network is up or down with some
590 * optional information which is protocol_dependent.
592 int frsh_send_endpoint_get_status
593 (const frsh_send_endpoint_t endpoint,
594 int *number_pending_msg,
595 frsh_endpoint_network_status_t *network_status,
596 frsh_protocol_status_t *protocol_status);
599 * frsh_receive_endpoint_create()
601 * This operation creates a receive endpoint associated with a
602 * undirectional stream within a network interface of the node.
604 * Receiving endpoints are not bound to any network vres, this is
605 * because don't originate any traffic.
607 * Note that the protocol address is not needed for reception because
608 * it can be determined internally by FRSH based on the resource_id.
610 * Note also that messages may come from diferent originators.
612 * @param[in] resource_id Id of the network from which we listen.
613 * @param[in] stream_id Id of the stream within the network.
614 * @param[in] queueing_info Buffering information(queue size and
616 * @param[in] protocol_info Extra protocol info opaque for the
618 * @param[in] endpoin Placeholder for the endpoint object.
620 * @return 0 if successful \n
621 * FRSH_ERR_BAD_ARGUMENT if the stream or the network id are not
624 int frsh_receive_endpoint_create
625 (frsh_resource_id_t resource_id,
626 frsh_stream_id_t stream_id,
627 frsh_endpoint_queueing_info_t queueing_info,
628 frsh_receive_endpoint_protocol_info_t protocol_info,
629 frsh_receive_endpoint_t *endpoint);
632 * frsh_receive_endpoint_get_params()
634 * This operation returns in the variables associated to the
635 * endpoint at creation time.
637 int frsh_receive_endpoint_get_params
638 (const frsh_receive_endpoint_t endpoint,
639 frsh_resource_id_t *resource_id,
640 frsh_stream_id_t *stream,
641 frsh_endpoint_queueing_info_t *queueing_info,
642 frsh_receive_endpoint_protocol_info_t *protocol_info);
645 * frsh_receive_endpoint_destroy()
647 * This operation eliminates any resources reserved for the referenced
648 * endpoint. Pending messages will be discarded and processor-vres
649 * waiting in a synchronous operation will be awoken with an error
652 int frsh_receive_endpoint_destroy
653 (frsh_receive_endpoint_t endpoint);
657 * frsh_receive_sync()
659 * If there are no messages available in the specified receive endpoint
660 * this operation blocks the calling thread waiting for a message to be
663 * When a message is available, if its size is less than or
664 * equal to the buffer_size, the function stores it in the variable
665 * pointed to by buffer and puts the number of bytes received in the
666 * variable pointed to by message size.
668 * The function fails with FRSH_ERR_NO_SPACE if the buffersize is
669 * too small for the message received. In this case the message is
672 * Messages arriving at a destination buffer that is full will be
673 * silently discarded (details in the queueing policy of the
674 * endpoint). The application is responsible of reading the receive
675 * endpoints with appropriate regularity, or of using a sequence
676 * number or some other mechanism to detect any lost messages.
678 * @return 0 if successful \n
679 * FRSH_ERR_BAD_ARGUMENT if the endpoint is not valid, or if
680 * buffer or message_size are NULL.\n
681 * FRSH_ERR_NO_SPACE if the message size is bigger than the
684 int frsh_receive_sync
685 (const frsh_receive_endpoint_t endpoint,
688 size_t *message_size,
689 frsh_network_address_t *from);
692 * frsh_receive_async()
694 * This operation is similar to the previous one but it works in a non
695 * blocking (asynchronous) fashion. If no message is available it
696 * returns with error FRSH_NO_MESSAGE.
698 * @return 0 if successful \n
699 * FRSH_ERR_BAD_ARGUMENT if the endpoint is not valid, or if
700 * buffer or message_size are NULL \n
701 * FRSH_NO_MESSAGE if no messages are available in the queue \n
702 * FRSH_ERR_NO_SPACE if the message size is bigger than the
705 int frsh_receive_async
706 (const frsh_receive_endpoint_t endpoint,
709 size_t *message_size,
710 frsh_network_address_t *from);
714 * frsh_receive_endpoint_get_status
716 * This function tells the number of messages still pending in the
717 * endpoint queue, whether the network is up or down and some optional
718 * information which is protocol dependent.
720 int frsh_receive_endpoint_get_status
721 (const frsh_receive_endpoint_t endpoint,
722 int *number_pending_messages,
723 frsh_endpoint_network_status_t *network_status,
724 frsh_protocol_status_t *protocol_status);
730 #endif // _FRSH_DISTRIBUTED_H_