On Wed, Jan 25, 2012 at 04:09:22PM +0100, Hendrik Schwartke wrote: > I wrote a patch to change the mapping between a virtual bridge > interface and the host bridge while the host is up. It's based on > commit 6fba577e505611e6c25c68e322942eab7754de7e. The host and the > interface definition I used for testing are also attached. > I would be glad if the patch could be added to the repo. Great ! > diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c > index 4b60839..f791795 100644 > --- a/src/qemu/qemu_hotplug.c > +++ b/src/qemu/qemu_hotplug.c > @@ -40,6 +40,7 @@ > #include "qemu_cgroup.h" > #include "locking/domain_lock.h" > #include "network/bridge_driver.h" > +#include "util/virnetdevbridge.h" > > #define VIR_FROM_THIS VIR_FROM_QEMU > > @@ -1163,6 +1164,28 @@ static virDomainNetDefPtr > qemuDomainFindNet(virDomainObjPtr vm, > return NULL; > } > > +int qemuDomainChangeNetBridge(virDomainNetDefPtr olddev, > + virDomainNetDefPtr newdev) > +{ > + const char *oldbridge=olddev->data.bridge.brname; > + const char *newbridge=newdev->data.bridge.brname; > + VIR_DEBUG("Change bridge for interface %s: %s -> %s", > olddev->ifname, oldbridge, newbridge); > + if(virNetDevBridgeRemovePort(oldbridge, olddev->ifname)<0) { > + qemuReportError(VIR_ERR_OPERATION_FAILED, > + _("unable to remove port from bridge")); Good idea to include the bridge device name too > + return -1; > + } > + if(virNetDevBridgeAddPort(newbridge, newdev->ifname)<0) { > + qemuReportError(VIR_ERR_OPERATION_FAILED, > + _("unable to add port to bridge")); > + return -1; > + } Hmm, we'd end up with no NIC backend command at all here. So we'd probably want to move the VIR_FREE() line before here, so if we fail half-way through, we still update the XML. To avoid stupid mistakes we also probably want to check for existance of the target bridge before unplugging fromthe source > + VIR_FREE(olddev->data.bridge.brname); > + olddev->data.bridge.brname=strdup(newbridge); We could just steal newbridge from the newdev and avoid the OOM potential > + return 0; > +} Various whitespace fixes - For assignment, we prefer 'foo = bar' instead of 'foo=bar' - For conditionals 'if (' instead of 'if(' - For tests "foo < 0" instead of "foo<0" So all in all I think I'd write this as int qemuDomainChangeNetBridge(virDomainNetDefPtr olddev, virDomainNetDefPtr newdev) { const char *oldbridge = olddev->data.bridge.brname; const char *newbridge = newdev->data.bridge.brname; VIR_DEBUG("Change bridge for interface %s: %s -> %s", olddev->ifname, oldbridge, newbridge); if (!virNetDevExists(newbridge)) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("unable to remove port from bridge")); return -1; } if (oldbridge && virNetDevBridgeRemovePort(oldbridge, olddev->ifname) < 0) { qemuReportError(VIR_ERR_OPERATION_FAILED, _("unable to remove port from bridge %s"), oldbridge); return -1; } VIR_FREE(olddev->data.bridge.brname); if (virNetDevBridgeAddPort(newbridge, newdev->ifname) < 0) { qemuReportError(VIR_ERR_OPERATION_FAILED, _("unable to add port to bridge"), newbridge); return -1; } olddev->data.bridge.brname = newdev->data.bridge.brname; newdev->data.bridge.brname = NULL; return 0; } > + > int qemuDomainChangeNetLinkState(struct qemud_driver *driver, > virDomainObjPtr vm, > virDomainNetDefPtr dev, > @@ -1293,6 +1316,12 @@ int qemuDomainChangeNet(struct qemud_driver *driver, > return -1; > } > > + if(olddev->type==VIR_DOMAIN_NET_TYPE_BRIDGE > + && dev->type==VIR_DOMAIN_NET_TYPE_BRIDGE > + && STRNEQ(olddev->data.bridge.brname, dev->data.bridge.brname)) { > + qemuDomainChangeNetBridge(olddev, dev); > + } And use STRNEQ_NULLABLE here to avoid risk of NULL brname field, and if qemuDomainChangeNetBridge() returns -1, we need to return to the caller here. > + > if (olddev->linkstate != dev->linkstate) { > if ((ret = qemuDomainChangeNetLinkState(driver, vm, olddev, > dev->linkstate)) < 0) > return ret; > diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h > index 0310361..1e1f75c 100644 > --- a/src/qemu/qemu_hotplug.h > +++ b/src/qemu/qemu_hotplug.h > @@ -80,6 +80,8 @@ int qemuDomainChangeNetLinkState(struct > qemud_driver *driver, > virDomainObjPtr vm, > virDomainNetDefPtr dev, > int linkstate); > +int qemuDomainChangeNetBridge(virDomainNetDefPtr olddev, > + virDomainNetDefPtr newdev); > int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver, > virDomainObjPtr vm, > virDomainDeviceDefPtr dev); > > > Host definition: > <domain type='kvm'> > <name>test</name> > <memory>32768</memory> > <currentMemory>32768</currentMemory> > <vcpu>1</vcpu> > <os> > <type arch='x86_64' machine='pc-0.12'>hvm</type> > <boot dev='cdrom'/> > <bootmenu enable='no'/> > </os> > <features> > <acpi/> > <apic/> > <pae/> > </features> > <clock offset='utc'/> > <on_poweroff>destroy</on_poweroff> > <on_reboot>restart</on_reboot> > <on_crash>restart</on_crash> > <devices> > <emulator>/usr/bin/kvm</emulator> > <controller type='ide' index='0'> > <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> > </controller> > <interface type='bridge'> > <mac address='52:54:00:ab:cd:02'/> > <source bridge='br0'/> > <target dev='testif'/> > <link state='up'/> > <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> > </interface> > <serial type='pty'> > <target port='0'/> > </serial> > <console type='pty'> > <target type='serial' port='0'/> > </console> > <input type='tablet' bus='usb'/> > <input type='mouse' bus='ps2'/> > <graphics type='vnc' port='-1' autoport='yes'/> > <video> > <model type='cirrus' vram='9216' heads='1'/> > <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> > </video> > <memballoon model='virtio'> > <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> > </memballoon> > </devices> > </domain> > > > Interface definition: > <interface type="bridge"> > <mac address="52:54:00:ab:cd:02"/> > <source bridge="br1"/> > <target dev="testif"/> > <link state="up"/> > <alias name="net0"/> > <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0"/> > </interface> > > > > Best regards > Hendrik Schwartke > > -- > libvir-list mailing list > libvir-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list