virtio-net: Make tx_timer timeout configurable
Add an option to make the TX mitigation timer adjustable as a device option. The 150us hard coded default used currently is reasonable, but may not be suitable for all workloads, this gives us a way to adjust it using a single binary. We can't support any random option though, so use the "x-" prefix to indicate this is a developer option. Usage: -device virtio-net-pci,x-txtimer=500000,... # .5ms timeout Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
ca736c8e74
commit
f0c07c7c7b
@ -27,6 +27,7 @@
|
|||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "hw/virtio.h"
|
#include "hw/virtio.h"
|
||||||
#include "hw/virtio-serial.h"
|
#include "hw/virtio-serial.h"
|
||||||
|
#include "hw/virtio-net.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "kvm.h"
|
#include "kvm.h"
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ static int s390_virtio_net_init(VirtIOS390Device *dev)
|
|||||||
{
|
{
|
||||||
VirtIODevice *vdev;
|
VirtIODevice *vdev;
|
||||||
|
|
||||||
vdev = virtio_net_init((DeviceState *)dev, &dev->nic);
|
vdev = virtio_net_init((DeviceState *)dev, &dev->nic, &dev->net);
|
||||||
if (!vdev) {
|
if (!vdev) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -327,6 +328,8 @@ static VirtIOS390DeviceInfo s390_virtio_net = {
|
|||||||
.qdev.size = sizeof(VirtIOS390Device),
|
.qdev.size = sizeof(VirtIOS390Device),
|
||||||
.qdev.props = (Property[]) {
|
.qdev.props = (Property[]) {
|
||||||
DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
|
DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
|
||||||
|
DEFINE_PROP_UINT32("x-txtimer", VirtIOS390Device,
|
||||||
|
net.txtimer, TX_TIMER_INTERVAL),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -43,6 +43,7 @@ typedef struct VirtIOS390Device {
|
|||||||
uint32_t host_features;
|
uint32_t host_features;
|
||||||
/* Max. number of ports we can have for a the virtio-serial device */
|
/* Max. number of ports we can have for a the virtio-serial device */
|
||||||
uint32_t max_virtserial_ports;
|
uint32_t max_virtserial_ports;
|
||||||
|
virtio_net_conf net;
|
||||||
} VirtIOS390Device;
|
} VirtIOS390Device;
|
||||||
|
|
||||||
typedef struct VirtIOS390Bus {
|
typedef struct VirtIOS390Bus {
|
||||||
|
@ -68,6 +68,7 @@ typedef struct {
|
|||||||
uint32_t id;
|
uint32_t id;
|
||||||
NICConf nic;
|
NICConf nic;
|
||||||
uint32_t host_features;
|
uint32_t host_features;
|
||||||
|
virtio_net_conf net;
|
||||||
} SyborgVirtIOProxy;
|
} SyborgVirtIOProxy;
|
||||||
|
|
||||||
static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
|
static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
|
||||||
@ -284,7 +285,7 @@ static int syborg_virtio_net_init(SysBusDevice *dev)
|
|||||||
VirtIODevice *vdev;
|
VirtIODevice *vdev;
|
||||||
SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
|
SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
|
||||||
|
|
||||||
vdev = virtio_net_init(&dev->qdev, &proxy->nic);
|
vdev = virtio_net_init(&dev->qdev, &proxy->nic, &proxy->net);
|
||||||
return syborg_virtio_init(proxy, vdev);
|
return syborg_virtio_init(proxy, vdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,6 +296,8 @@ static SysBusDeviceInfo syborg_virtio_net_info = {
|
|||||||
.qdev.props = (Property[]) {
|
.qdev.props = (Property[]) {
|
||||||
DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
|
DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
|
||||||
DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
|
DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
|
||||||
|
DEFINE_PROP_UINT32("x-txtimer", SyborgVirtIOProxy,
|
||||||
|
net.txtimer, TX_TIMER_INTERVAL),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -36,6 +36,7 @@ typedef struct VirtIONet
|
|||||||
VirtQueue *ctrl_vq;
|
VirtQueue *ctrl_vq;
|
||||||
NICState *nic;
|
NICState *nic;
|
||||||
QEMUTimer *tx_timer;
|
QEMUTimer *tx_timer;
|
||||||
|
uint32_t tx_timeout;
|
||||||
int tx_timer_active;
|
int tx_timer_active;
|
||||||
uint32_t has_vnet_hdr;
|
uint32_t has_vnet_hdr;
|
||||||
uint8_t has_ufo;
|
uint8_t has_ufo;
|
||||||
@ -702,7 +703,7 @@ static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
virtio_net_flush_tx(n, vq);
|
virtio_net_flush_tx(n, vq);
|
||||||
} else {
|
} else {
|
||||||
qemu_mod_timer(n->tx_timer,
|
qemu_mod_timer(n->tx_timer,
|
||||||
qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
|
qemu_get_clock(vm_clock) + n->tx_timeout);
|
||||||
n->tx_timer_active = 1;
|
n->tx_timer_active = 1;
|
||||||
virtio_queue_set_notification(vq, 0);
|
virtio_queue_set_notification(vq, 0);
|
||||||
}
|
}
|
||||||
@ -842,7 +843,7 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
|
|
||||||
if (n->tx_timer_active) {
|
if (n->tx_timer_active) {
|
||||||
qemu_mod_timer(n->tx_timer,
|
qemu_mod_timer(n->tx_timer,
|
||||||
qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
|
qemu_get_clock(vm_clock) + n->tx_timeout);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -903,7 +904,8 @@ static void virtio_net_vmstate_change(void *opaque, int running, int reason)
|
|||||||
virtio_net_set_status(&n->vdev, n->vdev.status & status);
|
virtio_net_set_status(&n->vdev, n->vdev.status & status);
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
|
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
|
||||||
|
virtio_net_conf *net)
|
||||||
{
|
{
|
||||||
VirtIONet *n;
|
VirtIONet *n;
|
||||||
|
|
||||||
@ -931,6 +933,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
|
|||||||
|
|
||||||
n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
|
n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
|
||||||
n->tx_timer_active = 0;
|
n->tx_timer_active = 0;
|
||||||
|
n->tx_timeout = net->txtimer;
|
||||||
n->mergeable_rx_bufs = 0;
|
n->mergeable_rx_bufs = 0;
|
||||||
n->promisc = 1; /* for compatibility */
|
n->promisc = 1; /* for compatibility */
|
||||||
|
|
||||||
|
@ -49,6 +49,11 @@
|
|||||||
|
|
||||||
#define TX_TIMER_INTERVAL 150000 /* 150 us */
|
#define TX_TIMER_INTERVAL 150000 /* 150 us */
|
||||||
|
|
||||||
|
typedef struct virtio_net_conf
|
||||||
|
{
|
||||||
|
uint32_t txtimer;
|
||||||
|
} virtio_net_conf;
|
||||||
|
|
||||||
/* Maximum packet size we can receive from tap device: header + 64k */
|
/* Maximum packet size we can receive from tap device: header + 64k */
|
||||||
#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
|
#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
|
||||||
|
|
||||||
|
@ -107,6 +107,7 @@ typedef struct {
|
|||||||
#endif
|
#endif
|
||||||
/* Max. number of ports we can have for a the virtio-serial device */
|
/* Max. number of ports we can have for a the virtio-serial device */
|
||||||
uint32_t max_virtserial_ports;
|
uint32_t max_virtserial_ports;
|
||||||
|
virtio_net_conf net;
|
||||||
} VirtIOPCIProxy;
|
} VirtIOPCIProxy;
|
||||||
|
|
||||||
/* virtio device */
|
/* virtio device */
|
||||||
@ -613,7 +614,7 @@ static int virtio_net_init_pci(PCIDevice *pci_dev)
|
|||||||
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
|
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
|
||||||
VirtIODevice *vdev;
|
VirtIODevice *vdev;
|
||||||
|
|
||||||
vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic);
|
vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net);
|
||||||
|
|
||||||
vdev->nvectors = proxy->nvectors;
|
vdev->nvectors = proxy->nvectors;
|
||||||
virtio_init_pci(proxy, vdev,
|
virtio_init_pci(proxy, vdev,
|
||||||
@ -690,6 +691,8 @@ static PCIDeviceInfo virtio_info[] = {
|
|||||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
|
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
|
||||||
DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
|
DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
|
||||||
DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
|
DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
|
||||||
|
DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy,
|
||||||
|
net.txtimer, TX_TIMER_INTERVAL),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
},
|
},
|
||||||
.qdev.reset = virtio_pci_reset,
|
.qdev.reset = virtio_pci_reset,
|
||||||
|
@ -185,7 +185,9 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
|
|||||||
|
|
||||||
/* Base devices. */
|
/* Base devices. */
|
||||||
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
|
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
|
||||||
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf);
|
struct virtio_net_conf;
|
||||||
|
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
|
||||||
|
struct virtio_net_conf *net);
|
||||||
VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports);
|
VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports);
|
||||||
VirtIODevice *virtio_balloon_init(DeviceState *dev);
|
VirtIODevice *virtio_balloon_init(DeviceState *dev);
|
||||||
#ifdef CONFIG_LINUX
|
#ifdef CONFIG_LINUX
|
||||||
|
Loading…
Reference in New Issue
Block a user