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