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