xref: /qemu/contrib/ivshmem-client/ivshmem-client.h (revision 834b9273d5cdab68180dc8c84d641aaa4344b057)
1a75eb03bSDavid Marchand /*
2a75eb03bSDavid Marchand  * Copyright 6WIND S.A., 2014
3a75eb03bSDavid Marchand  *
4a75eb03bSDavid Marchand  * This work is licensed under the terms of the GNU GPL, version 2 or
5a75eb03bSDavid Marchand  * (at your option) any later version.  See the COPYING file in the
6a75eb03bSDavid Marchand  * top-level directory.
7a75eb03bSDavid Marchand  */
8a75eb03bSDavid Marchand 
92a6a4076SMarkus Armbruster #ifndef IVSHMEM_CLIENT_H
102a6a4076SMarkus Armbruster #define IVSHMEM_CLIENT_H
11a75eb03bSDavid Marchand 
12a75eb03bSDavid Marchand /**
13a75eb03bSDavid Marchand  * This file provides helper to implement an ivshmem client. It is used
14a75eb03bSDavid Marchand  * on the host to ask QEMU to send an interrupt to an ivshmem PCI device in a
15a75eb03bSDavid Marchand  * guest. QEMU also implements an ivshmem client similar to this one, they both
16a75eb03bSDavid Marchand  * connect to an ivshmem server.
17a75eb03bSDavid Marchand  *
18a75eb03bSDavid Marchand  * A standalone ivshmem client based on this file is provided for debug/test
19a75eb03bSDavid Marchand  * purposes.
20a75eb03bSDavid Marchand  */
21a75eb03bSDavid Marchand 
22a75eb03bSDavid Marchand #include <sys/select.h>
23a75eb03bSDavid Marchand 
24a75eb03bSDavid Marchand #include "qemu/queue.h"
255105b1d8SDavid Marchand #include "hw/misc/ivshmem.h"
26a75eb03bSDavid Marchand 
27a75eb03bSDavid Marchand /**
28a75eb03bSDavid Marchand  * Maximum number of notification vectors supported by the client
29a75eb03bSDavid Marchand  */
30a75eb03bSDavid Marchand #define IVSHMEM_CLIENT_MAX_VECTORS 64
31a75eb03bSDavid Marchand 
32a75eb03bSDavid Marchand /**
33a75eb03bSDavid Marchand  * Structure storing a peer
34a75eb03bSDavid Marchand  *
35a75eb03bSDavid Marchand  * Each time a client connects to an ivshmem server, it is advertised to
36a75eb03bSDavid Marchand  * all connected clients through the unix socket. When our ivshmem
37a75eb03bSDavid Marchand  * client receives a notification, it creates a IvshmemClientPeer
38a75eb03bSDavid Marchand  * structure to store the infos of this peer.
39a75eb03bSDavid Marchand  *
40a75eb03bSDavid Marchand  * This structure is also used to store the information of our own
41a75eb03bSDavid Marchand  * client in (IvshmemClient)->local.
42a75eb03bSDavid Marchand  */
43a75eb03bSDavid Marchand typedef struct IvshmemClientPeer {
44a75eb03bSDavid Marchand     QTAILQ_ENTRY(IvshmemClientPeer) next;    /**< next in list*/
45f7a199b2SMarc-André Lureau     int64_t id;                              /**< the id of the peer */
46a75eb03bSDavid Marchand     int vectors[IVSHMEM_CLIENT_MAX_VECTORS]; /**< one fd per vector */
47a75eb03bSDavid Marchand     unsigned vectors_count;                  /**< number of vectors */
48a75eb03bSDavid Marchand } IvshmemClientPeer;
49a75eb03bSDavid Marchand 
50a75eb03bSDavid Marchand typedef struct IvshmemClient IvshmemClient;
51a75eb03bSDavid Marchand 
52a75eb03bSDavid Marchand /**
53a75eb03bSDavid Marchand  * Typedef of callback function used when our IvshmemClient receives a
54a75eb03bSDavid Marchand  * notification from a peer.
55a75eb03bSDavid Marchand  */
56a75eb03bSDavid Marchand typedef void (*IvshmemClientNotifCb)(
57a75eb03bSDavid Marchand     const IvshmemClient *client,
58a75eb03bSDavid Marchand     const IvshmemClientPeer *peer,
59a75eb03bSDavid Marchand     unsigned vect, void *arg);
60a75eb03bSDavid Marchand 
61a75eb03bSDavid Marchand /**
62a75eb03bSDavid Marchand  * Structure describing an ivshmem client
63a75eb03bSDavid Marchand  *
64a75eb03bSDavid Marchand  * This structure stores all information related to our client: the name
65a75eb03bSDavid Marchand  * of the server unix socket, the list of peers advertised by the
66a75eb03bSDavid Marchand  * server, our own client information, and a pointer the notification
67a75eb03bSDavid Marchand  * callback function used when we receive a notification from a peer.
68a75eb03bSDavid Marchand  */
69a75eb03bSDavid Marchand struct IvshmemClient {
70a75eb03bSDavid Marchand     char unix_sock_path[PATH_MAX];      /**< path to unix sock */
71a75eb03bSDavid Marchand     int sock_fd;                        /**< unix sock filedesc */
72a75eb03bSDavid Marchand     int shm_fd;                         /**< shm file descriptor */
73a75eb03bSDavid Marchand 
74b58deb34SPaolo Bonzini     QTAILQ_HEAD(, IvshmemClientPeer) peer_list;    /**< list of peers */
75a75eb03bSDavid Marchand     IvshmemClientPeer local;            /**< our own infos */
76a75eb03bSDavid Marchand 
77a75eb03bSDavid Marchand     IvshmemClientNotifCb notif_cb;      /**< notification callback */
78a75eb03bSDavid Marchand     void *notif_arg;                    /**< notification argument */
79a75eb03bSDavid Marchand 
80a75eb03bSDavid Marchand     bool verbose;                       /**< true to enable debug */
81a75eb03bSDavid Marchand };
82a75eb03bSDavid Marchand 
83a75eb03bSDavid Marchand /**
84a75eb03bSDavid Marchand  * Initialize an ivshmem client
85a75eb03bSDavid Marchand  *
86a75eb03bSDavid Marchand  * @client:         A pointer to an uninitialized IvshmemClient structure
87a75eb03bSDavid Marchand  * @unix_sock_path: The pointer to the unix socket file name
88a75eb03bSDavid Marchand  * @notif_cb:       If not NULL, the pointer to the function to be called when
89a75eb03bSDavid Marchand  *                  our IvshmemClient receives a notification from a peer
90a75eb03bSDavid Marchand  * @notif_arg:      Opaque pointer given as-is to the notification callback
91a75eb03bSDavid Marchand  *                  function
92a75eb03bSDavid Marchand  * @verbose:        True to enable debug
93a75eb03bSDavid Marchand  *
94a75eb03bSDavid Marchand  * Returns:         0 on success, or a negative value on error
95a75eb03bSDavid Marchand  */
96a75eb03bSDavid Marchand int ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
97a75eb03bSDavid Marchand                         IvshmemClientNotifCb notif_cb, void *notif_arg,
98a75eb03bSDavid Marchand                         bool verbose);
99a75eb03bSDavid Marchand 
100a75eb03bSDavid Marchand /**
101a75eb03bSDavid Marchand  * Connect to the server
102a75eb03bSDavid Marchand  *
103a75eb03bSDavid Marchand  * Connect to the server unix socket, and read the first initial
104a75eb03bSDavid Marchand  * messages sent by the server, giving the ID of the client and the file
105a75eb03bSDavid Marchand  * descriptor of the shared memory.
106a75eb03bSDavid Marchand  *
107a75eb03bSDavid Marchand  * @client: The ivshmem client
108a75eb03bSDavid Marchand  *
109a75eb03bSDavid Marchand  * Returns: 0 on success, or a negative value on error
110a75eb03bSDavid Marchand  */
111a75eb03bSDavid Marchand int ivshmem_client_connect(IvshmemClient *client);
112a75eb03bSDavid Marchand 
113a75eb03bSDavid Marchand /**
114a75eb03bSDavid Marchand  * Close connection to the server and free all peer structures
115a75eb03bSDavid Marchand  *
116a75eb03bSDavid Marchand  * @client: The ivshmem client
117a75eb03bSDavid Marchand  */
118a75eb03bSDavid Marchand void ivshmem_client_close(IvshmemClient *client);
119a75eb03bSDavid Marchand 
120a75eb03bSDavid Marchand /**
121a75eb03bSDavid Marchand  * Fill a fd_set with file descriptors to be monitored
122a75eb03bSDavid Marchand  *
123a75eb03bSDavid Marchand  * This function will fill a fd_set with all file descriptors
124a75eb03bSDavid Marchand  * that must be polled (unix server socket and peers eventfd). The
125a75eb03bSDavid Marchand  * function will not initialize the fd_set, it is up to the caller
126a75eb03bSDavid Marchand  * to do this.
127a75eb03bSDavid Marchand  *
128a75eb03bSDavid Marchand  * @client: The ivshmem client
129a75eb03bSDavid Marchand  * @fds:    The fd_set to be updated
130a75eb03bSDavid Marchand  * @maxfd:  Must be set to the max file descriptor + 1 in fd_set. This value is
131a75eb03bSDavid Marchand  *          updated if this function adds a greater fd in fd_set.
132a75eb03bSDavid Marchand  */
133a75eb03bSDavid Marchand void ivshmem_client_get_fds(const IvshmemClient *client, fd_set *fds,
134a75eb03bSDavid Marchand                             int *maxfd);
135a75eb03bSDavid Marchand 
136a75eb03bSDavid Marchand /**
137a75eb03bSDavid Marchand  * Read and handle new messages
138a75eb03bSDavid Marchand  *
139a75eb03bSDavid Marchand  * Given a fd_set filled by select(), handle incoming messages from
140a75eb03bSDavid Marchand  * server or peers.
141a75eb03bSDavid Marchand  *
142a75eb03bSDavid Marchand  * @client: The ivshmem client
143a75eb03bSDavid Marchand  * @fds:    The fd_set containing the file descriptors to be checked. Note
144a75eb03bSDavid Marchand  *          that file descriptors that are not related to our client are
145a75eb03bSDavid Marchand  *          ignored.
146a75eb03bSDavid Marchand  * @maxfd:  The maximum fd in fd_set, plus one.
147a75eb03bSDavid Marchand  *
148a75eb03bSDavid Marchand  * Returns: 0 on success, or a negative value on error
149a75eb03bSDavid Marchand  */
150a75eb03bSDavid Marchand int ivshmem_client_handle_fds(IvshmemClient *client, fd_set *fds, int maxfd);
151a75eb03bSDavid Marchand 
152a75eb03bSDavid Marchand /**
153a75eb03bSDavid Marchand  * Send a notification to a vector of a peer
154a75eb03bSDavid Marchand  *
155a75eb03bSDavid Marchand  * @client: The ivshmem client
156a75eb03bSDavid Marchand  * @peer:   The peer to be notified
157a75eb03bSDavid Marchand  * @vector: The number of the vector
158a75eb03bSDavid Marchand  *
159a75eb03bSDavid Marchand  * Returns: 0 on success, or a negative value on error
160a75eb03bSDavid Marchand  */
161a75eb03bSDavid Marchand int ivshmem_client_notify(const IvshmemClient *client,
162a75eb03bSDavid Marchand                           const IvshmemClientPeer *peer, unsigned vector);
163a75eb03bSDavid Marchand 
164a75eb03bSDavid Marchand /**
165a75eb03bSDavid Marchand  * Send a notification to all vectors of a peer
166a75eb03bSDavid Marchand  *
167a75eb03bSDavid Marchand  * @client: The ivshmem client
168a75eb03bSDavid Marchand  * @peer:   The peer to be notified
169a75eb03bSDavid Marchand  *
170a75eb03bSDavid Marchand  * Returns: 0 on success, or a negative value on error (at least one
171a75eb03bSDavid Marchand  *          notification failed)
172a75eb03bSDavid Marchand  */
173a75eb03bSDavid Marchand int ivshmem_client_notify_all_vects(const IvshmemClient *client,
174a75eb03bSDavid Marchand                                     const IvshmemClientPeer *peer);
175a75eb03bSDavid Marchand 
176a75eb03bSDavid Marchand /**
177*639b090dSzhaolichang  * Broadcast a notification to all vectors of all peers
178a75eb03bSDavid Marchand  *
179a75eb03bSDavid Marchand  * @client: The ivshmem client
180a75eb03bSDavid Marchand  *
181a75eb03bSDavid Marchand  * Returns: 0 on success, or a negative value on error (at least one
182a75eb03bSDavid Marchand  *          notification failed)
183a75eb03bSDavid Marchand  */
184a75eb03bSDavid Marchand int ivshmem_client_notify_broadcast(const IvshmemClient *client);
185a75eb03bSDavid Marchand 
186a75eb03bSDavid Marchand /**
187a75eb03bSDavid Marchand  * Search a peer from its identifier
188a75eb03bSDavid Marchand  *
189a75eb03bSDavid Marchand  * Return the peer structure from its peer_id. If the given peer_id is
190a75eb03bSDavid Marchand  * the local id, the function returns the local peer structure.
191a75eb03bSDavid Marchand  *
192a75eb03bSDavid Marchand  * @client:  The ivshmem client
193a75eb03bSDavid Marchand  * @peer_id: The identifier of the peer structure
194a75eb03bSDavid Marchand  *
195a75eb03bSDavid Marchand  * Returns:  The peer structure, or NULL if not found
196a75eb03bSDavid Marchand  */
197a75eb03bSDavid Marchand IvshmemClientPeer *
198f7a199b2SMarc-André Lureau ivshmem_client_search_peer(IvshmemClient *client, int64_t peer_id);
199a75eb03bSDavid Marchand 
200a75eb03bSDavid Marchand /**
201a75eb03bSDavid Marchand  * Dump information of this ivshmem client on stdout
202a75eb03bSDavid Marchand  *
203a75eb03bSDavid Marchand  * Dump the id and the vectors of the given ivshmem client and the list
204a75eb03bSDavid Marchand  * of its peers and their vectors on stdout.
205a75eb03bSDavid Marchand  *
206a75eb03bSDavid Marchand  * @client: The ivshmem client
207a75eb03bSDavid Marchand  */
208a75eb03bSDavid Marchand void ivshmem_client_dump(const IvshmemClient *client);
209a75eb03bSDavid Marchand 
2102a6a4076SMarkus Armbruster #endif /* IVSHMEM_CLIENT_H */
211