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