From e484cb3ecaa2292198721c5af6e4484ee5e7f9b7 Mon Sep 17 00:00:00 2001 From: Antoine Millet Date: Mon, 17 Jul 2017 17:49:00 +0200 Subject: [PATCH] Handle hotplug change on VLAN configuration using OVS A new function virNetDevOpenvswitchUpdateVlan has been created to instruct OVS of the changes. qemuDomainChangeNet has been modified to handle the update of the VLAN configuration for a running guest and rely on virNetDevOpenvswitchUpdateVlan to do the actual update if needed. Signed-off-by: Michal Privoznik --- src/libvirt_private.syms | 1 + src/qemu/qemu_hotplug.c | 16 +++++++++++--- src/util/virnetdevopenvswitch.c | 38 +++++++++++++++++++++++++++++++++ src/util/virnetdevopenvswitch.h | 4 ++++ 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 187b12b32b..36caf6fbfd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2206,6 +2206,7 @@ virNetDevOpenvswitchInterfaceStats; virNetDevOpenvswitchRemovePort; virNetDevOpenvswitchSetMigrateData; virNetDevOpenvswitchSetTimeout; +virNetDevOpenvswitchUpdateVlan; # util/virnetdevtap.h diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index da5aafaab3..4be0f546ca 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3005,6 +3005,7 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, bool needReplaceDevDef = false; bool needBandwidthSet = false; bool needCoalesceChange = false; + bool needVlanUpdate = false; int ret = -1; int changeidx = -1; @@ -3286,12 +3287,15 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, virDomainNetGetActualDirectDev(newdev)) || virDomainNetGetActualDirectMode(olddev) != virDomainNetGetActualDirectMode(newdev) || !virNetDevVPortProfileEqual(virDomainNetGetActualVirtPortProfile(olddev), - virDomainNetGetActualVirtPortProfile(newdev)) || - !virNetDevVlanEqual(virDomainNetGetActualVlan(olddev), - virDomainNetGetActualVlan(newdev))) { + virDomainNetGetActualVirtPortProfile(newdev))) { needReconnect = true; } + if (!virNetDevVlanEqual(virDomainNetGetActualVlan(olddev), + virDomainNetGetActualVlan(newdev))) { + needVlanUpdate = true; + } + if (olddev->linkstate != newdev->linkstate) needLinkStateChange = true; @@ -3351,6 +3355,12 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, goto cleanup; } + if (needVlanUpdate) { + if (virNetDevOpenvswitchUpdateVlan(newdev->ifname, &newdev->vlan) < 0) + goto cleanup; + needReplaceDevDef = true; + } + if (needReplaceDevDef) { /* the changes above warrant replacing olddev with newdev in * the domain's nets list. diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c index e002af0ba2..06ce9d8ee5 100644 --- a/src/util/virnetdevopenvswitch.c +++ b/src/util/virnetdevopenvswitch.c @@ -460,3 +460,41 @@ virNetDevOpenvswitchGetVhostuserIfname(const char *path, VIR_FREE(ovs_timeout); return ret; } + +/** + * virNetDevOpenvswitchUpdateVlan: + * @ifname: the network interface name + * @virtVlan: VLAN configuration to be applied + * + * Update VLAN configuration of an OVS port. + * + * Returns 0 in case of success or -1 in case of failure. + */ +int virNetDevOpenvswitchUpdateVlan(const char *ifname, + virNetDevVlanPtr virtVlan) +{ + int ret = -1; + virCommandPtr cmd = NULL; + + cmd = virCommandNew(OVSVSCTL); + virNetDevOpenvswitchAddTimeout(cmd); + virCommandAddArgList(cmd, + "--", "--if-exists", "clear", "Port", ifname, "tag", + "--", "--if-exists", "clear", "Port", ifname, "trunk", + "--", "--if-exists", "clear", "Port", ifname, "vlan_mode", + "--", "--if-exists", "set", "Port", ifname, NULL); + + if (virNetDevOpenvswitchConstructVlans(cmd, virtVlan) < 0) + goto cleanup; + + if (virCommandRun(cmd, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to set vlan configuration on port %s"), ifname); + goto cleanup; + } + + ret = 0; + cleanup: + virCommandFree(cmd); + return ret; +} diff --git a/src/util/virnetdevopenvswitch.h b/src/util/virnetdevopenvswitch.h index 51bb1dd006..6f6e620c22 100644 --- a/src/util/virnetdevopenvswitch.h +++ b/src/util/virnetdevopenvswitch.h @@ -61,4 +61,8 @@ int virNetDevOpenvswitchGetVhostuserIfname(const char *path, char **ifname) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NOINLINE; +int virNetDevOpenvswitchUpdateVlan(const char *ifname, + virNetDevVlanPtr virtVlan) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; + #endif /* __VIR_NETDEV_OPENVSWITCH_H__ */