From nobody Thu Apr 2 09:18:58 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1774861814; cv=none; d=zohomail.com; s=zohoarc; b=Hv1zAaZtAnIHvt9YjQ0c2owdqmvD5mQkLbS+juAk1EjoysXwhvRKRSiGDABIB6c5yvdWNjYf2q1Yst6nB4XBGmAN6fZleBjDFjk9QbgIZyxbejvT0D/Eo8t1WAeQB9afmElZSIEz9TN+wXcwvHEVsA56ybSvPmFqL5VI5Ff2EwU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774861814; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=HpaQMvAeBNymiB0YG0aOQ6XAIGIw2HM3uBe02GRoBK0=; b=X8NQTs3eibmsOPprVQPSIeqs2X/FMxjawweRFq3Qz4d5qKKBE5e3WD+ElNf8Cvf4S7xRbodgCOstem23kCsyjlGW6HGqzW43f6YiBWuIM3nEgnviwfeZuQh+mh7JrKXjvw/IXUHdPQjbgTLPlXGFIJ0cbrvYgOindJgb8WNUgWQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1774861814367565.1711266117326; Mon, 30 Mar 2026 02:10:14 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w78dM-0005P4-4B; Mon, 30 Mar 2026 05:10:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dI-0005Nj-8Z for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:05 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dF-00009n-Gl for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:03 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-351-TtB7zClROKezXDPPt7hBWw-1; Mon, 30 Mar 2026 05:09:59 -0400 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E367218005BA; Mon, 30 Mar 2026 09:09:57 +0000 (UTC) Received: from S2.redhat.com (unknown [10.72.112.39]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 95C0A30001A2; Mon, 30 Mar 2026 09:09:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1774861800; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HpaQMvAeBNymiB0YG0aOQ6XAIGIw2HM3uBe02GRoBK0=; b=hx3Gt88GE4dGBs01eQ49/2RdGLa8woam5V8y/qHbspbrjYSZce8CcOrW9fvmi1ht4bZ4W/ aJhYc/5Nvpu/wvPz8R/jxSn0WuwavxuiyTmagOpbjcQjM1j7gzjWhluxvASdkleoo3Kcsu W14AeKW3ahYCPu1RgpM56bUJhWByRAY= X-MC-Unique: TtB7zClROKezXDPPt7hBWw-1 X-Mimecast-MFC-AGG-ID: TtB7zClROKezXDPPt7hBWw_1774861798 From: Cindy Lu To: lulu@redhat.com, mst@redhat.com, jasowang@redhat.com, zhangckid@gmail.com, lizhijian@fujitsu.com, jmarcin@redhat.com, qemu-devel@nongnu.org Subject: [RFC v3 1/7] net/filter-mirror: keep mirroring while stopped Date: Mon, 30 Mar 2026 16:58:09 +0800 Message-ID: <20260330090944.1008027-2-lulu@redhat.com> In-Reply-To: <20260330090944.1008027-1-lulu@redhat.com> References: <20260330090944.1008027-1-lulu@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lulu@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -5 X-Spam_score: -0.6 X-Spam_bar: / X-Spam_report: (-0.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1774861817170158500 Content-Type: text/plain; charset="utf-8" During migration pre-switchover the VM runstate is stopped, which can cause= tap read_poll to be disabled (qemu_send_packet_async() returns 0) and inco= ming tap frames stop reaching the redirector/mirror filter. Re-enable tap read_poll when swredir is turned on while stopped, and allow = the redirector outdev path to keep draining packets while stopped by adding= a per-NetClientState allow_send_when_stopped bit used by qemu_can_send_pac= ket(). Signed-off-by: Cindy Lu --- include/net/net.h | 6 ++++++ net/filter-mirror.c | 49 +++++++++++++++++++++++++++++++++++++-------- net/net.c | 10 ++++++++- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/include/net/net.h b/include/net/net.h index d2b2e6fc44..bde052acbb 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -126,6 +126,12 @@ struct NetClientState { char *name; char info_str[256]; unsigned receive_disabled : 1; + /* + * Allow this sender to keep draining packets while VM is stopped. + * Used by COLO-style pre-switchover mirroring, where netfilter needs = to + * see incoming tap frames even when runstate is not running. + */ + unsigned allow_send_when_stopped:1; NetClientDestructor *destructor; unsigned int queue_index; unsigned rxfilter_notify_enabled:1; diff --git a/net/filter-mirror.c b/net/filter-mirror.c index c1b9dabacd..ab711e8835 100644 --- a/net/filter-mirror.c +++ b/net/filter-mirror.c @@ -267,6 +267,10 @@ static void filter_redirector_cleanup(NetFilterState *= nf) qemu_chr_fe_deinit(&s->chr_in, false); qemu_chr_fe_deinit(&s->chr_out, false); qemu_del_vm_change_state_handler(s->vmsentry); + + if (nf->netdev) { + nf->netdev->allow_send_when_stopped =3D 0; + } } =20 static void filter_mirror_setup(NetFilterState *nf, Error **errp) @@ -302,6 +306,27 @@ static void redirector_rs_finalize(SocketReadState *rs) redirector_to_filter(nf, rs->buf, rs->packet_len); } =20 +static void +filter_redirector_refresh_allow_send_when_stopped(NetFilterState *nf) +{ + MirrorState *s =3D FILTER_REDIRECTOR(nf); + NetClientState *nc =3D nf->netdev; + + if (!nc) { + return; + } + + /* + * Allow sending when stopped if enable_when_stopped is set and we have + * an outdev. This must be independent of nf->on (status) so that pack= ets + * can still flow through the filter chain to other filters even when = this + * redirector is disabled. Otherwise, tap_send() will disable read_poll + * when qemu_can_send_packet() returns false, preventing further packet + * processing. + */ + nc->allow_send_when_stopped =3D (s->enable_when_stopped && s->outdev); +} + static void filter_redirector_vm_state_change(void *opaque, bool running, RunState state) { @@ -389,24 +414,30 @@ static void filter_redirector_setup(NetFilterState *n= f, Error **errp) filter_redirector_vm_state_change, nf); =20 filter_redirector_maybe_enable_read_poll(nf); + + filter_redirector_refresh_allow_send_when_stopped(nf); } =20 static void filter_redirector_status_changed(NetFilterState *nf, Error **e= rrp) { MirrorState *s =3D FILTER_REDIRECTOR(nf); =20 - if (!s->indev) { - return; + if (s->indev) { + if (nf->on) { + qemu_chr_fe_set_handlers(&s->chr_in, redirector_chr_can_read, + redirector_chr_read, redirector_chr_e= vent, + NULL, nf, NULL, true); + } else { + qemu_chr_fe_set_handlers(&s->chr_in, NULL, NULL, NULL, + NULL, NULL, NULL, true); + } } =20 if (nf->on) { - qemu_chr_fe_set_handlers(&s->chr_in, redirector_chr_can_read, - redirector_chr_read, redirector_chr_event, - NULL, nf, NULL, true); - } else { - qemu_chr_fe_set_handlers(&s->chr_in, NULL, NULL, NULL, - NULL, NULL, NULL, true); + filter_redirector_maybe_enable_read_poll(nf); } + + filter_redirector_refresh_allow_send_when_stopped(nf); } =20 static char *filter_redirector_get_indev(Object *obj, Error **errp) @@ -518,6 +549,8 @@ static void filter_redirector_set_enable_when_stopped(O= bject *obj, if (value) { filter_redirector_maybe_enable_read_poll(nf); } + + filter_redirector_refresh_allow_send_when_stopped(nf); } =20 static void filter_mirror_class_init(ObjectClass *oc, const void *data) diff --git a/net/net.c b/net/net.c index b15f4db65e..06f54eebb4 100644 --- a/net/net.c +++ b/net/net.c @@ -632,7 +632,7 @@ int qemu_can_send_packet(NetClientState *sender) { int vm_running =3D runstate_is_running(); =20 - if (!vm_running) { + if (!vm_running && !sender->allow_send_when_stopped) { return 0; } =20 @@ -640,6 +640,14 @@ int qemu_can_send_packet(NetClientState *sender) return 1; } =20 + /* + * When VM is stopped (e.g. migration pre-switchover), allow draining = tap + * packets so netfilters (redirector/mirror) can operate. + */ + if (!vm_running && sender->allow_send_when_stopped) { + return 1; + } + return qemu_can_receive_packet(sender->peer); } =20 --=20 2.52.0 From nobody Thu Apr 2 09:18:58 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1774861824; cv=none; d=zohomail.com; s=zohoarc; b=bnwTKUJnd9kj2Q3bMYxxEUKqM0buuTeWlO55nG/Ap6NuIleN2VcYfMeD8KhqEWsTD1xyIys9YXTCpdsApNaL2kuq4Zf6mnZlDg+3qgk3UzDmUAuFRYSO+dF0X3RAcVc5L90cXJBZogrPV02JX7yRuErD0JSt6AuHzTew7VQK/uA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774861824; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=ARJckNFV7lxLiDyqSx4CiZiaQcGSW8eGYbJQBu9N1Fw=; b=UJ8u5difhBDZJUW9lDjmFiVFUjbTmOuNt3GxhRfYtHzDunEB2aUDoTopb0EZ1uxn10XzSEw9Sj7tQwlbRge/8/0G2BU64YGVOUY/ngSrqzWqD3CnRfSPjp3dqNlzeMeHhYPaEgd8BFjjqDkPHD2ZQxGrm81fWNM8ryzeLfwsQno= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1774861824346287.45331696058497; Mon, 30 Mar 2026 02:10:24 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w78dR-0005Q4-1X; Mon, 30 Mar 2026 05:10:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dN-0005PE-Po for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:11 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dL-0000N9-OC for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:09 -0400 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-580-3Q9rNd8yO52787MW6BFHNg-1; Mon, 30 Mar 2026 05:10:02 -0400 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 CE1341955E80; Mon, 30 Mar 2026 09:10:01 +0000 (UTC) Received: from S2.redhat.com (unknown [10.72.112.39]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9713C30001A1; Mon, 30 Mar 2026 09:09:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1774861806; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ARJckNFV7lxLiDyqSx4CiZiaQcGSW8eGYbJQBu9N1Fw=; b=WFtqLohAyRSw1MRdaXW3sA5bFWBrL3fqr6tA7PaT06BcEfindsOnJqJa2Lhtc4QEIuddcN /rqcN5TuuGDns0bB/oRgbNt2kB3FYiPAybx9qSeiGEh38VfHcaPJku600f37YLsrfLmLRU IfAb4pTyw2Je5CLNe2uCechFo5wJcUI= X-MC-Unique: 3Q9rNd8yO52787MW6BFHNg-1 X-Mimecast-MFC-AGG-ID: 3Q9rNd8yO52787MW6BFHNg_1774861802 From: Cindy Lu To: lulu@redhat.com, mst@redhat.com, jasowang@redhat.com, zhangckid@gmail.com, lizhijian@fujitsu.com, jmarcin@redhat.com, qemu-devel@nongnu.org Subject: [RFC v3 2/7] virtio-net: keep tap read polling disabled while vhost owns RX Date: Mon, 30 Mar 2026 16:58:10 +0800 Message-ID: <20260330090944.1008027-3-lulu@redhat.com> In-Reply-To: <20260330090944.1008027-1-lulu@redhat.com> References: <20260330090944.1008027-1-lulu@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=lulu@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 27 X-Spam_score: 2.7 X-Spam_bar: ++ X-Spam_report: (2.7 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_SBL_CSS=3.335, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1774861826697154100 Content-Type: text/plain; charset="utf-8" virtio_net_backend_read_poll_set() re-enables TAP read polling on vmstart even when kernel vhost has already taken over RX. That lets QEMU userspace and vhost race on the same tap fd and can corrupt the restored virtqueue state during migration switchover. Keep read_poll disabled for TAP backends with a started vhost_net, while leaving pure userspace backends unchanged. Signed-off-by: Cindy Lu --- hw/net/virtio-net.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index d6d2188863..616590fb82 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1322,9 +1322,19 @@ static void virtio_net_backend_read_poll_set(VirtION= et *n, bool enable) for (i =3D 0; i < (int)n->max_ncs; i++) { NetClientState *frontend =3D qemu_get_subqueue(n->nic, i); NetClientState *backend =3D frontend ? frontend->peer : NULL; + bool backend_enable =3D enable; =20 if (backend && backend->info && backend->info->read_poll) { - backend->info->read_poll(backend, enable); + /* + * When vhost is active, the kernel backend owns the tap RX pa= th. + * Re-enabling QEMU read_poll on vmstart makes userspace and v= host + * race on the same tap fd, which can corrupt the restored RX = ring + * during migration switchover replay. + */ + if (enable && get_vhost_net(backend) && n->vhost_started) { + backend_enable =3D false; + } + backend->info->read_poll(backend, backend_enable); } } } --=20 2.52.0 From nobody Thu Apr 2 09:18:58 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1774861826; cv=none; d=zohomail.com; s=zohoarc; b=HGg001X3TAKIqxgZXh1tXUnftECgWnQChPyHPbcFGD4LoI9UIrgDeN5AP0MXNbdyIHiSLzb/HrknDaI4KCxG0VLckW1jOychFp/ofWAfHADq4aW9d56b9Ua+Gjjpn8t+5nYPec0JpbWeAx4HxPRypjPLMyihWZI7yrKYPWwprSE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774861826; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=RRWno4DoMHQAFKmIk4fJA+2FKgaKaWQkcckpkoQAejg=; b=DwqDd0F2oQ3lmRnKYMiSnKUN7e3+MVZcipoHexTZvhvhutMmTt+F9aZaEfbW5z3X882vQqUvsJNyfVEvBnzxId8/4TtmrEDWZySscooW4sPplPvuefRShi11/8TlnmqI8SVELhgL8vZLFoaGmOzBhmLOSaCE98mu/EKgDKGc7No= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1774861826679266.3292854908659; Mon, 30 Mar 2026 02:10:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w78dS-0005SK-VJ; Mon, 30 Mar 2026 05:10:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dQ-0005Q3-SF for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:12 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dO-0000NX-Vl for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:12 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-423-0eCi7j8tP_iSZyg5YERkfA-1; Mon, 30 Mar 2026 05:10:06 -0400 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C93C618005B3; Mon, 30 Mar 2026 09:10:05 +0000 (UTC) Received: from S2.redhat.com (unknown [10.72.112.39]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7F34C30001A1; Mon, 30 Mar 2026 09:10:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1774861810; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RRWno4DoMHQAFKmIk4fJA+2FKgaKaWQkcckpkoQAejg=; b=HbqI5c4/18vBvE2PtiJOHlKmEDiXsSVYGBwA7/D0RozOEuli0P3lWJ2ORTY6xMgY/I1LDc ejFJL5l9+nu9UNjE7/6i2wOblkT2cJ5FRzSNeAXprpvH1qEunN/VMEDhg7sKbzCMriENcs 6OgNLmrVhqlX43u8SFrWQ6fK09T6Ta0= X-MC-Unique: 0eCi7j8tP_iSZyg5YERkfA-1 X-Mimecast-MFC-AGG-ID: 0eCi7j8tP_iSZyg5YERkfA_1774861806 From: Cindy Lu To: lulu@redhat.com, mst@redhat.com, jasowang@redhat.com, zhangckid@gmail.com, lizhijian@fujitsu.com, jmarcin@redhat.com, qemu-devel@nongnu.org Subject: [RFC v3 3/7] net/filter-redirector: add AF_PACKET netdev setup helpers Date: Mon, 30 Mar 2026 16:58:11 +0800 Message-ID: <20260330090944.1008027-4-lulu@redhat.com> In-Reply-To: <20260330090944.1008027-1-lulu@redhat.com> References: <20260330090944.1008027-1-lulu@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lulu@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -5 X-Spam_score: -0.6 X-Spam_bar: / X-Spam_report: (-0.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1774861826981158500 Content-Type: text/plain; charset="utf-8" Prepare filter-redirector for direct TAP access through AF_PACKET sockets. Add the setup-side plumbing needed by later capture/inject changes: - extend MirrorState with dedicated AF_PACKET fds and a capture buffer - resolve the TAP ifname from the backend fd - create and bind a nonblocking AF_PACKET socket on that interface - store the socket as the capture or inject endpoint based on the redirector role - clean up the AF_PACKET resources from cleanup/finalize paths This commit only prepares the sockets and object state. The actual capture and inject datapaths are added by follow-up commits. Signed-off-by: Cindy Lu --- net/filter-mirror.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/net/filter-mirror.c b/net/filter-mirror.c index ab711e8835..d9f6a11d6b 100644 --- a/net/filter-mirror.c +++ b/net/filter-mirror.c @@ -22,10 +22,18 @@ #include "qemu/error-report.h" #include "trace.h" #include "chardev/char-fe.h" +#include "net/vhost_net.h" #include "qemu/iov.h" #include "qemu/sockets.h" #include "block/aio-wait.h" #include "system/runstate.h" +#include "net/tap.h" +#include "net/tap_int.h" + +#include +#include +#include +#include =20 typedef struct MirrorState MirrorState; DECLARE_INSTANCE_CHECKER(MirrorState, FILTER_MIRROR, @@ -40,6 +48,9 @@ struct MirrorState { NetFilterState parent_obj; char *indev; char *outdev; + int in_netfd; + uint8_t *in_netbuf; + int out_netfd; CharFrontend chr_in; CharFrontend chr_out; SocketReadState rs; @@ -267,6 +278,15 @@ static void filter_redirector_cleanup(NetFilterState *= nf) qemu_chr_fe_deinit(&s->chr_in, false); qemu_chr_fe_deinit(&s->chr_out, false); qemu_del_vm_change_state_handler(s->vmsentry); + if (s->in_netfd >=3D 0) { + qemu_set_fd_handler(s->in_netfd, NULL, NULL, NULL); + close(s->in_netfd); + s->in_netfd =3D -1; + } + if (s->out_netfd >=3D 0) { + close(s->out_netfd); + s->out_netfd =3D -1; + } =20 if (nf->netdev) { nf->netdev->allow_send_when_stopped =3D 0; @@ -360,6 +380,70 @@ static void filter_redirector_maybe_enable_read_poll(N= etFilterState *nf) } } =20 +static bool filter_redirector_netdev_setup(NetFilterState *nf, Error **err= p) +{ + MirrorState *s =3D FILTER_REDIRECTOR(nf); + struct sockaddr_ll sll =3D { 0 }; + char ifname[IFNAMSIZ] =3D { 0 }; + bool capture_role; + bool inject_role; + int ifindex; + int fd; + NetClientState *nc =3D nf->netdev; + int tapfd; + + if (!nc || nc->info->type !=3D NET_CLIENT_DRIVER_TAP) { + return true; + } + + capture_role =3D s->outdev && !s->indev && get_vhost_net(nc); + inject_role =3D s->indev && !s->outdev && get_vhost_net(nc); + if (!capture_role && !inject_role) { + return true; + } + + tapfd =3D tap_get_fd(nc); + if (tapfd < 0 || tap_fd_get_ifname(tapfd, ifname) !=3D 0) { + error_setg(errp, "failed to resolve TAP ifname for netdev '%s'", + nf->netdev_id); + return false; + } + + ifindex =3D if_nametoindex(ifname); + if (!ifindex) { + error_setg_errno(errp, errno, + "failed to resolve ifindex for '%s'", ifname); + return false; + } + + fd =3D qemu_socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_AL= L)); + if (fd < 0) { + error_setg_errno(errp, errno, "failed to create AF_PACKET socket"); + return false; + } + + sll.sll_family =3D AF_PACKET; + sll.sll_ifindex =3D ifindex; + sll.sll_protocol =3D htons(ETH_P_ALL); + if (bind(fd, (struct sockaddr *)&sll, sizeof(sll)) < 0) { + error_setg_errno(errp, errno, + "failed to bind AF_PACKET socket for ifname '%s'", + ifname); + close(fd); + return false; + } + + if (capture_role) { + s->in_netfd =3D fd; + g_free(s->in_netbuf); + s->in_netbuf =3D g_malloc(REDIRECTOR_MAX_LEN); + } else { + s->out_netfd =3D fd; + } + + return true; +} + static void filter_redirector_setup(NetFilterState *nf, Error **errp) { MirrorState *s =3D FILTER_REDIRECTOR(nf); @@ -410,6 +494,10 @@ static void filter_redirector_setup(NetFilterState *nf= , Error **errp) } } =20 + if (!filter_redirector_netdev_setup(nf, errp)) { + return; + } + s->vmsentry =3D qemu_add_vm_change_state_handler( filter_redirector_vm_state_change, nf); =20 @@ -623,6 +711,8 @@ static void filter_redirector_init(Object *obj) MirrorState *s =3D FILTER_REDIRECTOR(obj); =20 s->vnet_hdr =3D false; + s->in_netfd =3D -1; + s->out_netfd =3D -1; } =20 static void filter_mirror_fini(Object *obj) @@ -638,6 +728,7 @@ static void filter_redirector_fini(Object *obj) =20 g_free(s->indev); g_free(s->outdev); + g_free(s->in_netbuf); } =20 static const TypeInfo filter_redirector_info =3D { --=20 2.52.0 From nobody Thu Apr 2 09:18:58 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1774861869; cv=none; d=zohomail.com; s=zohoarc; b=cNKXlodEXENiEnl1YgE14T8eJA6Wku1RvqW8kl8PUDnsmVoPjhfMdwq0d2wx8VuSiJXX+Bj6ZzB8ESiYQ54RLXTCVPOQD46rFMG68Svsm2Se8/Wy5NYUG61EB4T1Fev/RVRmuftdE6a+vZiGu4JxciKKVLn6jddt/IuM5vDNXGw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774861869; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=JCiM3aSs/f1RsAuqeti67op//+DqhHvZTedMuAAYf4w=; b=XRPxZSBm+BEg4JBxVIXxtsN5rHpCAJwc+pvrOYRo813E+Qnhx1ib8gqO6FuHGCFk6fkOb1LMBUyFoyZrJIbD60U+Vvxtuj4C0tTNRpwToRb9uxrRQGN8QOc0q9xss8rIPLimaSDVTFHp8EsprkL/FS6u3hWORt4B5uvcQ7AJUAw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1774861869520388.2795532682919; Mon, 30 Mar 2026 02:11:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w78eF-0006FO-So; Mon, 30 Mar 2026 05:11:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dr-00067Y-5d for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:39 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dp-0000Pa-4W for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:38 -0400 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-433-yRAAiayANlWoY3rpqRISPA-1; Mon, 30 Mar 2026 05:10:32 -0400 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 B4E7719560A1; Mon, 30 Mar 2026 09:10:31 +0000 (UTC) Received: from S2.redhat.com (unknown [10.72.112.39]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 422DD19560AB; Mon, 30 Mar 2026 09:10:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1774861834; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JCiM3aSs/f1RsAuqeti67op//+DqhHvZTedMuAAYf4w=; b=Sw17PCiD+uReuAiseG5SattOGpTvGVcfp9p+swltT+RTg4QuZPKqBjb47kh/5EN7P3vMdV FWV2/6gIUrQEuEcU7gOSRLl6egC1ssMLTt+BruIbkaTYLGGg6nO8j7RQE22Q0IJcXkQoJo 7nGy4EBng8PVVCoJOOJQaTSHbDvuwTU= X-MC-Unique: yRAAiayANlWoY3rpqRISPA-1 X-Mimecast-MFC-AGG-ID: yRAAiayANlWoY3rpqRISPA_1774861831 From: Cindy Lu To: lulu@redhat.com, mst@redhat.com, jasowang@redhat.com, zhangckid@gmail.com, lizhijian@fujitsu.com, jmarcin@redhat.com, qemu-devel@nongnu.org Subject: [RFC v3 4/7] net/filter-redirector: add AF_PACKET capture path Date: Mon, 30 Mar 2026 16:58:12 +0800 Message-ID: <20260330090944.1008027-5-lulu@redhat.com> In-Reply-To: <20260330090944.1008027-1-lulu@redhat.com> References: <20260330090944.1008027-1-lulu@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lulu@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 27 X-Spam_score: 2.7 X-Spam_bar: ++ X-Spam_report: (2.7 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_SBL_CSS=3.335, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1774861871171158500 Content-Type: text/plain; charset="utf-8" Wire the capture-side AF_PACKET socket into filter-redirector. When the redirector owns an AF_PACKET capture socket, install a read handler that drains PACKET_OUTGOING frames from the TAP device and forwards them into the existing redirector chardev path. Reuse the normal chardev packet framing so downstream code sees the same transport format as it already handles today, and keep redirector statistics updated through the same helper. AF_PACKET delivers a raw Ethernet frame while the redirector chardev path can carry packets with an empty vnet header wrapper. When the backend has a vnet header length, prepend an empty legacy virtio-net header before the frame so the captured packet can move through the same chardev transport as regular redirector traffic. Hook the fd handler up during setup, status changes and VM state changes so capture is only active when the redirector is enabled and allowed to run in the current VM state. Signed-off-by: Cindy Lu --- net/filter-mirror.c | 121 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/net/filter-mirror.c b/net/filter-mirror.c index d9f6a11d6b..e114ddb7d1 100644 --- a/net/filter-mirror.c +++ b/net/filter-mirror.c @@ -43,6 +43,7 @@ DECLARE_INSTANCE_CHECKER(MirrorState, FILTER_REDIRECTOR, TYPE_FILTER_REDIRECTOR) =20 #define REDIRECTOR_MAX_LEN NET_BUFSIZE +#define REDIRECTOR_AF_PACKET_WRAP_LEN sizeof(struct virtio_net_hdr) =20 struct MirrorState { NetFilterState parent_obj; @@ -181,6 +182,17 @@ static int redirector_chr_can_read(void *opaque) return REDIRECTOR_MAX_LEN; } =20 +static bool filter_redirector_input_active(NetFilterState *nf, bool enable) +{ + MirrorState *s =3D FILTER_REDIRECTOR(nf); + + if (!enable) { + return false; + } + + return runstate_is_running() || s->enable_when_stopped; +} + static void redirector_chr_read(void *opaque, const uint8_t *buf, int size) { NetFilterState *nf =3D opaque; @@ -217,6 +229,91 @@ static void redirector_chr_event(void *opaque, QEMUChr= Event event) } } =20 +static int filter_redirector_send_chardev_iov(MirrorState *s, + const struct iovec *iov, + int iovcnt) +{ + int ret; + + if (!qemu_chr_fe_backend_connected(&s->chr_out)) { + return 0; + } + + ret =3D filter_send(s, iov, iovcnt); + if (ret > 0) { + s->outdev_packets++; + s->outdev_bytes +=3D ret; + } + + return ret; +} + +static void filter_redirector_capture_netdev_read(void *opaque) +{ + NetFilterState *nf =3D opaque; + MirrorState *s =3D FILTER_REDIRECTOR(nf); + char vnet_hdr[REDIRECTOR_AF_PACKET_WRAP_LEN] =3D { 0 }; + struct iovec iov[2]; + struct sockaddr_ll sll; + socklen_t sll_len; + ssize_t len; + size_t wrap_vnet_hdr_len; + int iovcnt; + int ret; + + if (!s->in_netbuf || s->in_netfd < 0) { + return; + } + + for (;;) { + sll_len =3D sizeof(sll); + len =3D recvfrom(s->in_netfd, s->in_netbuf, REDIRECTOR_MAX_LEN, 0, + (struct sockaddr *)&sll, &sll_len); + if (len <=3D 0) { + break; + } + + if (sll.sll_pkttype !=3D PACKET_OUTGOING) { + continue; + } + + /* + * AF_PACKET gives us a raw Ethernet frame. Wrap it as a regular + * redirector payload by prepending an empty legacy virtio-net hea= der, + * so the downstream chardev path can treat it like a normal packe= t. + */ + wrap_vnet_hdr_len =3D qemu_get_vnet_hdr_len(nf->netdev) ? + REDIRECTOR_AF_PACKET_WRAP_LEN : 0; + if (len + wrap_vnet_hdr_len > REDIRECTOR_MAX_LEN) { + error_report("filter redirector packet too large after wrap(%z= d)", + len); + continue; + } + + iov[0].iov_base =3D s->in_netbuf; + iov[0].iov_len =3D len; + iovcnt =3D 1; + if (wrap_vnet_hdr_len) { + iov[0].iov_base =3D vnet_hdr; + iov[0].iov_len =3D wrap_vnet_hdr_len; + iov[1].iov_base =3D s->in_netbuf; + iov[1].iov_len =3D len; + iovcnt =3D 2; + } + + ret =3D filter_redirector_send_chardev_iov(s, iov, iovcnt); + if (ret < 0) { + error_report("filter redirector send failed(%s)", strerror(-re= t)); + } + } + + if (len < 0 && errno !=3D EAGAIN && errno !=3D EWOULDBLOCK && + errno !=3D EINTR) { + error_report("filter redirector read netdev failed(%s)", + strerror(errno)); + } +} + static ssize_t filter_mirror_receive_iov(NetFilterState *nf, NetClientState *sender, unsigned flags, @@ -353,6 +450,14 @@ static void filter_redirector_vm_state_change(void *op= aque, bool running, NetFilterState *nf =3D opaque; MirrorState *s =3D FILTER_REDIRECTOR(nf); NetClientState *nc =3D nf->netdev; + bool active =3D filter_redirector_input_active(nf, nf->on); + + if (s->in_netfd >=3D 0) { + qemu_set_fd_handler(s->in_netfd, + active ? + filter_redirector_capture_netdev_read : NULL, + NULL, active ? nf : NULL); + } =20 if (!running && s->enable_when_stopped && nc->info->read_poll) { nc->info->read_poll(nc, true); @@ -448,6 +553,7 @@ static void filter_redirector_setup(NetFilterState *nf,= Error **errp) { MirrorState *s =3D FILTER_REDIRECTOR(nf); Chardev *chr; + bool active =3D filter_redirector_input_active(nf, nf->on); =20 if (!s->indev && !s->outdev) { error_setg(errp, "filter redirector needs 'indev' or " @@ -501,6 +607,13 @@ static void filter_redirector_setup(NetFilterState *nf= , Error **errp) s->vmsentry =3D qemu_add_vm_change_state_handler( filter_redirector_vm_state_change, nf); =20 + if (s->in_netfd >=3D 0) { + qemu_set_fd_handler(s->in_netfd, + active ? + filter_redirector_capture_netdev_read : NULL, + NULL, active ? nf : NULL); + } + filter_redirector_maybe_enable_read_poll(nf); =20 filter_redirector_refresh_allow_send_when_stopped(nf); @@ -509,6 +622,7 @@ static void filter_redirector_setup(NetFilterState *nf,= Error **errp) static void filter_redirector_status_changed(NetFilterState *nf, Error **e= rrp) { MirrorState *s =3D FILTER_REDIRECTOR(nf); + bool active =3D filter_redirector_input_active(nf, nf->on); =20 if (s->indev) { if (nf->on) { @@ -521,6 +635,13 @@ static void filter_redirector_status_changed(NetFilter= State *nf, Error **errp) } } =20 + if (s->in_netfd >=3D 0) { + qemu_set_fd_handler(s->in_netfd, + active ? + filter_redirector_capture_netdev_read : NULL, + NULL, active ? nf : NULL); + } + if (nf->on) { filter_redirector_maybe_enable_read_poll(nf); } --=20 2.52.0 From nobody Thu Apr 2 09:18:58 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1774861876; cv=none; d=zohomail.com; s=zohoarc; b=joMoF3qZ5+5VgrIdtSvp4PHG3PBv8A0dnAMJqgCSZxfs/W9GgLZ685RarQrXtZoRx1vj8jqzPIOIR6YMTfSFwW45ZcGRkTlRk+IXcjZvGH9IXm6fdMVkiLuRV373K/vnNxlrx5/+WjXFsL7qZ2T67h5O6Ktv74SqhBUtmEG8Okw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774861876; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=b3CqbJi2MH8xVeq0Ual/M4Y93TyxFUpwdAas+AN4prc=; b=Yh0x59C8Pk0zTicGPNy79zExw364YP/BWDvyqNzT7PVP1weL9SF9hJ5L1ErZInZy5qguiXawp69vxY/uw9noZ/hyIaYGTHZ6oYDOP+6H5hiiVCCrl5JQEhQ61mg1UmZWfFXaDLiH6c4+OKeHOZ5v7w5aI3ONagUN5u27feZsDNY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1774861876089250.01903370209016; Mon, 30 Mar 2026 02:11:16 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w78eO-0006T2-A4; Mon, 30 Mar 2026 05:11:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dv-00069M-KY for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:49 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dt-0000Q8-0i for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:42 -0400 Received: from mx-prod-mc-03.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-497-OtkyH6U5P6-sJYQu2gy6JQ-1; Mon, 30 Mar 2026 05:10:36 -0400 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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9D97A1944EB3; Mon, 30 Mar 2026 09:10:35 +0000 (UTC) Received: from S2.redhat.com (unknown [10.72.112.39]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6720B19560AB; Mon, 30 Mar 2026 09:10:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1774861840; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=b3CqbJi2MH8xVeq0Ual/M4Y93TyxFUpwdAas+AN4prc=; b=DKM4I1zy769AwH66BvsfmfgUS81ovGV0coxaXvskN4xCiWIq9k7avl9MZWwjYv+UoCoerR bHSIKJj01UG2W14KubgTbDC4fEcf8KW7op7WnO38zmU332eNEs/KS5xfrN2R98za10seVR WNAbapwj3V3rXLEhX5dkJgiJe8T/9BI= X-MC-Unique: OtkyH6U5P6-sJYQu2gy6JQ-1 X-Mimecast-MFC-AGG-ID: OtkyH6U5P6-sJYQu2gy6JQ_1774861835 From: Cindy Lu To: lulu@redhat.com, mst@redhat.com, jasowang@redhat.com, zhangckid@gmail.com, lizhijian@fujitsu.com, jmarcin@redhat.com, qemu-devel@nongnu.org Subject: [RFC v3 5/7] net/filter-redirector: add AF_PACKET inject path Date: Mon, 30 Mar 2026 16:58:13 +0800 Message-ID: <20260330090944.1008027-6-lulu@redhat.com> In-Reply-To: <20260330090944.1008027-1-lulu@redhat.com> References: <20260330090944.1008027-1-lulu@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lulu@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 27 X-Spam_score: 2.7 X-Spam_bar: ++ X-Spam_report: (2.7 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_SBL_CSS=3.335, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1774861879173154100 Content-Type: text/plain; charset="utf-8" Allow redirector packets to be injected back into a vhost-backed TAP backend without going through the normal peer queue. Export a redirector helper that sends an iov directly through the redirector's AF_PACKET inject socket, and teach qemu_netfilter_pass_to_next= () to use it when the sender is backed by vhost. This lets the redirector reinject traffic into the TAP device even when the regular userspace path is bypassed by vhost. The redirector chardev transport may carry an empty vnet header wrapper before the Ethernet frame. Detect the longest supported all-zero wrapper and strip it before sendmsg() so the AF_PACKET inject side always writes a raw L2 frame back to TAP. Propagate sendmsg() failures through ssize_t so the caller can report partial/failed injection cleanly. Signed-off-by: Cindy Lu --- include/net/filter.h | 6 +++ net/filter-mirror.c | 94 ++++++++++++++++++++++++++++++++++++++++++++ net/filter.c | 11 +++++- 3 files changed, 110 insertions(+), 1 deletion(-) diff --git a/include/net/filter.h b/include/net/filter.h index f0673c9163..68076a66ad 100644 --- a/include/net/filter.h +++ b/include/net/filter.h @@ -91,6 +91,12 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *send= er, int iovcnt, void *opaque); =20 +bool qemu_netfilter_redirector_inject_netdev(NetFilterState *nf, + NetClientState *sender, + const struct iovec *iov, + int iovcnt, + ssize_t *retp); + void colo_notify_filters_event(int event, Error **errp); =20 #endif /* QEMU_NET_FILTER_H */ diff --git a/net/filter-mirror.c b/net/filter-mirror.c index e114ddb7d1..165a7ee1ea 100644 --- a/net/filter-mirror.c +++ b/net/filter-mirror.c @@ -74,6 +74,100 @@ typedef struct FilterSendCo { int ret; } FilterSendCo; =20 +static size_t filter_redirector_wrapped_vnet_hdr_len(const struct iovec *i= ov, + int iovcnt) +{ + static const size_t lens[] =3D { + sizeof(struct virtio_net_hdr_v1_hash_tunnel), + sizeof(struct virtio_net_hdr_v1_hash), + sizeof(struct virtio_net_hdr_mrg_rxbuf), + sizeof(struct virtio_net_hdr), + }; + uint8_t hdr[sizeof(struct virtio_net_hdr_v1_hash_tunnel)] =3D { 0 }; + uint8_t zero[sizeof(hdr)] =3D { 0 }; + size_t total =3D iov_size(iov, iovcnt); + size_t len; + int i; + + for (i =3D 0; i < ARRAY_SIZE(lens); i++) { + len =3D lens[i]; + if (len >=3D total) { + continue; + } + if (iov_to_buf(iov, iovcnt, 0, hdr, len) =3D=3D len && + !memcmp(hdr, zero, len)) { + return len; + } + } + + return 0; +} + + +bool qemu_netfilter_redirector_inject_netdev(NetFilterState *nf, + NetClientState *sender, + const struct iovec *iov, + int iovcnt, + ssize_t *retp) +{ + MirrorState *s; + struct iovec local_iov =3D { 0 }; + struct msghdr msg =3D { + .msg_iov =3D (struct iovec *)iov, + .msg_iovlen =3D iovcnt, + }; + ssize_t ret; + size_t size; + size_t wrapped_vnet_hdr_len; + + if (!object_dynamic_cast(OBJECT(nf), TYPE_FILTER_REDIRECTOR)) { + return false; + } + + s =3D FILTER_REDIRECTOR(nf); + if (s->out_netfd < 0 || !sender || sender !=3D nf->netdev) { + return false; + } + + wrapped_vnet_hdr_len =3D (!s->vnet_hdr && qemu_get_vnet_hdr_len(sender= )) ? + filter_redirector_wrapped_vnet_hdr_len(iov, iov= cnt) : + 0; + if (wrapped_vnet_hdr_len) { + /* + * Redirector chardev packets can carry an empty virtio-net header + * before the Ethernet frame. Strip the longest supported wrapped + * header before injecting the packet back to TAP. + */ + local_iov.iov_len =3D iov_size(iov, iovcnt) - wrapped_vnet_hdr_len; + local_iov.iov_base =3D g_malloc(local_iov.iov_len); + iov_to_buf(iov, iovcnt, wrapped_vnet_hdr_len, + local_iov.iov_base, + local_iov.iov_len); + msg.msg_iov =3D &local_iov; + msg.msg_iovlen =3D 1; + } + + size =3D iov_size(iov, iovcnt); + if (local_iov.iov_base) { + size =3D local_iov.iov_len; + } + do { + ret =3D sendmsg(s->out_netfd, &msg, 0); + } while (ret < 0 && errno =3D=3D EINTR); + + if (ret < 0) { + *retp =3D -errno; + } else if (ret !=3D size) { + *retp =3D -EIO; + } else { + *retp =3D ret; + } + + g_free(local_iov.iov_base); + + return true; +} + static int _filter_send(MirrorState *s, char *buf, ssize_t size) diff --git a/net/filter.c b/net/filter.c index 76345c1a9d..847dd34698 100644 --- a/net/filter.c +++ b/net/filter.c @@ -81,7 +81,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sende= r, int iovcnt, void *opaque) { - int ret =3D 0; + ssize_t ret =3D 0; int direction; NetFilterState *nf =3D opaque; NetFilterState *next =3D NULL; @@ -124,6 +124,15 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *se= nder, * deleted while we go through filters. */ if (sender && sender->peer) { + if (get_vhost_net(sender) && + qemu_netfilter_redirector_inject_netdev(nf, sender, + iov, iovcnt, &ret)) { + if (ret < 0) { + error_report("filter redirector AF_PACKET send failed(%s)", + strerror(-ret)); + } + goto out; + } qemu_net_queue_send_iov(sender->peer->incoming_queue, sender, flags, iov, iovcnt, NULL); } --=20 2.52.0 From nobody Thu Apr 2 09:18:58 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1774861900; cv=none; d=zohomail.com; s=zohoarc; b=DeUgUW+QwZ4klQH+gwTjqMsFsYuupPGMQTdwHjSuHGC5U0LcYixQ81BamruzSowFRSyDuT9q+Za1iiyNgih+XONLnbDAFtwCBbhEVUbmPrmdnnCBMCdGNJOwPZREydEkUrKVdOA6alnoL1FyJyQPM1aTvmtbY++POBOmjBCsWGU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774861900; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=xyb8HJu3evdR5u4pSDSMiqHu9Ih27Kcpw4fmToyE19s=; b=WYfa+C88nJv8kuwWlA330/bo53Kgumf5o5F4COrAaQNvB07oJSm5KdN50Ag053DiCgjct+VAMGY7kbJDZ4kQimQzX2jtUxpN0YiCLLAyAk/tClyZeZ4FpyuMqUCfjApfqP1yBkRU7eFden0v3hx16tc2uZVSXkXUL3E0/eX3RLw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177486190037446.5896624938033; Mon, 30 Mar 2026 02:11:40 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w78eP-0006aD-PF; Mon, 30 Mar 2026 05:11:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78e1-0006EF-F1 for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:54 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78dx-0000QY-F5 for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:48 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-605-BSpXRIxpOpW7miJCcATQ2w-1; Mon, 30 Mar 2026 05:10:40 -0400 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-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 913CD1800610; Mon, 30 Mar 2026 09:10:39 +0000 (UTC) Received: from S2.redhat.com (unknown [10.72.112.39]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5210419560AB; Mon, 30 Mar 2026 09:10:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1774861844; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xyb8HJu3evdR5u4pSDSMiqHu9Ih27Kcpw4fmToyE19s=; b=aoT/v38ZZ4PqQkNyzhQAnw76sskF0adpAjDpCyhZqOoJBYXM0D10BN7UqBb/rkNpqiz6CB MDggqPLVJnYh+If5JvNmnghxynA8sUYsnTxMF3h+vp4d4T3NjPywlwuAnWD9og1i+QRPAE aMdnsLQVBcjlctSHcYpgA2Ad/bjqmYo= X-MC-Unique: BSpXRIxpOpW7miJCcATQ2w-1 X-Mimecast-MFC-AGG-ID: BSpXRIxpOpW7miJCcATQ2w_1774861839 From: Cindy Lu To: lulu@redhat.com, mst@redhat.com, jasowang@redhat.com, zhangckid@gmail.com, lizhijian@fujitsu.com, jmarcin@redhat.com, qemu-devel@nongnu.org Subject: [RFC v3 6/7] net/filter: allow filters on vhost TAP backends Date: Mon, 30 Mar 2026 16:58:14 +0800 Message-ID: <20260330090944.1008027-7-lulu@redhat.com> In-Reply-To: <20260330090944.1008027-1-lulu@redhat.com> References: <20260330090944.1008027-1-lulu@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=lulu@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -5 X-Spam_score: -0.6 X-Spam_bar: / X-Spam_report: (-0.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1774861901232158500 Content-Type: text/plain; charset="utf-8" netfilter_complete() currently rejects any filter attached to a vhost-backed netdev. The AF_PACKET redirector series needs to attach filters to vhost-backed TAP devices, so relax the blanket vhost rejection and keep only the backend-type requirement. Signed-off-by: Cindy Lu --- net/filter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/filter.c b/net/filter.c index 847dd34698..636586e1f3 100644 --- a/net/filter.c +++ b/net/filter.c @@ -264,8 +264,10 @@ static void netfilter_complete(UserCreatable *uc, Erro= r **errp) } =20 if (get_vhost_net(ncs[0])) { - error_setg(errp, "Vhost is not supported"); - return; + if (ncs[0]->info->type !=3D NET_CLIENT_DRIVER_TAP) { + error_setg(errp, "Vhost filter support requires a TAP backend"= ); + return; + } } =20 if (strcmp(nf->position, "head") && strcmp(nf->position, "tail")) { --=20 2.52.0 From nobody Thu Apr 2 09:18:58 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1774861887; cv=none; d=zohomail.com; s=zohoarc; b=KT128AVuMwuE/2lNVGIgmCZjSOhtkfLkfECW4q1NdL/dFrkgWhl4MAEAaKpcomN3Pqzjja1ZFBkl7uPat0jhrFXpSs0YDxQbu0rI6jxBWIrNrfh+PIgsURUh73cpPsHyIQWTKhbE4SWJVkN8FCf2jsMCTwHwY9bNRPuoA1qhbBY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774861887; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=UIjxUX2mjHNiOeF8MWR0J6MRSnLuzQeAzy0f09dGBzM=; b=DVwwMS6dj8D97d57maSoBmGGNrjM89VBoLNqZ0W0XagNaCwjiI6T9LzwJyCUcc5G+5IsyZ8mRT1JqYt344jNmQaLSs+mJrrI5GNJ7XjhMXytOE9oTZ+aIss0YEvmSDN6kuj/5XGp/tiG0CMbYwksLTRGzr/9N9Q0zdsCHXIKG0Q= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1774861887818928.933645332345; Mon, 30 Mar 2026 02:11:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w78eO-0006Wb-WC; Mon, 30 Mar 2026 05:11:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78e2-0006EW-Nt for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:55 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w78e1-0000Qd-7t for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:50 -0400 Received: from mx-prod-mc-03.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-540-dfcDTA4NNOeE5keocY1m2w-1; Mon, 30 Mar 2026 05:10:44 -0400 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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 851451944B13; Mon, 30 Mar 2026 09:10:43 +0000 (UTC) Received: from S2.redhat.com (unknown [10.72.112.39]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 44B2319560B1; Mon, 30 Mar 2026 09:10:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1774861848; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UIjxUX2mjHNiOeF8MWR0J6MRSnLuzQeAzy0f09dGBzM=; b=KkRxtZcTsR827KA28SmbegKweBCZNogA+TgXuBWsvIt1vQ0ZGn/EqZXlEI4zvqbwEOakcl RtPWPpP0nDYtuqRVZaeetZAcoqUnoA5WAHwwdCdO45MWE3r6UqBRY+UE/hY3dpd0By6kqZ NeZvjhnltC/eVvUA8JsxoRp++koBWzU= X-MC-Unique: dfcDTA4NNOeE5keocY1m2w-1 X-Mimecast-MFC-AGG-ID: dfcDTA4NNOeE5keocY1m2w_1774861843 From: Cindy Lu To: lulu@redhat.com, mst@redhat.com, jasowang@redhat.com, zhangckid@gmail.com, lizhijian@fujitsu.com, jmarcin@redhat.com, qemu-devel@nongnu.org Subject: [RFC v3 7/7] net/filter-redirector: check CAP_NET_RAW before creating AF_PACKET Date: Mon, 30 Mar 2026 16:58:15 +0800 Message-ID: <20260330090944.1008027-8-lulu@redhat.com> In-Reply-To: <20260330090944.1008027-1-lulu@redhat.com> References: <20260330090944.1008027-1-lulu@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=lulu@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 27 X-Spam_score: 2.7 X-Spam_bar: ++ X-Spam_report: (2.7 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_SBL_CSS=3.335, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1774861889234158500 Content-Type: text/plain; charset="utf-8" Creating an AF_PACKET SOCK_RAW socket requires the CAP_NET_RAW capability. Without it the qemu_socket() call fails with EPERM, producing a generic error that gives no hint about the missing capability. Add an explicit capget()-based check in filter_redirector_netdev_setup() before the socket call. Signed-off-by: Cindy Lu --- net/filter-mirror.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/net/filter-mirror.c b/net/filter-mirror.c index 165a7ee1ea..a521eec02b 100644 --- a/net/filter-mirror.c +++ b/net/filter-mirror.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include =20 typedef struct MirrorState MirrorState; DECLARE_INSTANCE_CHECKER(MirrorState, FILTER_MIRROR, @@ -579,6 +581,21 @@ static void filter_redirector_maybe_enable_read_poll(N= etFilterState *nf) } } =20 +static bool filter_redirector_has_cap_net_raw(void) +{ + struct __user_cap_header_struct hdr =3D { + .version =3D _LINUX_CAPABILITY_VERSION_3, + .pid =3D 0, + }; + struct __user_cap_data_struct data[2] =3D {}; + + if (syscall(SYS_capget, &hdr, data) < 0) { + return false; + } + + return data[CAP_NET_RAW >> 5].effective & (1u << (CAP_NET_RAW & 31)); +} + static bool filter_redirector_netdev_setup(NetFilterState *nf, Error **err= p) { MirrorState *s =3D FILTER_REDIRECTOR(nf); @@ -615,6 +632,13 @@ static bool filter_redirector_netdev_setup(NetFilterSt= ate *nf, Error **errp) return false; } =20 + if (!filter_redirector_has_cap_net_raw()) { + error_setg(errp, + "AF_PACKET raw socket requires CAP_NET_RAW; " + "run with 'setcap cap_net_raw+ep ' or as r= oot"); + return false; + } + fd =3D qemu_socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_AL= L)); if (fd < 0) { error_setg_errno(errp, errno, "failed to create AF_PACKET socket"); --=20 2.52.0