mirror of https://gitee.com/openkylin/qemu.git
virtio, pci fixes, enhancements
Most notably this includes virtio cross-endian patches. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJVg+xdAAoJECgfDbjSjVRp6AAH/3ILznMtvJZjQ/WOjLEsL13M +0cYEM1LI6LbLhqeruQVVcY9/hx61yHxZMoLkVg/I2po7F4HDNI2vo5Y7eGx+xN0 5rlcAw9/ZQ6SkCVmjN/VZfISW5mSqCaKH8gNzu8AigjsryJSj5iDXv1YJimwsF+5 cgCerhLIVvEkXmNj1ChwR+fz1IgFzJ8TRaZ0N2glxLyVjgKS57diqZF3Rbg2DdQl BPbekbbtxesPgmKRvtarbhjx26TlnP1YShjhWA5r72gBNlqblLDycpaIGXr34b3a sLIZjxzQtTEGcaGtkifMgazyK3rY3JmzOshD0onFOWY1r6Abxuj7eTZOEE6JQXk= =tju/ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging virtio, pci fixes, enhancements Most notably this includes virtio cross-endian patches. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Fri Jun 19 11:18:05 2015 BST using RSA key ID D28D5469 # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" * remotes/mst/tags/for_upstream: vhost: enable vhost without without MSI-X pci: Don't register a specialized 'config_write' if default behavior is intended hw/core: rebase sysbus_get_fw_dev_path() to g_strdup_printf() vhost_net: re-enable when cross endian vhost-net: tell tap backend about the vnet endianness tap: fix non-linux build tap: add VNET_LE/VNET_BE operations vhost: set vring endianness for legacy virtio virtio: introduce virtio_legacy_is_cross_endian() linux-headers: sync vhost.h vhost-user: part of virtio Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
89e9429c3c
|
@ -702,6 +702,7 @@ virtio
|
|||
M: Michael S. Tsirkin <mst@redhat.com>
|
||||
S: Supported
|
||||
F: hw/*/virtio*
|
||||
F: net/vhost-user.c
|
||||
|
||||
virtio-9p
|
||||
M: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
|
|
|
@ -281,19 +281,15 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
|
|||
static char *sysbus_get_fw_dev_path(DeviceState *dev)
|
||||
{
|
||||
SysBusDevice *s = SYS_BUS_DEVICE(dev);
|
||||
char path[40];
|
||||
int off;
|
||||
|
||||
off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
|
||||
|
||||
if (s->num_mmio) {
|
||||
snprintf(path + off, sizeof(path) - off, "@"TARGET_FMT_plx,
|
||||
s->mmio[0].addr);
|
||||
} else if (s->num_pio) {
|
||||
snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]);
|
||||
return g_strdup_printf("%s@" TARGET_FMT_plx, qdev_fw_name(dev),
|
||||
s->mmio[0].addr);
|
||||
}
|
||||
|
||||
return g_strdup(path);
|
||||
if (s->num_pio) {
|
||||
return g_strdup_printf("%s@i%04x", qdev_fw_name(dev), s->pio[0]);
|
||||
}
|
||||
return g_strdup(qdev_fw_name(dev));
|
||||
}
|
||||
|
||||
void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
|
||||
|
|
|
@ -698,7 +698,6 @@ static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address,
|
|||
uint32_t val, int len)
|
||||
{
|
||||
pci_default_write_config(pci_dev, address, val, len);
|
||||
msix_write_config(pci_dev, address, val, len);
|
||||
}
|
||||
|
||||
static int pci_ivshmem_init(PCIDevice *dev)
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "standard-headers/linux/virtio_ring.h"
|
||||
#include "hw/virtio/vhost.h"
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
|
||||
struct vhost_net {
|
||||
struct vhost_dev dev;
|
||||
|
@ -162,7 +163,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
|||
net->dev.vq_index = net->nc->queue_index;
|
||||
|
||||
r = vhost_dev_init(&net->dev, options->opaque,
|
||||
options->backend_type, options->force);
|
||||
options->backend_type);
|
||||
if (r < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -187,16 +188,32 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
|
||||
{
|
||||
return vhost_dev_query(&net->dev, dev);
|
||||
}
|
||||
|
||||
static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index)
|
||||
{
|
||||
net->dev.vq_index = vq_index;
|
||||
}
|
||||
|
||||
static int vhost_net_set_vnet_endian(VirtIODevice *dev, NetClientState *peer,
|
||||
bool set)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if (virtio_has_feature(dev, VIRTIO_F_VERSION_1) ||
|
||||
(virtio_legacy_is_cross_endian(dev) && !virtio_is_big_endian(dev))) {
|
||||
r = qemu_set_vnet_le(peer, set);
|
||||
if (r) {
|
||||
error_report("backend does not support LE vnet headers");
|
||||
}
|
||||
} else if (virtio_legacy_is_cross_endian(dev)) {
|
||||
r = qemu_set_vnet_be(peer, set);
|
||||
if (r) {
|
||||
error_report("backend does not support BE vnet headers");
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int vhost_net_start_one(struct vhost_net *net,
|
||||
VirtIODevice *dev)
|
||||
{
|
||||
|
@ -281,19 +298,6 @@ static void vhost_net_stop_one(struct vhost_net *net,
|
|||
vhost_dev_disable_notifiers(&net->dev, dev);
|
||||
}
|
||||
|
||||
static bool vhost_net_device_endian_ok(VirtIODevice *vdev)
|
||||
{
|
||||
#ifdef TARGET_IS_BIENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
return virtio_is_big_endian(vdev);
|
||||
#else
|
||||
return !virtio_is_big_endian(vdev);
|
||||
#endif
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
|
||||
int total_queues)
|
||||
{
|
||||
|
@ -302,15 +306,14 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
|
|||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
|
||||
int r, e, i;
|
||||
|
||||
if (!vhost_net_device_endian_ok(dev)) {
|
||||
error_report("vhost-net does not support cross-endian");
|
||||
if (!k->set_guest_notifiers) {
|
||||
error_report("binding does not support guest notifiers");
|
||||
r = -ENOSYS;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!k->set_guest_notifiers) {
|
||||
error_report("binding does not support guest notifiers");
|
||||
r = -ENOSYS;
|
||||
r = vhost_net_set_vnet_endian(dev, ncs[0].peer, true);
|
||||
if (r < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -321,7 +324,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
|
|||
r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
|
||||
if (r < 0) {
|
||||
error_report("Error binding guest notifier: %d", -r);
|
||||
goto err;
|
||||
goto err_endian;
|
||||
}
|
||||
|
||||
for (i = 0; i < total_queues; i++) {
|
||||
|
@ -343,6 +346,8 @@ err_start:
|
|||
fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e);
|
||||
fflush(stderr);
|
||||
}
|
||||
err_endian:
|
||||
vhost_net_set_vnet_endian(dev, ncs[0].peer, false);
|
||||
err:
|
||||
return r;
|
||||
}
|
||||
|
@ -365,6 +370,8 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
|
|||
fflush(stderr);
|
||||
}
|
||||
assert(r >= 0);
|
||||
|
||||
assert(vhost_net_set_vnet_endian(dev, ncs[0].peer, false) >= 0);
|
||||
}
|
||||
|
||||
void vhost_net_cleanup(struct vhost_net *net)
|
||||
|
@ -412,11 +419,6 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int vhost_net_start(VirtIODevice *dev,
|
||||
NetClientState *ncs,
|
||||
int total_queues)
|
||||
|
|
|
@ -128,10 +128,6 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
|
|||
if (!n->vhost_started) {
|
||||
int r, i;
|
||||
|
||||
if (!vhost_net_query(get_vhost_net(nc->peer), vdev)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Any packets outstanding? Purge them to avoid touching rings
|
||||
* when vhost is running.
|
||||
*/
|
||||
|
|
|
@ -2477,14 +2477,6 @@ static const VMStateDescription vmstate_vmxnet3 = {
|
|||
}
|
||||
};
|
||||
|
||||
static void
|
||||
vmxnet3_write_config(PCIDevice *pci_dev, uint32_t addr, uint32_t val, int len)
|
||||
{
|
||||
pci_default_write_config(pci_dev, addr, val, len);
|
||||
msix_write_config(pci_dev, addr, val, len);
|
||||
msi_write_config(pci_dev, addr, val, len);
|
||||
}
|
||||
|
||||
static Property vmxnet3_properties[] = {
|
||||
DEFINE_NIC_PROPERTIES(VMXNET3State, conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
|
@ -2503,7 +2495,6 @@ static void vmxnet3_class_init(ObjectClass *class, void *data)
|
|||
c->class_id = PCI_CLASS_NETWORK_ETHERNET;
|
||||
c->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE;
|
||||
c->subsystem_id = PCI_DEVICE_ID_VMWARE_VMXNET3;
|
||||
c->config_write = vmxnet3_write_config,
|
||||
dc->desc = "VMWare Paravirtualized Ethernet v3";
|
||||
dc->reset = vmxnet3_qdev_reset;
|
||||
dc->vmsd = &vmstate_vmxnet3;
|
||||
|
|
|
@ -2407,13 +2407,6 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
megasas_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len)
|
||||
{
|
||||
pci_default_write_config(pci, addr, val, len);
|
||||
msi_write_config(pci, addr, val, len);
|
||||
}
|
||||
|
||||
static Property megasas_properties_gen1[] = {
|
||||
DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge,
|
||||
MEGASAS_DEFAULT_SGE),
|
||||
|
@ -2516,7 +2509,6 @@ static void megasas_class_init(ObjectClass *oc, void *data)
|
|||
dc->vmsd = info->vmsd;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
dc->desc = info->desc;
|
||||
pc->config_write = megasas_write_config;
|
||||
}
|
||||
|
||||
static const TypeInfo megasas_info = {
|
||||
|
|
|
@ -246,7 +246,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
|
|||
s->dev.backend_features = 0;
|
||||
|
||||
ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd,
|
||||
VHOST_BACKEND_TYPE_KERNEL, true);
|
||||
VHOST_BACKEND_TYPE_KERNEL);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
|
||||
strerror(-ret));
|
||||
|
|
|
@ -1174,13 +1174,6 @@ static const VMStateDescription vmstate_pvscsi = {
|
|||
}
|
||||
};
|
||||
|
||||
static void
|
||||
pvscsi_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len)
|
||||
{
|
||||
pci_default_write_config(pci, addr, val, len);
|
||||
msi_write_config(pci, addr, val, len);
|
||||
}
|
||||
|
||||
static Property pvscsi_properties[] = {
|
||||
DEFINE_PROP_UINT8("use_msg", PVSCSIState, use_msg, 1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
|
@ -1202,7 +1195,6 @@ static void pvscsi_class_init(ObjectClass *klass, void *data)
|
|||
dc->vmsd = &vmstate_pvscsi;
|
||||
dc->props = pvscsi_properties;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
k->config_write = pvscsi_write_config;
|
||||
hc->unplug = pvscsi_hot_unplug;
|
||||
hc->plug = pvscsi_hotplug;
|
||||
}
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
#include "hw/hw.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/range.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include <linux/vhost.h>
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
#include "migration/migration.h"
|
||||
|
||||
static struct vhost_log *vhost_log;
|
||||
|
@ -689,6 +691,27 @@ static void vhost_log_stop(MemoryListener *listener,
|
|||
/* FIXME: implement */
|
||||
}
|
||||
|
||||
static int vhost_virtqueue_set_vring_endian_legacy(struct vhost_dev *dev,
|
||||
bool is_big_endian,
|
||||
int vhost_vq_index)
|
||||
{
|
||||
struct vhost_vring_state s = {
|
||||
.index = vhost_vq_index,
|
||||
.num = is_big_endian
|
||||
};
|
||||
|
||||
if (!dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ENDIAN, &s)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (errno == ENOTTY) {
|
||||
error_report("vhost does not support cross-endian");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
static int vhost_virtqueue_start(struct vhost_dev *dev,
|
||||
struct VirtIODevice *vdev,
|
||||
struct vhost_virtqueue *vq,
|
||||
|
@ -719,6 +742,16 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
|
|||
return -errno;
|
||||
}
|
||||
|
||||
if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
||||
virtio_legacy_is_cross_endian(vdev)) {
|
||||
r = vhost_virtqueue_set_vring_endian_legacy(dev,
|
||||
virtio_is_big_endian(vdev),
|
||||
vhost_vq_index);
|
||||
if (r) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
s = l = virtio_queue_get_desc_size(vdev, idx);
|
||||
a = virtio_queue_get_desc_addr(vdev, idx);
|
||||
vq->desc = cpu_physical_memory_map(a, &l, 0);
|
||||
|
@ -789,8 +822,9 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
|
|||
struct vhost_virtqueue *vq,
|
||||
unsigned idx)
|
||||
{
|
||||
int vhost_vq_index = idx - dev->vq_index;
|
||||
struct vhost_vring_state state = {
|
||||
.index = idx - dev->vq_index
|
||||
.index = vhost_vq_index,
|
||||
};
|
||||
int r;
|
||||
assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
|
||||
|
@ -801,6 +835,20 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
|
|||
}
|
||||
virtio_queue_set_last_avail_idx(vdev, idx, state.num);
|
||||
virtio_queue_invalidate_signalled_used(vdev, idx);
|
||||
|
||||
/* In the cross-endian case, we need to reset the vring endianness to
|
||||
* native as legacy devices expect so by default.
|
||||
*/
|
||||
if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
||||
virtio_legacy_is_cross_endian(vdev)) {
|
||||
r = vhost_virtqueue_set_vring_endian_legacy(dev,
|
||||
!virtio_is_big_endian(vdev),
|
||||
vhost_vq_index);
|
||||
if (r < 0) {
|
||||
error_report("failed to reset vring endianness");
|
||||
}
|
||||
}
|
||||
|
||||
assert (r >= 0);
|
||||
cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
|
||||
0, virtio_queue_get_ring_size(vdev, idx));
|
||||
|
@ -853,7 +901,7 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
|
|||
}
|
||||
|
||||
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
||||
VhostBackendType backend_type, bool force)
|
||||
VhostBackendType backend_type)
|
||||
{
|
||||
uint64_t features;
|
||||
int i, r;
|
||||
|
@ -916,7 +964,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
|||
hdev->started = false;
|
||||
hdev->memory_changed = false;
|
||||
memory_listener_register(&hdev->memory_listener, &address_space_memory);
|
||||
hdev->force = force;
|
||||
return 0;
|
||||
fail_vq:
|
||||
while (--i >= 0) {
|
||||
|
@ -944,17 +991,6 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
|
|||
hdev->vhost_ops->vhost_backend_cleanup(hdev);
|
||||
}
|
||||
|
||||
bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev)
|
||||
{
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
|
||||
VirtioBusState *vbus = VIRTIO_BUS(qbus);
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
|
||||
|
||||
return !k->query_guest_notifiers ||
|
||||
k->query_guest_notifiers(qbus->parent) ||
|
||||
hdev->force;
|
||||
}
|
||||
|
||||
/* Stop processing guest IO notifications in qemu.
|
||||
* Start processing them in vhost in kernel.
|
||||
*/
|
||||
|
|
|
@ -51,7 +51,6 @@ struct vhost_dev {
|
|||
bool log_enabled;
|
||||
unsigned long long log_size;
|
||||
Error *migration_blocker;
|
||||
bool force;
|
||||
bool memory_changed;
|
||||
hwaddr mem_changed_start_addr;
|
||||
hwaddr mem_changed_end_addr;
|
||||
|
@ -61,7 +60,7 @@ struct vhost_dev {
|
|||
};
|
||||
|
||||
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
||||
VhostBackendType backend_type, bool force);
|
||||
VhostBackendType backend_type);
|
||||
void vhost_dev_cleanup(struct vhost_dev *hdev);
|
||||
bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev);
|
||||
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
|
||||
|
|
|
@ -32,6 +32,19 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
|
|||
#endif
|
||||
}
|
||||
|
||||
static inline bool virtio_legacy_is_cross_endian(VirtIODevice *vdev)
|
||||
{
|
||||
#ifdef TARGET_IS_BIENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
return !virtio_is_big_endian(vdev);
|
||||
#else
|
||||
return virtio_is_big_endian(vdev);
|
||||
#endif
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa)
|
||||
{
|
||||
if (virtio_access_is_big_endian(vdev)) {
|
||||
|
|
|
@ -55,6 +55,8 @@ typedef bool (HasVnetHdrLen)(NetClientState *, int);
|
|||
typedef void (UsingVnetHdr)(NetClientState *, bool);
|
||||
typedef void (SetOffload)(NetClientState *, int, int, int, int, int);
|
||||
typedef void (SetVnetHdrLen)(NetClientState *, int);
|
||||
typedef int (SetVnetLE)(NetClientState *, bool);
|
||||
typedef int (SetVnetBE)(NetClientState *, bool);
|
||||
|
||||
typedef struct NetClientInfo {
|
||||
NetClientOptionsKind type;
|
||||
|
@ -73,6 +75,8 @@ typedef struct NetClientInfo {
|
|||
UsingVnetHdr *using_vnet_hdr;
|
||||
SetOffload *set_offload;
|
||||
SetVnetHdrLen *set_vnet_hdr_len;
|
||||
SetVnetLE *set_vnet_le;
|
||||
SetVnetBE *set_vnet_be;
|
||||
} NetClientInfo;
|
||||
|
||||
struct NetClientState {
|
||||
|
@ -139,6 +143,8 @@ void qemu_using_vnet_hdr(NetClientState *nc, bool enable);
|
|||
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
|
||||
int ecn, int ufo);
|
||||
void qemu_set_vnet_hdr_len(NetClientState *nc, int len);
|
||||
int qemu_set_vnet_le(NetClientState *nc, bool is_le);
|
||||
int qemu_set_vnet_be(NetClientState *nc, bool is_be);
|
||||
void qemu_macaddr_default_if_unset(MACAddr *macaddr);
|
||||
int qemu_show_nic_models(const char *arg, const char *const *models);
|
||||
void qemu_check_nic_model(NICInfo *nd, const char *model);
|
||||
|
|
|
@ -11,12 +11,10 @@ typedef struct VhostNetOptions {
|
|||
VhostBackendType backend_type;
|
||||
NetClientState *net_backend;
|
||||
void *opaque;
|
||||
bool force;
|
||||
} VhostNetOptions;
|
||||
|
||||
struct vhost_net *vhost_net_init(VhostNetOptions *options);
|
||||
|
||||
bool vhost_net_query(VHostNetState *net, VirtIODevice *dev);
|
||||
int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, int total_queues);
|
||||
void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs, int total_queues);
|
||||
|
||||
|
|
|
@ -103,6 +103,20 @@ struct vhost_memory {
|
|||
/* Get accessor: reads index, writes value in num */
|
||||
#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
|
||||
|
||||
/* Set the vring byte order in num. Valid values are VHOST_VRING_LITTLE_ENDIAN
|
||||
* or VHOST_VRING_BIG_ENDIAN (other values return -EINVAL).
|
||||
* The byte order cannot be changed while the device is active: trying to do so
|
||||
* returns -EBUSY.
|
||||
* This is a legacy only API that is simply ignored when VIRTIO_F_VERSION_1 is
|
||||
* set.
|
||||
* Not all kernel configurations support this ioctl, but all configurations that
|
||||
* support SET also support GET.
|
||||
*/
|
||||
#define VHOST_VRING_LITTLE_ENDIAN 0
|
||||
#define VHOST_VRING_BIG_ENDIAN 1
|
||||
#define VHOST_SET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x13, struct vhost_vring_state)
|
||||
#define VHOST_GET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x14, struct vhost_vring_state)
|
||||
|
||||
/* The following ioctls use eventfd file descriptors to signal and poll
|
||||
* for events. */
|
||||
|
||||
|
|
18
net/net.c
18
net/net.c
|
@ -510,6 +510,24 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
|
|||
nc->info->set_vnet_hdr_len(nc, len);
|
||||
}
|
||||
|
||||
int qemu_set_vnet_le(NetClientState *nc, bool is_le)
|
||||
{
|
||||
if (!nc || !nc->info->set_vnet_le) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return nc->info->set_vnet_le(nc, is_le);
|
||||
}
|
||||
|
||||
int qemu_set_vnet_be(NetClientState *nc, bool is_be)
|
||||
{
|
||||
if (!nc || !nc->info->set_vnet_be) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return nc->info->set_vnet_be(nc, is_be);
|
||||
}
|
||||
|
||||
int qemu_can_send_packet(NetClientState *sender)
|
||||
{
|
||||
int vm_running = runstate_is_running();
|
||||
|
|
|
@ -55,6 +55,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
|
|||
{
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_le(int fd, int is_le)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_be(int fd, int is_be)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void tap_fd_set_offload(int fd, int csum, int tso4,
|
||||
int tso6, int ecn, int ufo)
|
||||
{
|
||||
|
|
|
@ -196,6 +196,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
|
|||
{
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_le(int fd, int is_le)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_be(int fd, int is_be)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void tap_fd_set_offload(int fd, int csum, int tso4,
|
||||
int tso6, int ecn, int ufo)
|
||||
{
|
||||
|
|
|
@ -55,6 +55,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
|
|||
{
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_le(int fd, int is_le)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_be(int fd, int is_be)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void tap_fd_set_offload(int fd, int csum, int tso4,
|
||||
int tso6, int ecn, int ufo)
|
||||
{
|
||||
|
|
|
@ -198,6 +198,40 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
|
|||
}
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_le(int fd, int is_le)
|
||||
{
|
||||
int arg = is_le ? 1 : 0;
|
||||
|
||||
if (!ioctl(fd, TUNSETVNETLE, &arg)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if our kernel supports TUNSETVNETLE */
|
||||
if (errno == EINVAL) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
error_report("TUNSETVNETLE ioctl() failed: %s.\n", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_be(int fd, int is_be)
|
||||
{
|
||||
int arg = is_be ? 1 : 0;
|
||||
|
||||
if (!ioctl(fd, TUNSETVNETBE, &arg)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if our kernel supports TUNSETVNETBE */
|
||||
if (errno == EINVAL) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
error_report("TUNSETVNETBE ioctl() failed: %s.\n", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
|
||||
void tap_fd_set_offload(int fd, int csum, int tso4,
|
||||
int tso6, int ecn, int ufo)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#define TUNGETVNETHDRSZ _IOR('T', 215, int)
|
||||
#define TUNSETVNETHDRSZ _IOW('T', 216, int)
|
||||
#define TUNSETQUEUE _IOW('T', 217, int)
|
||||
#define TUNSETVNETLE _IOW('T', 220, int)
|
||||
#define TUNSETVNETBE _IOW('T', 222, int)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -223,6 +223,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
|
|||
{
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_le(int fd, int is_le)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_be(int fd, int is_be)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void tap_fd_set_offload(int fd, int csum, int tso4,
|
||||
int tso6, int ecn, int ufo)
|
||||
{
|
||||
|
|
|
@ -688,6 +688,16 @@ void tap_fd_set_vnet_hdr_len(int fd, int len)
|
|||
{
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_le(int fd, int is_le)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int tap_fd_set_vnet_be(int fd, int is_be)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
|
||||
{
|
||||
}
|
||||
|
|
17
net/tap.c
17
net/tap.c
|
@ -266,6 +266,20 @@ static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
|
|||
s->using_vnet_hdr = using_vnet_hdr;
|
||||
}
|
||||
|
||||
static int tap_set_vnet_le(NetClientState *nc, bool is_le)
|
||||
{
|
||||
TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
|
||||
return tap_fd_set_vnet_le(s->fd, is_le);
|
||||
}
|
||||
|
||||
static int tap_set_vnet_be(NetClientState *nc, bool is_be)
|
||||
{
|
||||
TAPState *s = DO_UPCAST(TAPState, nc, nc);
|
||||
|
||||
return tap_fd_set_vnet_be(s->fd, is_be);
|
||||
}
|
||||
|
||||
static void tap_set_offload(NetClientState *nc, int csum, int tso4,
|
||||
int tso6, int ecn, int ufo)
|
||||
{
|
||||
|
@ -332,6 +346,8 @@ static NetClientInfo net_tap_info = {
|
|||
.using_vnet_hdr = tap_using_vnet_hdr,
|
||||
.set_offload = tap_set_offload,
|
||||
.set_vnet_hdr_len = tap_set_vnet_hdr_len,
|
||||
.set_vnet_le = tap_set_vnet_le,
|
||||
.set_vnet_be = tap_set_vnet_be,
|
||||
};
|
||||
|
||||
static TAPState *net_tap_fd_init(NetClientState *peer,
|
||||
|
@ -646,7 +662,6 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
|
|||
|
||||
options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
|
||||
options.net_backend = &s->nc;
|
||||
options.force = tap->has_vhostforce && tap->vhostforce;
|
||||
|
||||
if (tap->has_vhostfd || tap->has_vhostfds) {
|
||||
vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
|
||||
|
|
|
@ -40,6 +40,8 @@ int tap_probe_vnet_hdr_len(int fd, int len);
|
|||
int tap_probe_has_ufo(int fd);
|
||||
void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo);
|
||||
void tap_fd_set_vnet_hdr_len(int fd, int len);
|
||||
int tap_fd_set_vnet_le(int fd, int vnet_is_le);
|
||||
int tap_fd_set_vnet_be(int fd, int vnet_is_be);
|
||||
int tap_fd_enable(int fd);
|
||||
int tap_fd_disable(int fd);
|
||||
int tap_fd_get_ifname(int fd, char *ifname);
|
||||
|
|
|
@ -50,7 +50,6 @@ static int vhost_user_start(VhostUserState *s)
|
|||
options.backend_type = VHOST_BACKEND_TYPE_USER;
|
||||
options.net_backend = &s->nc;
|
||||
options.opaque = s->chr;
|
||||
options.force = true;
|
||||
|
||||
s->vhost_net = vhost_net_init(&options);
|
||||
|
||||
|
|
Loading…
Reference in New Issue