2014-09-08 17:17:48 +08:00
|
|
|
/*
|
|
|
|
* Copyright 6WIND S.A., 2014
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
|
|
|
* (at your option) any later version. See the COPYING file in the
|
|
|
|
* top-level directory.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _IVSHMEM_SERVER_H_
|
|
|
|
#define _IVSHMEM_SERVER_H_
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The ivshmem server is a daemon that creates a unix socket in listen
|
|
|
|
* mode. The ivshmem clients (qemu or ivshmem-client) connect to this
|
|
|
|
* unix socket. For each client, the server will create some eventfd
|
|
|
|
* (see EVENTFD(2)), one per vector. These fd are transmitted to all
|
|
|
|
* clients using the SCM_RIGHTS cmsg message. Therefore, each client is
|
|
|
|
* able to send a notification to another client without beeing
|
|
|
|
* "profixied" by the server.
|
|
|
|
*
|
|
|
|
* We use this mechanism to send interruptions between guests.
|
|
|
|
* qemu is able to transform an event on a eventfd into a PCI MSI-x
|
|
|
|
* interruption in the guest.
|
|
|
|
*
|
|
|
|
* The ivshmem server is also able to share the file descriptor
|
|
|
|
* associated to the ivshmem shared memory.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
#include <sys/select.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
|
|
#include "qemu/event_notifier.h"
|
|
|
|
#include "qemu/queue.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maximum number of notification vectors supported by the server
|
|
|
|
*/
|
|
|
|
#define IVSHMEM_SERVER_MAX_VECTORS 64
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Structure storing a peer
|
|
|
|
*
|
|
|
|
* Each time a client connects to an ivshmem server, a new
|
|
|
|
* IvshmemServerPeer structure is created. This peer and all its
|
|
|
|
* vectors are advertised to all connected clients through the connected
|
|
|
|
* unix sockets.
|
|
|
|
*/
|
|
|
|
typedef struct IvshmemServerPeer {
|
|
|
|
QTAILQ_ENTRY(IvshmemServerPeer) next; /**< next in list*/
|
|
|
|
int sock_fd; /**< connected unix sock */
|
|
|
|
long id; /**< the id of the peer */
|
|
|
|
EventNotifier vectors[IVSHMEM_SERVER_MAX_VECTORS]; /**< one per vector */
|
|
|
|
unsigned vectors_count; /**< number of vectors */
|
|
|
|
} IvshmemServerPeer;
|
|
|
|
QTAILQ_HEAD(IvshmemServerPeerList, IvshmemServerPeer);
|
|
|
|
|
|
|
|
typedef struct IvshmemServerPeerList IvshmemServerPeerList;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Structure describing an ivshmem server
|
|
|
|
*
|
|
|
|
* This structure stores all information related to our server: the name
|
|
|
|
* of the server unix socket and the list of connected peers.
|
|
|
|
*/
|
|
|
|
typedef struct IvshmemServer {
|
|
|
|
char unix_sock_path[PATH_MAX]; /**< path to unix socket */
|
|
|
|
int sock_fd; /**< unix sock file descriptor */
|
|
|
|
char shm_path[PATH_MAX]; /**< path to shm */
|
|
|
|
size_t shm_size; /**< size of shm */
|
|
|
|
int shm_fd; /**< shm file descriptor */
|
|
|
|
unsigned n_vectors; /**< number of vectors */
|
2015-06-23 23:09:59 +08:00
|
|
|
uint16_t cur_id; /**< id to be given to next client */
|
2014-09-08 17:17:48 +08:00
|
|
|
bool verbose; /**< true in verbose mode */
|
|
|
|
IvshmemServerPeerList peer_list; /**< list of peers */
|
|
|
|
} IvshmemServer;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize an ivshmem server
|
|
|
|
*
|
|
|
|
* @server: A pointer to an uninitialized IvshmemServer structure
|
|
|
|
* @unix_sock_path: The pointer to the unix socket file name
|
|
|
|
* @shm_path: Path to the shared memory. The path corresponds to a POSIX
|
|
|
|
* shm name. To use a real file, for instance in a hugetlbfs,
|
|
|
|
* it is possible to use /../../abspath/to/file.
|
|
|
|
* @shm_size: Size of shared memory
|
|
|
|
* @n_vectors: Number of interrupt vectors per client
|
|
|
|
* @verbose: True to enable verbose mode
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, or a negative value on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
|
|
|
|
const char *shm_path, size_t shm_size, unsigned n_vectors,
|
|
|
|
bool verbose);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Open the shm, then create and bind to the unix socket
|
|
|
|
*
|
|
|
|
* @server: The pointer to the initialized IvshmemServer structure
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, or a negative value on error
|
|
|
|
*/
|
|
|
|
int ivshmem_server_start(IvshmemServer *server);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Close the server
|
|
|
|
*
|
|
|
|
* Close connections to all clients, close the unix socket and the
|
|
|
|
* shared memory file descriptor. The structure remains initialized, so
|
|
|
|
* it is possible to call ivshmem_server_start() again after a call to
|
|
|
|
* ivshmem_server_close().
|
|
|
|
*
|
|
|
|
* @server: The ivshmem server
|
|
|
|
*/
|
|
|
|
void ivshmem_server_close(IvshmemServer *server);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fill a fd_set with file descriptors to be monitored
|
|
|
|
*
|
|
|
|
* This function will fill a fd_set with all file descriptors that must
|
|
|
|
* be polled (unix server socket and peers unix socket). The function
|
|
|
|
* will not initialize the fd_set, it is up to the caller to do it.
|
|
|
|
*
|
|
|
|
* @server: The ivshmem server
|
|
|
|
* @fds: The fd_set to be updated
|
|
|
|
* @maxfd: Must be set to the max file descriptor + 1 in fd_set. This value is
|
|
|
|
* updated if this function adds a greater fd in fd_set.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ivshmem_server_get_fds(const IvshmemServer *server, fd_set *fds, int *maxfd);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Read and handle new messages
|
|
|
|
*
|
|
|
|
* Given a fd_set (for instance filled by a call to select()), handle
|
|
|
|
* incoming messages from peers.
|
|
|
|
*
|
|
|
|
* @server: The ivshmem server
|
|
|
|
* @fds: The fd_set containing the file descriptors to be checked. Note that
|
|
|
|
* file descriptors that are not related to our server are ignored.
|
|
|
|
* @maxfd: The maximum fd in fd_set, plus one.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success, or a negative value on error
|
|
|
|
*/
|
|
|
|
int ivshmem_server_handle_fds(IvshmemServer *server, fd_set *fds, int maxfd);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Search a peer from its identifier
|
|
|
|
*
|
|
|
|
* @server: The ivshmem server
|
|
|
|
* @peer_id: The identifier of the peer structure
|
|
|
|
*
|
|
|
|
* Returns: The peer structure, or NULL if not found
|
|
|
|
*/
|
|
|
|
IvshmemServerPeer *
|
|
|
|
ivshmem_server_search_peer(IvshmemServer *server, long peer_id);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dump information of this ivshmem server and its peers on stdout
|
|
|
|
*
|
|
|
|
* @server: The ivshmem server
|
|
|
|
*/
|
|
|
|
void ivshmem_server_dump(const IvshmemServer *server);
|
|
|
|
|
|
|
|
#endif /* _IVSHMEM_SERVER_H_ */
|