mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
vhost: vhost net support
This adds vhost net device support in qemu. Will be tied to tap device and virtio by following patches. Raw backend is currently missing, will be worked on/submitted separately. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
committed by
Anthony Liguori
parent
ade80dc845
commit
d59700553e
@@ -166,6 +166,8 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o vl.o
|
||||
# need to fix this properly
|
||||
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
|
||||
obj-y += event_notifier.o
|
||||
obj-y += vhost_net.o
|
||||
obj-$(CONFIG_VHOST_NET) += vhost.o
|
||||
obj-y += rwhandler.o
|
||||
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
|
||||
LIBS+=-lz
|
||||
|
||||
@@ -263,6 +263,7 @@ vnc_tls=""
|
||||
vnc_sasl=""
|
||||
xen=""
|
||||
linux_aio=""
|
||||
vhost_net=""
|
||||
|
||||
gprof="no"
|
||||
debug_tcg="no"
|
||||
@@ -653,6 +654,10 @@ for opt do
|
||||
;;
|
||||
--enable-docs) docs="yes"
|
||||
;;
|
||||
--disable-vhost-net) vhost_net="no"
|
||||
;;
|
||||
--enable-vhost-net) vhost_net="yes"
|
||||
;;
|
||||
*) echo "ERROR: unknown option $opt"; show_help="yes"
|
||||
;;
|
||||
esac
|
||||
@@ -811,6 +816,8 @@ echo " --disable-blobs disable installing provided firmware blobs"
|
||||
echo " --kerneldir=PATH look for kernel includes in PATH"
|
||||
echo " --enable-docs enable documentation build"
|
||||
echo " --disable-docs disable documentation build"
|
||||
echo " --disable-vhost-net disable vhost-net acceleration support"
|
||||
echo " --enable-vhost-net enable vhost-net acceleration support"
|
||||
echo ""
|
||||
echo "NOTE: The object files are built at the place where configure is launched"
|
||||
exit 1
|
||||
@@ -1502,6 +1509,32 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# test for vhost net
|
||||
|
||||
if test "$vhost_net" != "no"; then
|
||||
if test "$kvm" != "no"; then
|
||||
cat > $TMPC <<EOF
|
||||
#include <linux/vhost.h>
|
||||
int main(void) { return 0; }
|
||||
EOF
|
||||
if compile_prog "$kvm_cflags" "" ; then
|
||||
vhost_net=yes
|
||||
else
|
||||
if test "$vhost_net" = "yes" ; then
|
||||
feature_not_found "vhost-net"
|
||||
fi
|
||||
vhost_net=no
|
||||
fi
|
||||
else
|
||||
if test "$vhost_net" = "yes" ; then
|
||||
echo -e "NOTE: vhost-net feature requires KVM (--enable-kvm)."
|
||||
feature_not_found "vhost-net"
|
||||
fi
|
||||
vhost_net=no
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# pthread probe
|
||||
PTHREADLIBS_LIST="-lpthread -lpthreadGC2"
|
||||
@@ -1988,6 +2021,7 @@ echo "fdt support $fdt"
|
||||
echo "preadv support $preadv"
|
||||
echo "fdatasync $fdatasync"
|
||||
echo "uuid support $uuid"
|
||||
echo "vhost-net support $vhost_net"
|
||||
|
||||
if test $sdl_too_old = "yes"; then
|
||||
echo "-> Your SDL version is too old - please upgrade to have SDL support"
|
||||
@@ -2522,6 +2556,9 @@ case "$target_arch2" in
|
||||
if test "$kvm_para" = "yes"; then
|
||||
echo "CONFIG_KVM_PARA=y" >> $config_target_mak
|
||||
fi
|
||||
if test $vhost_net = "yes" ; then
|
||||
echo "CONFIG_VHOST_NET=y" >> $config_target_mak
|
||||
fi
|
||||
fi
|
||||
esac
|
||||
if test "$target_bigendian" = "yes" ; then
|
||||
|
||||
+711
File diff suppressed because it is too large
Load Diff
+48
@@ -0,0 +1,48 @@
|
||||
#ifndef VHOST_H
|
||||
#define VHOST_H
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/virtio.h"
|
||||
|
||||
/* Generic structures common for any vhost based device. */
|
||||
struct vhost_virtqueue {
|
||||
int kick;
|
||||
int call;
|
||||
void *desc;
|
||||
void *avail;
|
||||
void *used;
|
||||
int num;
|
||||
unsigned long long used_phys;
|
||||
unsigned used_size;
|
||||
void *ring;
|
||||
unsigned long long ring_phys;
|
||||
unsigned ring_size;
|
||||
};
|
||||
|
||||
typedef unsigned long vhost_log_chunk_t;
|
||||
#define VHOST_LOG_PAGE 0x1000
|
||||
#define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t))
|
||||
#define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS)
|
||||
|
||||
struct vhost_memory;
|
||||
struct vhost_dev {
|
||||
CPUPhysMemoryClient client;
|
||||
int control;
|
||||
struct vhost_memory *mem;
|
||||
struct vhost_virtqueue *vqs;
|
||||
int nvqs;
|
||||
unsigned long long features;
|
||||
unsigned long long acked_features;
|
||||
unsigned long long backend_features;
|
||||
bool started;
|
||||
bool log_enabled;
|
||||
vhost_log_chunk_t *log;
|
||||
unsigned long long log_size;
|
||||
};
|
||||
|
||||
int vhost_dev_init(struct vhost_dev *hdev, int devfd);
|
||||
void vhost_dev_cleanup(struct vhost_dev *hdev);
|
||||
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
|
||||
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
|
||||
|
||||
#endif
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* vhost-net support
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2010
|
||||
*
|
||||
* Authors:
|
||||
* Michael S. Tsirkin <mst@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "net.h"
|
||||
#include "net/tap.h"
|
||||
|
||||
#include "virtio-net.h"
|
||||
#include "vhost_net.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CONFIG_VHOST_NET
|
||||
#include <linux/vhost.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/kvm.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/virtio_ring.h>
|
||||
#include <netpacket/packet.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vhost.h"
|
||||
|
||||
struct vhost_net {
|
||||
struct vhost_dev dev;
|
||||
struct vhost_virtqueue vqs[2];
|
||||
int backend;
|
||||
VLANClientState *vc;
|
||||
};
|
||||
|
||||
unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
|
||||
{
|
||||
/* Clear features not supported by host kernel. */
|
||||
if (!(net->dev.features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY))) {
|
||||
features &= ~(1 << VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
}
|
||||
if (!(net->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC))) {
|
||||
features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
void vhost_net_ack_features(struct vhost_net *net, unsigned features)
|
||||
{
|
||||
net->dev.acked_features = net->dev.backend_features;
|
||||
if (features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) {
|
||||
net->dev.acked_features |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
}
|
||||
if (features & (1 << VIRTIO_RING_F_INDIRECT_DESC)) {
|
||||
net->dev.acked_features |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
|
||||
}
|
||||
}
|
||||
|
||||
static int vhost_net_get_fd(VLANClientState *backend)
|
||||
{
|
||||
switch (backend->info->type) {
|
||||
case NET_CLIENT_TYPE_TAP:
|
||||
return tap_get_fd(backend);
|
||||
default:
|
||||
fprintf(stderr, "vhost-net requires tap backend\n");
|
||||
return -EBADFD;
|
||||
}
|
||||
}
|
||||
|
||||
struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
|
||||
{
|
||||
int r;
|
||||
struct vhost_net *net = qemu_malloc(sizeof *net);
|
||||
if (!backend) {
|
||||
fprintf(stderr, "vhost-net requires backend to be setup\n");
|
||||
goto fail;
|
||||
}
|
||||
r = vhost_net_get_fd(backend);
|
||||
if (r < 0) {
|
||||
goto fail;
|
||||
}
|
||||
net->vc = backend;
|
||||
net->dev.backend_features = tap_has_vnet_hdr(backend) ? 0 :
|
||||
(1 << VHOST_NET_F_VIRTIO_NET_HDR);
|
||||
net->backend = r;
|
||||
|
||||
r = vhost_dev_init(&net->dev, devfd);
|
||||
if (r < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if (~net->dev.features & net->dev.backend_features) {
|
||||
fprintf(stderr, "vhost lacks feature mask %llu for backend\n",
|
||||
~net->dev.features & net->dev.backend_features);
|
||||
vhost_dev_cleanup(&net->dev);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set sane init value. Override when guest acks. */
|
||||
vhost_net_ack_features(net, 0);
|
||||
return net;
|
||||
fail:
|
||||
qemu_free(net);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int vhost_net_start(struct vhost_net *net,
|
||||
VirtIODevice *dev)
|
||||
{
|
||||
struct vhost_vring_file file = { };
|
||||
int r;
|
||||
|
||||
net->dev.nvqs = 2;
|
||||
net->dev.vqs = net->vqs;
|
||||
r = vhost_dev_start(&net->dev, dev);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
net->vc->info->poll(net->vc, false);
|
||||
qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
|
||||
file.fd = net->backend;
|
||||
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
|
||||
r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
|
||||
if (r < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
file.fd = -1;
|
||||
while (--file.index >= 0) {
|
||||
int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
|
||||
assert(r >= 0);
|
||||
}
|
||||
net->vc->info->poll(net->vc, true);
|
||||
vhost_dev_stop(&net->dev, dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
void vhost_net_stop(struct vhost_net *net,
|
||||
VirtIODevice *dev)
|
||||
{
|
||||
struct vhost_vring_file file = { .fd = -1 };
|
||||
|
||||
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
|
||||
int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
|
||||
assert(r >= 0);
|
||||
}
|
||||
net->vc->info->poll(net->vc, true);
|
||||
vhost_dev_stop(&net->dev, dev);
|
||||
}
|
||||
|
||||
void vhost_net_cleanup(struct vhost_net *net)
|
||||
{
|
||||
vhost_dev_cleanup(&net->dev);
|
||||
qemu_free(net);
|
||||
}
|
||||
#else
|
||||
struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int vhost_net_start(struct vhost_net *net,
|
||||
VirtIODevice *dev)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
void vhost_net_stop(struct vhost_net *net,
|
||||
VirtIODevice *dev)
|
||||
{
|
||||
}
|
||||
|
||||
void vhost_net_cleanup(struct vhost_net *net)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
|
||||
{
|
||||
return features;
|
||||
}
|
||||
void vhost_net_ack_features(struct vhost_net *net, unsigned features)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef VHOST_NET_H
|
||||
#define VHOST_NET_H
|
||||
|
||||
#include "net.h"
|
||||
|
||||
struct vhost_net;
|
||||
typedef struct vhost_net VHostNetState;
|
||||
|
||||
VHostNetState *vhost_net_init(VLANClientState *backend, int devfd);
|
||||
|
||||
int vhost_net_start(VHostNetState *net, VirtIODevice *dev);
|
||||
void vhost_net_stop(VHostNetState *net, VirtIODevice *dev);
|
||||
|
||||
void vhost_net_cleanup(VHostNetState *net);
|
||||
|
||||
unsigned vhost_net_get_features(VHostNetState *net, unsigned features);
|
||||
void vhost_net_ack_features(VHostNetState *net, unsigned features);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user