1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2024-12-25 01:34:11 +03:00

conf: Add support for virtio-net.rx_queue_size

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

QEMU added another virtio-net tunable [1]. It basically allows
users to set the size of RX virtio ring. But because virtio-net
uses two separate ring buffers to pass data from/to guest they
named it explicitly rx_queue_size. We should expose it in our XML
too.

1: http://lists.nongnu.org/archive/html/qemu-devel/2016-08/msg02029.html

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Michal Privoznik 2016-08-18 18:19:13 +02:00
parent 13350a17e4
commit c56cdf2593
10 changed files with 145 additions and 1 deletions

View File

@ -4674,7 +4674,7 @@ qemu-kvm -net nic,model=? /dev/null
&lt;source network='default'/&gt; &lt;source network='default'/&gt;
&lt;target dev='vnet1'/&gt; &lt;target dev='vnet1'/&gt;
&lt;model type='virtio'/&gt; &lt;model type='virtio'/&gt;
<b>&lt;driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5'&gt; <b>&lt;driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5' rx_queue_size='256'&gt;
&lt;host csum='off' gso='off' tso4='off' tso6='off' ecn='off' ufo='off' mrg_rxbuf='off'/&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;guest csum='off' tso4='off' tso6='off' ecn='off' ufo='off'/&gt;
&lt;/driver&gt; &lt;/driver&gt;
@ -4790,6 +4790,20 @@ qemu-kvm -net nic,model=? /dev/null
<span class="since">virtio-net since 1.0.6 (QEMU and KVM only)</span> <span class="since">virtio-net since 1.0.6 (QEMU and KVM only)</span>
<span class="since">vhost-user since 1.2.17 (QEMU and KVM only)</span> <span class="since">vhost-user since 1.2.17 (QEMU and KVM only)</span>
</dd> </dd>
<dt><code>rx_queue_size</code></dt>
<dd>
The optional <code>rx_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, latest
QEMU (as of 2016-09-01) requires value to be a power of two
from [256, 1024] range.
<span class="since">Since 2.3.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>
</dl> </dl>
<p> <p>
Offloading options for the host and guest can be configured using Offloading options for the host and guest can be configured using

View File

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

View File

@ -8981,6 +8981,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
char *ioeventfd = NULL; char *ioeventfd = NULL;
char *event_idx = NULL; char *event_idx = NULL;
char *queues = NULL; char *queues = NULL;
char *rx_queue_size = NULL;
char *str = NULL; char *str = NULL;
char *filter = NULL; char *filter = NULL;
char *internal = NULL; char *internal = NULL;
@ -9153,6 +9154,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
ioeventfd = virXMLPropString(cur, "ioeventfd"); ioeventfd = virXMLPropString(cur, "ioeventfd");
event_idx = virXMLPropString(cur, "event_idx"); event_idx = virXMLPropString(cur, "event_idx");
queues = virXMLPropString(cur, "queues"); queues = virXMLPropString(cur, "queues");
rx_queue_size = virXMLPropString(cur, "rx_queue_size");
} else if (xmlStrEqual(cur->name, BAD_CAST "filterref")) { } else if (xmlStrEqual(cur->name, BAD_CAST "filterref")) {
if (filter) { if (filter) {
virReportError(VIR_ERR_XML_ERROR, "%s", virReportError(VIR_ERR_XML_ERROR, "%s",
@ -9536,6 +9538,16 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
if (q > 1) if (q > 1)
def->driver.virtio.queues = q; def->driver.virtio.queues = q;
} }
if (rx_queue_size) {
unsigned int q;
if (virStrToLong_uip(rx_queue_size, NULL, 10, &q) < 0) {
virReportError(VIR_ERR_XML_DETAIL,
_("'rx_queue_size' attribute must be positive number: %s"),
rx_queue_size);
goto error;
}
def->driver.virtio.rx_queue_size = q;
}
if ((str = virXPathString("string(./driver/host/@csum)", ctxt))) { if ((str = virXPathString("string(./driver/host/@csum)", ctxt))) {
if ((val = virTristateSwitchTypeFromString(str)) <= 0) { if ((val = virTristateSwitchTypeFromString(str)) <= 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@ -9716,6 +9728,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
VIR_FREE(ioeventfd); VIR_FREE(ioeventfd);
VIR_FREE(event_idx); VIR_FREE(event_idx);
VIR_FREE(queues); VIR_FREE(queues);
VIR_FREE(rx_queue_size);
VIR_FREE(str); VIR_FREE(str);
VIR_FREE(filter); VIR_FREE(filter);
VIR_FREE(type); VIR_FREE(type);
@ -20919,6 +20932,9 @@ virDomainVirtioNetDriverFormat(char **outstr,
} }
if (def->driver.virtio.queues) if (def->driver.virtio.queues)
virBufferAsprintf(&buf, "queues='%u' ", def->driver.virtio.queues); virBufferAsprintf(&buf, "queues='%u' ", def->driver.virtio.queues);
if (def->driver.virtio.rx_queue_size)
virBufferAsprintf(&buf, "rx_queue_size='%u' ",
def->driver.virtio.rx_queue_size);
virBufferTrim(&buf, " ", -1); virBufferTrim(&buf, " ", -1);

View File

@ -906,6 +906,7 @@ struct _virDomainNetDef {
virTristateSwitch ioeventfd; virTristateSwitch ioeventfd;
virTristateSwitch event_idx; virTristateSwitch event_idx;
unsigned int queues; /* Multiqueue virtio-net */ unsigned int queues; /* Multiqueue virtio-net */
unsigned int rx_queue_size;
struct { struct {
virTristateSwitch csum; virTristateSwitch csum;
virTristateSwitch gso; virTristateSwitch gso;

View File

@ -2475,6 +2475,13 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
"not supported by QEMU")); "not supported by QEMU"));
goto cleanup; 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;
}
} }
ret = 0; ret = 0;

View File

@ -0,0 +1,29 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219100</memory>
<currentMemory unit='KiB'>219100</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<disk type='block' device='disk'>
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='hda' bus='ide'/>
</disk>
<controller type='usb' index='0'/>
<interface type='user'>
<mac address='00:11:22:33:44:55'/>
<model type='virtio'/>
<driver rx_queue_size='511'/>
</interface>
<memballoon model='virtio'/>
</devices>
</domain>

View File

@ -0,0 +1,29 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219100</memory>
<currentMemory unit='KiB'>219100</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<disk type='block' device='disk'>
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='hda' bus='ide'/>
</disk>
<controller type='usb' index='0'/>
<interface type='user'>
<mac address='00:11:22:33:44:55'/>
<model type='virtio'/>
<driver rx_queue_size='512'/>
</interface>
<memballoon model='virtio'/>
</devices>
</domain>

View File

@ -1047,6 +1047,7 @@ mymain(void)
QEMU_CAPS_VIRTIO_S390); QEMU_CAPS_VIRTIO_S390);
DO_TEST("net-virtio-ccw", DO_TEST("net-virtio-ccw",
QEMU_CAPS_VIRTIO_CCW, QEMU_CAPS_VIRTIO_S390); QEMU_CAPS_VIRTIO_CCW, QEMU_CAPS_VIRTIO_S390);
DO_TEST_PARSE_ERROR("net-virtio-rxqueuesize-invalid-size", NONE);
DO_TEST("net-eth", NONE); DO_TEST("net-eth", NONE);
DO_TEST("net-eth-ifname", NONE); DO_TEST("net-eth-ifname", NONE);
DO_TEST("net-eth-names", NONE); DO_TEST("net-eth-names", NONE);

View File

@ -0,0 +1,41 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219100</memory>
<currentMemory unit='KiB'>219100</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<disk type='block' device='disk'>
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='hda' bus='ide'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<interface type='user'>
<mac address='00:11:22:33:44:55'/>
<model type='virtio'/>
<driver rx_queue_size='512'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</memballoon>
</devices>
</domain>

View File

@ -514,6 +514,7 @@ mymain(void)
DO_TEST("net-eth-ifname", NONE); DO_TEST("net-eth-ifname", NONE);
DO_TEST("net-eth-hostip", NONE); DO_TEST("net-eth-hostip", NONE);
DO_TEST("net-virtio-network-portgroup", NONE); DO_TEST("net-virtio-network-portgroup", NONE);
DO_TEST("net-virtio-rxqueuesize", NONE);
DO_TEST("net-hostdev", NONE); DO_TEST("net-hostdev", NONE);
DO_TEST("net-hostdev-vfio", NONE); DO_TEST("net-hostdev-vfio", NONE);
DO_TEST("net-midonet", NONE); DO_TEST("net-midonet", NONE);