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 */ 43typedef 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; 49QTAILQ_HEAD(IvshmemClientPeerList, IvshmemClientPeer); 50 51typedef struct IvshmemClientPeerList IvshmemClientPeerList; 52typedef struct IvshmemClient IvshmemClient; 53 54/** 55 * Typedef of callback function used when our IvshmemClient receives a 56 * notification from a peer. 57 */ 58typedef 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 */ 71struct 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 */ 98int 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 */ 113int 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 */ 120void 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 */ 135void 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 */ 152int 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 */ 163int 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 */ 175int 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 */ 186int 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 */ 199IvshmemClientPeer * 200ivshmem_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 */ 210void ivshmem_client_dump(const IvshmemClient *client); 211 212#endif /* _IVSHMEM_CLIENT_H_ */ 213