[libvirt PATCH v4] hypervisor: Move interface mgmt methods to hypervisor

Praveen K Paladugu posted 1 patch 6 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/20231030192622.2254-1-prapal@linux.microsoft.com
po/POTFILES                       |   1 +
src/hypervisor/domain_interface.c | 370 ++++++++++++++++++++++++++++++
src/hypervisor/domain_interface.h |  41 ++++
src/hypervisor/meson.build        |   1 +
src/libvirt_private.syms          |   8 +
src/qemu/qemu_command.c           |   6 +-
src/qemu/qemu_hotplug.c           |   5 +-
src/qemu/qemu_interface.c         | 339 +--------------------------
src/qemu/qemu_interface.h         |  11 -
src/qemu/qemu_process.c           |   5 +-
10 files changed, 436 insertions(+), 351 deletions(-)
create mode 100644 src/hypervisor/domain_interface.c
create mode 100644 src/hypervisor/domain_interface.h
[libvirt PATCH v4] hypervisor: Move interface mgmt methods to hypervisor
Posted by Praveen K Paladugu 6 months ago
Move guest interface management methods from qemu to hypervisor. These
methods will be shared by networking support in ch driver.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>

---
v4:
* logging and formatting fixes

v3:
* Moved qemuInterfaceStopDevice/s methods into hypervisor, to keep all the
  related methods together.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
---
 po/POTFILES                       |   1 +
 src/hypervisor/domain_interface.c | 370 ++++++++++++++++++++++++++++++
 src/hypervisor/domain_interface.h |  41 ++++
 src/hypervisor/meson.build        |   1 +
 src/libvirt_private.syms          |   8 +
 src/qemu/qemu_command.c           |   6 +-
 src/qemu/qemu_hotplug.c           |   5 +-
 src/qemu/qemu_interface.c         | 339 +--------------------------
 src/qemu/qemu_interface.h         |  11 -
 src/qemu/qemu_process.c           |   5 +-
 10 files changed, 436 insertions(+), 351 deletions(-)
 create mode 100644 src/hypervisor/domain_interface.c
 create mode 100644 src/hypervisor/domain_interface.h

diff --git a/po/POTFILES b/po/POTFILES
index 3a51aea5cb..023c041f61 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -92,6 +92,7 @@ src/hyperv/hyperv_util.c
 src/hyperv/hyperv_wmi.c
 src/hypervisor/domain_cgroup.c
 src/hypervisor/domain_driver.c
+src/hypervisor/domain_interface.c
 src/hypervisor/virhostdev.c
 src/interface/interface_backend_netcf.c
 src/interface/interface_backend_udev.c
diff --git a/src/hypervisor/domain_interface.c b/src/hypervisor/domain_interface.c
new file mode 100644
index 0000000000..07a83d2034
--- /dev/null
+++ b/src/hypervisor/domain_interface.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ * Copyright IBM Corp. 2014
+ *
+ * domain_interface.c: methods to manage guest/domain interfaces
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "domain_audit.h"
+#include "domain_conf.h"
+#include "domain_interface.h"
+#include "domain_nwfilter.h"
+#include "network_conf.h"
+#include "viralloc.h"
+#include "virconftypes.h"
+#include "virebtables.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virmacaddr.h"
+#include "virnetdevbridge.h"
+#include "virnetdevtap.h"
+
+#define VIR_FROM_THIS VIR_FROM_DOMAIN
+
+VIR_LOG_INIT("domain.interface");
+
+bool
+virDomainInterfaceIsVnetCompatModel(const virDomainNetDef *net)
+{
+    return (virDomainNetIsVirtioModel(net) ||
+            net->model == VIR_DOMAIN_NET_MODEL_E1000E ||
+            net->model == VIR_DOMAIN_NET_MODEL_IGB ||
+            net->model == VIR_DOMAIN_NET_MODEL_VMXNET3);
+}
+
+/* virDomainInterfaceEthernetConnect:
+ * @def: the definition of the VM
+ * @net: a net definition in the VM
+ * @ebtables: ebtales context
+ * @macFilter: whether driver support mac Filtering
+ * @privileged: whether running as privileged user
+ * @tapfd: array of file descriptor return value for the new device
+ * @tapfdsize: number of file descriptors in @tapfd
+ *
+ * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET
+ * (i.e. if the connection is made with a tap device)
+ */
+int
+virDomainInterfaceEthernetConnect(virDomainDef *def,
+                                  virDomainNetDef *net,
+                                  ebtablesContext *ebtables,
+                                  bool macFilter,
+                                  bool privileged,
+                                  int *tapfd,
+                                  size_t tapfdSize)
+{
+    virMacAddr tapmac;
+    int ret = -1;
+    unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
+    bool template_ifname = false;
+    const char *tunpath = "/dev/net/tun";
+    const char *auditdev = tunpath;
+
+    if (net->backend.tap) {
+        tunpath = net->backend.tap;
+        if (!privileged) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("cannot use custom tap device in session mode"));
+            goto cleanup;
+        }
+    }
+
+    if (virDomainInterfaceIsVnetCompatModel(net))
+        tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
+
+    if (net->managed_tap == VIR_TRISTATE_BOOL_NO) {
+        if (!net->ifname) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("target dev must be supplied when managed='no'"));
+            goto cleanup;
+        }
+        if (virNetDevExists(net->ifname) != 1) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("target managed='no' but specified dev doesn't exist"));
+            goto cleanup;
+        }
+
+        tap_create_flags |= VIR_NETDEV_TAP_CREATE_ALLOW_EXISTING;
+
+        if (virNetDevMacVLanIsMacvtap(net->ifname)) {
+            auditdev = net->ifname;
+            if (virNetDevMacVLanTapOpen(net->ifname, tapfd, tapfdSize) < 0)
+                goto cleanup;
+            if (virNetDevMacVLanTapSetup(tapfd, tapfdSize,
+                               virDomainInterfaceIsVnetCompatModel(net)) < 0) {
+                goto cleanup;
+            }
+        } else {
+            if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
+                                   tap_create_flags) < 0)
+                goto cleanup;
+        }
+    } else {
+
+        if (!net->ifname)
+            template_ifname = true;
+
+        if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
+                               tap_create_flags) < 0) {
+            goto cleanup;
+        }
+
+        /* The tap device's MAC address cannot match the MAC address
+         * used by the guest. This results in "received packet on
+         * vnetX with own address as source address" error logs from
+         * the kernel.
+         */
+        virMacAddrSet(&tapmac, &net->mac);
+        if (tapmac.addr[0] == 0xFE)
+            tapmac.addr[0] = 0xFA;
+        else
+            tapmac.addr[0] = 0xFE;
+
+        if (virNetDevSetMAC(net->ifname, &tapmac) < 0)
+            goto cleanup;
+
+        if (virNetDevSetOnline(net->ifname, true) < 0)
+            goto cleanup;
+    }
+
+    if (net->script &&
+        virNetDevRunEthernetScript(net->ifname, net->script) < 0)
+        goto cleanup;
+
+    if (macFilter &&
+        ebtablesAddForwardAllowIn(ebtables,
+                                  net->ifname,
+                                  &net->mac) < 0)
+        goto cleanup;
+
+    if (net->filter &&
+        virDomainConfNWFilterInstantiate(def->name, def->uuid, net, false) < 0) {
+        goto cleanup;
+    }
+
+    virDomainAuditNetDevice(def, net, auditdev, true);
+
+    ret = 0;
+
+ cleanup:
+    if (ret < 0) {
+        size_t i;
+
+        virDomainAuditNetDevice(def, net, auditdev, false);
+        for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++)
+            VIR_FORCE_CLOSE(tapfd[i]);
+        if (template_ifname)
+            VIR_FREE(net->ifname);
+    }
+
+    return ret;
+}
+
+/**
+ * virDomainInterfaceStartDevice:
+ * @net: net device to start
+ *
+ * Based upon the type of device provided, perform the appropriate
+ * work to completely activate the device and make it reachable from
+ * the rest of the network.
+ */
+int
+virDomainInterfaceStartDevice(virDomainNetDef *net)
+{
+    virDomainNetType actualType = virDomainNetGetActualType(net);
+
+    switch (actualType) {
+    case VIR_DOMAIN_NET_TYPE_BRIDGE:
+    case VIR_DOMAIN_NET_TYPE_NETWORK:
+        if (virDomainNetGetActualBridgeMACTableManager(net)
+            == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
+            /* libvirt is managing the FDB of the bridge this device
+             * is attaching to, so we have turned off learning and
+             * unicast_flood on the device to prevent the kernel from
+             * adding any FDB entries for it. This means we need to
+             * add an fdb entry ourselves, using the MAC address from
+             * the interface config.
+             */
+            if (virNetDevBridgeFDBAdd(&net->mac, net->ifname,
+                                      VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
+                                      VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
+                return -1;
+        }
+        break;
+
+    case VIR_DOMAIN_NET_TYPE_DIRECT: {
+        const char *physdev = virDomainNetGetActualDirectDev(net);
+        bool isOnline = true;
+
+        /* set the physdev online if necessary. It may already be up,
+         * in which case we shouldn't re-up it just in case that causes
+         * some sort of "blip" in the physdev's status.
+         */
+        if (physdev && virNetDevGetOnline(physdev, &isOnline) < 0)
+            return -1;
+        if (!isOnline && virNetDevSetOnline(physdev, true) < 0)
+            return -1;
+
+        /* macvtap devices share their MAC address with the guest
+         * domain, and if they are set online prior to the domain CPUs
+         * being started, the host may send out traffic from this
+         * device that could confuse other entities on the network (in
+         * particular, if this new domain is the destination of a
+         * migration, and the source domain is still running, another
+         * host may mistakenly direct traffic for the guest to the
+         * destination domain rather than source domain). To prevent
+         * this, we create the macvtap device with IFF_UP false
+         * (i.e. "offline") then wait to bring it online until just as
+         * we are starting the domain CPUs.
+         */
+        if (virNetDevSetOnline(net->ifname, true) < 0)
+            return -1;
+        break;
+    }
+
+    case VIR_DOMAIN_NET_TYPE_ETHERNET:
+        if (virNetDevIPInfoAddToDev(net->ifname, &net->hostIP) < 0)
+            return -1;
+
+        break;
+
+    case VIR_DOMAIN_NET_TYPE_USER:
+    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
+    case VIR_DOMAIN_NET_TYPE_SERVER:
+    case VIR_DOMAIN_NET_TYPE_CLIENT:
+    case VIR_DOMAIN_NET_TYPE_MCAST:
+    case VIR_DOMAIN_NET_TYPE_UDP:
+    case VIR_DOMAIN_NET_TYPE_INTERNAL:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_VDPA:
+    case VIR_DOMAIN_NET_TYPE_NULL:
+    case VIR_DOMAIN_NET_TYPE_VDS:
+    case VIR_DOMAIN_NET_TYPE_LAST:
+        /* these types all require no action */
+        break;
+    }
+
+    return 0;
+}
+
+/**
+ * virDomainInterfaceStartDevices:
+ * @def: domain definition
+ *
+ * Set all ifaces associated with this domain to the online state.
+ */
+int
+virDomainInterfaceStartDevices(virDomainDef *def)
+{
+    size_t i;
+
+    for (i = 0; i < def->nnets; i++) {
+        if (virDomainInterfaceStartDevice(def->nets[i]) < 0)
+            return -1;
+    }
+    return 0;
+}
+
+/**
+ * virDomainInterfaceStopDevice:
+ * @net: net device to stop
+ *
+ * Based upon the type of device provided, perform the appropriate
+ * work to deactivate the device so that packets aren't forwarded to
+ * it from the rest of the network.
+ */
+int
+virDomainInterfaceStopDevice(virDomainNetDef *net)
+{
+    virDomainNetType actualType = virDomainNetGetActualType(net);
+
+    switch (actualType) {
+    case VIR_DOMAIN_NET_TYPE_BRIDGE:
+    case VIR_DOMAIN_NET_TYPE_NETWORK:
+        if (virDomainNetGetActualBridgeMACTableManager(net)
+            == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
+            /* remove the FDB entries that were added during
+             * virDomainInterfaceStartDevices()
+             */
+            if (virNetDevBridgeFDBDel(&net->mac, net->ifname,
+                                      VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
+                                      VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
+                return -1;
+        }
+        break;
+
+    case VIR_DOMAIN_NET_TYPE_DIRECT: {
+        const char *physdev = virDomainNetGetActualDirectDev(net);
+
+        /* macvtap interfaces need to be marked !IFF_UP (ie "down") to
+         * prevent any host-generated traffic sent from this interface
+         * from putting bad info into the arp caches of other machines
+         * on this network.
+         */
+        if (virNetDevSetOnline(net->ifname, false) < 0)
+            return -1;
+
+        /* also mark the physdev down for passthrough macvtap, as the
+         * physdev has the same MAC address as the macvtap device.
+         */
+        if (virDomainNetGetActualDirectMode(net) ==
+            VIR_NETDEV_MACVLAN_MODE_PASSTHRU &&
+            physdev && virNetDevSetOnline(physdev, false) < 0)
+            return -1;
+        break;
+    }
+
+    case VIR_DOMAIN_NET_TYPE_ETHERNET:
+    case VIR_DOMAIN_NET_TYPE_USER:
+    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
+    case VIR_DOMAIN_NET_TYPE_SERVER:
+    case VIR_DOMAIN_NET_TYPE_CLIENT:
+    case VIR_DOMAIN_NET_TYPE_MCAST:
+    case VIR_DOMAIN_NET_TYPE_UDP:
+    case VIR_DOMAIN_NET_TYPE_INTERNAL:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_VDPA:
+    case VIR_DOMAIN_NET_TYPE_NULL:
+    case VIR_DOMAIN_NET_TYPE_VDS:
+    case VIR_DOMAIN_NET_TYPE_LAST:
+        /* these types all require no action */
+        break;
+    }
+
+    return 0;
+}
+
+/**
+ * virDomainInterfaceStopDevices:
+ * @def: domain definition
+ *
+ * Make all interfaces associated with this domain inaccessible from
+ * the rest of the network.
+ */
+int
+virDomainInterfaceStopDevices(virDomainDef *def)
+{
+    size_t i;
+
+    for (i = 0; i < def->nnets; i++) {
+        if (virDomainInterfaceStopDevice(def->nets[i]) < 0)
+            return -1;
+    }
+    return 0;
+}
diff --git a/src/hypervisor/domain_interface.h b/src/hypervisor/domain_interface.h
new file mode 100644
index 0000000000..68bf2ae51d
--- /dev/null
+++ b/src/hypervisor/domain_interface.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ * Copyright IBM Corp. 2014
+ *
+ * domain_interface.h: methods to manage guest/domain interfaces
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "virebtables.h"
+
+int
+virDomainInterfaceEthernetConnect(virDomainDef *def,
+                           virDomainNetDef *net,
+                           ebtablesContext *ebtables,
+                           bool macFilter,
+                           bool privileged,
+                           int *tapfd,
+                           size_t tapfdSize);
+
+bool
+virDomainInterfaceIsVnetCompatModel(const virDomainNetDef *net);
+
+int virDomainInterfaceStartDevice(virDomainNetDef *net);
+int virDomainInterfaceStartDevices(virDomainDef *def);
+int virDomainInterfaceStopDevice(virDomainNetDef *net);
+int virDomainInterfaceStopDevices(virDomainDef *def);
diff --git a/src/hypervisor/meson.build b/src/hypervisor/meson.build
index f35565b16b..819a9a82a2 100644
--- a/src/hypervisor/meson.build
+++ b/src/hypervisor/meson.build
@@ -1,6 +1,7 @@
 hypervisor_sources = [
   'domain_cgroup.c',
   'domain_driver.c',
+  'domain_interface.c',
   'virclosecallbacks.c',
   'virhostdev.c',
 ]
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 553b01b8c0..b7f329be43 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1630,6 +1630,14 @@ virDomainDriverNodeDeviceReset;
 virDomainDriverParseBlkioDeviceStr;
 virDomainDriverSetupPersistentDefBlkioParams;
 
+# hypervisor/domain_interface.h
+virDomainInterfaceEthernetConnect;
+virDomainInterfaceIsVnetCompatModel;
+virDomainInterfaceStartDevice;
+virDomainInterfaceStartDevices;
+virDomainInterfaceStopDevice;
+virDomainInterfaceStopDevices;
+
 
 # hypervisor/virclosecallbacks.h
 virCloseCallbacksDomainAdd;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index fd0f12f304..036f6ba2e5 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -43,6 +43,7 @@
 #include "domain_nwfilter.h"
 #include "domain_addr.h"
 #include "domain_conf.h"
+#include "domain_interface.h"
 #include "netdev_bandwidth_conf.h"
 #include "virnetdevopenvswitch.h"
 #include "device_conf.h"
@@ -8505,7 +8506,10 @@ qemuBuildInterfaceConnect(virDomainObj *vm,
         break;
 
     case VIR_DOMAIN_NET_TYPE_ETHERNET:
-        if (qemuInterfaceEthernetConnect(vm->def, priv->driver, net,
+        if (virDomainInterfaceEthernetConnect(vm->def, net,
+                                        priv->driver->ebtables,
+                                        priv->driver->config->macFilter,
+                                        priv->driver->privileged,
                                          tapfd, tapfdSize) < 0)
             return -1;
         vhostfd = true;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index fec7c4be4e..63a130c201 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -39,6 +39,7 @@
 #include "qemu_virtiofs.h"
 #include "domain_audit.h"
 #include "domain_cgroup.h"
+#include "domain_interface.h"
 #include "netdev_bandwidth_conf.h"
 #include "domain_nwfilter.h"
 #include "virlog.h"
@@ -1272,7 +1273,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
     }
 
     /* Set device online immediately */
-    if (qemuInterfaceStartDevice(net) < 0)
+    if (virDomainInterfaceStartDevice(net) < 0)
         goto cleanup;
 
     qemuDomainInterfaceSetDefaultQDisc(driver, net);
@@ -4772,7 +4773,7 @@ qemuDomainRemoveNetDevice(virQEMUDriver *driver,
      * affect the parent device (e.g. macvtap passthrough mode sets
      * the parent device offline)
      */
-    ignore_value(qemuInterfaceStopDevice(net));
+    ignore_value(virDomainInterfaceStopDevice(net));
 
     qemuDomainObjEnterMonitor(vm);
     if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) {
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
index 8856bb95a8..c2007c7043 100644
--- a/src/qemu/qemu_interface.c
+++ b/src/qemu/qemu_interface.c
@@ -24,6 +24,7 @@
 #include "network_conf.h"
 #include "domain_audit.h"
 #include "domain_nwfilter.h"
+#include "domain_interface.h"
 #include "qemu_interface.h"
 #include "viralloc.h"
 #include "virlog.h"
@@ -41,211 +42,6 @@
 
 VIR_LOG_INIT("qemu.qemu_interface");
 
-/**
- * qemuInterfaceStartDevice:
- * @net: net device to start
- *
- * Based upon the type of device provided, perform the appropriate
- * work to completely activate the device and make it reachable from
- * the rest of the network.
- */
-int
-qemuInterfaceStartDevice(virDomainNetDef *net)
-{
-    virDomainNetType actualType = virDomainNetGetActualType(net);
-
-    switch (actualType) {
-    case VIR_DOMAIN_NET_TYPE_BRIDGE:
-    case VIR_DOMAIN_NET_TYPE_NETWORK:
-        if (virDomainNetGetActualBridgeMACTableManager(net)
-            == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
-            /* libvirt is managing the FDB of the bridge this device
-             * is attaching to, so we have turned off learning and
-             * unicast_flood on the device to prevent the kernel from
-             * adding any FDB entries for it. This means we need to
-             * add an fdb entry ourselves, using the MAC address from
-             * the interface config.
-             */
-            if (virNetDevBridgeFDBAdd(&net->mac, net->ifname,
-                                      VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
-                                      VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
-                return -1;
-        }
-        break;
-
-    case VIR_DOMAIN_NET_TYPE_DIRECT: {
-        const char *physdev = virDomainNetGetActualDirectDev(net);
-        bool isOnline = true;
-
-        /* set the physdev online if necessary. It may already be up,
-         * in which case we shouldn't re-up it just in case that causes
-         * some sort of "blip" in the physdev's status.
-         */
-        if (physdev && virNetDevGetOnline(physdev, &isOnline) < 0)
-            return -1;
-        if (!isOnline && virNetDevSetOnline(physdev, true) < 0)
-            return -1;
-
-        /* macvtap devices share their MAC address with the guest
-         * domain, and if they are set online prior to the domain CPUs
-         * being started, the host may send out traffic from this
-         * device that could confuse other entities on the network (in
-         * particular, if this new domain is the destination of a
-         * migration, and the source domain is still running, another
-         * host may mistakenly direct traffic for the guest to the
-         * destination domain rather than source domain). To prevent
-         * this, we create the macvtap device with IFF_UP false
-         * (i.e. "offline") then wait to bring it online until just as
-         * we are starting the domain CPUs.
-         */
-        if (virNetDevSetOnline(net->ifname, true) < 0)
-            return -1;
-        break;
-    }
-
-    case VIR_DOMAIN_NET_TYPE_ETHERNET:
-        if (virNetDevIPInfoAddToDev(net->ifname, &net->hostIP) < 0)
-            return -1;
-
-        break;
-
-    case VIR_DOMAIN_NET_TYPE_USER:
-    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
-    case VIR_DOMAIN_NET_TYPE_SERVER:
-    case VIR_DOMAIN_NET_TYPE_CLIENT:
-    case VIR_DOMAIN_NET_TYPE_MCAST:
-    case VIR_DOMAIN_NET_TYPE_UDP:
-    case VIR_DOMAIN_NET_TYPE_INTERNAL:
-    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
-    case VIR_DOMAIN_NET_TYPE_VDPA:
-    case VIR_DOMAIN_NET_TYPE_NULL:
-    case VIR_DOMAIN_NET_TYPE_VDS:
-    case VIR_DOMAIN_NET_TYPE_LAST:
-        /* these types all require no action */
-        break;
-    }
-
-    return 0;
-}
-
-/**
- * qemuInterfaceStartDevices:
- * @def: domain definition
- *
- * Set all ifaces associated with this domain to the online state.
- */
-int
-qemuInterfaceStartDevices(virDomainDef *def)
-{
-    size_t i;
-
-    for (i = 0; i < def->nnets; i++) {
-        if (qemuInterfaceStartDevice(def->nets[i]) < 0)
-            return -1;
-    }
-    return 0;
-}
-
-
-/**
- * qemuInterfaceStopDevice:
- * @net: net device to stop
- *
- * Based upon the type of device provided, perform the appropriate
- * work to deactivate the device so that packets aren't forwarded to
- * it from the rest of the network.
- */
-int
-qemuInterfaceStopDevice(virDomainNetDef *net)
-{
-    virDomainNetType actualType = virDomainNetGetActualType(net);
-
-    switch (actualType) {
-    case VIR_DOMAIN_NET_TYPE_BRIDGE:
-    case VIR_DOMAIN_NET_TYPE_NETWORK:
-        if (virDomainNetGetActualBridgeMACTableManager(net)
-            == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
-            /* remove the FDB entries that were added during
-             * qemuInterfaceStartDevices()
-             */
-            if (virNetDevBridgeFDBDel(&net->mac, net->ifname,
-                                      VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
-                                      VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
-                return -1;
-        }
-        break;
-
-    case VIR_DOMAIN_NET_TYPE_DIRECT: {
-        const char *physdev = virDomainNetGetActualDirectDev(net);
-
-        /* macvtap interfaces need to be marked !IFF_UP (ie "down") to
-         * prevent any host-generated traffic sent from this interface
-         * from putting bad info into the arp caches of other machines
-         * on this network.
-         */
-        if (virNetDevSetOnline(net->ifname, false) < 0)
-            return -1;
-
-        /* also mark the physdev down for passthrough macvtap, as the
-         * physdev has the same MAC address as the macvtap device.
-         */
-        if (virDomainNetGetActualDirectMode(net) ==
-            VIR_NETDEV_MACVLAN_MODE_PASSTHRU &&
-            physdev && virNetDevSetOnline(physdev, false) < 0)
-            return -1;
-        break;
-    }
-
-    case VIR_DOMAIN_NET_TYPE_ETHERNET:
-    case VIR_DOMAIN_NET_TYPE_USER:
-    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
-    case VIR_DOMAIN_NET_TYPE_SERVER:
-    case VIR_DOMAIN_NET_TYPE_CLIENT:
-    case VIR_DOMAIN_NET_TYPE_MCAST:
-    case VIR_DOMAIN_NET_TYPE_UDP:
-    case VIR_DOMAIN_NET_TYPE_INTERNAL:
-    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
-    case VIR_DOMAIN_NET_TYPE_VDPA:
-    case VIR_DOMAIN_NET_TYPE_NULL:
-    case VIR_DOMAIN_NET_TYPE_VDS:
-    case VIR_DOMAIN_NET_TYPE_LAST:
-        /* these types all require no action */
-        break;
-    }
-
-    return 0;
-}
-
-/**
- * qemuInterfaceStopDevices:
- * @def: domain definition
- *
- * Make all interfaces associated with this domain inaccessible from
- * the rest of the network.
- */
-int
-qemuInterfaceStopDevices(virDomainDef *def)
-{
-    size_t i;
-
-    for (i = 0; i < def->nnets; i++) {
-        if (qemuInterfaceStopDevice(def->nets[i]) < 0)
-            return -1;
-    }
-    return 0;
-}
-
-
-static bool
-qemuInterfaceIsVnetCompatModel(const virDomainNetDef *net)
-{
-    return (virDomainNetIsVirtioModel(net) ||
-            net->model == VIR_DOMAIN_NET_MODEL_E1000E ||
-            net->model == VIR_DOMAIN_NET_MODEL_IGB ||
-            net->model == VIR_DOMAIN_NET_MODEL_VMXNET3);
-}
-
-
 /**
  * qemuInterfaceDirectConnect:
  * @def: the definition of the VM (needed by 802.1Qbh and audit)
@@ -271,7 +67,7 @@ qemuInterfaceDirectConnect(virDomainDef *def,
     unsigned int macvlan_create_flags = VIR_NETDEV_MACVLAN_CREATE_WITH_TAP;
     qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
 
-    if (qemuInterfaceIsVnetCompatModel(net))
+    if (virDomainInterfaceIsVnetCompatModel(net))
         macvlan_create_flags |= VIR_NETDEV_MACVLAN_VNET_HDR;
 
     if (virNetDevMacVLanCreateWithVPortProfile(net->ifname,
@@ -409,133 +205,6 @@ qemuCreateInBridgePortWithHelper(virQEMUDriverConfig *cfg,
     return *tapfd < 0 ? -1 : 0;
 }
 
-
-/* qemuInterfaceEthernetConnect:
- * @def: the definition of the VM
- * @driver: qemu driver data
- * @net: pointer to the VM's interface description
- * @tapfd: array of file descriptor return value for the new device
- * @tapfdsize: number of file descriptors in @tapfd
- *
- * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET
- * (i.e. if the connection is made with a tap device)
- */
-int
-qemuInterfaceEthernetConnect(virDomainDef *def,
-                           virQEMUDriver *driver,
-                           virDomainNetDef *net,
-                           int *tapfd,
-                           size_t tapfdSize)
-{
-    virMacAddr tapmac;
-    int ret = -1;
-    unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
-    bool template_ifname = false;
-    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
-    const char *tunpath = "/dev/net/tun";
-    const char *auditdev = tunpath;
-
-    if (net->backend.tap) {
-        tunpath = net->backend.tap;
-        if (!driver->privileged) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("cannot use custom tap device in session mode"));
-            goto cleanup;
-        }
-    }
-
-    if (qemuInterfaceIsVnetCompatModel(net))
-        tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
-
-    if (net->managed_tap == VIR_TRISTATE_BOOL_NO) {
-        if (!net->ifname) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("target dev must be supplied when managed='no'"));
-            goto cleanup;
-        }
-        if (virNetDevExists(net->ifname) != 1) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("target managed='no' but specified dev doesn't exist"));
-            goto cleanup;
-        }
-
-        tap_create_flags |= VIR_NETDEV_TAP_CREATE_ALLOW_EXISTING;
-
-        if (virNetDevMacVLanIsMacvtap(net->ifname)) {
-            auditdev = net->ifname;
-            if (virNetDevMacVLanTapOpen(net->ifname, tapfd, tapfdSize) < 0)
-                goto cleanup;
-            if (virNetDevMacVLanTapSetup(tapfd, tapfdSize,
-                                         qemuInterfaceIsVnetCompatModel(net)) < 0) {
-                goto cleanup;
-            }
-        } else {
-            if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
-                                   tap_create_flags) < 0)
-                goto cleanup;
-        }
-    } else {
-
-        if (!net->ifname)
-            template_ifname = true;
-
-        if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
-                               tap_create_flags) < 0) {
-            goto cleanup;
-        }
-
-        /* The tap device's MAC address cannot match the MAC address
-         * used by the guest. This results in "received packet on
-         * vnetX with own address as source address" error logs from
-         * the kernel.
-         */
-        virMacAddrSet(&tapmac, &net->mac);
-        if (tapmac.addr[0] == 0xFE)
-            tapmac.addr[0] = 0xFA;
-        else
-            tapmac.addr[0] = 0xFE;
-
-        if (virNetDevSetMAC(net->ifname, &tapmac) < 0)
-            goto cleanup;
-
-        if (virNetDevSetOnline(net->ifname, true) < 0)
-            goto cleanup;
-    }
-
-    if (net->script &&
-        virNetDevRunEthernetScript(net->ifname, net->script) < 0)
-        goto cleanup;
-
-    if (cfg->macFilter &&
-        ebtablesAddForwardAllowIn(driver->ebtables,
-                                  net->ifname,
-                                  &net->mac) < 0)
-        goto cleanup;
-
-    if (net->filter &&
-        virDomainConfNWFilterInstantiate(def->name, def->uuid, net, false) < 0) {
-        goto cleanup;
-    }
-
-    virDomainAuditNetDevice(def, net, auditdev, true);
-
-    ret = 0;
-
- cleanup:
-    if (ret < 0) {
-        size_t i;
-
-        virDomainAuditNetDevice(def, net, auditdev, false);
-        for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++)
-            VIR_FORCE_CLOSE(tapfd[i]);
-        if (template_ifname)
-            VIR_FREE(net->ifname);
-    }
-
-    return ret;
-}
-
-
 /* qemuInterfaceBridgeConnect:
  * @def: the definition of the VM
  * @driver: qemu driver data
@@ -578,7 +247,7 @@ qemuInterfaceBridgeConnect(virDomainDef *def,
     if (!net->ifname)
         template_ifname = true;
 
-    if (qemuInterfaceIsVnetCompatModel(net))
+    if (virDomainInterfaceIsVnetCompatModel(net))
         tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
 
     if (driver->privileged) {
@@ -598,7 +267,7 @@ qemuInterfaceBridgeConnect(virDomainDef *def,
              * is attaching to, so we need to turn off learning and
              * unicast_flood on the device to prevent the kernel from
              * adding any FDB entries for it. We will add an fdb
-             * entry ourselves (during qemuInterfaceStartDevices(),
+             * entry ourselves (during virDomainInterfaceStartDevices(),
              * using the MAC address from the interface config.
              */
             if (virNetDevBridgePortSetLearning(brname, net->ifname, false) < 0)
diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h
index 6eed3e6bd7..47d7ec03fd 100644
--- a/src/qemu/qemu_interface.h
+++ b/src/qemu/qemu_interface.h
@@ -25,11 +25,6 @@
 #include "qemu_domain.h"
 #include "qemu_slirp.h"
 
-int qemuInterfaceStartDevice(virDomainNetDef *net);
-int qemuInterfaceStartDevices(virDomainDef *def);
-int qemuInterfaceStopDevice(virDomainNetDef *net);
-int qemuInterfaceStopDevices(virDomainDef *def);
-
 int qemuInterfaceDirectConnect(virDomainDef *def,
                                virQEMUDriver *driver,
                                virDomainNetDef *net,
@@ -37,12 +32,6 @@ int qemuInterfaceDirectConnect(virDomainDef *def,
                                size_t tapfdSize,
                                virNetDevVPortProfileOp vmop);
 
-int qemuInterfaceEthernetConnect(virDomainDef *def,
-                                 virQEMUDriver *driver,
-                                 virDomainNetDef *net,
-                                 int *tapfd,
-                                 size_t tapfdSize);
-
 int qemuInterfaceBridgeConnect(virDomainDef *def,
                                virQEMUDriver *driver,
                                virDomainNetDef *net,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1ef032dbd2..1626f368bd 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -74,6 +74,7 @@
 #include "virhostcpu.h"
 #include "domain_audit.h"
 #include "domain_cgroup.h"
+#include "domain_interface.h"
 #include "domain_nwfilter.h"
 #include "domain_postparse.h"
 #include "domain_validate.h"
@@ -3121,7 +3122,7 @@ qemuProcessStartCPUs(virQEMUDriver *driver, virDomainObj *vm,
     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
 
     /* Bring up netdevs before starting CPUs */
-    if (qemuInterfaceStartDevices(vm->def) < 0)
+    if (virDomainInterfaceStartDevices(vm->def) < 0)
        return -1;
 
     VIR_DEBUG("Using lock state '%s'", NULLSTR(priv->lockState));
@@ -3184,7 +3185,7 @@ int qemuProcessStopCPUs(virQEMUDriver *driver,
         goto cleanup;
 
     /* de-activate netdevs after stopping CPUs */
-    ignore_value(qemuInterfaceStopDevices(vm->def));
+    ignore_value(virDomainInterfaceStopDevices(vm->def));
 
     if (vm->job->current)
         ignore_value(virTimeMillisNow(&vm->job->current->stopped));
-- 
2.41.0