From nobody Thu Dec 26 11:25:10 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=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 173259156287910.021664924110723; Mon, 25 Nov 2024 19:26:02 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id 2F74C17E8; Mon, 25 Nov 2024 22:26:02 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 8061418C8; Mon, 25 Nov 2024 22:25:00 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id A0B5D1364; Mon, 25 Nov 2024 22:24:56 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 B1BC317E1 for ; Mon, 25 Nov 2024 22:24:55 -0500 (EST) Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-145-CXB1skarOsmIXnyMphKISg-1; Mon, 25 Nov 2024 22:24:53 -0500 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CB5271954128 for ; Tue, 26 Nov 2024 03:24:52 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.88.88]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 96323195DF81; Tue, 26 Nov 2024 03:24:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-1.7 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732591495; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YXnd9gm03MvepqaWvTd649NIaYeeHOnz14nJ/Aum9e8=; b=KgOpOD0MUfDhYMVgf3zaongp0Be9eadtw4g1Gc/iKSwjAA/+HBx13cTdyucCzReXAXPjmn gd5uFkcDdskd1k+hFhO4D0nVBochDtJAtTH29A/b+M1tQzvg+LKJ5zqNERU1H9edKhEOYL g0wWVIbsZP0JVy9wRI7LJzBWZQoP7+k= X-MC-Unique: CXB1skarOsmIXnyMphKISg-1 X-Mimecast-MFC-AGG-ID: CXB1skarOsmIXnyMphKISg From: Laine Stump To: devel@lists.libvirt.org Subject: [PATCH v2 1/6] util: use a single flags arg for virNetDevBandwidthSet(), not multiple bools Date: Mon, 25 Nov 2024 22:24:44 -0500 Message-ID: <20241126032449.912167-2-laine@redhat.com> In-Reply-To: <20241126032449.912167-1-laine@redhat.com> References: <20241126032449.912167-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: wBfsUT6mjhGLjwWjVqz_KdFH8WbM6FZ9rNCIK5Yc69I_1732591492 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 335B3XN3DNRVLCOYLFXMKFJNLXYNCOZE X-Message-ID-Hash: 335B3XN3DNRVLCOYLFXMKFJNLXYNCOZE X-MailFrom: laine@redhat.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: egarver@redhat.com, mprivozn@redhat.com, psutter@redhat.com, abologna@redhat.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: 1732591578778019100 Content-Type: text/plain; charset="utf-8"; x-default="true" Having two bools in the arg list is on the borderline of being confusing to anyone trying to read the code, but we're about to add a 3rd. This patch replaces the two bools with a single flags argument which will instead have one or more bits from virNetDevBandwidthFlags set. Signed-off-by: Laine Stump Reviewed-by: Michal Privoznik --- src/lxc/lxc_driver.c | 8 ++++++-- src/lxc/lxc_process.c | 8 ++++++-- src/network/bridge_driver.c | 10 ++++++++-- src/qemu/qemu_command.c | 11 ++++++++--- src/qemu/qemu_driver.c | 29 ++++++++++++++------------- src/qemu/qemu_hotplug.c | 22 +++++++++++++++------ src/util/virnetdevbandwidth.c | 36 ++++++++++++++++++++-------------- src/util/virnetdevbandwidth.h | 11 ++++++++--- tests/virnetdevbandwidthtest.c | 8 +++++++- 9 files changed, 95 insertions(+), 48 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 0e31e5e4b9..a64cfef1a0 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3570,8 +3570,12 @@ lxcDomainAttachDeviceNetLive(virLXCDriver *driver, actualBandwidth =3D virDomainNetGetActualBandwidth(net); if (actualBandwidth) { if (virNetDevSupportsBandwidth(actualType)) { - if (virNetDevBandwidthSet(net->ifname, actualBandwidth, false, - !virDomainNetTypeSharesHostView(net)= ) < 0) + unsigned int flags =3D 0; + + if (!virDomainNetTypeSharesHostView(net)) + flags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; + + if (virNetDevBandwidthSet(net->ifname, actualBandwidth, flags)= < 0) goto cleanup; } else { VIR_WARN("setting bandwidth on interfaces of " diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 083ab83ec6..7eba7a2c46 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -609,8 +609,12 @@ virLXCProcessSetupInterfaces(virLXCDriver *driver, actualBandwidth =3D virDomainNetGetActualBandwidth(net); if (actualBandwidth) { if (virNetDevSupportsBandwidth(type)) { - if (virNetDevBandwidthSet(net->ifname, actualBandwidth, fa= lse, - !virDomainNetTypeSharesHostView(= net)) < 0) + unsigned int flags =3D 0; + + if (!virDomainNetTypeSharesHostView(net)) + flags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; + + if (virNetDevBandwidthSet(net->ifname, actualBandwidth, fl= ags) < 0) goto cleanup; } else { VIR_WARN("setting bandwidth on interfaces of " diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index d408f17de7..e700a614a9 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2109,8 +2109,11 @@ networkStartNetworkVirtual(virNetworkDriverState *dr= iver, } } =20 - if (virNetDevBandwidthSet(def->bridge, def->bandwidth, true, true) < 0) + if (virNetDevBandwidthSet(def->bridge, def->bandwidth, + VIR_NETDEV_BANDWIDTH_SET_HIERARCHICAL_CLASS + | VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED) < 0)= { goto error; + } =20 return 0; =20 @@ -2190,8 +2193,11 @@ networkStartNetworkBridge(virNetworkObj *obj) * type BRIDGE, is started. On failure, undo anything you've done, * and return -1. On success return 0. */ - if (virNetDevBandwidthSet(def->bridge, def->bandwidth, true, true) < 0) + if (virNetDevBandwidthSet(def->bridge, def->bandwidth, + VIR_NETDEV_BANDWIDTH_SET_HIERARCHICAL_CLASS + | VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED) < 0)= { goto error; + } =20 if (networkStartHandleMACTableManagerMode(obj) < 0) goto error; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f4430275dc..3d0a5dd460 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8694,9 +8694,14 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver, def->uuid, !virDomainNetTypeS= haresHostView(net)) < 0) goto cleanup; - } else if (virNetDevBandwidthSet(net->ifname, actualBandwidth,= false, - !virDomainNetTypeSharesHostVi= ew(net)) < 0) { - goto cleanup; + } else { + unsigned int flags =3D 0; + + if (!virDomainNetTypeSharesHostView(net)) + flags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; + + if (virNetDevBandwidthSet(net->ifname, actualBandwidth, fl= ags) < 0) + goto cleanup; } } else { VIR_WARN("setting bandwidth on interfaces of " diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5b9c55f704..425d583e99 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -9938,21 +9938,22 @@ qemuDomainSetInterfaceParameters(virDomainPtr dom, virErrorRestore(&orig_err); goto endjob; } - } else if (virNetDevBandwidthSet(net->ifname, newBandwidth, false, - !virDomainNetTypeSharesHostView(n= et)) < 0) { - virErrorPtr orig_err; - - virErrorPreserveLast(&orig_err); - ignore_value(virNetDevBandwidthSet(net->ifname, - net->bandwidth, - false, - !virDomainNetTypeSharesHost= View(net))); - if (net->bandwidth) { - ignore_value(virDomainNetBandwidthUpdate(net, - net->bandwidth)); + } else { + unsigned int bwflags =3D 0; + + if (!virDomainNetTypeSharesHostView(net)) + bwflags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; + + if (virNetDevBandwidthSet(net->ifname, newBandwidth, bwflags) = < 0) { + virErrorPtr orig_err; + + virErrorPreserveLast(&orig_err); + ignore_value(virNetDevBandwidthSet(net->ifname, net->bandw= idth, bwflags)); + if (net->bandwidth) + ignore_value(virDomainNetBandwidthUpdate(net, net->ban= dwidth)); + virErrorRestore(&orig_err); + goto endjob; } - virErrorRestore(&orig_err); - goto endjob; } =20 /* If the old bandwidth was cleared out, restore qdisc. */ diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 55512476e4..b06ae61a44 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1331,9 +1331,14 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver, vm->def->uuid, !virDomainNetTypeS= haresHostView(net)) < 0) goto cleanup; - } else if (virNetDevBandwidthSet(net->ifname, actualBandwidth,= false, - !virDomainNetTypeSharesHostVi= ew(net)) < 0) { - goto cleanup; + } else { + int flags =3D 0; + + if (!virDomainNetTypeSharesHostView(net)) + flags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; + + if (virNetDevBandwidthSet(net->ifname, actualBandwidth, fl= ags) < 0) + goto cleanup; } } else { VIR_WARN("setting bandwidth on interfaces of " @@ -4181,9 +4186,14 @@ qemuDomainChangeNet(virQEMUDriver *driver, vm->def->uuid, !virDomainNetTypeS= haresHostView(newdev)) < 0) goto cleanup; - } else if (virNetDevBandwidthSet(newdev->ifname, newb, false, - !virDomainNetTypeSharesHostVi= ew(newdev)) < 0) { - goto cleanup; + } else { + int flags =3D 0; + + if (!virDomainNetTypeSharesHostView(newdev)) + flags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; + + if (virNetDevBandwidthSet(newdev->ifname, newb, flags) < 0) + goto cleanup; } } else { if (virDomainInterfaceClearQoS(vm->def, olddev) < 0) diff --git a/src/util/virnetdevbandwidth.c b/src/util/virnetdevbandwidth.c index 2b58c58d3e..1baad849c6 100644 --- a/src/util/virnetdevbandwidth.c +++ b/src/util/virnetdevbandwidth.c @@ -173,30 +173,35 @@ virNetDevBandwidthManipulateFilter(const char *ifname, * virNetDevBandwidthSet: * @ifname: on which interface * @bandwidth: rates to set (may be NULL) - * @hierarchical_class: whether to create hierarchical class - * @swapped: true if IN/OUT should be set contrariwise + * @flags: bits indicating certain optional actions * + * This function enables QoS on specified interface * and set given traffic limits for both, incoming - * and outgoing traffic. Any previous setting get - * overwritten. If @hierarchical_class is TRUE, create - * hierarchical class. It is used to guarantee minimal - * throughput ('floor' attribute in NIC). + * and outgoing traffic. + * + * @flags bits and their meanings: + * + * VIR_NETDEV_BANDWIDTH_SET_HIERARCHICAL_CLASS + * whether to create a hierarchical class + * A hiearchical class structure is used to implement a minimal + * throughput guarantee ('floor' attribute in NIC). * - * If @swapped is set, the IN part of @bandwidth is set on - * @ifname's TX, and vice versa. If it is not set, IN is set on - * RX and OUT on TX. This is because for some types of interfaces - * domain and the host live on the same side of the interface (so - * domain's RX/TX is host's RX/TX), and for some it's swapped - * (domain's RX/TX is hosts's TX/RX). + * VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED + * set if IN/OUT should be set backwards from what's indicated in + * the bandwidth, i.e. the IN part of @bandwidth is set on + * @ifname's TX, and the OUT part of @bandwidth is set on + * @ifname's RX. This is needed because for some types of + * interfaces the domain and the host live on the same side of the + * interface (so domain's RX/TX is host's RX/TX), and for some + * it's swapped (domain's RX/TX is hosts's TX/RX). * * Return 0 on success, -1 otherwise. */ int virNetDevBandwidthSet(const char *ifname, const virNetDevBandwidth *bandwidth, - bool hierarchical_class, - bool swapped) + unsigned int flags) { int ret =3D -1; virNetDevBandwidthRate *rx =3D NULL; /* From domain POV */ @@ -205,6 +210,7 @@ virNetDevBandwidthSet(const char *ifname, char *average =3D NULL; char *peak =3D NULL; char *burst =3D NULL; + bool hierarchical_class =3D flags & VIR_NETDEV_BANDWIDTH_SET_HIERARCHI= CAL_CLASS; =20 if (!bandwidth) { /* nothing to be enabled */ @@ -224,7 +230,7 @@ virNetDevBandwidthSet(const char *ifname, return -1; } =20 - if (swapped) { + if (flags & VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED) { rx =3D bandwidth->out; tx =3D bandwidth->in; } else { diff --git a/src/util/virnetdevbandwidth.h b/src/util/virnetdevbandwidth.h index 6d268fb119..414d6c97eb 100644 --- a/src/util/virnetdevbandwidth.h +++ b/src/util/virnetdevbandwidth.h @@ -35,15 +35,20 @@ struct _virNetDevBandwidth { virNetDevBandwidthRate *out; }; =20 -void virNetDevBandwidthFree(virNetDevBandwidth *def); + void virNetDevBandwidthFree(virNetDevBandwidth *def); =20 G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNetDevBandwidth, virNetDevBandwidthFree); =20 +typedef enum { + VIR_NETDEV_BANDWIDTH_SET_HIERARCHICAL_CLASS =3D (1 << 0), + VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED =3D (1 << 1), +} virNetDevBandwidthSetFlags; + int virNetDevBandwidthSet(const char *ifname, const virNetDevBandwidth *bandwidth, - bool hierarchical_class, - bool swapped) + unsigned int flags) G_GNUC_WARN_UNUSED_RESULT; + int virNetDevBandwidthClear(const char *ifname); int virNetDevBandwidthCopy(virNetDevBandwidth **dest, const virNetDevBandwidth *src) diff --git a/tests/virnetdevbandwidthtest.c b/tests/virnetdevbandwidthtest.c index f7c38faa2e..3a87d876c8 100644 --- a/tests/virnetdevbandwidthtest.c +++ b/tests/virnetdevbandwidthtest.c @@ -82,8 +82,14 @@ testVirNetDevBandwidthSet(const void *data) if (virNetDevOpenvswitchInterfaceSetQos(iface, band, info->uuid, t= rue) < 0) return -1; } else { + int flags =3D (VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED); + + if (info->hierarchical_class) + flags |=3D VIR_NETDEV_BANDWIDTH_SET_HIERARCHICAL_CLASS; + exp_cmd =3D info->exp_cmd_tc; - if (virNetDevBandwidthSet(iface, band, info->hierarchical_class, t= rue) < 0) + + if (virNetDevBandwidthSet(iface, band, flags) < 0) return -1; } =20 --=20 2.47.0 From nobody Thu Dec 26 11:25:10 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=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1732591599556776.1582835262561; Mon, 25 Nov 2024 19:26:39 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id D41F71B5F; Mon, 25 Nov 2024 22:26:38 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 96A1219D6; Mon, 25 Nov 2024 22:25:03 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 6BC1217E7; Mon, 25 Nov 2024 22:24:57 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 C565117E1 for ; Mon, 25 Nov 2024 22:24:56 -0500 (EST) Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-396-6TreGjNbNPewswF5otD14g-1; Mon, 25 Nov 2024 22:24:55 -0500 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 43B9219560BE for ; Tue, 26 Nov 2024 03:24:54 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.88.88]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 233BB195DF81; Tue, 26 Nov 2024 03:24:52 +0000 (UTC) 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_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732591496; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=zgI36OhW/sEpc65/ffsq8ZK0hIASTbxeeLtMHn9BKDA=; b=FNDyqYOFmt/IuMHdupOrcozZlxP3mJVLh7JWviuj3Vc5s3RosR7Uz31cdJhf6yrnscT1a/ YATrjz0iJ8vqrvfGRbjqfWbmYaf1Ncy9vEhEYyIUidlvPSY48lZsj4JZ73YJgJgEbgiv7U RzA1jEihG0c7pFOL3yrrxkn+Dpvuj6E= X-MC-Unique: 6TreGjNbNPewswF5otD14g-1 X-Mimecast-MFC-AGG-ID: 6TreGjNbNPewswF5otD14g From: Laine Stump To: devel@lists.libvirt.org Subject: [PATCH v2 2/6] util: make it optional to clear existing tc qdiscs/filters in virNetDevBandwidthSet() Date: Mon, 25 Nov 2024 22:24:45 -0500 Message-ID: <20241126032449.912167-3-laine@redhat.com> In-Reply-To: <20241126032449.912167-1-laine@redhat.com> References: <20241126032449.912167-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: sWSCFWlqReN8PMP9aOcdSaf3xOdb6dR2Ip1gE-kar2k_1732591494 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: YTG2CBAWLQAZIXWJ4CC4BMCVUP2IUWG3 X-Message-ID-Hash: YTG2CBAWLQAZIXWJ4CC4BMCVUP2IUWG3 X-MailFrom: laine@redhat.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: egarver@redhat.com, mprivozn@redhat.com, psutter@redhat.com, abologna@redhat.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: 1732591604912019100 Content-Type: text/plain; charset="utf-8"; x-default="true" virNetDevBandwidthSet() always clears all existing qdiscs and their subordinate filters before adding all the new qdiscs/filters. This is normally exactly what we want, but there is one case (the network driver) where the Qdisc added by virNetDevBandwidthSet() may already be in use by the nftables backend (which will add a rule to fix the checksum of dhcp packets); in that case, we *don't* want virNetDevBandwidthSet() to clear out the qdisc that was already added for nftables, and none of the bandwidth filters have been added yet, so there already aren't any "old" filters that need to be removed either - it is safe to just skip virNetDevBandwidthClear() in this case. To allow the network driver to set bandwidth without first clearing it, this patch adds the flag VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL to the virNetDevBandwidthSetFlags enum, and recognizes it in virNetDevBandwidthSet() - if the flag is set, then virNetDevBandwidth() will call virNetDevBandwidthClear() just as it always has. But if the flag isn't set it *won't* call virNetDevBandwidthClear(). As suggested above, VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL is set for all calls to virNetdevBandwidthSet() except for two places in the network driver. Signed-off-by: Laine Stump Reviewed-by: Michal Privoznik --- src/lxc/lxc_driver.c | 2 +- src/lxc/lxc_process.c | 2 +- src/qemu/qemu_command.c | 2 +- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_hotplug.c | 4 ++-- src/util/virnetdevbandwidth.c | 21 ++++++++++++++++++++- src/util/virnetdevbandwidth.h | 1 + tests/virnetdevbandwidthtest.c | 3 ++- 8 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index a64cfef1a0..d682e7168a 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3570,7 +3570,7 @@ lxcDomainAttachDeviceNetLive(virLXCDriver *driver, actualBandwidth =3D virDomainNetGetActualBandwidth(net); if (actualBandwidth) { if (virNetDevSupportsBandwidth(actualType)) { - unsigned int flags =3D 0; + unsigned int flags =3D VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL; =20 if (!virDomainNetTypeSharesHostView(net)) flags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 7eba7a2c46..cd8bcfc282 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -609,7 +609,7 @@ virLXCProcessSetupInterfaces(virLXCDriver *driver, actualBandwidth =3D virDomainNetGetActualBandwidth(net); if (actualBandwidth) { if (virNetDevSupportsBandwidth(type)) { - unsigned int flags =3D 0; + unsigned int flags =3D VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL; =20 if (!virDomainNetTypeSharesHostView(net)) flags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3d0a5dd460..47fe0a819c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8695,7 +8695,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver, !virDomainNetTypeS= haresHostView(net)) < 0) goto cleanup; } else { - unsigned int flags =3D 0; + unsigned int flags =3D VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL; =20 if (!virDomainNetTypeSharesHostView(net)) flags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 425d583e99..d1b32de56a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -9939,7 +9939,7 @@ qemuDomainSetInterfaceParameters(virDomainPtr dom, goto endjob; } } else { - unsigned int bwflags =3D 0; + unsigned int bwflags =3D VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL; =20 if (!virDomainNetTypeSharesHostView(net)) bwflags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index b06ae61a44..3c18af6b0c 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1332,7 +1332,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver, !virDomainNetTypeS= haresHostView(net)) < 0) goto cleanup; } else { - int flags =3D 0; + int flags =3D VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL; =20 if (!virDomainNetTypeSharesHostView(net)) flags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; @@ -4187,7 +4187,7 @@ qemuDomainChangeNet(virQEMUDriver *driver, !virDomainNetTypeS= haresHostView(newdev)) < 0) goto cleanup; } else { - int flags =3D 0; + int flags =3D VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL; =20 if (!virDomainNetTypeSharesHostView(newdev)) flags |=3D VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED; diff --git a/src/util/virnetdevbandwidth.c b/src/util/virnetdevbandwidth.c index 1baad849c6..9c48844c5d 100644 --- a/src/util/virnetdevbandwidth.c +++ b/src/util/virnetdevbandwidth.c @@ -196,6 +196,21 @@ virNetDevBandwidthManipulateFilter(const char *ifname, * interface (so domain's RX/TX is host's RX/TX), and for some * it's swapped (domain's RX/TX is hosts's TX/RX). * + * VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL + * If VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL is set, then the root + * qdisc is deleted before adding any new qdisc/class/filter, + * which causes any pre-existing filters to also be deleted. If + * not set, then it's assumed that there are no existing rules (or + * that those already there need to be kept). The caller should + * set this flag for an existing interface that is having its + * bandwidth settings modified, but can leave it unset if the + * interface was newly created and this is the first time + * bandwidth has been set, but someone else might have already + * added the qdisc (e.g. this is the case when the network driver + * is setting bandwidth for a virtual network bridge device - the + * nftables backend may have already added qdisc handle 1:0 and a + * filter, and we don't want to delete them) + * * Return 0 on success, -1 otherwise. */ int @@ -238,7 +253,11 @@ virNetDevBandwidthSet(const char *ifname, tx =3D bandwidth->out; } =20 - virNetDevBandwidthClear(ifname); + /* Only if the caller requests, clear everything including root + * qdisc and all filters before adding everything. + */ + if (flags & VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL) + virNetDevBandwidthClear(ifname); =20 if (tx && tx->average) { average =3D g_strdup_printf("%llukbps", tx->average); diff --git a/src/util/virnetdevbandwidth.h b/src/util/virnetdevbandwidth.h index 414d6c97eb..69c204389c 100644 --- a/src/util/virnetdevbandwidth.h +++ b/src/util/virnetdevbandwidth.h @@ -42,6 +42,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNetDevBandwidth, virNetD= evBandwidthFree); typedef enum { VIR_NETDEV_BANDWIDTH_SET_HIERARCHICAL_CLASS =3D (1 << 0), VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED =3D (1 << 1), + VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL =3D (1 << 2), } virNetDevBandwidthSetFlags; =20 int virNetDevBandwidthSet(const char *ifname, diff --git a/tests/virnetdevbandwidthtest.c b/tests/virnetdevbandwidthtest.c index 3a87d876c8..c34fbd5073 100644 --- a/tests/virnetdevbandwidthtest.c +++ b/tests/virnetdevbandwidthtest.c @@ -82,7 +82,8 @@ testVirNetDevBandwidthSet(const void *data) if (virNetDevOpenvswitchInterfaceSetQos(iface, band, info->uuid, t= rue) < 0) return -1; } else { - int flags =3D (VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED); + int flags =3D (VIR_NETDEV_BANDWIDTH_SET_DIR_SWAPPED + | VIR_NETDEV_BANDWIDTH_SET_CLEAR_ALL); =20 if (info->hierarchical_class) flags |=3D VIR_NETDEV_BANDWIDTH_SET_HIERARCHICAL_CLASS; --=20 2.47.0 From nobody Thu Dec 26 11:25:10 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=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1732591633378377.87303057752115; Mon, 25 Nov 2024 19:27:13 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id CCB491A82; Mon, 25 Nov 2024 22:27:12 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 20FE218A0; Mon, 25 Nov 2024 22:25:12 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 4206818B7; Mon, 25 Nov 2024 22:25:07 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 E7CF218AD for ; Mon, 25 Nov 2024 22:24:58 -0500 (EST) Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-383--iUdxT1oN06CEYC47mD5-A-1; Mon, 25 Nov 2024 22:24:56 -0500 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A97921956096 for ; Tue, 26 Nov 2024 03:24:55 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.88.88]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8B086195DF81; Tue, 26 Nov 2024 03:24:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-1.7 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732591498; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AoJ+CsxYk1sS+UEo6K6T1JmOXNnrtNnZxMO/t+0UbR4=; b=FBMQu06ha23k0aBfap8IR9EAiFXJLKxkk8Thhy4TyRrybmg2cqdOfq9reBM65kxneH9I/h egYZp5vjR14ZACNDIB3H94QIU3xVDWQLZ5zsvIvXDhdqNPmk1KElihwdVdxKdJoO1Rbi9K F6KZYazIZKJD2crie+PXVJWfa7/8NO8= X-MC-Unique: -iUdxT1oN06CEYC47mD5-A-1 X-Mimecast-MFC-AGG-ID: -iUdxT1oN06CEYC47mD5-A From: Laine Stump To: devel@lists.libvirt.org Subject: [PATCH v2 3/6] util: put the command that adds a tx filter qdisc into a separate function Date: Mon, 25 Nov 2024 22:24:46 -0500 Message-ID: <20241126032449.912167-4-laine@redhat.com> In-Reply-To: <20241126032449.912167-1-laine@redhat.com> References: <20241126032449.912167-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: mvx_qbqrC9O2_I7xKh-sBbbD_omjY_9UwhmK1ZH1QF4_1732591495 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 5QAMR2LK5GLG6MMYFZ7PNHPST7RVS27F X-Message-ID-Hash: 5QAMR2LK5GLG6MMYFZ7PNHPST7RVS27F X-MailFrom: laine@redhat.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: egarver@redhat.com, mprivozn@redhat.com, psutter@redhat.com, abologna@redhat.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: 1732591634729019100 Content-Type: text/plain; charset="utf-8"; x-default="true" virNetDevBandwidthSet() adds a queue discipline (qdisc) for each interface that it will need to add tc transmit filters to, and the filters are then attached to the qdisc. There are other circumstances where some other function will need to add tc transmit filters to an interface (in particular an upcoming patch to the network driver nftables backend that will use a tc tx filter to fix the checksum of dhcp packets), so that function will also need a qdisc for the tx filter. To assure both always use exactly the same qdisc, this patch puts the command that adds the tx filter qdisc into a separate helper function that can (and will) be called from either place Signed-off-by: Laine Stump Reviewed-by: Michal Privoznik --- src/libvirt_private.syms | 1 + src/util/virnetdevbandwidth.c | 30 +++++++++++++++++++++++++----- src/util/virnetdevbandwidth.h | 3 +++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5b9b44ef96..90a7c6fa01 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2874,6 +2874,7 @@ virNetDevVFInterfaceStats; =20 =20 # util/virnetdevbandwidth.h +virNetDevBandWidthAddTxFilterParentQdisc; virNetDevBandwidthClear; virNetDevBandwidthCopy; virNetDevBandwidthEqual; diff --git a/src/util/virnetdevbandwidth.c b/src/util/virnetdevbandwidth.c index 9c48844c5d..90eebe6576 100644 --- a/src/util/virnetdevbandwidth.c +++ b/src/util/virnetdevbandwidth.c @@ -266,11 +266,7 @@ virNetDevBandwidthSet(const char *ifname, if (tx->burst) burst =3D g_strdup_printf("%llukb", tx->burst); =20 - cmd =3D virCommandNew(TC); - virCommandAddArgList(cmd, "qdisc", "add", "dev", ifname, "root", - "handle", "1:", "htb", "default", - hierarchical_class ? "2" : "1", NULL); - if (virCommandRun(cmd, NULL) < 0) + if (virNetDevBandWidthAddTxFilterParentQdisc(ifname, hierarchical_= class) < 0) goto cleanup; =20 /* If we are creating a hierarchical class, all non guaranteed tra= ffic @@ -794,3 +790,27 @@ virNetDevBandwidthSetRootQDisc(const char *ifname, =20 return 0; } + +/** + * virNetDevBandwidthAddTxFilterParentQdisc: + * @ifname: name of interface that needs a qdisc to attach tx filters to + * @hierarchical_class: true if hierarchical classes will be used on this = interface + * + * Add a root Qdisc (Queueing Discipline) for attaching Tx filters to + * @ifname. + * + * returns 0 on success, -1 on failure + */ +int +virNetDevBandWidthAddTxFilterParentQdisc(const char *ifname, + bool hierarchical_class) +{ + g_autoptr(virCommand) cmd =3D NULL; + + cmd =3D virCommandNew(TC); + virCommandAddArgList(cmd, "qdisc", "add", "dev", ifname, "root", + "handle", "1:", "htb", "default", + hierarchical_class ? "2" : "1", NULL); + + return virCommandRun(cmd, NULL); +} diff --git a/src/util/virnetdevbandwidth.h b/src/util/virnetdevbandwidth.h index 69c204389c..080d509d6e 100644 --- a/src/util/virnetdevbandwidth.h +++ b/src/util/virnetdevbandwidth.h @@ -84,3 +84,6 @@ int virNetDevBandwidthUpdateFilter(const char *ifname, int virNetDevBandwidthSetRootQDisc(const char *ifname, const char *qdisc) G_NO_INLINE; + +int virNetDevBandWidthAddTxFilterParentQdisc(const char *ifname, + bool hierarchical_class); --=20 2.47.0 From nobody Thu Dec 26 11:25:10 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=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1732591657886448.787612272444; Mon, 25 Nov 2024 19:27:37 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id 469631877; Mon, 25 Nov 2024 22:27:37 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 4C2F91AA7; Mon, 25 Nov 2024 22:25:15 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 62FD01808; Mon, 25 Nov 2024 22:25:10 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 75DAB18EF for ; Mon, 25 Nov 2024 22:24:59 -0500 (EST) Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-180-taMea_McOZOAM8IvQqSQkQ-1; Mon, 25 Nov 2024 22:24:57 -0500 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 113501955EE9 for ; Tue, 26 Nov 2024 03:24:57 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.88.88]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E705D195DF81; Tue, 26 Nov 2024 03:24:55 +0000 (UTC) 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_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732591499; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ObubO42fnTgvQBMm4CVH8+5cfm7tVcKNRsWGxzRQqjw=; b=M7QJ0tnne6gdRj8UzjN/Hrh6Vy7bVwgxm3EwITFEv7wdZPl43AwpM3pa5UliPwYRtWzz1q w+9He3Cni1mi1wwbAz1Ikupe73hSi8JuSG8/JvsuzssmZrUWHEYSVGs0vpM+PSv+bBqu+b NPaNUfwpPivuY3DL3xuLAlDvy/5qzLk= X-MC-Unique: taMea_McOZOAM8IvQqSQkQ-1 X-Mimecast-MFC-AGG-ID: taMea_McOZOAM8IvQqSQkQ From: Laine Stump To: devel@lists.libvirt.org Subject: [PATCH v2 4/6] util: don't re-add the qdisc used for tx filters if it already exists Date: Mon, 25 Nov 2024 22:24:47 -0500 Message-ID: <20241126032449.912167-5-laine@redhat.com> In-Reply-To: <20241126032449.912167-1-laine@redhat.com> References: <20241126032449.912167-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 3HJmkgPlKaSuLXVjjyXJ257aRCq5Z13qKuj1448yKZo_1732591497 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: Y2X44CAQX6FYO75HABNQUJ7QGHDS6WQF X-Message-ID-Hash: Y2X44CAQX6FYO75HABNQUJ7QGHDS6WQF X-MailFrom: laine@redhat.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: egarver@redhat.com, mprivozn@redhat.com, psutter@redhat.com, abologna@redhat.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: 1732591702351019100 Content-Type: text/plain; charset="utf-8"; x-default="true" There will soon be two separate users of tc on virtual networks, and both will use the "qdisc root handle 1: htb" to add tx filters. One or the other could get the first chance to add the qdisc, and then if at a later time the other decides to use it, we need to prevent the 2nd user from attempting to re-add the qdisc (because that just generates an error). We do this by running "tc qdisc show dev $bridge handle 1:" then checking if the output of that command contains both "qdisc" and " 1: ".[*] If it does then the qdisc has already been added. If not then we need to add it now. [*]As of this writing, the output more exactly starts with "qdisc htb 1: root", but our comparison is made purposefully generous to increase the chances that it will continue to work properly if tc modifies the format of its output. Signed-off-by: Laine Stump Reviewed-by: Michal Privoznik --- src/util/virnetdevbandwidth.c | 35 ++++++++++++++++++++++++++++------ tests/virnetdevbandwidthtest.c | 3 +++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/util/virnetdevbandwidth.c b/src/util/virnetdevbandwidth.c index 90eebe6576..5c6a65528c 100644 --- a/src/util/virnetdevbandwidth.c +++ b/src/util/virnetdevbandwidth.c @@ -805,12 +805,35 @@ int virNetDevBandWidthAddTxFilterParentQdisc(const char *ifname, bool hierarchical_class) { - g_autoptr(virCommand) cmd =3D NULL; + g_autoptr(virCommand) testCmd =3D NULL; + g_autofree char *testResult =3D NULL; =20 - cmd =3D virCommandNew(TC); - virCommandAddArgList(cmd, "qdisc", "add", "dev", ifname, "root", - "handle", "1:", "htb", "default", - hierarchical_class ? "2" : "1", NULL); + /* first check it the qdisc with handle 1: was already added for + * this interface by someone else + */ + testCmd =3D virCommandNew(TC); + virCommandAddArgList(testCmd, "qdisc", "show", "dev", ifname, + "handle", "1:", NULL); + virCommandSetOutputBuffer(testCmd, &testResult); =20 - return virCommandRun(cmd, NULL); + if (virCommandRun(testCmd, NULL) < 0) + return -1; + + /* output will be something like: "qdisc htb 1: root refcnt ..." + * if the qdisc was already added. We just search for "qdisc" and + * " 1: " anywhere in the output to allow for tc changing its + * output format. + */ + if (!(testResult && strstr(testResult, "qdisc") && strstr(testResult, = " 1: "))) { + /* didn't find qdisc in output, so we need to add one */ + g_autoptr(virCommand) addCmd =3D virCommandNew(TC); + + virCommandAddArgList(addCmd, "qdisc", "add", "dev", ifname, "root", + "handle", "1:", "htb", "default", + hierarchical_class ? "2" : "1", NULL); + + return virCommandRun(addCmd, NULL); + } + + return 0; } diff --git a/tests/virnetdevbandwidthtest.c b/tests/virnetdevbandwidthtest.c index c34fbd5073..8d78502b0c 100644 --- a/tests/virnetdevbandwidthtest.c +++ b/tests/virnetdevbandwidthtest.c @@ -147,6 +147,7 @@ mymain(void) "", TC " qdisc del dev eth0 root\n" TC " qdisc del dev eth0 ingress\n" + TC " qdisc show dev eth0 handle 1:\n" TC " qdisc add dev eth0 root handle 1: htb default 1\n" TC " class add dev eth0 parent 1: classid 1:1 htb rate 102= 4kbps quantum 87\n" TC " qdisc add dev eth0 parent 1:1 handle 2: sfq perturb 1= 0\n" @@ -177,6 +178,7 @@ mymain(void) "", TC " qdisc del dev eth0 root\n" TC " qdisc del dev eth0 ingress\n" + TC " qdisc show dev eth0 handle 1:\n" TC " qdisc add dev eth0 root handle 1: htb default 1\n" TC " class add dev eth0 parent 1: classid 1:1 htb rate 1kb= ps ceil 2kbps burst 4kb quantum 1\n" TC " qdisc add dev eth0 parent 1:1 handle 2: sfq perturb 1= 0\n" @@ -199,6 +201,7 @@ mymain(void) "", TC " qdisc del dev eth0 root\n" TC " qdisc del dev eth0 ingress\n" + TC " qdisc show dev eth0 handle 1:\n" TC " qdisc add dev eth0 root handle 1: htb default 1\n" TC " class add dev eth0 parent 1: classid 1:1 htb rate 429= 4967295kbps quantum 366503875\n" TC " qdisc add dev eth0 parent 1:1 handle 2: sfq perturb 1= 0\n" --=20 2.47.0 From nobody Thu Dec 26 11:25:10 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=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1732591723609862.6823223591441; Mon, 25 Nov 2024 19:28:43 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id E9FDC14A9; Mon, 25 Nov 2024 22:28:42 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 4856318FF; Mon, 25 Nov 2024 22:25:24 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 92AA2187C; Mon, 25 Nov 2024 22:25:18 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 B43571947 for ; Mon, 25 Nov 2024 22:25:03 -0500 (EST) Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-197-5NuS0QT3PHmNCmZVb8Y3Mg-1; Mon, 25 Nov 2024 22:25:01 -0500 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 85097195608A for ; Tue, 26 Nov 2024 03:24:58 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.88.88]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4D896195DF81; Tue, 26 Nov 2024 03:24:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-1.7 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732591503; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UEaZwsIo6xJi1cURAXtl7mblzJI2uA93KPQ/7f+qgDo=; b=AkYZkUd+UBfiFF66YkuRUN7EqqB8YcARKRtYtY6y3qneuoyoqnuVOobuJUGP15rHrvmHQ7 uul45TZZujPFIkJpYLL+u15KkJpBVqlkIQB//nuOfMoe1E85+YCkOO44dB6yBgYVVqJ4ku yAkZuvOj5uvSd/fbfGwAancDUELHcVo= X-MC-Unique: 5NuS0QT3PHmNCmZVb8Y3Mg-1 X-Mimecast-MFC-AGG-ID: 5NuS0QT3PHmNCmZVb8Y3Mg From: Laine Stump To: devel@lists.libvirt.org Subject: [PATCH v2 5/6] util: add new "tc" layer for virFirewallCmd objects Date: Mon, 25 Nov 2024 22:24:48 -0500 Message-ID: <20241126032449.912167-6-laine@redhat.com> In-Reply-To: <20241126032449.912167-1-laine@redhat.com> References: <20241126032449.912167-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: Awdvv86BEmhyCxKsdkv_P5Q6w6UWN1gKESTU85NdJ9U_1732591498 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 4KODTUEL7PYIJF47SYWRT37MB6CQ2XLV X-Message-ID-Hash: 4KODTUEL7PYIJF47SYWRT37MB6CQ2XLV X-MailFrom: laine@redhat.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: egarver@redhat.com, mprivozn@redhat.com, psutter@redhat.com, abologna@redhat.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: 1732591725164019100 Content-Type: text/plain; charset="utf-8"; x-default="true" If the layer of a virFirewallCmd is "tc", then the "tc" utility will be executed using the arguments that had been added to the virFirewallCmd tc layer doesn't support auto-rollback command creation (any rollback needs to be added manually with virFirewallAddRollbackCmd()), and also tc layer isn't supported by the iptables backend (it would have been straightforward to add, but the iptables backend doesn't need it, and I didn't want to take the chance of causing a regression in that code for no good reason). Signed-off-by: Laine Stump Reviewed-by: Michal Privoznik --- src/network/network_nftables.c | 1 + src/util/virfirewall.c | 66 +++++++++++++++++++++------------- src/util/virfirewall.h | 1 + src/util/virfirewalld.c | 1 + 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/network/network_nftables.c b/src/network/network_nftables.c index f8b5ab665d..b3605bd40e 100644 --- a/src/network/network_nftables.c +++ b/src/network/network_nftables.c @@ -73,6 +73,7 @@ VIR_ENUM_IMPL(nftablesLayer, "", "ip", "ip6", + "", ); =20 =20 diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c index 811b787ecc..754bc18162 100644 --- a/src/util/virfirewall.c +++ b/src/util/virfirewall.c @@ -47,6 +47,7 @@ VIR_ENUM_IMPL(virFirewallLayer, "ethernet", "ipv4", "ipv6", + "tc", ); =20 typedef struct _virFirewallGroup virFirewallGroup; @@ -57,6 +58,7 @@ VIR_ENUM_IMPL(virFirewallLayerCommand, EBTABLES, IPTABLES, IP6TABLES, + TC, ); =20 struct _virFirewallCmd { @@ -591,6 +593,7 @@ virFirewallCmdIptablesApply(virFirewall *firewall, case VIR_FIREWALL_LAYER_IPV6: virCommandAddArg(cmd, "-w"); break; + case VIR_FIREWALL_LAYER_TC: case VIR_FIREWALL_LAYER_LAST: break; } @@ -672,39 +675,52 @@ virFirewallCmdNftablesApply(virFirewall *firewall G_G= NUC_UNUSED, size_t i; int status; =20 - cmd =3D virCommandNew(NFT); + if (fwCmd->layer =3D=3D VIR_FIREWALL_LAYER_TC) { =20 - if ((virFirewallTransactionGetFlags(firewall) & VIR_FIREWALL_TRANSACTI= ON_AUTO_ROLLBACK) && - fwCmd->argsLen > 1) { - /* skip any leading options to get to command verb */ - for (i =3D 0; i < fwCmd->argsLen - 1; i++) { - if (fwCmd->args[i][0] !=3D '-') - break; - } + /* for VIR_FIREWALL_LAYER_TC, we run the 'tc' (traffic control) co= mmand with + * the supplied args. + */ + cmd =3D virCommandNew(TC); =20 - if (i + 1 < fwCmd->argsLen && - VIR_NFTABLES_ARG_IS_CREATE(fwCmd->args[i])) { + /* NB: RAW commands don't support auto-rollback command creation */ =20 - cmdIdx =3D i; - objectType =3D fwCmd->args[i + 1]; + } else { =20 - /* we currently only handle auto-rollback for rules, - * chains, and tables, and those all can be "rolled - * back" by a delete command using the handle that is - * returned when "-ae" is added to the add/insert - * command. - */ - if (STREQ_NULLABLE(objectType, "rule") || - STREQ_NULLABLE(objectType, "chain") || - STREQ_NULLABLE(objectType, "table")) { + cmd =3D virCommandNew(NFT); =20 - needRollback =3D true; - /* this option to nft instructs it to add the - * "handle" of the created object to stdout + if ((virFirewallTransactionGetFlags(firewall) & VIR_FIREWALL_TRANS= ACTION_AUTO_ROLLBACK) && + fwCmd->argsLen > 1) { + /* skip any leading options to get to command verb */ + for (i =3D 0; i < fwCmd->argsLen - 1; i++) { + if (fwCmd->args[i][0] !=3D '-') + break; + } + + if (i + 1 < fwCmd->argsLen && + VIR_NFTABLES_ARG_IS_CREATE(fwCmd->args[i])) { + + cmdIdx =3D i; + objectType =3D fwCmd->args[i + 1]; + + /* we currently only handle auto-rollback for rules, + * chains, and tables, and those all can be "rolled + * back" by a delete command using the handle that is + * returned when "-ae" is added to the add/insert + * command. */ - virCommandAddArg(cmd, "-ae"); + if (STREQ_NULLABLE(objectType, "rule") || + STREQ_NULLABLE(objectType, "chain") || + STREQ_NULLABLE(objectType, "table")) { + + needRollback =3D true; + /* this option to nft instructs it to add the + * "handle" of the created object to stdout + */ + virCommandAddArg(cmd, "-ae"); + } } } + } =20 for (i =3D 0; i < fwCmd->argsLen; i++) diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h index bce51259d2..d42e60884b 100644 --- a/src/util/virfirewall.h +++ b/src/util/virfirewall.h @@ -39,6 +39,7 @@ typedef enum { VIR_FIREWALL_LAYER_ETHERNET, VIR_FIREWALL_LAYER_IPV4, VIR_FIREWALL_LAYER_IPV6, + VIR_FIREWALL_LAYER_TC, =20 VIR_FIREWALL_LAYER_LAST, } virFirewallLayer; diff --git a/src/util/virfirewalld.c b/src/util/virfirewalld.c index 0a886780ad..21a9e02061 100644 --- a/src/util/virfirewalld.c +++ b/src/util/virfirewalld.c @@ -43,6 +43,7 @@ VIR_LOG_INIT("util.firewalld"); VIR_ENUM_DECL(virFirewallLayerFirewallD); VIR_ENUM_IMPL(virFirewallLayerFirewallD, VIR_FIREWALL_LAYER_LAST, + "", "eb", "ipv4", "ipv6", --=20 2.47.0 From nobody Thu Dec 26 11:25:10 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=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 173259169853949.675737832728714; Mon, 25 Nov 2024 19:28:18 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id D620F18D7; Mon, 25 Nov 2024 22:28:17 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 7E8A018AD; Mon, 25 Nov 2024 22:25:22 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 046FA19AE; Mon, 25 Nov 2024 22:25:17 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 1C2D419AE for ; Mon, 25 Nov 2024 22:25:03 -0500 (EST) Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-223-LsRltaMxMfSVT66hjxfJng-1; Mon, 25 Nov 2024 22:25:00 -0500 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D573D1955EEA for ; Tue, 26 Nov 2024 03:24:59 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.88.88]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B3567195E483; Tue, 26 Nov 2024 03:24:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-1.7 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732591502; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=saXCzlzOfPMXlk/Z/H1ZnD2QLWMiNMv4ACOZHtCjRZc=; b=HpLqFX5nc/O40MU30X74Gv8KKhD3SqZZ1SO+D9p/uDVkXGnYV1NxCdcNpHrF2TxxOF0naA zRus49OicMxRwgre6/CBaKjG+rydmq1XjjClbq94oFyWcwwTRgjSs9ZwoEOb8aFBieHIEJ k63HxEIvhfyrw6okqMBSZ3e1vULrES4= X-MC-Unique: LsRltaMxMfSVT66hjxfJng-1 X-Mimecast-MFC-AGG-ID: LsRltaMxMfSVT66hjxfJng From: Laine Stump To: devel@lists.libvirt.org Subject: [PATCH v2 6/6] network: add tc filter rule to nftables backend to fix checksum of DHCP responses Date: Mon, 25 Nov 2024 22:24:49 -0500 Message-ID: <20241126032449.912167-7-laine@redhat.com> In-Reply-To: <20241126032449.912167-1-laine@redhat.com> References: <20241126032449.912167-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: SgQWnIcarprDI9CGSOsQ8pXcfAkEDGrXT5crf08nK40_1732591499 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: VSHVSF6CKYYTCVOCK3CN7OILJ2QCITDA X-Message-ID-Hash: VSHVSF6CKYYTCVOCK3CN7OILJ2QCITDA X-MailFrom: laine@redhat.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: egarver@redhat.com, mprivozn@redhat.com, psutter@redhat.com, abologna@redhat.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: 1732591703370019100 Content-Type: text/plain; charset="utf-8"; x-default="true" Please see the commit log for commit v10.9.0-rc1-1-g42ab0148dd for the history and explanation of the problem that this patch is fixing. A shorter explanation is that when a guest is connected to a libvirt virtual network using a virtio-net adapter with in-kernel "vhost-net" packet processing enabled, it will fail to acquire an IP address from a DHCP seever running on the host. In commit v10.9.0-rc1-1-g42ab0148dd we tried fixing this by *zeroing out* the checksums of these packets with an nftables rule (nftables can't recompute the checksum, but it can set it to 0) . This *appeared* to work initially, but it turned out that zeroing the checksum ends up breaking dhcp packets on *non* virtio/vhost-net guest interfaces. That attempt was reverted in commit v10.9.0-rc2. Fortunately, there is an existing way to recompute the checksum of a packet as it leaves an interface - the "tc" (traffic control) utility that libvirt already uses for bandwidth management. This patch uses a tc filter rule to match dhcp response packets on the bridge and recompute their checksum. The filter rule must be attached to a tc qdisc, which may also have a filter attached for bandwidth management (in the element of the network config). Not only must we add the qdisc only once (which was already handled by the patch two prior to this one), but also the filter rule for checksum fixing and the filter rule for bandwidth management must be different priorities so they don't clash; this is solved by adding the checksum-fix filter with "priority 2", while the bandwidth management filter remains "priority 1" (both will always be evaluated anyway, it's just a matter of which is evaluated first). So far this method has worked with every different guest we could throw at it, including several that failed with the previous method. Fixes: b89c4991daa0ee9371f10937fab3b03c5ffdabc6 Reported-by: Rich Jones Reported-by: Andrea Bolognani Fix-Suggested-by: Eric Garver Fix-Suggested-by: Phil Sutter Signed-off-by: Laine Stump Reviewed-by: Michal Privoznik --- src/network/network_nftables.c | 68 +++++++++++++++++++ .../forward-dev-linux.nftables | 40 +++++++++++ .../isolated-linux.nftables | 40 +++++++++++ .../nat-default-linux.nftables | 40 +++++++++++ .../nat-ipv6-linux.nftables | 40 +++++++++++ .../nat-ipv6-masquerade-linux.nftables | 40 +++++++++++ .../nat-many-ips-linux.nftables | 40 +++++++++++ .../nat-no-dhcp-linux.nftables | 40 +++++++++++ .../nat-port-range-ipv6-linux.nftables | 40 +++++++++++ .../nat-port-range-linux.nftables | 40 +++++++++++ .../nat-tftp-linux.nftables | 40 +++++++++++ .../route-default-linux.nftables | 40 +++++++++++ 12 files changed, 508 insertions(+) diff --git a/src/network/network_nftables.c b/src/network/network_nftables.c index b3605bd40e..5d716264bf 100644 --- a/src/network/network_nftables.c +++ b/src/network/network_nftables.c @@ -29,6 +29,7 @@ =20 #include "internal.h" #include "virfirewalld.h" +#include "vircommand.h" #include "virerror.h" #include "virlog.h" #include "virhash.h" @@ -924,6 +925,67 @@ nftablesAddIPSpecificFirewallRules(virFirewall *fw, } =20 =20 +/** + * nftablesAddUdpChecksumFixWithTC: + * + * Add a tc filter rule to @ifname (the bridge device of this network) + * that will recompute the checksum of udp packets output from @iface with + * destination port @port. + * + * Normally the checksum should be filled by some part of the basic + * network stack, but there are cases (e.g. DHCP response packets sent + * from virtualization host to a QEMU guest when the guest NIC uses + * vhost-net packet processing) when the host (sender) thinks that + * packet checksums will be computed elsewhere (and so leaves a + * partially computed checksum in the packet header) while the guest + * (receiver) thinks that the checksum has already been fully + * computed; in the meantime none of the code in between has actually + * finished computing the checksum. + * + * An example of this is DHCP response packets from host to guest. If + * the checksum of each of these packets isn't properly computed, then + * many guests (e.g. FreeBSD) will drop them with reason BAD CHECKSUM; + * this tc filter rule will fix the ip and udp checksums, and the + * FreeBSD dhcp client will happily accept the packet. + * + * (NB: if you're wondering how the tc qdisc and filter are removed + * when the network is destroyed, the answer is that the kernel + * automatically (and properly) removes them for us, so we don't need + * to worry about keeping track/deleting as we do with nftables rules) + */ +static int +nftablesAddUdpChecksumFixWithTC(virFirewall *fw, + const char *iface, + int port) +{ + g_autofree char *portstr =3D g_strdup_printf("%d", port); + + /* this will add the qdisc (that the filter below is attached to) + * unless it already exists + */ + if (virNetDevBandWidthAddTxFilterParentQdisc(iface, true) < 0) + return -1; + + /* add a filter to catch all udp packets with dst "port" and + * recompute their checksum + */ + virFirewallAddCmd(fw, VIR_FIREWALL_LAYER_TC, + "filter", "add", "dev", iface, + "prio", "2", "protocol", "ip", "parent", "1:", + "u32", "match", "ip", "dport", portstr, "ffff", + "action", "csum", "ip", "and", "udp", + NULL); + + virFirewallAddRollbackCmd(fw, VIR_FIREWALL_LAYER_TC, + "filter", "del", "dev", iface, + "prio", "2", "protocol", "ip", "parent", "1:= ", + "u32", "match", "ip", "dport", portstr, "fff= f", + "action", "csum", "ip", "and", "udp", + NULL); + return 0; +} + + /* nftablesAddFirewallrules: * * @def - the network that needs an nftables firewall added @@ -944,6 +1006,12 @@ nftablesAddFirewallRules(virNetworkDef *def, virFirew= all **fwRemoval) =20 virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK= ); =20 + /* add the tc filter rule needed to fixup the checksum of dhcp + * response packets going from host to guest. + */ + if (nftablesAddUdpChecksumFixWithTC(fw, def->bridge, 68) < 0) + return -1; + nftablesAddGeneralFirewallRules(fw, def); =20 for (i =3D 0; diff --git a/tests/networkxml2firewalldata/forward-dev-linux.nftables b/tes= ts/networkxml2firewalldata/forward-dev-linux.nftables index 8badb74beb..6772383b37 100644 --- a/tests/networkxml2firewalldata/forward-dev-linux.nftables +++ b/tests/networkxml2firewalldata/forward-dev-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ diff --git a/tests/networkxml2firewalldata/isolated-linux.nftables b/tests/= networkxml2firewalldata/isolated-linux.nftables index d1b4dac178..546a18b75a 100644 --- a/tests/networkxml2firewalldata/isolated-linux.nftables +++ b/tests/networkxml2firewalldata/isolated-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ diff --git a/tests/networkxml2firewalldata/nat-default-linux.nftables b/tes= ts/networkxml2firewalldata/nat-default-linux.nftables index 28508292f9..08623c1381 100644 --- a/tests/networkxml2firewalldata/nat-default-linux.nftables +++ b/tests/networkxml2firewalldata/nat-default-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ diff --git a/tests/networkxml2firewalldata/nat-ipv6-linux.nftables b/tests/= networkxml2firewalldata/nat-ipv6-linux.nftables index d8a9ba706d..3fd6b94eef 100644 --- a/tests/networkxml2firewalldata/nat-ipv6-linux.nftables +++ b/tests/networkxml2firewalldata/nat-ipv6-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ diff --git a/tests/networkxml2firewalldata/nat-ipv6-masquerade-linux.nftabl= es b/tests/networkxml2firewalldata/nat-ipv6-masquerade-linux.nftables index a7f09cda59..2811e098d1 100644 --- a/tests/networkxml2firewalldata/nat-ipv6-masquerade-linux.nftables +++ b/tests/networkxml2firewalldata/nat-ipv6-masquerade-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ diff --git a/tests/networkxml2firewalldata/nat-many-ips-linux.nftables b/te= sts/networkxml2firewalldata/nat-many-ips-linux.nftables index b826fe6134..5409d5b552 100644 --- a/tests/networkxml2firewalldata/nat-many-ips-linux.nftables +++ b/tests/networkxml2firewalldata/nat-many-ips-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ diff --git a/tests/networkxml2firewalldata/nat-no-dhcp-linux.nftables b/tes= ts/networkxml2firewalldata/nat-no-dhcp-linux.nftables index d8a9ba706d..3fd6b94eef 100644 --- a/tests/networkxml2firewalldata/nat-no-dhcp-linux.nftables +++ b/tests/networkxml2firewalldata/nat-no-dhcp-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ diff --git a/tests/networkxml2firewalldata/nat-port-range-ipv6-linux.nftabl= es b/tests/networkxml2firewalldata/nat-port-range-ipv6-linux.nftables index ceaed6fa40..d74417cdb3 100644 --- a/tests/networkxml2firewalldata/nat-port-range-ipv6-linux.nftables +++ b/tests/networkxml2firewalldata/nat-port-range-ipv6-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ diff --git a/tests/networkxml2firewalldata/nat-port-range-linux.nftables b/= tests/networkxml2firewalldata/nat-port-range-linux.nftables index 1dc37a26ec..b55bb287a9 100644 --- a/tests/networkxml2firewalldata/nat-port-range-linux.nftables +++ b/tests/networkxml2firewalldata/nat-port-range-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ diff --git a/tests/networkxml2firewalldata/nat-tftp-linux.nftables b/tests/= networkxml2firewalldata/nat-tftp-linux.nftables index 28508292f9..08623c1381 100644 --- a/tests/networkxml2firewalldata/nat-tftp-linux.nftables +++ b/tests/networkxml2firewalldata/nat-tftp-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ diff --git a/tests/networkxml2firewalldata/route-default-linux.nftables b/t= ests/networkxml2firewalldata/route-default-linux.nftables index 282c9542a5..76d6902517 100644 --- a/tests/networkxml2firewalldata/route-default-linux.nftables +++ b/tests/networkxml2firewalldata/route-default-linux.nftables @@ -1,3 +1,43 @@ +tc \ +qdisc \ +show \ +dev \ +virbr0 \ +handle \ +1: +tc \ +qdisc \ +add \ +dev \ +virbr0 \ +root \ +handle \ +1: \ +htb \ +default \ +2 +tc \ +filter \ +add \ +dev \ +virbr0 \ +prio \ +2 \ +protocol \ +ip \ +parent \ +1: \ +u32 \ +match \ +ip \ +dport \ +68 \ +ffff \ +action \ +csum \ +ip \ +and \ +udp nft \ -ae insert \ rule \ --=20 2.47.0