vhost-user: introduce vhost-user API

Add vhost_user.c and vhost_user.h that define the functions needed
to implement vhost-user backend.

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
This commit is contained in:
Laurent Vivier 2022-11-08 21:16:46 +01:00
parent 45b1403f42
commit b2229bd24f
7 changed files with 1206 additions and 3 deletions

View file

@ -47,7 +47,7 @@ FLAGS += -DDUAL_STACK_SOCKETS=$(DUAL_STACK_SOCKETS)
PASST_SRCS = arch.c arp.c checksum.c conf.c dhcp.c dhcpv6.c flow.c fwd.c \ PASST_SRCS = arch.c arp.c checksum.c conf.c dhcp.c dhcpv6.c flow.c fwd.c \
icmp.c igmp.c inany.c iov.c ip.c isolation.c lineread.c log.c mld.c \ icmp.c igmp.c inany.c iov.c ip.c isolation.c lineread.c log.c mld.c \
ndp.c netlink.c packet.c passt.c pasta.c pcap.c pif.c tap.c tcp.c \ ndp.c netlink.c packet.c passt.c pasta.c pcap.c pif.c tap.c tcp.c \
tcp_buf.c tcp_splice.c udp.c util.c virtio.c tcp_buf.c tcp_splice.c udp.c util.c vhost_user.c virtio.c
QRAP_SRCS = qrap.c QRAP_SRCS = qrap.c
SRCS = $(PASST_SRCS) $(QRAP_SRCS) SRCS = $(PASST_SRCS) $(QRAP_SRCS)
@ -56,7 +56,8 @@ MANPAGES = passt.1 pasta.1 qrap.1
PASST_HEADERS = arch.h arp.h checksum.h conf.h dhcp.h dhcpv6.h flow.h fwd.h \ PASST_HEADERS = arch.h arp.h checksum.h conf.h dhcp.h dhcpv6.h flow.h fwd.h \
flow_table.h icmp.h inany.h iov.h ip.h isolation.h lineread.h log.h \ flow_table.h icmp.h inany.h iov.h ip.h isolation.h lineread.h log.h \
ndp.h netlink.h packet.h passt.h pasta.h pcap.h pif.h siphash.h tap.h \ ndp.h netlink.h packet.h passt.h pasta.h pcap.h pif.h siphash.h tap.h \
tcp.h tcp_buf.h tcp_conn.h tcp_splice.h udp.h util.h virtio.h tcp.h tcp_buf.h tcp_conn.h tcp_splice.h udp.h util.h vhost_user.h \
virtio.h
HEADERS = $(PASST_HEADERS) seccomp.h HEADERS = $(PASST_HEADERS) seccomp.h
C := \#include <linux/tcp.h>\nstruct tcp_info x = { .tcpi_snd_wnd = 0 }; C := \#include <linux/tcp.h>\nstruct tcp_info x = { .tcpi_snd_wnd = 0 };

View file

@ -73,6 +73,8 @@ char *epoll_type_str[] = {
[EPOLL_TYPE_TAP_PASTA] = "/dev/net/tun device", [EPOLL_TYPE_TAP_PASTA] = "/dev/net/tun device",
[EPOLL_TYPE_TAP_PASST] = "connected qemu socket", [EPOLL_TYPE_TAP_PASST] = "connected qemu socket",
[EPOLL_TYPE_TAP_LISTEN] = "listening qemu socket", [EPOLL_TYPE_TAP_LISTEN] = "listening qemu socket",
[EPOLL_TYPE_VHOST_CMD] = "vhost-user command socket",
[EPOLL_TYPE_VHOST_KICK] = "vhost-user kick socket",
}; };
static_assert(ARRAY_SIZE(epoll_type_str) == EPOLL_NUM_TYPES, static_assert(ARRAY_SIZE(epoll_type_str) == EPOLL_NUM_TYPES,
"epoll_type_str[] doesn't match enum epoll_type"); "epoll_type_str[] doesn't match enum epoll_type");

View file

@ -42,6 +42,7 @@ union epoll_ref;
#include "fwd.h" #include "fwd.h"
#include "tcp.h" #include "tcp.h"
#include "udp.h" #include "udp.h"
#include "vhost_user.h"
/** /**
* enum epoll_type - Different types of fds we poll over * enum epoll_type - Different types of fds we poll over
@ -73,6 +74,10 @@ enum epoll_type {
EPOLL_TYPE_TAP_PASST, EPOLL_TYPE_TAP_PASST,
/* socket listening for qemu socket connections */ /* socket listening for qemu socket connections */
EPOLL_TYPE_TAP_LISTEN, EPOLL_TYPE_TAP_LISTEN,
/* vhost-user command socket */
EPOLL_TYPE_VHOST_CMD,
/* vhost-user kick event socket */
EPOLL_TYPE_VHOST_KICK,
EPOLL_NUM_TYPES, EPOLL_NUM_TYPES,
}; };
@ -307,6 +312,9 @@ struct ctx {
int low_wmem; int low_wmem;
int low_rmem; int low_rmem;
/* vhost-user */
struct VuDev vdev;
}; };
void proto_update_l2_buf(const unsigned char *eth_d, void proto_update_l2_buf(const unsigned char *eth_d,

2
tap.c
View file

@ -1054,7 +1054,7 @@ void packet_add_all_do(struct ctx *c, ssize_t len, char *p,
* tap_sock_reset() - Handle closing or failure of connect AF_UNIX socket * tap_sock_reset() - Handle closing or failure of connect AF_UNIX socket
* @c: Execution context * @c: Execution context
*/ */
static void tap_sock_reset(struct ctx *c) void tap_sock_reset(struct ctx *c)
{ {
if (c->one_off) { if (c->one_off) {
info("Client closed connection, exiting"); info("Client closed connection, exiting");

3
tap.h
View file

@ -97,12 +97,15 @@ void tap_handler_pasta(struct ctx *c, uint32_t events,
const struct timespec *now); const struct timespec *now);
void tap_handler_passt(struct ctx *c, uint32_t events, void tap_handler_passt(struct ctx *c, uint32_t events,
const struct timespec *now); const struct timespec *now);
void tap_sock_reset(struct ctx *c);
void tap_sock_init(struct ctx *c); void tap_sock_init(struct ctx *c);
void pool_flush_all(void); void pool_flush_all(void);
void tap_handler_all(struct ctx *c, const struct timespec *now); void tap_handler_all(struct ctx *c, const struct timespec *now);
void packet_add_do(struct pool *p, size_t len, const char *start, void packet_add_do(struct pool *p, size_t len, const char *start,
const char *func, int line); const char *func, int line);
void packet_add_all_do(struct ctx *c, ssize_t len, char *p,
const char *func, int line);
#define packet_add_all(p, len, start) \ #define packet_add_all(p, len, start) \
packet_add_all_do(p, len, start, __func__, __LINE__) packet_add_all_do(p, len, start, __func__, __LINE__)

1050
vhost_user.c Normal file

File diff suppressed because it is too large Load diff

139
vhost_user.h Normal file
View file

@ -0,0 +1,139 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* some parts from subprojects/libvhost-user/libvhost-user.h */
#ifndef VHOST_USER_H
#define VHOST_USER_H
#include "virtio.h"
#include "iov.h"
#define VHOST_USER_F_PROTOCOL_FEATURES 30
#define VHOST_MEMORY_BASELINE_NREGIONS 8
enum vhost_user_protocol_feature {
VHOST_USER_PROTOCOL_F_MQ = 0,
VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
VHOST_USER_PROTOCOL_F_RARP = 2,
VHOST_USER_PROTOCOL_F_REPLY_ACK = 3,
VHOST_USER_PROTOCOL_F_NET_MTU = 4,
VHOST_USER_PROTOCOL_F_BACKEND_REQ = 5,
VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
VHOST_USER_PROTOCOL_F_PAGEFAULT = 8,
VHOST_USER_PROTOCOL_F_CONFIG = 9,
VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10,
VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11,
VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12,
VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS = 14,
VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15,
VHOST_USER_PROTOCOL_F_MAX
};
enum vhost_user_request {
VHOST_USER_NONE = 0,
VHOST_USER_GET_FEATURES = 1,
VHOST_USER_SET_FEATURES = 2,
VHOST_USER_SET_OWNER = 3,
VHOST_USER_RESET_OWNER = 4,
VHOST_USER_SET_MEM_TABLE = 5,
VHOST_USER_SET_LOG_BASE = 6,
VHOST_USER_SET_LOG_FD = 7,
VHOST_USER_SET_VRING_NUM = 8,
VHOST_USER_SET_VRING_ADDR = 9,
VHOST_USER_SET_VRING_BASE = 10,
VHOST_USER_GET_VRING_BASE = 11,
VHOST_USER_SET_VRING_KICK = 12,
VHOST_USER_SET_VRING_CALL = 13,
VHOST_USER_SET_VRING_ERR = 14,
VHOST_USER_GET_PROTOCOL_FEATURES = 15,
VHOST_USER_SET_PROTOCOL_FEATURES = 16,
VHOST_USER_GET_QUEUE_NUM = 17,
VHOST_USER_SET_VRING_ENABLE = 18,
VHOST_USER_SEND_RARP = 19,
VHOST_USER_NET_SET_MTU = 20,
VHOST_USER_SET_BACKEND_REQ_FD = 21,
VHOST_USER_IOTLB_MSG = 22,
VHOST_USER_SET_VRING_ENDIAN = 23,
VHOST_USER_GET_CONFIG = 24,
VHOST_USER_SET_CONFIG = 25,
VHOST_USER_CREATE_CRYPTO_SESSION = 26,
VHOST_USER_CLOSE_CRYPTO_SESSION = 27,
VHOST_USER_POSTCOPY_ADVISE = 28,
VHOST_USER_POSTCOPY_LISTEN = 29,
VHOST_USER_POSTCOPY_END = 30,
VHOST_USER_GET_INFLIGHT_FD = 31,
VHOST_USER_SET_INFLIGHT_FD = 32,
VHOST_USER_GPU_SET_SOCKET = 33,
VHOST_USER_VRING_KICK = 35,
VHOST_USER_GET_MAX_MEM_SLOTS = 36,
VHOST_USER_ADD_MEM_REG = 37,
VHOST_USER_REM_MEM_REG = 38,
VHOST_USER_MAX
};
typedef struct {
enum vhost_user_request request;
#define VHOST_USER_VERSION_MASK 0x3
#define VHOST_USER_REPLY_MASK (0x1 << 2)
#define VHOST_USER_NEED_REPLY_MASK (0x1 << 3)
uint32_t flags;
uint32_t size; /* the following payload size */
} __attribute__ ((__packed__)) vhost_user_header;
typedef struct VhostUserMemory_region {
uint64_t guest_phys_addr;
uint64_t memory_size;
uint64_t userspace_addr;
uint64_t mmap_offset;
} VhostUserMemory_region;
struct VhostUserMemory {
uint32_t nregions;
uint32_t padding;
struct VhostUserMemory_region regions[VHOST_MEMORY_BASELINE_NREGIONS];
};
typedef union {
#define VHOST_USER_VRING_IDX_MASK 0xff
#define VHOST_USER_VRING_NOFD_MASK (0x1 << 8)
uint64_t u64;
struct vhost_vring_state state;
struct vhost_vring_addr addr;
struct VhostUserMemory memory;
} vhost_user_payload;
typedef struct VhostUserMsg {
vhost_user_header hdr;
vhost_user_payload payload;
int fds[VHOST_MEMORY_BASELINE_NREGIONS];
int fd_num;
uint8_t *data;
} __attribute__ ((__packed__)) VhostUserMsg;
#define VHOST_USER_HDR_SIZE sizeof(vhost_user_header)
#define VHOST_USER_RX_QUEUE 0
#define VHOST_USER_TX_QUEUE 1
static inline bool vu_queue_enabled(VuVirtq *vq)
{
return vq->enable;
}
static inline bool vu_queue_started(const VuVirtq *vq)
{
return vq->started;
}
size_t tap_send_frames_vu(const struct ctx *c, const struct iovec *iov,
size_t n);
int vu_send(const struct ctx *c, const void *data, size_t len);
void vu_print_capabilities(void);
void vu_init(struct ctx *c);
void vu_kick_cb(struct ctx *c, union epoll_ref ref);
void tap_handler_vu(struct ctx *c, uint32_t events);
#endif /* VHOST_USER_H */