diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 91195be0b398fee84511e5a0c57cd18a64944fd7..680830fbdddd8c29de804da9ede2b4e0c8760323 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -5074,7 +5074,7 @@ qemu-kvm -net nic,model=? /dev/null
<source network='default'/>
<target dev='vnet1'/>
<model type='virtio'/>
- <driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5' rx_queue_size='256'>
+ <driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5' rx_queue_size='256' tx_queue_size='256'>
<host csum='off' gso='off' tso4='off' tso6='off' ecn='off' ufo='off' mrg_rxbuf='off'/>
<guest csum='off' tso4='off' tso6='off' ecn='off' ufo='off'/>
</driver>
@@ -5204,6 +5204,19 @@ qemu-kvm -net nic,model=? /dev/null
In general you should leave this option alone, unless you
are very certain you know what you are doing.
+
tx_queue_size
+
+ The optional tx_queue_size attribute controls
+ the size of virtio ring for each queue as described above.
+ The default value is hypervisor dependent and may change
+ across its releases. Moreover, some hypervisors may pose
+ some restrictions on actual value. For instance, QEMU
+ v2.9 requires value to be a power of two from [256, 1024] range.
+ Since 3.7.0 (QEMU and KVM only)
+
+ In general you should leave this option alone, unless you
+ are very certain you know what you are doing.
+
virtio options
For virtio interfaces,
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index a49ce9303eb896f9e8fa8b5f025dacf871db6a1c..3f56d8f45b29ffb8b8ca2c413bd20180eb8fd3d1 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2711,6 +2711,11 @@
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 34c8f45ed11ac5e36d2820e2e27c9ea044400213..c3a167576966f93c08c11497929f92a2555ec3bd 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -9833,6 +9833,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
char *event_idx = NULL;
char *queues = NULL;
char *rx_queue_size = NULL;
+ char *tx_queue_size = NULL;
char *str = NULL;
char *filter = NULL;
char *internal = NULL;
@@ -10006,6 +10007,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
event_idx = virXMLPropString(cur, "event_idx");
queues = virXMLPropString(cur, "queues");
rx_queue_size = virXMLPropString(cur, "rx_queue_size");
+ tx_queue_size = virXMLPropString(cur, "tx_queue_size");
} else if (xmlStrEqual(cur->name, BAD_CAST "filterref")) {
if (filter) {
virReportError(VIR_ERR_XML_ERROR, "%s",
@@ -10403,6 +10405,16 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
}
def->driver.virtio.rx_queue_size = q;
}
+ if (tx_queue_size) {
+ unsigned int q;
+ if (virStrToLong_uip(tx_queue_size, NULL, 10, &q) < 0) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("'tx_queue_size' attribute must be positive number: %s"),
+ tx_queue_size);
+ goto error;
+ }
+ def->driver.virtio.tx_queue_size = q;
+ }
if ((str = virXPathString("string(./driver/host/@csum)", ctxt))) {
if ((val = virTristateSwitchTypeFromString(str)) <= 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -10600,6 +10612,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
VIR_FREE(event_idx);
VIR_FREE(queues);
VIR_FREE(rx_queue_size);
+ VIR_FREE(tx_queue_size);
VIR_FREE(str);
VIR_FREE(filter);
VIR_FREE(type);
@@ -22497,6 +22510,9 @@ virDomainVirtioNetDriverFormat(char **outstr,
if (def->driver.virtio.rx_queue_size)
virBufferAsprintf(&buf, " rx_queue_size='%u'",
def->driver.virtio.rx_queue_size);
+ if (def->driver.virtio.tx_queue_size)
+ virBufferAsprintf(&buf, " tx_queue_size='%u'",
+ def->driver.virtio.tx_queue_size);
virDomainVirtioOptionsFormat(&buf, def->virtio);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 239b21813013b9bc6f930452df05d6310c5fd85c..f857f509e474a7f21b9cf21c51d2b95299788b7c 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -969,6 +969,7 @@ struct _virDomainNetDef {
virTristateSwitch event_idx;
unsigned int queues; /* Multiqueue virtio-net */
unsigned int rx_queue_size;
+ unsigned int tx_queue_size;
struct {
virTristateSwitch csum;
virTristateSwitch gso;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index afe70d00d97fd2f4e9518542e28b05a8545faa50..e61d2f7b0d296ac1366653ce1b49a8cb28ee5bcf 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -435,7 +435,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
/* 265 */
"spapr-pci-host-bridge.numa_node",
- "vnc-multi-servers"
+ "vnc-multi-servers",
+ "virtio-net.tx_queue_size",
);
@@ -1705,6 +1706,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioNet[] = {
{ "tx", QEMU_CAPS_VIRTIO_TX_ALG },
{ "event_idx", QEMU_CAPS_VIRTIO_NET_EVENT_IDX },
{ "rx_queue_size", QEMU_CAPS_VIRTIO_NET_RX_QUEUE_SIZE },
+ { "tx_queue_size", QEMU_CAPS_VIRTIO_NET_TX_QUEUE_SIZE },
{ "host_mtu", QEMU_CAPS_VIRTIO_NET_HOST_MTU },
};
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 8b856e1b2f088aec2511939b9c51d18afedc710a..8804cc7819f5de346b0e358c06e2a139c1a76b22 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -422,6 +422,7 @@ typedef enum {
/* 265 */
QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE, /* spapr-pci-host-bridge.numa_node= */
QEMU_CAPS_VNC_MULTI_SERVERS, /* -vnc vnc=unix:/path */
+ QEMU_CAPS_VIRTIO_NET_TX_QUEUE_SIZE, /* virtio-net-*.tx_queue_size */
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d1f5c3642309ecfdccf058a8460733a669181c59..da6ddff6cbb22c1573852eb07706e96961ea834d 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3725,6 +3725,14 @@ qemuBuildNicDevStr(virDomainDefPtr def,
}
virBufferAsprintf(&buf, ",rx_queue_size=%u", net->driver.virtio.rx_queue_size);
}
+ if (usingVirtio && net->driver.virtio.tx_queue_size) {
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_TX_QUEUE_SIZE)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("virtio tx_queue_size option is not supported with this QEMU binary"));
+ goto error;
+ }
+ virBufferAsprintf(&buf, ",tx_queue_size=%u", net->driver.virtio.tx_queue_size);
+ }
if (usingVirtio && net->mtu) {
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_HOST_MTU)) {
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 6fe9aa85585de1a58418d7b8ecb41aa4fbdc6548..fe27e1122dce71e78620228247f9aa0118f23f51 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -3226,11 +3226,17 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
goto cleanup;
}
- if (STREQ_NULLABLE(net->model, "virtio") &&
- net->driver.virtio.rx_queue_size & (net->driver.virtio.rx_queue_size - 1)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("rx_queue_size has to be a power of two"));
- goto cleanup;
+ if (STREQ_NULLABLE(net->model, "virtio")) {
+ if (net->driver.virtio.rx_queue_size & (net->driver.virtio.rx_queue_size - 1)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("rx_queue_size has to be a power of two"));
+ goto cleanup;
+ }
+ if (net->driver.virtio.tx_queue_size & (net->driver.virtio.tx_queue_size - 1)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("tx_queue_size has to be a power of two"));
+ goto cleanup;
+ }
}
if (net->mtu &&
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxqueuesize.args b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxtxqueuesize.args
similarity index 85%
rename from tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxqueuesize.args
rename to tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxtxqueuesize.args
index 07c358a0222e43f2ae14d8f90d2a05388641a1e9..c78da3d1798422a5f458d262eec6d6471750b998 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxqueuesize.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxtxqueuesize.args
@@ -21,7 +21,7 @@ server,nowait \
-usb \
-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
--device virtio-net-pci,rx_queue_size=512,vlan=0,id=net0,mac=00:11:22:33:44:55,\
-bus=pci.0,addr=0x3 \
+-device virtio-net-pci,rx_queue_size=512,tx_queue_size=1024,vlan=0,id=net0,\
+mac=00:11:22:33:44:55,bus=pci.0,addr=0x3 \
-net user,vlan=0,name=hostnet0 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxqueuesize.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxtxqueuesize.xml
similarity index 93%
rename from tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxqueuesize.xml
rename to tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxtxqueuesize.xml
index d64e31df2812feb586d77b88885464199395fe13..b51931d525f0ffd33e19b9d66fc31eb1c3b33a0a 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxqueuesize.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-rxtxqueuesize.xml
@@ -22,7 +22,7 @@
-
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index c2c1767c7e2a301a42d25773bc1d9675a6bae26e..aa83013a200c66c65b149c54a6b55d9e823dafdc 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1167,8 +1167,9 @@ mymain(void)
QEMU_CAPS_VIRTIO_S390);
DO_TEST("net-virtio-ccw",
QEMU_CAPS_VIRTIO_CCW, QEMU_CAPS_VIRTIO_S390);
- DO_TEST("net-virtio-rxqueuesize",
- QEMU_CAPS_VIRTIO_NET_RX_QUEUE_SIZE);
+ DO_TEST("net-virtio-rxtxqueuesize",
+ QEMU_CAPS_VIRTIO_NET_RX_QUEUE_SIZE,
+ QEMU_CAPS_VIRTIO_NET_TX_QUEUE_SIZE);
DO_TEST_PARSE_ERROR("net-virtio-rxqueuesize-invalid-size", NONE);
DO_TEST("net-eth", NONE);
DO_TEST("net-eth-ifname", NONE);
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-virtio-rxqueuesize.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-virtio-rxtxqueuesize.xml
similarity index 96%
rename from tests/qemuxml2xmloutdata/qemuxml2xmlout-net-virtio-rxqueuesize.xml
rename to tests/qemuxml2xmloutdata/qemuxml2xmlout-net-virtio-rxtxqueuesize.xml
index 78433026cc099277b0a11c6d1457e4676260f26e..5c33a58ad54cda0eb04748d93659aa41919c347b 100644
--- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-virtio-rxqueuesize.xml
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-virtio-rxtxqueuesize.xml
@@ -29,7 +29,7 @@
-
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 5b47b0711445a4ee89d11d4e0065170bec3dbb5c..bf4d507f66731b2bd8a7a2abd5e6f7a3ab4a2629 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -537,7 +537,7 @@ mymain(void)
DO_TEST("net-eth-ifname", NONE);
DO_TEST("net-eth-hostip", NONE);
DO_TEST("net-virtio-network-portgroup", NONE);
- DO_TEST("net-virtio-rxqueuesize", NONE);
+ DO_TEST("net-virtio-rxtxqueuesize", NONE);
DO_TEST("net-hostdev", NONE);
DO_TEST("net-hostdev-vfio", NONE);
DO_TEST("net-midonet", NONE);