[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