* Laine Stump (laine@xxxxxxxxx) 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@xxxxxxxxxx / Manchester, UK -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list