diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 1757a6aaad..e9bc0f375d 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1235,6 +1235,31 @@ qemuDomainTPMPrivateFormat(const virDomainTPMDef *tpm, } +static int +qemuDomainNetworkPrivateParse(xmlXPathContextPtr ctxt, + virDomainNetDef *net) +{ + qemuDomainNetworkPrivate *priv = QEMU_DOMAIN_NETWORK_PRIVATE(net); + + priv->created = virXPathBoolean("string(./created[@value='yes'])", ctxt); + + return 0; +} + + +static int +qemuDomainNetworkPrivateFormat(const virDomainNetDef *net, + virBuffer *buf) +{ + qemuDomainNetworkPrivate *priv = QEMU_DOMAIN_NETWORK_PRIVATE(net); + + if (priv->created) + virBufferAddLit(buf, "\n"); + + return 0; +} + + /* qemuDomainSecretInfoSetup: * @priv: pointer to domain private object * @alias: alias of the secret @@ -3328,6 +3353,8 @@ virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks = { .vsockNew = qemuDomainVsockPrivateNew, .graphicsNew = qemuDomainGraphicsPrivateNew, .networkNew = qemuDomainNetworkPrivateNew, + .networkParse = qemuDomainNetworkPrivateParse, + .networkFormat = qemuDomainNetworkPrivateFormat, .videoNew = qemuDomainVideoPrivateNew, .tpmNew = qemuDomainTPMPrivateNew, .tpmParse = qemuDomainTPMPrivateParse, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index eca5404cdc..1053d1d4cb 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -412,6 +412,11 @@ typedef struct _qemuDomainNetworkPrivate qemuDomainNetworkPrivate; struct _qemuDomainNetworkPrivate { virObject parent; + /* True if the device was created by us. Otherwise we should + * avoid removing it. Currently only used for + * VIR_DOMAIN_NET_TYPE_DIRECT. */ + bool created; + qemuSlirp *slirp; /* file descriptor transfer helpers */ diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index ed2c209167..076640cbde 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -268,6 +268,7 @@ qemuInterfaceDirectConnect(virDomainDef *def, char *res_ifname = NULL; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); unsigned int macvlan_create_flags = VIR_NETDEV_MACVLAN_CREATE_WITH_TAP; + qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net); if (qemuInterfaceIsVnetCompatModel(net)) macvlan_create_flags |= VIR_NETDEV_MACVLAN_VNET_HDR; @@ -285,6 +286,8 @@ qemuInterfaceDirectConnect(virDomainDef *def, macvlan_create_flags) < 0) goto cleanup; + netpriv->created = true; + virDomainAuditNetDevice(def, net, res_ifname, true); VIR_FREE(net->ifname); net->ifname = res_ifname; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 9a31a11acc..ff219e0030 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -8443,11 +8443,13 @@ void qemuProcessStop(virQEMUDriver *driver, vport = virDomainNetGetActualVirtPortProfile(net); switch (virDomainNetGetActualType(net)) { case VIR_DOMAIN_NET_TYPE_DIRECT: - virNetDevMacVLanDeleteWithVPortProfile(net->ifname, &net->mac, - virDomainNetGetActualDirectDev(net), - virDomainNetGetActualDirectMode(net), - virDomainNetGetActualVirtPortProfile(net), - cfg->stateDir); + if (QEMU_DOMAIN_NETWORK_PRIVATE(net)->created) { + virNetDevMacVLanDeleteWithVPortProfile(net->ifname, &net->mac, + virDomainNetGetActualDirectDev(net), + virDomainNetGetActualDirectMode(net), + virDomainNetGetActualVirtPortProfile(net), + cfg->stateDir); + } break; case VIR_DOMAIN_NET_TYPE_ETHERNET: if (net->managed_tap != VIR_TRISTATE_BOOL_NO && net->ifname) {