[libvirt] [PATCH v2 4/4] qemu: propagate bridge MTU into qemu "host_mtu" option

Michal Privoznik mprivozn at redhat.com
Mon Feb 6 12:57:45 UTC 2017


On 03.02.2017 18:35, Laine Stump wrote:
> libvirt was able to set the host_mtu option when an MTU was explicitly
> given in the interface config (with <mtu size='n'/>), set the MTU of a
> libvirt network in the network config (with the same named
> subelement), and would automatically set the MTU of any tap device to
> the MTU of the network.
> 
> This patch ties that all together (for networks based on tap devices
> and either Linux host bridges or OVS bridges) by learning the MTU of
> the network (i.e. the bridge) during qemuInterfaceBridgeConnect(), and
> returning that value so that it can be passed to qemuBuildNicDevStr();
> qemuBuildNicDevStr() then sets host_mtu in the interface's commandline
> options.
> 
> The result is that a higher MTU for all guests connecting to a
> particular network will be plumbed top to bottom by simply changing
> the MTU of the network (in libvirt's config for libvirt-managed
> networks, or directly on the bridge device for simple host bridges or
> OVS bridges managed outside of libvirt).
> 
> One question I have about this - it occurred to me that in the case of
> migrating a guest from a host with an older libvirt to one with a
> newer libvirt, the guest may have *not* had the host_mtu option on the
> older machine, but *will* have it on the newer machine. I'm curious if
> this could lead to incompatibilities between source and destination (I
> guess it all depends on whether or not the setting of host_mtu has a
> practical effect on a guest that is already running - Maxime?) (I hope
> we don't have to add a "<mtu auto='yes'/>" and only set host_mtu when
> that is present :-/)

This is a question for qemu folks. I know nothing about qemu internals.

> 
> Likewise, we could run into problems when migrating from a newer
> libvirt to older libvirt - The guest would have been told of the
> higher MTU on the newer libvirt, then migrated to a host that didn't
> understand <mtu size='blah'/>. (If this really is a problem, it would
> be a problem with or without the current patch).


Well, if it turns out to be a problem there's yet another variation of it: users can supply new domain XML upon migration and thus change MTU. But that should be easy to check (not that we are doing that now).

> ---
> 
> New in V2.
> 
>  src/qemu/qemu_command.c   | 32 ++++++++++++++++++++++----------
>  src/qemu/qemu_command.h   |  3 ++-
>  src/qemu/qemu_hotplug.c   |  5 +++--
>  src/qemu/qemu_interface.c |  5 +++--
>  src/qemu/qemu_interface.h |  3 ++-
>  5 files changed, 32 insertions(+), 16 deletions(-)
> 
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 6d65872..522152d 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -3555,7 +3555,8 @@ qemuBuildNicDevStr(virDomainDefPtr def,
>                     int vlan,
>                     unsigned int bootindex,
>                     size_t vhostfdSize,
> -                   virQEMUCapsPtr qemuCaps)
> +                   virQEMUCapsPtr qemuCaps,
> +                   unsigned int mtu)
>  {
>      virBuffer buf = VIR_BUFFER_INITIALIZER;
>      const char *nic = net->model;
> @@ -3679,13 +3680,23 @@ qemuBuildNicDevStr(virDomainDefPtr def,
>          virBufferAsprintf(&buf, ",rx_queue_size=%u", net->driver.virtio.rx_queue_size);
>      }
>  
> -    if (usingVirtio && net->mtu) {
> -        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_HOST_MTU)) {
> -            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> -                           _("setting MTU is not supported with this QEMU binary"));
> -            goto error;
> +    if (usingVirtio && mtu) {
> +        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_HOST_MTU)) {
> +
> +            virBufferAsprintf(&buf, ",host_mtu=%u", mtu);
> +
> +        } else {
> +            /* log an error if mtu was requested specifically for this
> +             * interface, otherwise, if it's just what was reported by
> +             * the attached network, ignore it.
> +             */
> +            if (net->mtu) {
> +                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                               _("setting MTU is not supported with "
> +                                 "this QEMU binary"));
> +                goto error;
> +            }
>          }

This requires users to pass net->mtu even though net is already passed into this function. I wonder whether we should alter meaning of @mtu argument slightly. Something like you're going with in 1/4:
- a nonzero value means caller is requesting that particular MTU size
- a zero value means stick with net->mtu value.

Although, now that I've tried and changed code accordingly the difference is just one line changed (apart from these line above):

index 0767c6649..a556dc60a 100644
--- i/src/qemu/qemu_command.c
+++ w/src/qemu/qemu_command.c
@@ -3680,10 +3680,10 @@ qemuBuildNicDevStr(virDomainDefPtr def,
         virBufferAsprintf(&buf, ",rx_queue_size=%u", net->driver.virtio.rx_queue_size);
     }
 
-    if (usingVirtio && mtu) {
+    if (usingVirtio && (net->mtu || mtu)) {
         if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_HOST_MTU)) {
 
-            virBufferAsprintf(&buf, ",host_mtu=%u", mtu);
+            virBufferAsprintf(&buf, ",host_mtu=%u", net->mtu ? net->mtu : mtu);
 
         } else {
             /* log an error if mtu was requested specifically for this
@@ -8053,7 +8053,7 @@ qemuBuildVhostuserCommandLine(virQEMUDriverPtr driver,
     VIR_FREE(netdev);
 
     if (!(nic = qemuBuildNicDevStr(def, net, -1, bootindex,
-                                   queues, qemuCaps, net->mtu))) {
+                                   queues, qemuCaps, 0))) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Error generating NIC -device string"));
         goto error;


This is because we need one bit as well:

@@ -8273,8 +8273,8 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
         }
     }
 
-    if (net->mtu &&
-        virNetDevSetMTU(net->ifname, net->mtu) < 0)
+    if (mtu &&
+        virNetDevSetMTU(net->ifname, mtu) < 0)
         goto cleanup;
 
     if ((actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
diff --git i/src/qemu/qemu_hotplug.c w/src/qemu/qemu_hotplug.c
index 7784dad3c..a083b2a3f 100644
--- i/src/qemu/qemu_hotplug.c
+++ w/src/qemu/qemu_hotplug.c
@@ -1116,6 +1116,9 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
         goto cleanup;
     }
 
+    if (mtu &&
+        virNetDevSetMTU(net->ifname, mtu) < 0)
+
     /* Set device online immediately */
     if (qemuInterfaceStartDevice(net) < 0)
         goto cleanup;

It just feels better than ternary operator. So ACK to whatever version you choose.

Michal




More information about the libvir-list mailing list