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