Status/issues of auto installation
by Li Ming
Greetings,
I am writing the following to tell you what the progress of auto
install and what issues we are facing now. I have developed a script
which can do DVD+ kickstart auto install,you can download and run it:
# git clone git://git.fedorahosted.org/autoqa.git
# cd autoqa/tests/anaconda
# you need to install libguestfs, group install
Virtualization,python-virtinst ,etc... first
# mount -o loop DVDImage.iso /InstallTree
Then you can run it like this:
1. http/ftp... kickstart file:
./dvd_install.py -k http://server/ks.cfg -a i386 -d /InstallTree |tee
test.log
2. local kickstart file:
./dvd_install.py -k /path/to/ks.cfg -a i386 -d /InstallTree |tee test.log
3. remote install tree:
./dvd_install.py -k /path/to/ks.cfg -a i386 -d http://install/tree |tee
test.log
./dvd_install.py -k http://server/ks.cfg -a i386 -d ftp://install/tree
|tee test.log
.....
but we prefer the second one:
2. local kickstart file:
./dvd_install.py -k /path/to/ks.cfg -a i386 -d /InstallTree |tee test.log
because we want to imitate a true local DVD install, but this test still
has an issue: In this test,the virt-install --location still will
activate network which request a DHCP server, this will be a big problem
for testers who are not in DHCP environment. If use virt-install --cdrom
will get what we want: imitate true local DVD install,but the ks
parameter can not be passed to grub in this case. If try to solve these
problems, we have such options:
# uncompress the ISO,then update the syslinux kernel args,then build ISO
again,my concern is this will consume big resource and it will waste
lots of time before each test.
# Guys from virt list give us a solution:
call qemu directly:
qemu -name 'vm1' -monitor
unix:/tmp/monitor-20100207-221920-Q1pS,server,nowait -drive
file=/var/lib/libvirt/images/fedoratest.img -drive
file=/var/lib/libvirt/images/ksdata.img -net nic,vlan=0 -net user,vlan=0
-m 512 -smp 1 -drive
file=/nfs/iso/f12-ga/Fedora-12-i386-DVD.iso,index=2,media=cdrom -fda
/var/lib/libvirt/images/ksdata.img -tftp /var/lib/tftpboot -boot d
-bootp /pxelinux.0 -boot n -redir tcp:5000::22
This method works,the network was not activated,because the pxe install
can help download boot file and start system,this is before the system
can active network.But this method needs to copy the pxelinux.0 to tftp
server root directory,if the tester did not install syslinux, the
install will fail,I am not sure whether this will demand that the host
and the guest VM have the same system. because pxelinux.0 is located in
host system. The vmlinuz and initrd.img also have to be copied from iso
to tftp directory and the default config file need to be created. I have
some concerns about this method:
1. The qemu is very slow, I tested the whole installation,even the
hardware is very good, the install speed is still very slow.
2. The install needs to copy a pxelinux.0 file to tftp server root
directory, the pxelinux.0 was provided by syslinux which has to be
installed on host,that means the host and the guest should install the
same system? if we want to test f13, the host system has to be f13? If
it's true, we have to update the syslinux every time.
3. the virt-install --location can handle the remote installation,
if we want to support remote install in the future, virt-install --cdrom
is not a good choice
# James Laska provided a method: use dogtail to pass args to
virt-viewer.It will append the supplied boot arguments to the guest and
initiate a kickstart DVD install. I still did not get time to try it
till now.
Thanks
Liam
14 years, 2 months
[PATCH 24/24] virtio: avoid crash with non-tap backends
by Michael S. Tsirkin
verify that peer is tap before checking for vhost net
Reported-by: Shirley Ma <mashirle(a)us.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst(a)redhat.com>
---
hw/virtio-net.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 088029b..b28fd92 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -179,6 +179,10 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
}
+ if (!n->nic->nc.peer ||
+ n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) {
+ return features;
+ }
if (!tap_get_vhost_net(n->nic->nc.peer)) {
return features;
}
--
1.6.6.144.g5c3af
14 years, 2 months
[PATCH 23/24] virtio-pci: irqfd support
by Michael S. Tsirkin
Use irqfd when supported by kernel.
This uses msix mask notifiers: when vector is masked, we poll it from
userspace. When it is unmasked, we poll it from kernel.
Signed-off-by: Michael S. Tsirkin <mst(a)redhat.com>
---
hw/virtio-pci.c | 31 +++++++++++++++++++++++++++++--
1 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index c454093..e8e0d82 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -404,6 +404,27 @@ static void virtio_pci_guest_notifier_read(void *opaque)
}
}
+static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
+ void *opaque, int masked)
+{
+ VirtQueue *vq = opaque;
+ EventNotifier *notifier = virtio_queue_guest_notifier(vq);
+ int r = kvm_set_irqfd(dev->msix_irq_entries[vector].gsi,
+ event_notifier_get_fd(notifier),
+ !masked);
+ if (r < 0) {
+ return (r == -ENOSYS) ? 0 : r;
+ }
+ if (masked) {
+ qemu_set_fd_handler(event_notifier_get_fd(notifier),
+ virtio_pci_guest_notifier_read, NULL, vq);
+ } else {
+ qemu_set_fd_handler(event_notifier_get_fd(notifier),
+ NULL, NULL, vq);
+ }
+ return 0;
+}
+
static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
{
VirtIOPCIProxy *proxy = opaque;
@@ -412,11 +433,15 @@ static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
if (assign) {
int r = event_notifier_init(notifier, 0);
- if (r < 0)
- return r;
+ if (r < 0)
+ return r;
qemu_set_fd_handler(event_notifier_get_fd(notifier),
virtio_pci_guest_notifier_read, NULL, vq);
+ msix_set_mask_notifier(&proxy->pci_dev,
+ virtio_queue_vector(proxy->vdev, n), vq);
} else {
+ msix_set_mask_notifier(&proxy->pci_dev,
+ virtio_queue_vector(proxy->vdev, n), NULL);
qemu_set_fd_handler(event_notifier_get_fd(notifier),
NULL, NULL, vq);
event_notifier_cleanup(notifier);
@@ -501,6 +526,8 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
proxy->pci_dev.config_write = virtio_write_config;
+ proxy->pci_dev.msix_mask_notifier = virtio_pci_mask_notifier;
+
size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
if (size & (size-1))
size = 1 << qemu_fls(size);
--
1.6.6.144.g5c3af
14 years, 2 months
[PATCH 22/24] msix: add mask/unmask notifiers
by Michael S. Tsirkin
Support per-vector callbacks for msix mask/unmask.
Will be used for vhost net.
Signed-off-by: Michael S. Tsirkin <mst(a)redhat.com>
---
hw/msix.c | 36 +++++++++++++++++++++++++++++++++++-
hw/msix.h | 1 +
hw/pci.h | 6 ++++++
3 files changed, 42 insertions(+), 1 deletions(-)
diff --git a/hw/msix.c b/hw/msix.c
index d117bcf..3fcf3a1 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -318,6 +318,13 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
if (kvm_enabled() && kvm_irqchip_in_kernel()) {
kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector));
}
+ if (was_masked != msix_is_masked(dev, vector) &&
+ dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
+ int r = dev->msix_mask_notifier(dev, vector,
+ dev->msix_mask_notifier_opaque[vector],
+ msix_is_masked(dev, vector));
+ assert(r >= 0);
+ }
msix_handle_mask_update(dev, vector);
}
@@ -356,10 +363,18 @@ void msix_mmio_map(PCIDevice *d, int region_num,
static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
{
- int vector;
+ int vector, r;
for (vector = 0; vector < nentries; ++vector) {
unsigned offset = vector * MSIX_ENTRY_SIZE + MSIX_VECTOR_CTRL;
+ int was_masked = msix_is_masked(dev, vector);
dev->msix_table_page[offset] |= MSIX_VECTOR_MASK;
+ if (was_masked != msix_is_masked(dev, vector) &&
+ dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
+ r = dev->msix_mask_notifier(dev, vector,
+ dev->msix_mask_notifier_opaque[vector],
+ msix_is_masked(dev, vector));
+ assert(r >= 0);
+ }
}
}
@@ -382,6 +397,9 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
sizeof *dev->msix_irq_entries);
}
#endif
+ dev->msix_mask_notifier_opaque =
+ qemu_mallocz(nentries * sizeof *dev->msix_mask_notifier_opaque);
+ dev->msix_mask_notifier = NULL;
dev->msix_entry_used = qemu_mallocz(MSIX_MAX_ENTRIES *
sizeof *dev->msix_entry_used);
@@ -444,6 +462,8 @@ int msix_uninit(PCIDevice *dev)
dev->msix_entry_used = NULL;
qemu_free(dev->msix_irq_entries);
dev->msix_irq_entries = NULL;
+ qemu_free(dev->msix_mask_notifier_opaque);
+ dev->msix_mask_notifier_opaque = NULL;
dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
return 0;
}
@@ -587,3 +607,17 @@ void msix_unuse_all_vectors(PCIDevice *dev)
return;
msix_free_irq_entries(dev);
}
+
+int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque)
+{
+ int r = 0;
+ if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
+ return 0;
+
+ if (dev->msix_mask_notifier)
+ r = dev->msix_mask_notifier(dev, vector, opaque,
+ msix_is_masked(dev, vector));
+ if (r >= 0)
+ dev->msix_mask_notifier_opaque[vector] = opaque;
+ return r;
+}
diff --git a/hw/msix.h b/hw/msix.h
index a9f7993..f167231 100644
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -33,4 +33,5 @@ void msix_reset(PCIDevice *dev);
extern int msix_supported;
+int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque);
#endif
diff --git a/hw/pci.h b/hw/pci.h
index a225a6a..bf722ca 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -217,6 +217,9 @@ enum {
#define PCI_CAPABILITY_CONFIG_MSI_LENGTH 0x10
#define PCI_CAPABILITY_CONFIG_MSIX_LENGTH 0x10
+typedef int (*msix_mask_notifier_func)(PCIDevice *, unsigned vector,
+ void *opaque, int masked);
+
struct PCIDevice {
DeviceState qdev;
/* PCI config space */
@@ -282,6 +285,9 @@ struct PCIDevice {
struct kvm_irq_routing_entry *msix_irq_entries;
+ void **msix_mask_notifier_opaque;
+ msix_mask_notifier_func msix_mask_notifier;
+
/* Device capability configuration space */
struct {
int supported;
--
1.6.6.144.g5c3af
14 years, 2 months
[PATCH 21/24] kvm: irqfd support
by Michael S. Tsirkin
Add API to assign/deassign irqfd to kvm.
Add stub so that users do not have to use
ifdefs.
Signed-off-by: Michael S. Tsirkin <mst(a)redhat.com>
---
kvm-all.c | 19 +++++++++++++++++++
kvm.h | 10 ++++++++++
2 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index efdf40c..b3fdf29 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1122,4 +1122,23 @@ int kvm_set_ioeventfd(uint16_t addr, uint16_t data, int fd, bool assigned)
}
#endif
+#if defined(KVM_IRQFD)
+int kvm_set_irqfd(int gsi, int fd, bool assigned)
+{
+ struct kvm_irqfd irqfd = {
+ .fd = fd,
+ .gsi = gsi,
+ .flags = assigned ? 0 : KVM_IRQFD_FLAG_DEASSIGN,
+ };
+ int r;
+ if (!kvm_irqchip_in_kernel())
+ return -ENOSYS;
+
+ r = kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd);
+ if (r < 0)
+ return r;
+ return 0;
+}
+#endif
+
#include "qemu-kvm.c"
diff --git a/kvm.h b/kvm.h
index e98b5c8..ad8d122 100644
--- a/kvm.h
+++ b/kvm.h
@@ -167,4 +167,14 @@ int kvm_set_ioeventfd(uint16_t data, uint16_t addr, int fd, bool assigned)
}
#endif
+#if defined(KVM_IRQFD) && defined(CONFIG_KVM)
+int kvm_set_irqfd(int gsi, int fd, bool assigned);
+#else
+static inline
+int kvm_set_irqfd(int gsi, int fd, bool assigned)
+{
+ return -ENOSYS;
+}
+#endif
+
#endif
--
1.6.6.144.g5c3af
14 years, 2 months
[PATCH 20/24] qemu-kvm: add vhost.h header
by Michael S. Tsirkin
This makes it possible to build vhost support
on systems which do not have this header.
Signed-off-by: Michael S. Tsirkin <mst(a)redhat.com>
---
kvm/include/linux/vhost.h | 130 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 130 insertions(+), 0 deletions(-)
create mode 100644 kvm/include/linux/vhost.h
diff --git a/kvm/include/linux/vhost.h b/kvm/include/linux/vhost.h
new file mode 100644
index 0000000..165a484
--- /dev/null
+++ b/kvm/include/linux/vhost.h
@@ -0,0 +1,130 @@
+#ifndef _LINUX_VHOST_H
+#define _LINUX_VHOST_H
+/* Userspace interface for in-kernel virtio accelerators. */
+
+/* vhost is used to reduce the number of system calls involved in virtio.
+ *
+ * Existing virtio net code is used in the guest without modification.
+ *
+ * This header includes interface used by userspace hypervisor for
+ * device configuration.
+ */
+
+#include <linux/types.h>
+
+#include <linux/ioctl.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
+
+struct vhost_vring_state {
+ unsigned int index;
+ unsigned int num;
+};
+
+struct vhost_vring_file {
+ unsigned int index;
+ int fd; /* Pass -1 to unbind from file. */
+
+};
+
+struct vhost_vring_addr {
+ unsigned int index;
+ /* Option flags. */
+ unsigned int flags;
+ /* Flag values: */
+ /* Whether log address is valid. If set enables logging. */
+#define VHOST_VRING_F_LOG 0
+
+ /* Start of array of descriptors (virtually contiguous) */
+ __u64 desc_user_addr;
+ /* Used structure address. Must be 32 bit aligned */
+ __u64 used_user_addr;
+ /* Available structure address. Must be 16 bit aligned */
+ __u64 avail_user_addr;
+ /* Logging support. */
+ /* Log writes to used structure, at offset calculated from specified
+ * address. Address must be 32 bit aligned. */
+ __u64 log_guest_addr;
+};
+
+struct vhost_memory_region {
+ __u64 guest_phys_addr;
+ __u64 memory_size; /* bytes */
+ __u64 userspace_addr;
+ __u64 flags_padding; /* No flags are currently specified. */
+};
+
+/* All region addresses and sizes must be 4K aligned. */
+#define VHOST_PAGE_SIZE 0x1000
+
+struct vhost_memory {
+ __u32 nregions;
+ __u32 padding;
+ struct vhost_memory_region regions[0];
+};
+
+/* ioctls */
+
+#define VHOST_VIRTIO 0xAF
+
+/* Features bitmask for forward compatibility. Transport bits are used for
+ * vhost specific features. */
+#define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
+#define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64)
+
+/* Set current process as the (exclusive) owner of this file descriptor. This
+ * must be called before any other vhost command. Further calls to
+ * VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */
+#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
+/* Give up ownership, and reset the device to default values.
+ * Allows subsequent call to VHOST_OWNER_SET to succeed. */
+#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
+
+/* Set up/modify memory layout */
+#define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
+
+/* Write logging setup. */
+/* Memory writes can optionally be logged by setting bit at an offset
+ * (calculated from the physical address) from specified log base.
+ * The bit is set using an atomic 32 bit operation. */
+/* Set base address for logging. */
+#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
+/* Specify an eventfd file descriptor to signal on log write. */
+#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
+
+/* Ring setup. */
+/* Set number of descriptors in ring. This parameter can not
+ * be modified while ring is running (bound to a device). */
+#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
+/* Set addresses for the ring. */
+#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
+/* Base value where queue looks for available descriptors */
+#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
+/* Get accessor: reads index, writes value in num */
+#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
+
+/* The following ioctls use eventfd file descriptors to signal and poll
+ * for events. */
+
+/* Set eventfd to poll for added buffers */
+#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
+/* Set eventfd to signal when buffers have beed used */
+#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
+/* Set eventfd to signal an error */
+#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
+
+/* VHOST_NET specific defines */
+
+/* Attach virtio net ring to a raw socket, or tap device.
+ * The socket must be already bound to an ethernet device, this device will be
+ * used for transmit. Pass fd -1 to unbind from the socket and the transmit
+ * device. This can be used to stop the ring (e.g. for migration). */
+#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
+
+/* Feature bits */
+/* Log all write descriptors. Can be changed while device is active. */
+#define VHOST_F_LOG_ALL 26
+/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
+#define VHOST_NET_F_VIRTIO_NET_HDR 27
+
+#endif
--
1.6.6.144.g5c3af
14 years, 2 months
[PATCH 19/24] virtio-net: vhost net support
by Michael S. Tsirkin
This connects virtio-net to vhost net backend.
The code is structured in a way analogous to what we have with vnet
header capability in tap. We start/stop backend on driver start/stop as
well as on save and vm start (for migration).
Signed-off-by: Michael S. Tsirkin <mst(a)redhat.com>
---
hw/virtio-net.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 02d9180..088029b 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -17,6 +17,7 @@
#include "net/tap.h"
#include "qemu-timer.h"
#include "virtio-net.h"
+#include "vhost_net.h"
#define VIRTIO_NET_VM_VERSION 11
@@ -47,6 +48,8 @@ typedef struct VirtIONet
uint8_t nomulti;
uint8_t nouni;
uint8_t nobcast;
+ uint8_t vhost_started;
+ VMChangeStateEntry *vmstate;
struct {
int in_use;
int first_multi;
@@ -114,6 +117,10 @@ static void virtio_net_reset(VirtIODevice *vdev)
n->nomulti = 0;
n->nouni = 0;
n->nobcast = 0;
+ if (n->vhost_started) {
+ vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
+ n->vhost_started = 0;
+ }
/* Flush any MAC and VLAN filter table state */
n->mac_table.in_use = 0;
@@ -172,7 +179,10 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
}
- return features;
+ if (!tap_get_vhost_net(n->nic->nc.peer)) {
+ return features;
+ }
+ return vhost_net_get_features(tap_get_vhost_net(n->nic->nc.peer), features);
}
static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
@@ -690,6 +700,12 @@ static void virtio_net_save(QEMUFile *f, void *opaque)
{
VirtIONet *n = opaque;
+ if (n->vhost_started) {
+ /* TODO: should we really stop the backend?
+ * If we don't, it might keep writing to memory. */
+ vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
+ n->vhost_started = 0;
+ }
virtio_save(&n->vdev, f);
qemu_put_buffer(f, n->mac, ETH_ALEN);
@@ -802,7 +818,6 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
qemu_mod_timer(n->tx_timer,
qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
}
-
return 0;
}
@@ -822,6 +837,47 @@ static NetClientInfo net_virtio_info = {
.link_status_changed = virtio_net_set_link_status,
};
+static void virtio_net_set_status(struct VirtIODevice *vdev)
+{
+ VirtIONet *n = to_virtio_net(vdev);
+ if (!n->nic->nc.peer) {
+ return;
+ }
+ if (n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) {
+ return;
+ }
+
+ if (!tap_get_vhost_net(n->nic->nc.peer)) {
+ return;
+ }
+ if (!!n->vhost_started == !!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+ return;
+ }
+ if (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) {
+ int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), vdev);
+ if (r < 0) {
+ fprintf(stderr, "unable to start vhost net: %d: "
+ "falling back on userspace virtio\n", -r);
+ } else {
+ n->vhost_started = 1;
+ }
+ } else {
+ vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
+ n->vhost_started = 0;
+ }
+}
+
+static void virtio_net_vmstate_change(void *opaque, int running, int reason)
+{
+ VirtIONet *n = opaque;
+ if (!running) {
+ return;
+ }
+ /* This is called when vm is started, it will start vhost backend if it
+ * appropriate e.g. after migration. */
+ virtio_net_set_status(&n->vdev);
+}
+
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
{
VirtIONet *n;
@@ -837,6 +893,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
n->vdev.set_features = virtio_net_set_features;
n->vdev.bad_features = virtio_net_bad_features;
n->vdev.reset = virtio_net_reset;
+ n->vdev.set_status = virtio_net_set_status;
n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
n->ctrl_vq = virtio_add_queue(&n->vdev, 64, virtio_net_handle_ctrl);
@@ -859,6 +916,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
virtio_net_save, virtio_net_load, n);
+ n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
return &n->vdev;
}
@@ -866,6 +924,11 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
void virtio_net_exit(VirtIODevice *vdev)
{
VirtIONet *n = DO_UPCAST(VirtIONet, vdev, vdev);
+ qemu_del_vm_change_state_handler(n->vmstate);
+
+ if (n->vhost_started) {
+ vhost_net_stop(tap_get_vhost_net(n->nic->nc.peer), vdev);
+ }
qemu_purge_queued_packets(&n->nic->nc);
--
1.6.6.144.g5c3af
14 years, 2 months
[PATCH 18/24] tap: add API to retrieve vhost net header
by Michael S. Tsirkin
will be used by virtio-net for vhost net support
Signed-off-by: Michael S. Tsirkin <mst(a)redhat.com>
---
net/tap.c | 7 +++++++
net/tap.h | 3 +++
2 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/net/tap.c b/net/tap.c
index d9f2e41..166cf05 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -491,3 +491,10 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
return 0;
}
+
+struct vhost_net *tap_get_vhost_net(VLANClientState *nc)
+{
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ assert(nc->info->type == NET_CLIENT_TYPE_TAP);
+ return s->vhost_net;
+}
diff --git a/net/tap.h b/net/tap.h
index a244b28..b8cec83 100644
--- a/net/tap.h
+++ b/net/tap.h
@@ -50,4 +50,7 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo);
int tap_get_fd(VLANClientState *vc);
+struct vhost_net;
+struct vhost_net *tap_get_vhost_net(VLANClientState *vc);
+
#endif /* QEMU_NET_TAP_H */
--
1.6.6.144.g5c3af
14 years, 2 months
[PATCH 17/24] tap: add vhost/vhostfd options
by Michael S. Tsirkin
Signed-off-by: Michael S. Tsirkin <mst(a)redhat.com>
---
net.c | 8 ++++++++
net/tap.c | 29 +++++++++++++++++++++++++++++
qemu-options.hx | 4 +++-
3 files changed, 40 insertions(+), 1 deletions(-)
diff --git a/net.c b/net.c
index 6ef93e6..b942d03 100644
--- a/net.c
+++ b/net.c
@@ -976,6 +976,14 @@ static struct {
.name = "vnet_hdr",
.type = QEMU_OPT_BOOL,
.help = "enable the IFF_VNET_HDR flag on the tap interface"
+ }, {
+ .name = "vhost",
+ .type = QEMU_OPT_BOOL,
+ .help = "enable vhost-net network accelerator",
+ }, {
+ .name = "vhostfd",
+ .type = QEMU_OPT_STRING,
+ .help = "file descriptor of an already opened vhost net device",
},
#endif /* _WIN32 */
{ /* end of list */ }
diff --git a/net/tap.c b/net/tap.c
index 7e9ca79..d9f2e41 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -41,6 +41,8 @@
#include "net/tap-linux.h"
+#include "hw/vhost_net.h"
+
/* Maximum GSO packet size (64k) plus plenty of room for
* the ethernet and virtio_net headers
*/
@@ -57,6 +59,7 @@ typedef struct TAPState {
unsigned int has_vnet_hdr : 1;
unsigned int using_vnet_hdr : 1;
unsigned int has_ufo: 1;
+ struct vhost_net *vhost_net;
} TAPState;
static int launch_script(const char *setup_script, const char *ifname, int fd);
@@ -252,6 +255,10 @@ static void tap_cleanup(VLANClientState *nc)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ if (s->vhost_net) {
+ vhost_net_cleanup(s->vhost_net);
+ }
+
qemu_purge_queued_packets(nc);
if (s->down_script[0])
@@ -307,6 +314,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
s->has_ufo = tap_probe_has_ufo(s->fd);
tap_set_offload(&s->nc, 0, 0, 0, 0, 0);
tap_read_poll(s, 1);
+ s->vhost_net = NULL;
return s;
}
@@ -456,6 +464,27 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
}
}
+ if (qemu_opt_get_bool(opts, "vhost", 0)) {
+ int vhostfd, r;
+ if (qemu_opt_get(opts, "vhostfd")) {
+ r = net_handle_fd_param(mon, qemu_opt_get(opts, "vhostfd"));
+ if (r == -1) {
+ return -1;
+ }
+ vhostfd = r;
+ } else {
+ vhostfd = -1;
+ }
+ s->vhost_net = vhost_net_init(&s->nc, vhostfd);
+ if (!s->vhost_net) {
+ qemu_error("vhost-net requested but could not be initialized\n");
+ return -1;
+ }
+ } else if (qemu_opt_get(opts, "vhostfd")) {
+ qemu_error("vhostfd= is not valid without vhost\n");
+ return -1;
+ }
+
if (vlan) {
vlan->nb_host_devs++;
}
diff --git a/qemu-options.hx b/qemu-options.hx
index ca73ba5..2b3d9b8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -814,7 +814,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
"-net tap[,vlan=n][,name=str],ifname=name\n"
" connect the host TAP network interface to VLAN 'n'\n"
#else
- "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off]\n"
+ "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h]\n"
" connect the host TAP network interface to VLAN 'n' and use the\n"
" network scripts 'file' (default=%s)\n"
" and 'dfile' (default=%s);\n"
@@ -824,6 +824,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
" default of 'sndbuf=1048576' can be disabled using 'sndbuf=0'\n"
" use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flag; use\n"
" vnet_hdr=on to make the lack of IFF_VNET_HDR support an error condition\n"
+ " use vhost=on to enable experimental in kernel accelerator\n"
+ " use 'vhostfd=h' to connect to an already opened vhost net device\n"
#endif
"-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
" connect the vlan 'n' to another VLAN using a socket connection\n"
--
1.6.6.144.g5c3af
14 years, 2 months