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