From nobody Sun Nov 24 09:22:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1722551186855179.60674591823954; Thu, 1 Aug 2024 15:26:26 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id B53B314B6; Thu, 1 Aug 2024 18:26:25 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id B742C14A3; Thu, 1 Aug 2024 18:25:23 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id E91F913D2; Thu, 1 Aug 2024 18:25:18 -0400 (EDT) Received: from mail-ot1-f46.google.com (mail-ot1-f46.google.com [209.85.210.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id BB26913BA for ; Thu, 1 Aug 2024 18:25:17 -0400 (EDT) Received: by mail-ot1-f46.google.com with SMTP id 46e09a7af769-709345dd01dso1177831a34.0 for ; Thu, 01 Aug 2024 15:25:17 -0700 (PDT) Received: from home.. ([2603:8081:c640:1::1002]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-70a3a768e12sm178646a34.65.2024.08.01.15.25.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Aug 2024 15:25:15 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1722551117; x=1723155917; darn=lists.libvirt.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NbGZqxbskREQjbteduS2viNHq9OKslEL9oA7uE6Yvqg=; b=gxlb7vKLwmPx/XuMbMSmscspFBW/shDN2HKgHQJx/6kzba6Sl/BIJxku6R6veuNTBl H2p9IN4XgHxyqPtBA2o+zX1lsQmHBGYgtIe43lvlvOSZEdez28jTki+9n/Geeh20wf4c 2tBa5SQK4/O4s6cz9uuPuCnKSUEBYctaVDveh3yn56fLPLeM8WymTpvRuXpKxdZ5Boov Yn0TEKNVbsu7lWHknLAX4qQJmsbrW0ANvE6nVb6EuQ5SOrW9vu14MD8hasz4u84f3IFk KD5+n4pvY7yQBS/XMTpwE/NJ0NHo234dW0TdtTGomT0WOtGEEJxL/0AlVWFB3f5FJk67 5DYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722551117; x=1723155917; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NbGZqxbskREQjbteduS2viNHq9OKslEL9oA7uE6Yvqg=; b=dAglhzOcGsy2vagu94n8lJrXIAebfDy8OGJEoXBSwoksPR97uu+PGcnNMWQ85uzsT/ +npemuaIYcZIjt39vSGtTlBwLBsxKaSEFBvN6yDfDjlQoaiEunHyrIYBqAgJ5f8lMx05 xSlfJebg0ggqKWdf/lN/0EMNbp8KssiGsRfZ7Yci6artpyrbcKGCMnbh97STtF4v8AaE CeavluLqkyJkwXlhoU4EfpDyHEJwPWY6E0d6ZjWWj0xdbWmIjRH6CSMYsNU2j6mtHTpP ztFbCOZ8AjiZMepoWoI3YiuoH0Pj7046xHJA0MH/6vVKJ1lIOCKwPvP1niS/8jJNloM/ btTw== X-Gm-Message-State: AOJu0Yzrj+LwmMihZrK7DLOTKdBTRdGr5fyQmXh78TTEockVlTFXnkGY caR6flF4ys+TQBBZUosVONiRpCu4pa3RJ4jqD/7zSBtqYdy1TozBGb9ah9yJ X-Google-Smtp-Source: AGHT+IECw+Y/0n+NU0EJNO2bhgQhoykT6rXJK4L5osq5a0JJHa+do3SqdpVHZgJQsyy5wKhVkmQxhw== X-Received: by 2002:a05:6830:2aa1:b0:703:606f:3d20 with SMTP id 46e09a7af769-709de2f7c91mr808260a34.10.1722551116591; Thu, 01 Aug 2024 15:25:16 -0700 (PDT) From: Praveen K Paladugu X-Google-Original-From: Praveen K Paladugu To: devel@lists.libvirt.org Subject: [PATCH 1/2] hypervisor: Move domain interface mgmt methods Date: Thu, 1 Aug 2024 17:25:13 -0500 Message-ID: <20240801222514.16742-2-prapal@linux.microsoft.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240801222514.16742-1-prapal@linux.microsoft.com> References: <20240801222514.16742-1-prapal@linux.microsoft.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: XV44JCNYRSF6RPA5YK7LOYQCKXIDJ2KK X-Message-ID-Hash: XV44JCNYRSF6RPA5YK7LOYQCKXIDJ2KK X-MailFrom: praveenkpaladugu@gmail.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header CC: liuwe@microsoft.com X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1722551188460116600 Content-Type: text/plain; charset="utf-8" From: Praveen K Paladugu From: Praveen K Paladugu Move methods to connect domain interfaces to host bridges to hypervisor. This is to allow reuse between qemu and ch drivers. Signed-off-by: Praveen K Paladugu Signed-off-by: Praveen K Paladugu --- src/hypervisor/domain_interface.c | 228 ++++++++++++++++++++++++++++++ src/hypervisor/domain_interface.h | 10 ++ src/libvirt_private.syms | 1 + src/qemu/qemu_command.c | 9 +- src/qemu/qemu_interface.c | 219 +--------------------------- 5 files changed, 247 insertions(+), 220 deletions(-) diff --git a/src/hypervisor/domain_interface.c b/src/hypervisor/domain_inte= rface.c index 756abb08e9..0c19ff859a 100644 --- a/src/hypervisor/domain_interface.c +++ b/src/hypervisor/domain_interface.c @@ -39,6 +39,7 @@ #include "virnetdevmidonet.h" #include "virnetdevopenvswitch.h" #include "virnetdevtap.h" +#include "vircommand.h" =20 =20 #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -514,3 +515,230 @@ virDomainClearNetBandwidth(virDomainDef *def) virDomainInterfaceClearQoS(def, def->nets[i]); } } + +/** + * virDomainCreateInBridgePortWithHelper: + * @bridgeHelperName: name of the bridge helper program + * @brname: the bridge name + * @ifname: the returned interface name + * @tapfd: file descriptor return value for the new tap device + * @flags: OR of virNetDevTapCreateFlags: + + * VIR_NETDEV_TAP_CREATE_VNET_HDR + * - Enable IFF_VNET_HDR on the tap device + * + * This function creates a new tap device on a bridge using an external + * helper. The final name for the bridge will be stored in @ifname. + * + * Returns 0 in case of success or -1 on failure + */ +static int +virDomainCreateInBridgePortWithHelper(const char *bridgeHelperName, + const char *brname, + char **ifname, + int *tapfd, + unsigned int flags) +{ + const char *const bridgeHelperDirs[] =3D { + "/usr/libexec", + "/usr/lib/qemu", + "/usr/lib", + NULL, + }; + g_autoptr(virCommand) cmd =3D NULL; + g_autofree char *bridgeHelperPath =3D NULL; + char *errbuf =3D NULL, *cmdstr =3D NULL; + int pair[2] =3D { -1, -1 }; + + if (!bridgeHelperName) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge hel= per name")); + return -1; + } + + if ((flags & ~VIR_NETDEV_TAP_CREATE_VNET_HDR) !=3D VIR_NETDEV_TAP_CREA= TE_IFUP) + return -1; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) { + virReportSystemError(errno, "%s", _("failed to create socket")); + return -1; + } + + bridgeHelperPath =3D virFindFileInPathFull(bridgeHelperName, bridgeHel= perDirs); + + if (!bridgeHelperPath) { + virReportSystemError(errno, _("'%1$s' is not a suitable bridge hel= per"), + bridgeHelperName); + return -1; + } + + VIR_DEBUG("Using qemu-bridge-helper: %s", bridgeHelperPath); + cmd =3D virCommandNew(bridgeHelperPath); + if (flags & VIR_NETDEV_TAP_CREATE_VNET_HDR) + virCommandAddArgFormat(cmd, "--use-vnet"); + virCommandAddArgFormat(cmd, "--br=3D%s", brname); + virCommandAddArgFormat(cmd, "--fd=3D%d", pair[1]); + virCommandSetErrorBuffer(cmd, &errbuf); + virCommandDoAsyncIO(cmd); + virCommandPassFD(cmd, pair[1], + VIR_COMMAND_PASS_FD_CLOSE_PARENT); + virCommandClearCaps(cmd); +#ifdef CAP_NET_ADMIN + virCommandAllowCap(cmd, CAP_NET_ADMIN); +#endif + if (virCommandRunAsync(cmd, NULL) < 0) { + *tapfd =3D -1; + goto cleanup; + } + + do { + *tapfd =3D virSocketRecvFD(pair[0], 0); + } while (*tapfd < 0 && errno =3D=3D EINTR); + + if (*tapfd < 0) { + char *errstr =3D NULL; + + if (!(cmdstr =3D virCommandToString(cmd, false))) + goto cleanup; + virCommandAbort(cmd); + + if (errbuf && *errbuf) + errstr =3D g_strdup_printf("stderr=3D%s", errbuf); + + virReportSystemError(errno, + _("%1$s: failed to communicate with bridge he= lper: %2$s"), + cmdstr, + NULLSTR_EMPTY(errstr)); + VIR_FREE(errstr); + goto cleanup; + } + + if (virNetDevTapGetName(*tapfd, ifname) < 0 || + virCommandWait(cmd, NULL) < 0) { + VIR_FORCE_CLOSE(*tapfd); + *tapfd =3D -1; + } + + cleanup: + VIR_FREE(cmdstr); + VIR_FREE(errbuf); + VIR_FORCE_CLOSE(pair[0]); + return *tapfd < 0 ? -1 : 0; +} + + +/* virDomainInterfaceBridgeConnect: + * @def: the definition of the VM + * @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 + * @privileged: whether running as privileged user + * @ebtables: ebtales context + * @macFilter: whether driver support mac Filtering + * @bridgeHelperName:name of the bridge helper program to run in non-privi= leged mode + * + * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_NETWORK or + * VIR_DOMAIN_NET_TYPE_BRIDGE (i.e. if the connection is made with a tap + * device connecting to a bridge device) + */ +int +virDomainInterfaceBridgeConnect(virDomainDef *def, + virDomainNetDef *net, + int *tapfd, + size_t tapfdSize, + bool privileged, + ebtablesContext *ebtables, + bool macFilter, + const char *bridgeHelperName) +{ + const char *brname; + int ret =3D -1; + unsigned int tap_create_flags =3D VIR_NETDEV_TAP_CREATE_IFUP; + bool template_ifname =3D false; + const char *tunpath =3D "/dev/net/tun"; + + if (net->backend.tap) { + tunpath =3D net->backend.tap; + if (!privileged) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("cannot use custom tap device in session mode= ")); + goto cleanup; + } + } + + if (!(brname =3D virDomainNetGetActualBridgeName(net))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge nam= e")); + goto cleanup; + } + + if (!net->ifname) + template_ifname =3D true; + + if (virDomainInterfaceIsVnetCompatModel(net)) + tap_create_flags |=3D VIR_NETDEV_TAP_CREATE_VNET_HDR; + + if (privileged) { + if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, + def->uuid, tunpath, tapfd, tapf= dSize, + virDomainNetGetActualVirtPortPr= ofile(net), + virDomainNetGetActualVlan(net), + virDomainNetGetActualPortOption= sIsolated(net), + net->coalesce, 0, NULL, + tap_create_flags) < 0) { + virDomainAuditNetDevice(def, net, tunpath, false); + goto cleanup; + } + if (virDomainNetGetActualBridgeMACTableManager(net) + =3D=3D VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) { + /* libvirt is managing the FDB of the bridge this device + * 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 virDomainInterfaceStartDevices(), + * using the MAC address from the interface config. + */ + if (virNetDevBridgePortSetLearning(brname, net->ifname, false)= < 0) + goto cleanup; + if (virNetDevBridgePortSetUnicastFlood(brname, net->ifname, fa= lse) < 0) + goto cleanup; + } + } else { + if (virDomainCreateInBridgePortWithHelper(bridgeHelperName, brname, + &net->ifname, + tapfd, + tap_create_flags) < 0) { + virDomainAuditNetDevice(def, net, tunpath, false); + goto cleanup; + } + /* virDomainCreateInBridgePortWithHelper can only create a single = FD */ + if (tapfdSize > 1) { + VIR_WARN("Ignoring multiqueue network request"); + tapfdSize =3D 1; + } + } + + virDomainAuditNetDevice(def, net, tunpath, true); + + if (macFilter && + ebtablesAddForwardAllowIn(ebtables, + net->ifname, + &net->mac) < 0) + goto cleanup; + + if (net->filter && + virDomainConfNWFilterInstantiate(def->name, def->uuid, net, false)= < 0) { + goto cleanup; + } + + ret =3D 0; + + cleanup: + if (ret < 0) { + size_t i; + for (i =3D 0; i < tapfdSize && tapfd[i] >=3D 0; i++) + VIR_FORCE_CLOSE(tapfd[i]); + if (template_ifname) + VIR_FREE(net->ifname); + } + + return ret; +} diff --git a/src/hypervisor/domain_interface.h b/src/hypervisor/domain_inte= rface.h index 572b4dd8c5..6d06fe2499 100644 --- a/src/hypervisor/domain_interface.h +++ b/src/hypervisor/domain_interface.h @@ -48,3 +48,13 @@ int virDomainInterfaceClearQoS(virDomainDef *def, virDomainNetDef *net); void virDomainClearNetBandwidth(virDomainDef *def) ATTRIBUTE_NONNULL(1); + +int virDomainInterfaceBridgeConnect(virDomainDef *def, + virDomainNetDef *net, + int *tapfd, + size_t tapfdSize, + bool privileged, + ebtablesContext *ebtables, + bool macFilter, + const char *bridgeHelperName) + ATTRIBUTE_NONNULL(2) G_NO_INLINE; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d15d6a6a9d..8132a17c28 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1646,6 +1646,7 @@ virDomainDriverSetupPersistentDefBlkioParams; =20 # hypervisor/domain_interface.h virDomainClearNetBandwidth; +virDomainInterfaceBridgeConnect; virDomainInterfaceClearQoS; virDomainInterfaceDeleteDevice; virDomainInterfaceEthernetConnect; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f15e6bda1e..0d22bebe89 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8626,6 +8626,7 @@ qemuBuildInterfaceConnect(virDomainObj *vm, bool vhostfd =3D false; /* also used to signal processing of tapfds */ size_t tapfdSize =3D net->driver.virtio.queues; g_autofree int *tapfd =3D g_new0(int, tapfdSize + 1); + g_autoptr(virQEMUDriverConfig) cfg =3D virQEMUDriverGetConfig(priv->dr= iver); =20 memset(tapfd, -1, (tapfdSize + 1) * sizeof(*tapfd)); =20 @@ -8636,8 +8637,12 @@ qemuBuildInterfaceConnect(virDomainObj *vm, case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_BRIDGE: vhostfd =3D true; - if (qemuInterfaceBridgeConnect(vm->def, priv->driver, net, - tapfd, &tapfdSize) < 0) + if (virDomainInterfaceBridgeConnect(vm->def, net, + tapfd, tapfdSize, + priv->driver->privileged, + priv->driver->ebtables, + priv->driver->config->macFilter, + cfg->bridgeHelperName) < 0) return -1; break; =20 diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index c2007c7043..23a23d201a 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -34,6 +34,7 @@ #include "virnetdevbridge.h" #include "virnetdevvportprofile.h" #include "virsocket.h" +#include "vircommand.h" =20 #include #include @@ -99,224 +100,6 @@ qemuInterfaceDirectConnect(virDomainDef *def, } =20 =20 -/** - * qemuCreateInBridgePortWithHelper: - * @cfg: the configuration object in which the helper name is looked up - * @brname: the bridge name - * @ifname: the returned interface name - * @macaddr: the returned MAC address - * @tapfd: file descriptor return value for the new tap device - * @flags: OR of virNetDevTapCreateFlags: - - * VIR_NETDEV_TAP_CREATE_VNET_HDR - * - Enable IFF_VNET_HDR on the tap device - * - * This function creates a new tap device on a bridge using an external - * helper. The final name for the bridge will be stored in @ifname. - * - * Returns 0 in case of success or -1 on failure - */ -static int -qemuCreateInBridgePortWithHelper(virQEMUDriverConfig *cfg, - const char *brname, - char **ifname, - int *tapfd, - unsigned int flags) -{ - const char *const bridgeHelperDirs[] =3D { - "/usr/libexec", - "/usr/lib/qemu", - "/usr/lib", - NULL, - }; - g_autoptr(virCommand) cmd =3D NULL; - g_autofree char *bridgeHelperPath =3D NULL; - char *errbuf =3D NULL, *cmdstr =3D NULL; - int pair[2] =3D { -1, -1 }; - - if ((flags & ~VIR_NETDEV_TAP_CREATE_VNET_HDR) !=3D VIR_NETDEV_TAP_CREA= TE_IFUP) - return -1; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) { - virReportSystemError(errno, "%s", _("failed to create socket")); - return -1; - } - - bridgeHelperPath =3D virFindFileInPathFull(cfg->bridgeHelperName, brid= geHelperDirs); - - if (!bridgeHelperPath) { - virReportSystemError(errno, _("'%1$s' is not a suitable bridge hel= per"), - cfg->bridgeHelperName); - return -1; - } - - VIR_DEBUG("Using qemu-bridge-helper: %s", bridgeHelperPath); - - cmd =3D virCommandNew(bridgeHelperPath); - if (flags & VIR_NETDEV_TAP_CREATE_VNET_HDR) - virCommandAddArgFormat(cmd, "--use-vnet"); - virCommandAddArgFormat(cmd, "--br=3D%s", brname); - virCommandAddArgFormat(cmd, "--fd=3D%d", pair[1]); - virCommandSetErrorBuffer(cmd, &errbuf); - virCommandDoAsyncIO(cmd); - virCommandPassFD(cmd, pair[1], - VIR_COMMAND_PASS_FD_CLOSE_PARENT); - virCommandClearCaps(cmd); -#ifdef CAP_NET_ADMIN - virCommandAllowCap(cmd, CAP_NET_ADMIN); -#endif - if (virCommandRunAsync(cmd, NULL) < 0) { - *tapfd =3D -1; - goto cleanup; - } - - do { - *tapfd =3D virSocketRecvFD(pair[0], 0); - } while (*tapfd < 0 && errno =3D=3D EINTR); - - if (*tapfd < 0) { - char *errstr =3D NULL; - - if (!(cmdstr =3D virCommandToString(cmd, false))) - goto cleanup; - virCommandAbort(cmd); - - if (errbuf && *errbuf) - errstr =3D g_strdup_printf("stderr=3D%s", errbuf); - - virReportSystemError(errno, - _("%1$s: failed to communicate with bridge he= lper: %2$s"), - cmdstr, - NULLSTR_EMPTY(errstr)); - VIR_FREE(errstr); - goto cleanup; - } - - if (virNetDevTapGetName(*tapfd, ifname) < 0 || - virCommandWait(cmd, NULL) < 0) { - VIR_FORCE_CLOSE(*tapfd); - *tapfd =3D -1; - } - - cleanup: - VIR_FREE(cmdstr); - VIR_FREE(errbuf); - VIR_FORCE_CLOSE(pair[0]); - return *tapfd < 0 ? -1 : 0; -} - -/* qemuInterfaceBridgeConnect: - * @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_NETWORK or - * VIR_DOMAIN_NET_TYPE_BRIDGE (i.e. if the connection is made with a tap - * device connecting to a bridge device) - */ -int -qemuInterfaceBridgeConnect(virDomainDef *def, - virQEMUDriver *driver, - virDomainNetDef *net, - int *tapfd, - size_t *tapfdSize) -{ - const char *brname; - int ret =3D -1; - unsigned int tap_create_flags =3D VIR_NETDEV_TAP_CREATE_IFUP; - bool template_ifname =3D false; - g_autoptr(virQEMUDriverConfig) cfg =3D virQEMUDriverGetConfig(driver); - const char *tunpath =3D "/dev/net/tun"; - - if (net->backend.tap) { - tunpath =3D net->backend.tap; - if (!driver->privileged) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("cannot use custom tap device in session mode= ")); - goto cleanup; - } - } - - if (!(brname =3D virDomainNetGetActualBridgeName(net))) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge nam= e")); - goto cleanup; - } - - if (!net->ifname) - template_ifname =3D true; - - if (virDomainInterfaceIsVnetCompatModel(net)) - tap_create_flags |=3D VIR_NETDEV_TAP_CREATE_VNET_HDR; - - if (driver->privileged) { - if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, - def->uuid, tunpath, tapfd, *tap= fdSize, - virDomainNetGetActualVirtPortPr= ofile(net), - virDomainNetGetActualVlan(net), - virDomainNetGetActualPortOption= sIsolated(net), - net->coalesce, 0, NULL, - tap_create_flags) < 0) { - virDomainAuditNetDevice(def, net, tunpath, false); - goto cleanup; - } - if (virDomainNetGetActualBridgeMACTableManager(net) - =3D=3D VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) { - /* libvirt is managing the FDB of the bridge this device - * 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 virDomainInterfaceStartDevices(), - * using the MAC address from the interface config. - */ - if (virNetDevBridgePortSetLearning(brname, net->ifname, false)= < 0) - goto cleanup; - if (virNetDevBridgePortSetUnicastFlood(brname, net->ifname, fa= lse) < 0) - goto cleanup; - } - } else { - if (qemuCreateInBridgePortWithHelper(cfg, brname, - &net->ifname, - tapfd, tap_create_flags) < 0)= { - virDomainAuditNetDevice(def, net, tunpath, false); - goto cleanup; - } - /* qemuCreateInBridgePortWithHelper can only create a single FD */ - if (*tapfdSize > 1) { - VIR_WARN("Ignoring multiqueue network request"); - *tapfdSize =3D 1; - } - } - - virDomainAuditNetDevice(def, net, tunpath, true); - - 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; - } - - ret =3D 0; - - cleanup: - if (ret < 0) { - size_t i; - for (i =3D 0; i < *tapfdSize && tapfd[i] >=3D 0; i++) - VIR_FORCE_CLOSE(tapfd[i]); - if (template_ifname) - VIR_FREE(net->ifname); - } - - return ret; -} - - /* * Returns: -1 on error, 0 on success. Populates net->privateData->slirp if * the slirp helper is needed. --=20 2.44.0