[libvirt] [PATCH 0/3] exposing busy polling support for vhost-net

From: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> In version 2.7.0, QEMU introduced support of busy polling for vhost-net [0]. To avoid paraphrasing original authors of that feature and the purpose it I prefer to share a pointer [1]. This patch serie exposes throught the NIC driver-specific element a new option 'poll_us'. That option is only available with the backend driver 'vhost'. The option 'poll_us' takes a positive number. 0 means that the option is not going to be exposed. [0] 69e87b32680a41d9761191443587c595b6f5fc3f [1] https://lists.gnu.org/archive/html/qemu-devel/2016-11/msg04595.html Sahid Orentino Ferdjaoui (3): qemu: add capability for vhost-net busy polling conf: introduce 'poll_us' attribute for domain interface qemu: add busy polling support docs/formatdomain.html.in | 12 ++++++++++- docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 16 +++++++++++++++ src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 6 ++++++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 22 +++++++++++++++++++++ src/qemu/qemu_hotplug.c | 12 +++++++++++ tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 + .../qemuxml2argv-net-virtio-netdev-pollus-fail.xml | 23 ++++++++++++++++++++++ ...xml2argv-net-virtio-netdev-pollus-qemu-fail.xml | 23 ++++++++++++++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus.args | 23 ++++++++++++++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus.xml | 23 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 9 +++++++++ 18 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml -- 2.9.4

From: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> QEMU 2.7.0 adds support of busy polling on vhost-net. 69e87b32680a41d9761191443587c595b6f5fc3f Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> --- src/qemu/qemu_capabilities.c | 6 ++++++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 + 7 files changed, 12 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index c0c39bd..faf6d82 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -376,6 +376,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "intel-iommu.device-iotlb", /* 260 */ "virtio.iommu_platform", "virtio.ats", + "vhost-net.poll_us", ); @@ -4773,6 +4774,11 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps, if (qemuCaps->version >= 2006000) virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_KERNEL_IRQCHIP_SPLIT); + /* Support for busy polling on vhost-net devices ("-netdev + * tap,...,poll-us=n") */ + if (qemuCaps->version >= 2007000) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_VHOST_NET_POLL_US); + if (virQEMUCapsProbeQMPCommands(qemuCaps, mon) < 0) goto cleanup; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index e57cae9..33f8ed0 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -415,6 +415,7 @@ typedef enum { QEMU_CAPS_INTEL_IOMMU_DEVICE_IOTLB, /* intel-iommu.device-iotlb */ QEMU_CAPS_VIRTIO_PCI_IOMMU_PLATFORM, /* virtio-*-pci.iommu_platform */ QEMU_CAPS_VIRTIO_PCI_ATS, /* virtio-*-pci.ats */ + QEMU_CAPS_VHOST_NET_POLL_US, /* vhost-net with -netdev poll-us= */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml index 70cce64..f833d4a 100644 --- a/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml @@ -132,6 +132,7 @@ <flag name='query-named-block-nodes'/> <flag name='kernel-irqchip'/> <flag name='kernel-irqchip.split'/> + <flag name='vhost-net.poll_us'/> <version>2007000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml index 49c0462..2ab44cf 100644 --- a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml @@ -205,6 +205,7 @@ <flag name='kernel-irqchip'/> <flag name='kernel-irqchip.split'/> <flag name='intel-iommu.intremap'/> + <flag name='vhost-net.poll_us'/> <version>2007000</version> <kvmVersion>0</kvmVersion> <package> (v2.7.0)</package> diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml index 51be9bc..98f763d 100644 --- a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml @@ -134,6 +134,7 @@ <flag name='query-named-block-nodes'/> <flag name='kernel-irqchip'/> <flag name='kernel-irqchip.split'/> + <flag name='vhost-net.poll_us'/> <version>2007093</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml index 01edbc8..bafe08f 100644 --- a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml @@ -207,6 +207,7 @@ <flag name='kernel-irqchip.split'/> <flag name='intel-iommu.intremap'/> <flag name='intel-iommu.eim'/> + <flag name='vhost-net.poll_us'/> <version>2008000</version> <kvmVersion>0</kvmVersion> <package> (v2.8.0)</package> diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml index 58dd9f6..dc93b5a 100644 --- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml @@ -218,6 +218,7 @@ <flag name='intel-iommu.device-iotlb'/> <flag name='virtio.iommu_platform'/> <flag name='virtio.ats'/> + <flag name='vhost-net.poll_us'/> <version>2009000</version> <kvmVersion>0</kvmVersion> <package> (v2.9.0)</package> -- 2.9.4

(Eduardo - I Cc'ed you because there's a question you may be able to answer about halfway down the message...) On 06/15/2017 10:17 AM, sferdjao@redhat.com wrote:
From: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com>
QEMU 2.7.0 adds support of busy polling on vhost-net.
69e87b32680a41d9761191443587c595b6f5fc3f
I guess this is the upstream commit ID of the feature in qemu? I haven't noticed people referencing qemu commit ID's in libvirt in the past, but there's nothing wrong with it either. If you're going to put it in though, you should make it clear what the number is, maybe something like: Detect support for vhost-net busy polling (the "poll-us" commandline option). This was added to upstream qemu in version 2.7.0, commit 69e87b32....
Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> --- src/qemu/qemu_capabilities.c | 6 ++++++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 + 7 files changed, 12 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index c0c39bd..faf6d82 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -376,6 +376,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "intel-iommu.device-iotlb", /* 260 */ "virtio.iommu_platform", "virtio.ats", + "vhost-net.poll_us",
It's not 100% done in existing code, but generally people have tried to reproduce qemu option names exactly in the capability name (I think less so in the past, more so now). So this should be vhost-net.poll-us (dash instead of underscore), or even more exactly "netdev.poll-us" or "netdev.tap.poll-us".
);
@@ -4773,6 +4774,11 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps, if (qemuCaps->version >= 2006000) virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_KERNEL_IRQCHIP_SPLIT);
+ /* Support for busy polling on vhost-net devices ("-netdev + * tap,...,poll-us=n") */ + if (qemuCaps->version >= 2007000) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_VHOST_NET_POLL_US); +
Enabling a capability based purely on the qemu binary version is something that's only done as a last resort if it can't be determined by QMP probes. This is because the version number is an inaccurate indicator - it often happens that a new capability is added to upstream in qemu version "Y", but then that feature is backported to qemu version "X" in some downstream distro package; if we based the capability on version number, then libvirt wouldn't take advantage of the feature even though qemu had it. What *should* get us the info we need is to add a table entry to virQEMUCapsCommandLine to check whether or not the poll-us option exists in the current qemu binary. Something like this: static struct virQEMUCapsCommandLineProps virQEMUCapsCommandLine[] = { ... { "netdev", "poll-us", QEMU_CAPS_NETDEV_POLL_US }, Unfortunately when I add that and regenerate the .replies file for qemu 2.9.0 (with the command "tests/qemucapsprobe /usr/bin/qemu-system-x86_64"), this is the info it finds for netdev: { "parameters": [ ], "option": "netdev" }, My understanding was that the possible parameters to the netdev commandline option should be listed, but instead the parameters list is empty :-/. Maybe Eduardo can help me understand why the parameters are empty, and (more importantly) what needs to be done to get the supported parameters for -netdev - basically we need to know what are the available parameters to "-netdev tap,...". I hope we don't end up needing to base the check purely on qemu version.
if (virQEMUCapsProbeQMPCommands(qemuCaps, mon) < 0) goto cleanup;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index e57cae9..33f8ed0 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -415,6 +415,7 @@ typedef enum { QEMU_CAPS_INTEL_IOMMU_DEVICE_IOTLB, /* intel-iommu.device-iotlb */ QEMU_CAPS_VIRTIO_PCI_IOMMU_PLATFORM, /* virtio-*-pci.iommu_platform */ QEMU_CAPS_VIRTIO_PCI_ATS, /* virtio-*-pci.ats */ + QEMU_CAPS_VHOST_NET_POLL_US, /* vhost-net with -netdev poll-us= */
As implied up above, I think the capability should be called QEMU_CAPS_NETDEV_POLL_US, since that's an exact description of that goes on the commandline (and even though it currently only has an effect when vhost-net is turned on, that could possibly change in the future).
QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml index 70cce64..f833d4a 100644 --- a/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml @@ -132,6 +132,7 @@ <flag name='query-named-block-nodes'/> <flag name='kernel-irqchip'/> <flag name='kernel-irqchip.split'/> + <flag name='vhost-net.poll_us'/> <version>2007000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml index 49c0462..2ab44cf 100644 --- a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml @@ -205,6 +205,7 @@ <flag name='kernel-irqchip'/> <flag name='kernel-irqchip.split'/> <flag name='intel-iommu.intremap'/> + <flag name='vhost-net.poll_us'/> <version>2007000</version> <kvmVersion>0</kvmVersion> <package> (v2.7.0)</package> diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml index 51be9bc..98f763d 100644 --- a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml @@ -134,6 +134,7 @@ <flag name='query-named-block-nodes'/> <flag name='kernel-irqchip'/> <flag name='kernel-irqchip.split'/> + <flag name='vhost-net.poll_us'/> <version>2007093</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml index 01edbc8..bafe08f 100644 --- a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml @@ -207,6 +207,7 @@ <flag name='kernel-irqchip.split'/> <flag name='intel-iommu.intremap'/> <flag name='intel-iommu.eim'/> + <flag name='vhost-net.poll_us'/> <version>2008000</version> <kvmVersion>0</kvmVersion> <package> (v2.8.0)</package> diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml index 58dd9f6..dc93b5a 100644 --- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml @@ -218,6 +218,7 @@ <flag name='intel-iommu.device-iotlb'/> <flag name='virtio.iommu_platform'/> <flag name='virtio.ats'/> + <flag name='vhost-net.poll_us'/> <version>2009000</version> <kvmVersion>0</kvmVersion> <package> (v2.9.0)</package>

(CCing qemu-devel and the QAPI maintainers. I have a question about introspection below.) On Sat, Jun 17, 2017 at 11:48:10AM -0400, Laine Stump wrote: [...]
+ /* Support for busy polling on vhost-net devices ("-netdev + * tap,...,poll-us=n") */ + if (qemuCaps->version >= 2007000) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_VHOST_NET_POLL_US); +
Enabling a capability based purely on the qemu binary version is something that's only done as a last resort if it can't be determined by QMP probes. This is because the version number is an inaccurate indicator - it often happens that a new capability is added to upstream in qemu version "Y", but then that feature is backported to qemu version "X" in some downstream distro package; if we based the capability on version number, then libvirt wouldn't take advantage of the feature even though qemu had it.
What *should* get us the info we need is to add a table entry to virQEMUCapsCommandLine to check whether or not the poll-us option exists in the current qemu binary. Something like this:
static struct virQEMUCapsCommandLineProps virQEMUCapsCommandLine[] = { ... { "netdev", "poll-us", QEMU_CAPS_NETDEV_POLL_US },
Unfortunately when I add that and regenerate the .replies file for qemu 2.9.0 (with the command "tests/qemucapsprobe /usr/bin/qemu-system-x86_64"), this is the info it finds for netdev:
{ "parameters": [ ], "option": "netdev" },
My understanding was that the possible parameters to the netdev commandline option should be listed, but instead the parameters list is empty :-/.
Maybe Eduardo can help me understand why the parameters are empty, and (more importantly) what needs to be done to get the supported parameters for -netdev - basically we need to know what are the available parameters to "-netdev tap,...". I hope we don't end up needing to base the check purely on qemu version.
query-command-line-options is incomplete and useless on many cases (including but not limited to -device, -object, and -netdev). It is not capable to model cases where the set of accepted options depends on a discriminator option (e.g. a "driver" or "type" option). Fortunately, netdev options are modelled in the QAPI schema as union Netdev. However, 'query-qmp-schema' doesn't seem to include union Netdev because it is not referenced by any QMP command or event. Markus, Eric, Michael: is there any way libvirt can query the definition of union Netdev from the schema with current QEMU? -- Eduardo

On 06/17/2017 09:15 PM, Eduardo Habkost wrote:
(CCing qemu-devel and the QAPI maintainers. I have a question about introspection below.)
Fortunately, netdev options are modelled in the QAPI schema as union Netdev. However, 'query-qmp-schema' doesn't seem to include union Netdev because it is not referenced by any QMP command or event.
I've posted patches in the past (qemu 2.6 timeframe, if I recall) that changed netdev_add into a fully-advertised interface, but we didn't take it then because we weren't sure how to handle the fact that netdev_add can currently accept both an integer (1) and a string ("1") as identical, and we didn't want to risk breaking clients that passed a string when the promoted command would only accept integers. I guess we should revive that.
Markus, Eric, Michael: is there any way libvirt can query the definition of union Netdev from the schema with current QEMU?
Really, we need to promote netdev_add to a full-fledged QMP command. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org

On Mon, Jun 26, 2017 at 07:23:50AM -0600, Eric Blake wrote:
On 06/17/2017 09:15 PM, Eduardo Habkost wrote:
(CCing qemu-devel and the QAPI maintainers. I have a question about introspection below.)
Fortunately, netdev options are modelled in the QAPI schema as union Netdev. However, 'query-qmp-schema' doesn't seem to include union Netdev because it is not referenced by any QMP command or event.
I've posted patches in the past (qemu 2.6 timeframe, if I recall) that changed netdev_add into a fully-advertised interface, but we didn't take it then because we weren't sure how to handle the fact that netdev_add can currently accept both an integer (1) and a string ("1") as identical, and we didn't want to risk breaking clients that passed a string when the promoted command would only accept integers. I guess we should revive that.
Markus, Eric, Michael: is there any way libvirt can query the definition of union Netdev from the schema with current QEMU?
Really, we need to promote netdev_add to a full-fledged QMP command.
This may be enough for -netdev, but do we want to make command-line option introspection always depend on having the same struct being used in a QMP command to work? What if the arguments for the command-line option don't match precisely the input of a QMP command? -- Eduardo

On 06/26/2017 09:24 PM, Eduardo Habkost wrote:
I've posted patches in the past (qemu 2.6 timeframe, if I recall) that changed netdev_add into a fully-advertised interface, but we didn't take it then because we weren't sure how to handle the fact that netdev_add can currently accept both an integer (1) and a string ("1") as identical, and we didn't want to risk breaking clients that passed a string when the promoted command would only accept integers. I guess we should revive that.
Markus, Eric, Michael: is there any way libvirt can query the definition of union Netdev from the schema with current QEMU?
Really, we need to promote netdev_add to a full-fledged QMP command.
Remember, netdev_add and object_add are the only two outlier QMP commands that have NOT been converted to use QAPI. We've already done most of the work at making QMP netdev_add and command line -netdev be compatible, it is just the last bit of switching on full QAPI support that has some interface ramifications that we were not comfortable making during a release freeze, and haven't had time to revisit since. object_add is much further away from being introspectible.
This may be enough for -netdev, but do we want to make command-line option introspection always depend on having the same struct being used in a QMP command to work? What if the arguments for the command-line option don't match precisely the input of a QMP command?
Then that's arguably a poor user interface, and only something we should do for back-compat reasons, and not for new design. We WANT to make the command-line introspectible, and the easiest way to do that is to make the command-line and QMP share common guts (see the recent -blockdev addition in qemu 2.9, along with Dan and Markus' work at tweaking visitors so that the command line directly feeds into the QObject representation used by QMP commands rather than the hackish QemuOpts that is already too bloated with workarounds). -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org

From: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> In this commit we introduce 'poll_us' attribute which will be passed then to the QEMU command line to enable support of busy polling. This commit also take into account that attribute to generate the XML. Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> --- src/conf/domain_conf.c | 16 ++++++++++++++++ src/conf/domain_conf.h | 1 + 2 files changed, 17 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 0507ec1..803f517 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9748,6 +9748,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *event_idx = NULL; char *queues = NULL; char *rx_queue_size = NULL; + char *pollus = NULL; char *str = NULL; char *filter = NULL; char *internal = NULL; @@ -9921,6 +9922,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, event_idx = virXMLPropString(cur, "event_idx"); queues = virXMLPropString(cur, "queues"); rx_queue_size = virXMLPropString(cur, "rx_queue_size"); + pollus = virXMLPropString(cur, "poll_us"); } else if (xmlStrEqual(cur->name, BAD_CAST "filterref")) { if (filter) { virReportError(VIR_ERR_XML_ERROR, "%s", @@ -10318,6 +10320,17 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, } def->driver.virtio.rx_queue_size = q; } + if (pollus) { + unsigned int us; + if (virStrToLong_uip(pollus, NULL, 10, &us) < 0) { + virReportError(VIR_ERR_XML_DETAIL, + _("'poll_us' attribute must be positive number: %s"), + pollus); + goto error; + } + if (us > 1) + def->driver.virtio.pollus = us; + } if ((str = virXPathString("string(./driver/host/@csum)", ctxt))) { if ((val = virTristateSwitchTypeFromString(str)) <= 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -10515,6 +10528,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(event_idx); VIR_FREE(queues); VIR_FREE(rx_queue_size); + VIR_FREE(pollus); VIR_FREE(str); VIR_FREE(filter); VIR_FREE(type); @@ -22308,6 +22322,8 @@ 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.pollus) + virBufferAsprintf(&buf, " poll_us='%u'", def->driver.virtio.pollus); virDomainVirtioOptionsFormat(&buf, def->virtio); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e67b6fd..d97d776 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -967,6 +967,7 @@ struct _virDomainNetDef { virTristateSwitch event_idx; unsigned int queues; /* Multiqueue virtio-net */ unsigned int rx_queue_size; + unsigned int pollus; /* busy polling for tap */ struct { virTristateSwitch csum; virTristateSwitch gso; -- 2.9.4

On 06/15/2017 10:17 AM, sferdjao@redhat.com wrote:
From: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com>
In this commit we introduce 'poll_us' attribute which will be passed then to the QEMU command line to enable support of busy polling. This commit also take into account that attribute to generate the XML.
Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> --- src/conf/domain_conf.c | 16 ++++++++++++++++ src/conf/domain_conf.h | 1 + 2 files changed, 17 insertions(+)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 0507ec1..803f517 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9748,6 +9748,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *event_idx = NULL; char *queues = NULL; char *rx_queue_size = NULL; + char *pollus = NULL;
since the option is "poll-us", but you can't have "-" in an identifier name, this should either be "poll_us", or "pollUS" (there is some amount of preference for camelCase in C and XML identifier names in libvirt, but it is by no means universal, so probably best just to go along with what's done for nearby identifiers in a similar class, e.g. event_idx). (Of course some purists would say that we shouldn't include the type of units in the name, but since this number is so specific to a particular driver, I think it's reasonable to treat it as an opaque setting, named "poll-us", with no units-type associated with it).
char *str = NULL; char *filter = NULL; char *internal = NULL; @@ -9921,6 +9922,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, event_idx = virXMLPropString(cur, "event_idx"); queues = virXMLPropString(cur, "queues"); rx_queue_size = virXMLPropString(cur, "rx_queue_size"); + pollus = virXMLPropString(cur, "poll_us"); } else if (xmlStrEqual(cur->name, BAD_CAST "filterref")) { if (filter) { virReportError(VIR_ERR_XML_ERROR, "%s", @@ -10318,6 +10320,17 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, } def->driver.virtio.rx_queue_size = q; } + if (pollus) { + unsigned int us; + if (virStrToLong_uip(pollus, NULL, 10, &us) < 0) { + virReportError(VIR_ERR_XML_DETAIL, + _("'poll_us' attribute must be positive number: %s"),
"...must be positive" or "...must be a positive integer"
+ pollus); + goto error; + } + if (us > 1) + def->driver.virtio.pollus = us; + } if ((str = virXPathString("string(./driver/host/@csum)", ctxt))) { if ((val = virTristateSwitchTypeFromString(str)) <= 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -10515,6 +10528,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(event_idx); VIR_FREE(queues); VIR_FREE(rx_queue_size); + VIR_FREE(pollus); VIR_FREE(str); VIR_FREE(filter); VIR_FREE(type); @@ -22308,6 +22322,8 @@ 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.pollus) + virBufferAsprintf(&buf, " poll_us='%u'", def->driver.virtio.pollus);
virDomainVirtioOptionsFormat(&buf, def->virtio);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e67b6fd..d97d776 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -967,6 +967,7 @@ struct _virDomainNetDef { virTristateSwitch event_idx; unsigned int queues; /* Multiqueue virtio-net */ unsigned int rx_queue_size; + unsigned int pollus; /* busy polling for tap */ struct { virTristateSwitch csum; virTristateSwitch gso;
Generally I like to have the schema change (RNG file) and formatdomain.html.in (documentation) change, along with xml2xml tests. in the same commit as the change to the parser/formatter, but you've included them in the commit that connects the parser/formatter change into the qemu driver. Of course it all comes out the same in the end, but separating it in the way I suggest makes each patch self documenting and self-testing (xml2argv tests will still be added in the final patch).

From: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> This patch finalizes support of 'poll_us' attribute as an option of the NIC driver-specific element, the commit also takes care of hotplug. <devices> <interface type='ethernet'> <mac address='52:54:00:23:bc:ba'/> <model type='virtio'/> <driver name="vhost" poll_us='50'/> </interface> </devices> That option is supported for all networks which are using a tap device. To be used the backend should be specificly set to use vhost. Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> --- docs/formatdomain.html.in | 12 ++++++++++- docs/schemas/domaincommon.rng | 5 +++++ src/qemu/qemu_command.c | 22 +++++++++++++++++++++ src/qemu/qemu_hotplug.c | 12 +++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus-fail.xml | 23 ++++++++++++++++++++++ ...xml2argv-net-virtio-netdev-pollus-qemu-fail.xml | 23 ++++++++++++++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus.args | 23 ++++++++++++++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus.xml | 23 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 9 +++++++++ 9 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 52119f0..7bfeabc 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5043,7 +5043,7 @@ qemu-kvm -net nic,model=? /dev/null <model type='virtio'/> <b><driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5' rx_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'/> + <guest csum='off' tso4='off' tso6='off' ecn='off' ufo='off' poll_us='50'/> </driver> </b> </interface> @@ -5171,6 +5171,16 @@ 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> + <dd> + The optional <code>poll_us</code> attribute configure the + maximum number of microseconds that could be spent on busy + polling. It improves the performance, but requires more + CPU. This option is only available with vhost backend driver. + <span class="since">Since 2.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, diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 4950ddc..f304385 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2687,6 +2687,11 @@ <optional> <ref name="event_idx"/> </optional> + <optional> + <attribute name='poll_us'> + <ref name='positiveInteger'/> + </attribute> + </optional> </group> </choice> <ref name="virtioOptions"/> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8c12b2b..412496e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3955,6 +3955,9 @@ qemuBuildHostNetStr(virDomainNetDefPtr net, } if (net->tune.sndbuf_specified) virBufferAsprintf(&buf, "sndbuf=%lu,", net->tune.sndbuf); + if (net->driver.virtio.pollus) + virBufferAsprintf(&buf, "poll-us=%u,", + net->driver.virtio.pollus); } virObjectUnref(cfg); @@ -8451,6 +8454,25 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, return -1; } + if (net->driver.virtio.pollus > 0) { + if (net->driver.virtio.name != VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) { + virReportError( + VIR_ERR_CONFIG_UNSUPPORTED, + _("Busy polling is only supported with vhost backend driver")); + return -1; + } + /* Nothing besides TAP devices supports busy polling. */ + if (!(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || + actualType == VIR_DOMAIN_NET_TYPE_DIRECT || + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Busy polling is not supported for: %s"), + virDomainNetTypeToString(actualType)); + return -1; + } + } + /* and only TAP devices support nwfilter rules */ if (net->filter && !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 0b8d3d8..33884b7 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -995,6 +995,18 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, return -1; } + /* and nothing besides TAP devices supports busy polling. */ + if (net->driver.virtio.pollus > 0 && + !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || + actualType == VIR_DOMAIN_NET_TYPE_DIRECT || + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Busy polling is not supported for: %s"), + virDomainNetTypeToString(actualType)); + return -1; + } + /* and only TAP devices support nwfilter rules */ if (net->filter && !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml new file mode 100644 index 0000000..3b664b9 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml @@ -0,0 +1,23 @@ +<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-system-i686</emulator> + <interface type='ethernet'> + <mac address='52:54:00:23:bc:ba'/> + <model type='virtio'/> + <driver poll_us='50'/> + </interface> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml new file mode 100644 index 0000000..18999c3 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml @@ -0,0 +1,23 @@ +<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-system-i686</emulator> + <interface type='ethernet'> + <mac address='52:54:00:23:bc:ba'/> + <model type='virtio'/> + <driver name="qemu" poll_us='50'/> + </interface> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args new file mode 100644 index 0000000..8d44134 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args @@ -0,0 +1,23 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-i686 \ +-name QEMUGuest1 \ +-S \ +-M pc \ +-m 214 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-usb \ +-netdev tap,fd=3,id=hostnet0,poll-us=50 \ +-device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:23:bc:ba,bus=pci.0,\ +addr=0x3 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml new file mode 100644 index 0000000..46ef7d6 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml @@ -0,0 +1,23 @@ +<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-system-i686</emulator> + <interface type='ethernet'> + <mac address='52:54:00:23:bc:ba'/> + <model type='virtio'/> + <driver name="vhost" poll_us='50'/> + </interface> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 799aea9..54d1b07 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1133,6 +1133,15 @@ mymain(void) QEMU_CAPS_NODEFCONFIG); DO_TEST("net-virtio-netdev", QEMU_CAPS_NETDEV, QEMU_CAPS_NODEFCONFIG); + DO_TEST("net-virtio-netdev-pollus", + QEMU_CAPS_NETDEV, + QEMU_CAPS_VHOST_NET_POLL_US); + DO_TEST_FAILURE("net-virtio-netdev-pollus-fail", + QEMU_CAPS_NETDEV, + QEMU_CAPS_VHOST_NET_POLL_US); + DO_TEST_FAILURE("net-virtio-netdev-pollus-qemu-fail", + QEMU_CAPS_NETDEV, + QEMU_CAPS_VHOST_NET_POLL_US); DO_TEST("net-virtio-s390", QEMU_CAPS_VIRTIO_S390); DO_TEST("net-virtio-ccw", -- 2.9.4

On 06/15/2017 10:17 AM, sferdjao@redhat.com wrote:
From: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com>
This patch finalizes support of 'poll_us' attribute as an option of the NIC driver-specific element, the commit also takes care of hotplug.
<devices> <interface type='ethernet'> <mac address='52:54:00:23:bc:ba'/> <model type='virtio'/> <driver name="vhost" poll_us='50'/> </interface> </devices>
That option is supported for all networks which are using a tap device.
To be used the backend should be specificly set to use vhost.
Actually, libvirt's qemu driver will use vhost-net automatically as long as the qemu binary supports it (unless 1) the domain is using TCG instead of KVM, or 2) the interface configuration specifically says "<driver name='qemu" .../>).
Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> --- docs/formatdomain.html.in | 12 ++++++++++- docs/schemas/domaincommon.rng | 5 +++++ src/qemu/qemu_command.c | 22 +++++++++++++++++++++ src/qemu/qemu_hotplug.c | 12 +++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus-fail.xml | 23 ++++++++++++++++++++++ ...xml2argv-net-virtio-netdev-pollus-qemu-fail.xml | 23 ++++++++++++++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus.args | 23 ++++++++++++++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus.xml | 23 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 9 +++++++++
The successful tests should all be done in qemuxml2xmltest.c as well
9 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 52119f0..7bfeabc 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5043,7 +5043,7 @@ qemu-kvm -net nic,model=? /dev/null <model type='virtio'/> <b><driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5' rx_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'/> + <guest csum='off' tso4='off' tso6='off' ecn='off' ufo='off' poll_us='50'/> </driver> </b> </interface> @@ -5171,6 +5171,16 @@ 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> + <dd> + The optional <code>poll_us</code> attribute configure the + maximum number of microseconds that could be spent on busy + polling. It improves the performance, but requires more + CPU. This option is only available with vhost backend driver. + <span class="since">Since 2.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, diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 4950ddc..f304385 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2687,6 +2687,11 @@ <optional> <ref name="event_idx"/> </optional> + <optional> + <attribute name='poll_us'> + <ref name='positiveInteger'/> + </attribute> + </optional> </group> </choice> <ref name="virtioOptions"/>
As mentioned in the previous patch, the RNG and docs changes should be in the previous patch. (In this patch you're going to want to add an entry to docs/news.xml)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8c12b2b..412496e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3955,6 +3955,9 @@ qemuBuildHostNetStr(virDomainNetDefPtr net, } if (net->tune.sndbuf_specified) virBufferAsprintf(&buf, "sndbuf=%lu,", net->tune.sndbuf); + if (net->driver.virtio.pollus) + virBufferAsprintf(&buf, "poll-us=%u,", + net->driver.virtio.pollus); }
virObjectUnref(cfg); @@ -8451,6 +8454,25 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, return -1; }
+ if (net->driver.virtio.pollus > 0) { + if (net->driver.virtio.name != VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) {
I haven't checked - does this get set automatically when the vhost-net FD's are successfully opened?
+ virReportError( + VIR_ERR_CONFIG_UNSUPPORTED, + _("Busy polling is only supported with vhost backend driver"));
I wonder if anyone would be confused by the lack of the exact option name "poll_us" in these error messages.
+ return -1; + } + /* Nothing besides TAP devices supports busy polling. */ + if (!(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || + actualType == VIR_DOMAIN_NET_TYPE_DIRECT || + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Busy polling is not supported for: %s"), + virDomainNetTypeToString(actualType)); + return -1; + } + } + /* and only TAP devices support nwfilter rules */ if (net->filter && !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 0b8d3d8..33884b7 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -995,6 +995,18 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, return -1; }
+ /* and nothing besides TAP devices supports busy polling. */ + if (net->driver.virtio.pollus > 0 && + !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || + actualType == VIR_DOMAIN_NET_TYPE_DIRECT || + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Busy polling is not supported for: %s"), + virDomainNetTypeToString(actualType)); + return -1; + }
Huh. I just noticed there's a lot of duplicated code between qemuBuildInterfaceCommandLine() and qemuDomainAttachNetDevice()... (not your problem, but it seems like this is just *screaming* to be vombined/consolidated to eliminate behavioral differences / half-fixed bugs etc.
+ /* and only TAP devices support nwfilter rules */ if (net->filter && !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml new file mode 100644 index 0000000..3b664b9 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml @@ -0,0 +1,23 @@ +<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-system-i686</emulator> + <interface type='ethernet'> + <mac address='52:54:00:23:bc:ba'/> + <model type='virtio'/> + <driver poll_us='50'/>
So this is supposed to fail because the config doesn't explicitly say "driver name='vhost'". But as I said in the review of patch 2, vhost-net is used by default. So this would normally be a correct config.
+ </interface> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml new file mode 100644 index 0000000..18999c3 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml @@ -0,0 +1,23 @@ +<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-system-i686</emulator> + <interface type='ethernet'> + <mac address='52:54:00:23:bc:ba'/> + <model type='virtio'/> + <driver name="qemu" poll_us='50'/>
This one is okay - it *should* fail.
+ </interface> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args new file mode 100644 index 0000000..8d44134 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args @@ -0,0 +1,23 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-i686 \ +-name QEMUGuest1 \ +-S \ +-M pc \ +-m 214 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-usb \ +-netdev tap,fd=3,id=hostnet0,poll-us=50 \ +-device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:23:bc:ba,bus=pci.0,\ +addr=0x3 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml new file mode 100644 index 0000000..46ef7d6 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml @@ -0,0 +1,23 @@ +<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-system-i686</emulator> + <interface type='ethernet'> + <mac address='52:54:00:23:bc:ba'/> + <model type='virtio'/> + <driver name="vhost" poll_us='50'/> + </interface> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 799aea9..54d1b07 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1133,6 +1133,15 @@ mymain(void) QEMU_CAPS_NODEFCONFIG); DO_TEST("net-virtio-netdev", QEMU_CAPS_NETDEV, QEMU_CAPS_NODEFCONFIG); + DO_TEST("net-virtio-netdev-pollus", + QEMU_CAPS_NETDEV, + QEMU_CAPS_VHOST_NET_POLL_US); + DO_TEST_FAILURE("net-virtio-netdev-pollus-fail", + QEMU_CAPS_NETDEV, + QEMU_CAPS_VHOST_NET_POLL_US); + DO_TEST_FAILURE("net-virtio-netdev-pollus-qemu-fail", + QEMU_CAPS_NETDEV, + QEMU_CAPS_VHOST_NET_POLL_US); DO_TEST("net-virtio-s390", QEMU_CAPS_VIRTIO_S390); DO_TEST("net-virtio-ccw",

On Sat, Jun 17, 2017 at 12:30:29PM -0400, Laine Stump wrote:
On 06/15/2017 10:17 AM, sferdjao@redhat.com wrote:
From: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com>
This patch finalizes support of 'poll_us' attribute as an option of the NIC driver-specific element, the commit also takes care of hotplug.
<devices> <interface type='ethernet'> <mac address='52:54:00:23:bc:ba'/> <model type='virtio'/> <driver name="vhost" poll_us='50'/> </interface> </devices>
That option is supported for all networks which are using a tap device.
To be used the backend should be specificly set to use vhost.
Actually, libvirt's qemu driver will use vhost-net automatically as long as the qemu binary supports it (unless 1) the domain is using TCG instead of KVM, or 2) the interface configuration specifically says "<driver name='qemu" .../>).
Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> --- docs/formatdomain.html.in | 12 ++++++++++- docs/schemas/domaincommon.rng | 5 +++++ src/qemu/qemu_command.c | 22 +++++++++++++++++++++ src/qemu/qemu_hotplug.c | 12 +++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus-fail.xml | 23 ++++++++++++++++++++++ ...xml2argv-net-virtio-netdev-pollus-qemu-fail.xml | 23 ++++++++++++++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus.args | 23 ++++++++++++++++++++++ .../qemuxml2argv-net-virtio-netdev-pollus.xml | 23 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 9 +++++++++
The successful tests should all be done in qemuxml2xmltest.c as well
9 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 52119f0..7bfeabc 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5043,7 +5043,7 @@ qemu-kvm -net nic,model=? /dev/null <model type='virtio'/> <b><driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off' queues='5' rx_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'/> + <guest csum='off' tso4='off' tso6='off' ecn='off' ufo='off' poll_us='50'/> </driver> </b> </interface> @@ -5171,6 +5171,16 @@ 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> + <dd> + The optional <code>poll_us</code> attribute configure the + maximum number of microseconds that could be spent on busy + polling. It improves the performance, but requires more + CPU. This option is only available with vhost backend driver. + <span class="since">Since 2.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, diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 4950ddc..f304385 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2687,6 +2687,11 @@ <optional> <ref name="event_idx"/> </optional> + <optional> + <attribute name='poll_us'> + <ref name='positiveInteger'/> + </attribute> + </optional> </group> </choice> <ref name="virtioOptions"/>
As mentioned in the previous patch, the RNG and docs changes should be in the previous patch. (In this patch you're going to want to add an entry to docs/news.xml)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8c12b2b..412496e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3955,6 +3955,9 @@ qemuBuildHostNetStr(virDomainNetDefPtr net, } if (net->tune.sndbuf_specified) virBufferAsprintf(&buf, "sndbuf=%lu,", net->tune.sndbuf); + if (net->driver.virtio.pollus) + virBufferAsprintf(&buf, "poll-us=%u,", + net->driver.virtio.pollus); }
virObjectUnref(cfg); @@ -8451,6 +8454,25 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, return -1; }
+ if (net->driver.virtio.pollus > 0) { + if (net->driver.virtio.name != VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) {
I haven't checked - does this get set automatically when the vhost-net FD's are successfully opened?
+ virReportError( + VIR_ERR_CONFIG_UNSUPPORTED, + _("Busy polling is only supported with vhost backend driver"));
I wonder if anyone would be confused by the lack of the exact option name "poll_us" in these error messages.
+ return -1; + } + /* Nothing besides TAP devices supports busy polling. */ + if (!(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || + actualType == VIR_DOMAIN_NET_TYPE_DIRECT || + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Busy polling is not supported for: %s"), + virDomainNetTypeToString(actualType)); + return -1; + } + } + /* and only TAP devices support nwfilter rules */ if (net->filter && !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 0b8d3d8..33884b7 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -995,6 +995,18 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, return -1; }
+ /* and nothing besides TAP devices supports busy polling. */ + if (net->driver.virtio.pollus > 0 && + !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || + actualType == VIR_DOMAIN_NET_TYPE_DIRECT || + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Busy polling is not supported for: %s"), + virDomainNetTypeToString(actualType)); + return -1; + }
Huh. I just noticed there's a lot of duplicated code between qemuBuildInterfaceCommandLine() and qemuDomainAttachNetDevice()... (not your problem, but it seems like this is just *screaming* to be vombined/consolidated to eliminate behavioral differences / half-fixed bugs etc.
+ /* and only TAP devices support nwfilter rules */ if (net->filter && !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml new file mode 100644 index 0000000..3b664b9 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-fail.xml @@ -0,0 +1,23 @@ +<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-system-i686</emulator> + <interface type='ethernet'> + <mac address='52:54:00:23:bc:ba'/> + <model type='virtio'/> + <driver poll_us='50'/>
So this is supposed to fail because the config doesn't explicitly say "driver name='vhost'". But as I said in the review of patch 2, vhost-net is used by default. So this would normally be a correct config.
If the driver name is not explicitly set it seems that libvirt is going to use vhost but can fallback to qemu. Since that option is not available for qemu I prefered to make this explicit.
+ </interface> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml new file mode 100644 index 0000000..18999c3 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus-qemu-fail.xml @@ -0,0 +1,23 @@ +<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-system-i686</emulator> + <interface type='ethernet'> + <mac address='52:54:00:23:bc:ba'/> + <model type='virtio'/> + <driver name="qemu" poll_us='50'/>
This one is okay - it *should* fail.
+ </interface> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args new file mode 100644 index 0000000..8d44134 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.args @@ -0,0 +1,23 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-i686 \ +-name QEMUGuest1 \ +-S \ +-M pc \ +-m 214 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-usb \ +-netdev tap,fd=3,id=hostnet0,poll-us=50 \ +-device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:23:bc:ba,bus=pci.0,\ +addr=0x3 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml new file mode 100644 index 0000000..46ef7d6 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev-pollus.xml @@ -0,0 +1,23 @@ +<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-system-i686</emulator> + <interface type='ethernet'> + <mac address='52:54:00:23:bc:ba'/> + <model type='virtio'/> + <driver name="vhost" poll_us='50'/> + </interface> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 799aea9..54d1b07 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1133,6 +1133,15 @@ mymain(void) QEMU_CAPS_NODEFCONFIG); DO_TEST("net-virtio-netdev", QEMU_CAPS_NETDEV, QEMU_CAPS_NODEFCONFIG); + DO_TEST("net-virtio-netdev-pollus", + QEMU_CAPS_NETDEV, + QEMU_CAPS_VHOST_NET_POLL_US); + DO_TEST_FAILURE("net-virtio-netdev-pollus-fail", + QEMU_CAPS_NETDEV, + QEMU_CAPS_VHOST_NET_POLL_US); + DO_TEST_FAILURE("net-virtio-netdev-pollus-qemu-fail", + QEMU_CAPS_NETDEV, + QEMU_CAPS_VHOST_NET_POLL_US); DO_TEST("net-virtio-s390", QEMU_CAPS_VIRTIO_S390); DO_TEST("net-virtio-ccw",
participants (6)
-
Eduardo Habkost
-
Eric Blake
-
Laine Stump
-
Laine Stump
-
Sahid Orentino Ferdjaoui
-
sferdjao@redhat.com