diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 9f7a1133d1..84b1cab84f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1378,6 +1378,56 @@ qemu-kvm -net nic,model=? /dev/null ne2k_isa i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio
++ ... + <devices> + <interface type='network'> + <source network='default'/> + <target dev='vnet1'/> + <model type='virtio'/> + <driver txmode='iothread'/> + </interface> + </devices> + ...+ +
+ Some NICs may have tunable driver-specific options. These are
+ set as attributes of the driver
sub-element of the
+ interface definition. Currently the following attributes are
+ available for the "virtio"
NIC driver:
+
txmode
txmode
attribute specifies how to handle
+ transmission of packets when the transmit buffer is full. The
+ value can be either 'iothread' or 'timer'.
+ Since 0.8.8 (QEMU and KVM only)diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 7fe66e3c26..8b215f35df 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1042,6 +1042,14 @@ ++ + ++ +iothread +timer +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index bc4fe29d31..01a5b2ce2c 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -198,6 +198,11 @@ VIR_ENUM_IMPL(virDomainNetBackend, VIR_DOMAIN_NET_BACKEND_TYPE_LAST, "qemu", "vhost") +VIR_ENUM_IMPL(virDomainNetVirtioTxMode, VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST, + "default", + "iothread", + "timer") + VIR_ENUM_IMPL(virDomainChrChannelTarget, VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST, "guestfwd", @@ -2477,6 +2482,7 @@ virDomainNetDefParseXML(virCapsPtr caps, char *port = NULL; char *model = NULL; char *backend = NULL; + char *txmode = NULL; char *filter = NULL; char *internal = NULL; char *devaddr = NULL; @@ -2565,6 +2571,7 @@ virDomainNetDefParseXML(virCapsPtr caps, model = virXMLPropString(cur, "type"); } else if (xmlStrEqual (cur->name, BAD_CAST "driver")) { backend = virXMLPropString(cur, "name"); + txmode = virXMLPropString(cur, "txmode"); } else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) { filter = virXMLPropString(cur, "filter"); VIR_FREE(filterparams); @@ -2769,6 +2776,18 @@ virDomainNetDefParseXML(virCapsPtr caps, } def->driver.virtio.name = name; } + if (txmode != NULL) { + int m; + if (((m = virDomainNetVirtioTxModeTypeFromString(txmode)) < 0) || + (m == VIR_DOMAIN_NET_VIRTIO_TX_MODE_DEFAULT)) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown interface " + "has been specified"), + txmode); + goto error; + } + def->driver.virtio.txmode = m; + } } if (filter != NULL) { @@ -2808,6 +2827,7 @@ cleanup: VIR_FREE(bridge); VIR_FREE(model); VIR_FREE(backend); + VIR_FREE(txmode); VIR_FREE(filter); VIR_FREE(type); VIR_FREE(internal); @@ -6813,12 +6833,16 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " \n", def->model); if (STREQ(def->model, "virtio") && - def->driver.virtio.name) { + (def->driver.virtio.name || def->driver.virtio.txmode)) { virBufferAddLit(buf, " driver.virtio.name) { virBufferVSprintf(buf, " name='%s'", virDomainNetBackendTypeToString(def->driver.virtio.name)); } + if (def->driver.virtio.txmode) { + virBufferVSprintf(buf, " txmode='%s'", + virDomainNetVirtioTxModeTypeToString(def->driver.virtio.txmode)); + } virBufferAddLit(buf, "/>\n"); } } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e05064fb49..30aecccdb6 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -321,6 +321,15 @@ enum virDomainNetBackendType { VIR_DOMAIN_NET_BACKEND_TYPE_LAST, }; +/* the TX algorithm used for virtio interfaces */ +enum virDomainNetVirtioTxModeType { + VIR_DOMAIN_NET_VIRTIO_TX_MODE_DEFAULT, /* default for this version of qemu */ + VIR_DOMAIN_NET_VIRTIO_TX_MODE_IOTHREAD, + VIR_DOMAIN_NET_VIRTIO_TX_MODE_TIMER, + + VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST, +}; + /* the mode type for macvtap devices */ enum virDomainNetdevMacvtapType { VIR_DOMAIN_NETDEV_MACVTAP_MODE_VEPA, @@ -341,6 +350,7 @@ struct _virDomainNetDef { union { struct { enum virDomainNetBackendType name; /* which driver backend to use */ + enum virDomainNetVirtioTxModeType txmode; } virtio; } driver; union { @@ -1371,6 +1381,7 @@ VIR_ENUM_DECL(virDomainFS) VIR_ENUM_DECL(virDomainFSAccessMode) VIR_ENUM_DECL(virDomainNet) VIR_ENUM_DECL(virDomainNetBackend) +VIR_ENUM_DECL(virDomainNetVirtioTxMode) VIR_ENUM_DECL(virDomainChrDevice) VIR_ENUM_DECL(virDomainChrChannelTarget) VIR_ENUM_DECL(virDomainChrConsoleTarget) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index cc5552cc38..5f08a2012f 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -1074,6 +1074,7 @@ qemuCapsExtractDeviceStr(const char *qemu, "-device", "?", "-device", "pci-assign,?", "-device", "virtio-blk-pci,?", + "-device", "virtio-net-pci,?", NULL); virCommandAddEnvPassCommon(cmd); /* qemu -help goes to stdout, but qemu -device ? goes to stderr. */ @@ -1115,6 +1116,8 @@ qemuCapsParseDeviceStr(const char *str, unsigned long long *flags) if (strstr(str, "pci-assign.bootindex")) *flags |= QEMUD_CMD_FLAG_PCI_BOOTINDEX; } + if (strstr(str, "virtio-net-pci.tx=")) + *flags |= QEMUD_CMD_FLAG_VIRTIO_TX_ALG; return 0; } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index a130a4f993..63cbbb3975 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -92,6 +92,7 @@ enum qemuCapsFlags { QEMUD_CMD_FLAG_CCID_PASSTHRU = (1LL << 55), /* -device ccid-card-passthru */ QEMUD_CMD_FLAG_CHARDEV_SPICEVMC = (1LL << 56), /* newer -chardev spicevmc */ QEMUD_CMD_FLAG_DEVICE_SPICEVMC = (1LL << 57), /* older -device spicevmc*/ + QEMUD_CMD_FLAG_VIRTIO_TX_ALG = (1LL << 58), /* -device virtio-net-pci,tx=string */ }; virCapsPtr qemuCapsInit(virCapsPtr old_caps); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7a52f4e9ad..b0eddd4e73 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1606,16 +1606,43 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, { virBuffer buf = VIR_BUFFER_INITIALIZER; const char *nic; + bool usingVirtio = false; if (!net->model) { nic = "rtl8139"; } else if (STREQ(net->model, "virtio")) { nic = "virtio-net-pci"; + usingVirtio = true; } else { nic = net->model; } virBufferAdd(&buf, nic, strlen(nic)); + if (usingVirtio && net->driver.virtio.txmode) { + if (qemuCmdFlags & QEMUD_CMD_FLAG_VIRTIO_TX_ALG) { + virBufferAddLit(&buf, ",tx="); + switch (net->driver.virtio.txmode) { + case VIR_DOMAIN_NET_VIRTIO_TX_MODE_IOTHREAD: + virBufferAddLit(&buf, "bh"); + break; + + case VIR_DOMAIN_NET_VIRTIO_TX_MODE_TIMER: + virBufferAddLit(&buf, "timer"); + break; + default: + /* this should never happen, if it does, we need + * to add another case to this switch. + */ + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("unrecognized virtio-net-pci 'tx' option")); + goto error; + } + } else { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtio-net-pci 'tx' option not supported in this QEMU binary")); + goto error; + } + } if (vlan == -1) virBufferVSprintf(&buf, ",netdev=host%s", net->info.alias); else diff --git a/tests/qemuhelpdata/qemu-kvm-0.12.1.2-rhel61-device b/tests/qemuhelpdata/qemu-kvm-0.12.1.2-rhel61-device index 8a0e528315..8ac9630b40 100644 --- a/tests/qemuhelpdata/qemu-kvm-0.12.1.2-rhel61-device +++ b/tests/qemuhelpdata/qemu-kvm-0.12.1.2-rhel61-device @@ -72,3 +72,28 @@ virtio-blk-pci.ioeventfd=on/off virtio-blk-pci.vectors=uint32 virtio-blk-pci.indirect_desc=on/off virtio-blk-pci.scsi=on/off +virtio-net-pci.vectors=uint32 +virtio-net-pci.indirect_desc=on/off +virtio-net-pci.csum=on/off +virtio-net-pci.guest_csum=on/off +virtio-net-pci.gso=on/off +virtio-net-pci.guest_tso4=on/off +virtio-net-pci.guest_tso6=on/off +virtio-net-pci.guest_ecn=on/off +virtio-net-pci.guest_ufo=on/off +virtio-net-pci.host_tso4=on/off +virtio-net-pci.host_tso6=on/off +virtio-net-pci.host_ecn=on/off +virtio-net-pci.host_ufo=on/off +virtio-net-pci.mrg_rxbuf=on/off +virtio-net-pci.status=on/off +virtio-net-pci.ctrl_vq=on/off +virtio-net-pci.ctrl_rx=on/off +virtio-net-pci.ctrl_vlan=on/off +virtio-net-pci.ctrl_rx_extra=on/off +virtio-net-pci.mac=macaddr +virtio-net-pci.vlan=vlan +virtio-net-pci.netdev=netdev +virtio-net-pci.x-txtimer=uint32 +virtio-net-pci.x-txburst=int32 +virtio-net-pci.tx=string diff --git a/tests/qemuhelpdata/qemu-kvm-0.13.0-device b/tests/qemuhelpdata/qemu-kvm-0.13.0-device index b121257874..4888d187f7 100644 --- a/tests/qemuhelpdata/qemu-kvm-0.13.0-device +++ b/tests/qemuhelpdata/qemu-kvm-0.13.0-device @@ -68,3 +68,25 @@ name "pci-assign", bus PCI, desc "pass through host pci devices to the guest" pci-assign.host=pci-hostaddr pci-assign.iommu=uint32 pci-assign.configfd=string +virtio-net-pci.vectors=uint32 +virtio-net-pci.indirect_desc=on/off +virtio-net-pci.csum=on/off +virtio-net-pci.guest_csum=on/off +virtio-net-pci.gso=on/off +virtio-net-pci.guest_tso4=on/off +virtio-net-pci.guest_tso6=on/off +virtio-net-pci.guest_ecn=on/off +virtio-net-pci.guest_ufo=on/off +virtio-net-pci.host_tso4=on/off +virtio-net-pci.host_tso6=on/off +virtio-net-pci.host_ecn=on/off +virtio-net-pci.host_ufo=on/off +virtio-net-pci.mrg_rxbuf=on/off +virtio-net-pci.status=on/off +virtio-net-pci.ctrl_vq=on/off +virtio-net-pci.ctrl_rx=on/off +virtio-net-pci.ctrl_vlan=on/off +virtio-net-pci.ctrl_rx_extra=on/off +virtio-net-pci.mac=macaddr +virtio-net-pci.vlan=vlan +virtio-net-pci.netdev=netdev diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index 3a04b610f5..11890ab16d 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -480,7 +480,8 @@ mymain(int argc, char **argv) QEMUD_CMD_FLAG_HDA_DUPLEX | QEMUD_CMD_FLAG_DRIVE_AIO | QEMUD_CMD_FLAG_CCID_PASSTHRU | - QEMUD_CMD_FLAG_CHARDEV_SPICEVMC, + QEMUD_CMD_FLAG_CHARDEV_SPICEVMC | + QEMUD_CMD_FLAG_VIRTIO_TX_ALG, 12001, 1, 0); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args index 92bd889b12..843c3e9933 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args @@ -1,6 +1,6 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ -/dev/HostVG/QEMUGuest1 -device virtio-net-pci,vlan=0,id=net0,\ +/dev/HostVG/QEMUGuest1 -device virtio-net-pci,tx=bh,vlan=0,id=net0,\ mac=00:11:22:33:44:55,bus=pci.0,addr=0x2 -net user,vlan=0,name=hostnet0 -usb \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.xml index 572f3cc757..4e7abcd554 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.xml @@ -17,10 +17,13 @@ + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 96260c0d81..4817d511ce 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -365,7 +365,7 @@ mymain(int argc, char **argv) DO_TEST("net-user", 0, false); DO_TEST("net-virtio", 0, false); DO_TEST("net-virtio-device", QEMUD_CMD_FLAG_DEVICE | - QEMUD_CMD_FLAG_NODEFCONFIG, false); + QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_VIRTIO_TX_ALG, false); DO_TEST("net-virtio-netdev", QEMUD_CMD_FLAG_DEVICE | QEMUD_CMD_FLAG_NETDEV | QEMUD_CMD_FLAG_NODEFCONFIG, false); DO_TEST("net-eth", 0, false); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 15d94b764f..67e721b8b2 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -159,6 +159,7 @@ mymain(int argc, char **argv) DO_TEST("misc-no-reboot"); DO_TEST("net-user"); DO_TEST("net-virtio"); + DO_TEST("net-virtio-device"); DO_TEST("net-eth"); DO_TEST("net-eth-ifname"); DO_TEST("sound");