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

Dr. David Alan Gilbert dgilbert at redhat.com
Fri Feb 3 17:41:49 UTC 2017


* Laine Stump (laine at laine.org) 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 :-/)

Or what happens if I migrate between hosts where the host network
hardware has different MTU?

Dave

> 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).
> ---
> 
> 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;
> +            }
>          }
> -        virBufferAsprintf(&buf, ",host_mtu=%u", net->mtu);
>      }
>  
>      if (vlan == -1)
> @@ -8042,7 +8053,7 @@ qemuBuildVhostuserCommandLine(virQEMUDriverPtr driver,
>      VIR_FREE(netdev);
>  
>      if (!(nic = qemuBuildNicDevStr(def, net, -1, bootindex,
> -                                   queues, qemuCaps))) {
> +                                   queues, qemuCaps, net->mtu))) {
>          virReportError(VIR_ERR_INTERNAL_ERROR,
>                         "%s", _("Error generating NIC -device string"));
>          goto error;
> @@ -8088,6 +8099,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
>      virDomainNetType actualType = virDomainNetGetActualType(net);
>      virNetDevBandwidthPtr actualBandwidth;
>      size_t i;
> +    unsigned int mtu = net->mtu;
>  
>  
>      if (!bootindex)
> @@ -8142,7 +8154,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
>          memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));
>  
>          if (qemuInterfaceBridgeConnect(def, driver, net,
> -                                       tapfd, &tapfdSize) < 0)
> +                                       tapfd, &tapfdSize, &mtu) < 0)
>              goto cleanup;
>          break;
>  
> @@ -8322,7 +8334,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
>      }
>      if (qemuDomainSupportsNicdev(def, net)) {
>          if (!(nic = qemuBuildNicDevStr(def, net, vlan, bootindex,
> -                                       vhostfdSize, qemuCaps)))
> +                                       vhostfdSize, qemuCaps, mtu)))
>              goto cleanup;
>          virCommandAddArgList(cmd, "-device", nic, NULL);
>      } else {
> diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
> index 3bcfdc6..69fe846 100644
> --- a/src/qemu/qemu_command.h
> +++ b/src/qemu/qemu_command.h
> @@ -101,7 +101,8 @@ char *qemuBuildNicDevStr(virDomainDefPtr def,
>                           int vlan,
>                           unsigned int bootindex,
>                           size_t vhostfdSize,
> -                         virQEMUCapsPtr qemuCaps);
> +                         virQEMUCapsPtr qemuCaps,
> +                         unsigned int mtu);
>  
>  char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk);
>  
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index a6de254..c0d1ab9 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -969,6 +969,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
>      bool charDevPlugged = false;
>      bool netdevPlugged = false;
>      bool hostPlugged = false;
> +    unsigned int mtu = net->mtu;
>  
>      /* preallocate new slot for device */
>      if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0)
> @@ -1025,7 +1026,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
>              goto cleanup;
>          memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
>          if (qemuInterfaceBridgeConnect(vm->def, driver, net,
> -                                       tapfd, &tapfdSize) < 0)
> +                                       tapfd, &tapfdSize, &mtu) < 0)
>              goto cleanup;
>          iface_connected = true;
>          if (qemuInterfaceOpenVhostNet(vm->def, net, priv->qemuCaps,
> @@ -1236,7 +1237,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
>          VIR_FORCE_CLOSE(vhostfd[i]);
>  
>      if (!(nicstr = qemuBuildNicDevStr(vm->def, net, vlan, 0,
> -                                      queueSize, priv->qemuCaps)))
> +                                      queueSize, priv->qemuCaps, mtu)))
>          goto try_remove;
>  
>      qemuDomainObjEnterMonitor(driver, vm);
> diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
> index ce448d2..c5dca60 100644
> --- a/src/qemu/qemu_interface.c
> +++ b/src/qemu/qemu_interface.c
> @@ -503,7 +503,8 @@ qemuInterfaceBridgeConnect(virDomainDefPtr def,
>                             virQEMUDriverPtr driver,
>                             virDomainNetDefPtr net,
>                             int *tapfd,
> -                           size_t *tapfdSize)
> +                           size_t *tapfdSize,
> +                           unsigned int *mtu)
>  {
>      const char *brname;
>      int ret = -1;
> @@ -544,7 +545,7 @@ qemuInterfaceBridgeConnect(virDomainDefPtr def,
>                                             def->uuid, tunpath, tapfd, *tapfdSize,
>                                             virDomainNetGetActualVirtPortProfile(net),
>                                             virDomainNetGetActualVlan(net),
> -                                           0, NULL,
> +                                           net->mtu, mtu,
>                                             tap_create_flags) < 0) {
>              virDomainAuditNetDevice(def, net, tunpath, false);
>              goto cleanup;
> diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h
> index 66ead2a..0ec873f 100644
> --- a/src/qemu/qemu_interface.h
> +++ b/src/qemu/qemu_interface.h
> @@ -50,7 +50,8 @@ int qemuInterfaceBridgeConnect(virDomainDefPtr def,
>                                 virQEMUDriverPtr driver,
>                                 virDomainNetDefPtr net,
>                                 int *tapfd,
> -                               size_t *tapfdSize)
> +                               size_t *tapfdSize,
> +                               unsigned int *mtu)
>      ATTRIBUTE_NONNULL(2);
>  
>  int qemuInterfaceOpenVhostNet(virDomainDefPtr def,
> -- 
> 2.9.3
> 
--
Dr. David Alan Gilbert / dgilbert at redhat.com / Manchester, UK




More information about the libvir-list mailing list