Add support for virtio-net.tx_queue_size

https://bugzilla.redhat.com/show_bug.cgi?id=1462653

Just like I've added support for setting rx_queue_size (in
c56cdf259 and friends), qemu just gained support for setting tx
ring size.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Michal Privoznik 2017-07-12 14:19:26 +02:00
parent 8b9d017de3
commit 2074ef6cd4
13 changed files with 67 additions and 14 deletions

View File

@ -5074,7 +5074,7 @@ qemu-kvm -net nic,model=? /dev/null
&lt;source network='default'/&gt;
&lt;target dev='vnet1'/&gt;
&lt;model type='virtio'/&gt;
<b>&lt;driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5' rx_queue_size='256'&gt;
<b>&lt;driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5' rx_queue_size='256' tx_queue_size='256'&gt;
&lt;host csum='off' gso='off' tso4='off' tso6='off' ecn='off' ufo='off' mrg_rxbuf='off'/&gt;
&lt;guest csum='off' tso4='off' tso6='off' ecn='off' ufo='off'/&gt;
&lt;/driver&gt;
@ -5204,6 +5204,19 @@ qemu-kvm -net nic,model=? /dev/null
<b>In general you should leave this option alone, unless you
are very certain you know what you are doing.</b>
</dd>
<dt><code>tx_queue_size</code></dt>
<dd>
The optional <code>tx_queue_size</code> 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.
<span class="since">Since 3.7.0 (QEMU and KVM only)</span><br/><br/>
<b>In general you should leave this option alone, unless you
are very certain you know what you are doing.</b>
</dd>
<dt>virtio options</dt>
<dd>
For virtio interfaces,

View File

@ -2711,6 +2711,11 @@
<ref name='positiveInteger'/>
</attribute>
</optional>
<optional>
<attribute name='tx_queue_size'>
<ref name='positiveInteger'/>
</attribute>
</optional>
<optional>
<attribute name="txmode">
<choice>

View File

@ -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);

View File

@ -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;

View File

@ -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 },
};

View File

@ -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;

View File

@ -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)) {

View File

@ -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 &&

View File

@ -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

View File

@ -22,7 +22,7 @@
<interface type='user'>
<mac address='00:11:22:33:44:55'/>
<model type='virtio'/>
<driver rx_queue_size='512'/>
<driver rx_queue_size='512' tx_queue_size='1024'/>
</interface>
<memballoon model='virtio'/>
</devices>

View File

@ -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);

View File

@ -29,7 +29,7 @@
<interface type='user'>
<mac address='00:11:22:33:44:55'/>
<model type='virtio'/>
<driver rx_queue_size='512'/>
<driver rx_queue_size='512' tx_queue_size='1024'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<input type='mouse' bus='ps2'/>

View File

@ -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);