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 * Broadcast 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