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;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' 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;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;
@ -5204,6 +5204,19 @@ qemu-kvm -net nic,model=? /dev/null
<b>In general you should leave this option alone, unless you <b>In general you should leave this option alone, unless you
are very certain you know what you are doing.</b> are very certain you know what you are doing.</b>
</dd> </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> <dt>virtio options</dt>
<dd> <dd>
For virtio interfaces, For virtio interfaces,

View File

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

View File

@ -9833,6 +9833,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
char *event_idx = NULL; char *event_idx = NULL;
char *queues = NULL; char *queues = NULL;
char *rx_queue_size = NULL; char *rx_queue_size = NULL;
char *tx_queue_size = NULL;
char *str = NULL; char *str = NULL;
char *filter = NULL; char *filter = NULL;
char *internal = NULL; char *internal = NULL;
@ -10006,6 +10007,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
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"); rx_queue_size = virXMLPropString(cur, "rx_queue_size");
tx_queue_size = virXMLPropString(cur, "tx_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",
@ -10403,6 +10405,16 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
} }
def->driver.virtio.rx_queue_size = q; 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 ((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,
@ -10600,6 +10612,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
VIR_FREE(event_idx); VIR_FREE(event_idx);
VIR_FREE(queues); VIR_FREE(queues);
VIR_FREE(rx_queue_size); VIR_FREE(rx_queue_size);
VIR_FREE(tx_queue_size);
VIR_FREE(str); VIR_FREE(str);
VIR_FREE(filter); VIR_FREE(filter);
VIR_FREE(type); VIR_FREE(type);
@ -22497,6 +22510,9 @@ virDomainVirtioNetDriverFormat(char **outstr,
if (def->driver.virtio.rx_queue_size) if (def->driver.virtio.rx_queue_size)
virBufferAsprintf(&buf, " rx_queue_size='%u'", virBufferAsprintf(&buf, " rx_queue_size='%u'",
def->driver.virtio.rx_queue_size); 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); virDomainVirtioOptionsFormat(&buf, def->virtio);

View File

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

View File

@ -435,7 +435,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
/* 265 */ /* 265 */
"spapr-pci-host-bridge.numa_node", "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 }, { "tx", QEMU_CAPS_VIRTIO_TX_ALG },
{ "event_idx", QEMU_CAPS_VIRTIO_NET_EVENT_IDX }, { "event_idx", QEMU_CAPS_VIRTIO_NET_EVENT_IDX },
{ "rx_queue_size", QEMU_CAPS_VIRTIO_NET_RX_QUEUE_SIZE }, { "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 }, { "host_mtu", QEMU_CAPS_VIRTIO_NET_HOST_MTU },
}; };

View File

@ -422,6 +422,7 @@ typedef enum {
/* 265 */ /* 265 */
QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE, /* spapr-pci-host-bridge.numa_node= */ 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_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 */ QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags; } virQEMUCapsFlags;

View File

@ -3725,6 +3725,14 @@ qemuBuildNicDevStr(virDomainDefPtr def,
} }
virBufferAsprintf(&buf, ",rx_queue_size=%u", net->driver.virtio.rx_queue_size); 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 (usingVirtio && net->mtu) {
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_HOST_MTU)) { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_HOST_MTU)) {

View File

@ -3226,12 +3226,18 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
goto cleanup; goto cleanup;
} }
if (STREQ_NULLABLE(net->model, "virtio") && if (STREQ_NULLABLE(net->model, "virtio")) {
net->driver.virtio.rx_queue_size & (net->driver.virtio.rx_queue_size - 1)) { if (net->driver.virtio.rx_queue_size & (net->driver.virtio.rx_queue_size - 1)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("rx_queue_size has to be a power of two")); _("rx_queue_size has to be a power of two"));
goto cleanup; 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 && if (net->mtu &&
!qemuDomainNetSupportsMTU(net->type)) { !qemuDomainNetSupportsMTU(net->type)) {

View File

@ -21,7 +21,7 @@ server,nowait \
-usb \ -usb \
-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \ -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 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,\ -device virtio-net-pci,rx_queue_size=512,tx_queue_size=1024,vlan=0,id=net0,\
bus=pci.0,addr=0x3 \ mac=00:11:22:33:44:55,bus=pci.0,addr=0x3 \
-net user,vlan=0,name=hostnet0 \ -net user,vlan=0,name=hostnet0 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4

View File

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

View File

@ -1167,8 +1167,9 @@ 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("net-virtio-rxqueuesize", DO_TEST("net-virtio-rxtxqueuesize",
QEMU_CAPS_VIRTIO_NET_RX_QUEUE_SIZE); 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_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);

View File

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

View File

@ -537,7 +537,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-virtio-rxtxqueuesize", 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);