Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- src/libvirt_private.syms | 1 + src/util/virnetdevtap.c | 69 ++++++++++++++++++++++++++++++++++++++++ src/util/virnetdevtap.h | 12 +++++++ 3 files changed, 82 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 038a744981..07bc7d94d2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2437,6 +2437,7 @@ virNetDevTapDelete; virNetDevTapGetName; virNetDevTapGetRealDeviceName; virNetDevTapInterfaceStats; +virNetDevTapReattachBridge; # util/virnetdevveth.h diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c index 972f3405aa..0484c7c5a4 100644 --- a/src/util/virnetdevtap.c +++ b/src/util/virnetdevtap.c @@ -553,6 +553,75 @@ virNetDevTapAttachBridge(const char *tapname, } +/** + * virNetDevTapReattachBridge: + * @tapname: the tap interface name (or name template) + * @brname: the bridge name + * @macaddr: desired MAC address + * @virtPortProfile: bridge/port specific configuration + * @virtVlan: vlan tag info + * @mtu: requested MTU for port (or 0 for "default") + * @actualMTU: MTU actually set for port (after accounting for bridge's MTU) + * + * Ensures that the tap device (@tapname) is connected to the bridge + * (@brname), potentially removing it from any existing bridge that + * does not match. + * + * Returns 0 in case of success or -1 on failure + */ +int +virNetDevTapReattachBridge(const char *tapname, + const char *brname, + const virMacAddr *macaddr, + const unsigned char *vmuuid, + virNetDevVPortProfilePtr virtPortProfile, + virNetDevVlanPtr virtVlan, + unsigned int mtu, + unsigned int *actualMTU) +{ + bool useOVS = false; + char *master = NULL; + + if (virNetDevGetMaster(tapname, &master) < 0) + return -1; + + /* IFLA_MASTER for a tap on an OVS switch is always "ovs-system" */ + if (STREQ_NULLABLE(master, "ovs-system")) { + useOVS = true; + VIR_FREE(master); + if (virNetDevOpenvswitchInterfaceGetMaster(tapname, &master) < 0) + return -1; + } + + /* Nothing more todo if we're on the right bridge already */ + if (STREQ_NULLABLE(brname, master)) + return 0; + + /* disconnect from current (incorrect) bridge, if any */ + if (master) { + int ret; + VIR_INFO("Removing %s from %s", tapname, master); + if (useOVS) + ret = virNetDevOpenvswitchRemovePort(master, tapname); + else + ret = virNetDevBridgeRemovePort(master, tapname); + VIR_FREE(master); + if (ret < 0) + return -1; + } + + VIR_INFO("Attaching %s to %s", tapname, brname); + if (virNetDevTapAttachBridge(tapname, brname, + macaddr, vmuuid, + virtPortProfile, + virtVlan, + mtu, actualMTU) < 0) + return -1; + + return 0; +} + + /** * virNetDevTapCreateInBridgePort: * @brname: the bridge name diff --git a/src/util/virnetdevtap.h b/src/util/virnetdevtap.h index 226122aa2c..2b3893cd37 100644 --- a/src/util/virnetdevtap.h +++ b/src/util/virnetdevtap.h @@ -71,6 +71,18 @@ virNetDevTapAttachBridge(const char *tapname, ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK; +int +virNetDevTapReattachBridge(const char *tapname, + const char *brname, + const virMacAddr *macaddr, + const unsigned char *vmuuid, + virNetDevVPortProfilePtr virtPortProfile, + virNetDevVlanPtr virtVlan, + unsigned int mtu, + unsigned int *actualMTU) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_RETURN_CHECK; + int virNetDevTapCreateInBridgePort(const char *brname, char **ifname, const virMacAddr *macaddr, -- 2.20.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list