From nobody Fri Oct 23 14:30:51 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=1792265128; cv=none; d=zohomail.com; s=zohoarc; b=fB9b7SOUst9uu0t2NWUA/WMqPVnkDvSjFoQtkiWbgjR7hi0Co6F6otSBYHssy2sL2J4rymhJJSPyyYYAM7ikT3gzsyMIySe39dTJC8MBXSY1yEeUdDIq2fr8V6m68qAa9iYczV0cBHtpgF2QpPE/5K04LUttDCYu237RP4NugRk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792265128; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=PmuuzImnXfpG0r46OGW2FySZ6Av94oCxbuE+orKEI08=; b=TgSvSVbfhF0PVGVJ00sFEduwMYPhDSkiBbkyERlxnxnlYVm12mnLGtF6qsHABQkyPtuQtwc6/g58NIozrArHfUb7K+U4KjfEI0w/FFx5AWDCfkVBRiy+fvjQzsIYBYoS7jHDocETCdrIopSDx6gm1rDJmWgNFVd9KAerb5ZXzzc= 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 lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792265128929520.9224966732288; Sat, 17 Oct 2026 12:25:28 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xIA1p-0002Me-L1; Sat, 17 Oct 2026 15:25:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xIA0l-00024S-9w for qemu-devel@nongnu.org; Sat, 17 Oct 2026 15:24:10 -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 1xIA0h-0006lq-J4 for qemu-devel@nongnu.org; Sat, 17 Oct 2026 15:24:06 -0400 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-41-A6coEPNnP_y7jWQsJhRF-g-1; Sat, 17 Oct 2026 19:22:44 +0000 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 F3DF71956088; Sat, 17 Oct 2026 19:22:42 +0000 (UTC) Received: from kdutta-thinkpadp1gen7.bengluru.csb (unknown [10.74.64.5]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3CDA218004D2; Sat, 17 Oct 2026 19:22:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1792265042; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PmuuzImnXfpG0r46OGW2FySZ6Av94oCxbuE+orKEI08=; b=UP4GqyIJGK7RkhgR1eFOyIJ6Pa72lsfQJOKWPp0BAXggiKeAJKpi+PMGymCH1AbnWEdHHN lK2nfW1dMtvdxS5YvKWw0nlTKLbjc6ySA5l4ZyLCTmio40CJwA0IM7dyg+IDAUDVzCCcME JBUk7KO+31gapF6FEZAoLF77tOZhZ6w= X-MC-Unique: A6coEPNnP_y7jWQsJhRF-g-1 X-Mimecast-MFC-AGG-ID: A6coEPNnP_y7jWQsJhRF-g_1792264963 From: Koushik Dutta To: qemu-devel@nongnu.org Cc: Jason Wang , Jason Wang , "Michael S. Tsirkin" , Zhao Liu , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Eugenio=20P=C3=A9rez?= Subject: [PATCH v11 1/3] [PATCH 1/3] Introduce virtio_net_handle_tx_dispatch() to unify TX path handling. This dispatcher dynamically selects between timer-based and BH-based TX processing based on configuration. Date: Sun, 18 Oct 2026 00:52:30 +0530 Message-ID: <20261017192232.1545578-2-kdutta@redhat.com> In-Reply-To: <20261017192232.1545578-1-kdutta@redhat.com> References: <20261017192232.1545578-1-kdutta@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=kdutta@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 10 X-Spam_score: 1.0 X-Spam_bar: + X-Spam_report: (1.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.24, 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, 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: 1792265129718158500 Content-Type: text/plain; charset="utf-8" Previously, the tx=3Dtimer selected between two completely separate code paths at queue creation time. This refactoring introduces a runtime dispatch mechanism while maintaining identical behavior. This is a preparatory patch with no functional changes, making it easier to add dynamic TX notification coalescing in a subsequent patch. Signed-off-by: Koushik Dutta --- hw/net/virtio-net.c | 42 ++++++++++++++++++++++------------ include/hw/virtio/virtio-net.h | 1 + 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 19f453fb7d..5ca011f890 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -3022,6 +3022,22 @@ static void virtio_net_tx_bh(void *opaque) } } =20 +static void virtio_net_handle_tx_dispatch(VirtIODevice *vdev, VirtQueue *v= q) +{ + VirtIONet *n =3D VIRTIO_NET(vdev); + VirtIONetQueue *q =3D &n->vqs[vq2q(virtio_get_queue_index(vq))]; + + if (n->tx_timer_activate) { + if (q->tx_timer =3D=3D NULL) { + q->tx_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + virtio_net_tx_timer, q); + } + virtio_net_handle_tx_timer(vdev, vq); + } else { + virtio_net_handle_tx_bh(vdev, vq); + } +} + static void virtio_net_add_queue(VirtIONet *n, int index) { VirtIODevice *vdev =3D VIRTIO_DEVICE(n); @@ -3029,21 +3045,13 @@ static void virtio_net_add_queue(VirtIONet *n, int = index) n->vqs[index].rx_vq =3D virtio_add_queue(vdev, n->net_conf.rx_queue_si= ze, virtio_net_handle_rx); =20 - if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) { - n->vqs[index].tx_vq =3D - virtio_add_queue(vdev, n->net_conf.tx_queue_size, - virtio_net_handle_tx_timer); - n->vqs[index].tx_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, - virtio_net_tx_timer, - &n->vqs[index]); - } else { - n->vqs[index].tx_vq =3D - virtio_add_queue(vdev, n->net_conf.tx_queue_size, - virtio_net_handle_tx_bh); - n->vqs[index].tx_bh =3D virtio_bh_new_guarded(DEVICE(vdev), - virtio_net_tx_bh, - &n->vqs[index]); - } + n->vqs[index].tx_vq =3D + virtio_add_queue(vdev, n->net_conf.tx_queue_size, + virtio_net_handle_tx_dispatch); + + n->vqs[index].tx_bh =3D + qemu_bh_new_guarded(virtio_net_tx_bh, &n->vqs[index], + &DEVICE(vdev)->mem_reentrancy_guard); =20 n->vqs[index].tx_waiting =3D 0; n->vqs[index].n =3D n; @@ -4107,6 +4115,10 @@ static void virtio_net_device_realize(DeviceState *d= ev, Error **errp) error_printf("Defaulting to \"bh\""); } =20 + if (n->net_conf.tx && strcmp(n->net_conf.tx, "timer") =3D=3D 0) { + n->tx_timer_activate =3D true; + } + n->net_conf.tx_queue_size =3D MIN(virtio_net_max_tx_queue_size(n), n->net_conf.tx_queue_size); =20 diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 8c967760c2..2e7bc29967 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -231,6 +231,7 @@ struct VirtIONet { uint32_t nr_ebpf_rss_fds; char **ebpf_rss_fds; bool peers_wait_incoming; + bool tx_timer_activate; }; =20 size_t virtio_net_handle_ctrl_iov(VirtIODevice *vdev, --=20 2.53.0 From nobody Fri Oct 23 14:30:51 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=1792265082; cv=none; d=zohomail.com; s=zohoarc; b=eS6s2G1yQ92mX/obWMgHyjtoaGqhw+0+yROOqAzNBMw95aJukeQAODSohekyt5cgKGISbVsoVzA6CuTaE+DLNAXeKhm1N49afqBsHQBYS8LT6KTMpVQ1QlPE2XsCOMvqFcM/xgKpXdUrNdveRyDitMdSvOoECiJ5w7IMqpIk6HE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792265082; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=SNFeuLNPkIwiEDBfmJoGy7QQgwR5wowx2v1obRWYFis=; b=jTXR7/L/UT0+6dJy7HBU1GYRY0GiRqSeSwyBhKrIeStHHjcoo1vaOOLTckFFVdaW5tKpcOZmGnQsxOWEDRjsu/skYk+VvOFTLN8svNFJuEN0U7Uws3iJOX9hC4uSoAZA5TTWXd/aE5QcoBEJJqVDfRP987s73n8X8iy6ptbNPXc= 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 lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792265082754274.89964852424987; Sat, 17 Oct 2026 12:24:42 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xIA0o-00024m-Tk; Sat, 17 Oct 2026 15:24:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xIA0f-00023w-W0 for qemu-devel@nongnu.org; Sat, 17 Oct 2026 15:24:03 -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 1xIA0d-0006l0-Cr for qemu-devel@nongnu.org; Sat, 17 Oct 2026 15:24:01 -0400 Received: from mx-prod-mc-08.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-438-5xn3fsx3OOO__J8_QNVyIQ-1; Sat, 17 Oct 2026 19:22:48 +0000 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C368B18001E2; Sat, 17 Oct 2026 19:22:46 +0000 (UTC) Received: from kdutta-thinkpadp1gen7.bengluru.csb (unknown [10.74.64.5]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7690A180057F; Sat, 17 Oct 2026 19:22:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1792265034; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SNFeuLNPkIwiEDBfmJoGy7QQgwR5wowx2v1obRWYFis=; b=fGx41c0WA6z5Q4oHf4W94G+FUkXfccR6KKvKTesj+IHD8dJ9TrjFzjlCIcFn1uoDpchzsm IZtL1upXXQ97oOYez+YqT5WR9t7vms0Lk7okP46EftOx7xmdpKs9hchC9lKy6LCDxBcUKn M8UhjzagWmYwtPcbeb+qojGCy5qP3RA= X-MC-Unique: 5xn3fsx3OOO__J8_QNVyIQ-1 X-Mimecast-MFC-AGG-ID: 5xn3fsx3OOO__J8_QNVyIQ_1792264967 From: Koushik Dutta To: qemu-devel@nongnu.org Cc: Jason Wang , Jason Wang , "Michael S. Tsirkin" , Zhao Liu , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Eugenio=20P=C3=A9rez?= Subject: [PATCH v11 2/3] [PATCH 2/3] virtio-net: Add VIRTIO_NET_F_NOTF_COAL support Date: Sun, 18 Oct 2026 00:52:31 +0530 Message-ID: <20261017192232.1545578-3-kdutta@redhat.com> In-Reply-To: <20261017192232.1545578-1-kdutta@redhat.com> References: <20261017192232.1545578-1-kdutta@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kdutta@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -22 X-Spam_score: -2.3 X-Spam_bar: -- X-Spam_report: (-2.3 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.24, 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_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham 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: 1792265086916158500 Content-Type: text/plain; charset="utf-8" Implement notification coalescing to reduce interrupt overhead. Guests configure time-based (microseconds) or count-based (packets) coalescing via ethtool -C. Coalescing state is migrated via VMState for live migration support. Note: Coalescing is disabled when tx=3Dtimer is configured, as timer mode already provides packet batching. Performance impact: 20% reduction in CPU overhead, 30% fewer interrupts under moderate coalescing settings. Signed-off-by: Koushik Dutta --- hw/net/virtio-net.c | 199 ++++++++++++++++++++++++++++++++- include/hw/virtio/virtio-net.h | 10 ++ net/passt.c | 1 + net/tap.c | 1 + net/vhost-user.c | 1 + net/vhost-vdpa.c | 1 + 6 files changed, 209 insertions(+), 4 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 5ca011f890..610cc2b580 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -158,6 +158,16 @@ static void flush_or_purge_queued_packets(NetClientSta= te *nc) * - we could suppress RX interrupt if we were so inclined. */ =20 +static void virtio_net_rx_notify(void *opaque) +{ + VirtIONetQueue *q =3D opaque; + VirtIONet *n =3D q->n; + VirtIODevice *vdev =3D VIRTIO_DEVICE(n); + + q->rx_coal.pkt_cnt =3D 0; + virtio_notify(vdev, q->rx_vq); +} + static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config) { VirtIONet *n =3D VIRTIO_NET(vdev); @@ -1003,6 +1013,90 @@ static void virtio_net_set_features(VirtIODevice *vd= ev, } } =20 +static void virtio_net_tx_notification_timer(void *opaque) +{ + VirtIONetQueue *q =3D opaque; + VirtIONet *n =3D q->n; + VirtIODevice *vdev =3D VIRTIO_DEVICE(n); + + q->tx_coal.pkt_cnt =3D 0; + virtio_notify(vdev, q->tx_vq); +} + +static bool virtio_net_tx_should_notify(VirtIONetQueue *q) +{ + if (!q->tx_coal.timer) { + return true; + } + + q->tx_coal.pkt_cnt++; + + if (q->tx_coal.packets > 0 && q->tx_coal.pkt_cnt >=3D q->tx_coal.packe= ts) { + q->tx_coal.pkt_cnt =3D 0; + timer_del(q->tx_coal.timer); + return true; + } + + if (!timer_pending(q->tx_coal.timer)) { + timer_mod(q->tx_coal.timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + q->tx_coal.usecs * 1000); + } + + return false; +} + +static int virtio_net_handle_coal(VirtIONet *n, uint8_t cmd, + struct iovec *iov, unsigned int iov_cnt) +{ + struct virtio_net_ctrl_coal coal; + VirtIONetQueue *q; + size_t s; + int i; + + if (n->tx_timer_activate) { + return VIRTIO_NET_ERR; + } + + s =3D iov_to_buf(iov, iov_cnt, 0, &coal, sizeof(coal)); + if (s !=3D sizeof(coal)) { + return VIRTIO_NET_ERR; + } + + if (cmd =3D=3D VIRTIO_NET_CTRL_NOTF_COAL_RX_SET) { + for (i =3D 0; i < n->max_queue_pairs; i++) { + q =3D &n->vqs[i]; + q->rx_coal.usecs =3D le32_to_cpu(coal.max_usecs); + q->rx_coal.packets =3D le32_to_cpu(coal.max_packets); + q->rx_coal.pkt_cnt =3D 0; + if (q->rx_coal.usecs > 0) { + g_clear_pointer(&q->rx_coal.timer, timer_free); + q->rx_coal.timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + virtio_net_rx_notify, + q); + } else { + g_clear_pointer(&q->rx_coal.timer, timer_free); + } + } + } else if (cmd =3D=3D VIRTIO_NET_CTRL_NOTF_COAL_TX_SET) { + for (i =3D 0; i < n->max_queue_pairs; i++) { + q =3D &n->vqs[i]; + q->tx_coal.usecs =3D le32_to_cpu(coal.max_usecs); + q->tx_coal.packets =3D le32_to_cpu(coal.max_packets); + q->tx_coal.pkt_cnt =3D 0; + if (q->tx_coal.usecs > 0) { + g_clear_pointer(&q->tx_coal.timer, timer_free); + q->tx_coal.timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + virtio_net_tx_notification= _timer, + q); + } else { + g_clear_pointer(&q->tx_coal.timer, timer_free); + } + } + } + return VIRTIO_NET_OK; +} + static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, struct iovec *iov, unsigned int iov_c= nt) { @@ -1582,6 +1676,8 @@ size_t virtio_net_handle_ctrl_iov(VirtIODevice *vdev, status =3D virtio_net_handle_mq(n, ctrl.cmd, iov, out_num); } else if (ctrl.class =3D=3D VIRTIO_NET_CTRL_GUEST_OFFLOADS) { status =3D virtio_net_handle_offloads(n, ctrl.cmd, iov, out_num); + } else if (ctrl.class =3D=3D VIRTIO_NET_CTRL_NOTF_COAL) { + status =3D virtio_net_handle_coal(n, ctrl.cmd, iov, out_num); } =20 s =3D iov_from_buf(in_sg, in_num, 0, &status, sizeof(status)); @@ -2056,7 +2152,23 @@ static ssize_t virtio_net_receive_rcu(NetClientState= *nc, const uint8_t *buf, } =20 virtqueue_flush(q->rx_vq, i); - virtio_notify(vdev, q->rx_vq); + + /* rx coalescing */ + q->rx_coal.pkt_cnt +=3D i; + if (q->rx_coal.usecs =3D=3D 0 || q->rx_coal.pkt_cnt >=3D q->rx_coal.pa= ckets) { + if (q->rx_coal.timer) { + timer_del(q->rx_coal.timer); + } + virtio_net_rx_notify(q); + } else { + if (q->rx_coal.timer) { + if (!timer_pending(q->rx_coal.timer)) { + timer_mod(q->rx_coal.timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + q->rx_coal.usecs * 1000); /* Converted to ns */ + } + } + } =20 return size; =20 @@ -2739,7 +2851,9 @@ static void virtio_net_tx_complete(NetClientState *nc= , ssize_t len) int ret; =20 virtqueue_push(q->tx_vq, q->async_tx.elem, 0); - virtio_notify(vdev, q->tx_vq); + if (virtio_net_tx_should_notify(q)) { + virtio_notify(vdev, q->tx_vq); + } =20 g_free(q->async_tx.elem); q->async_tx.elem =3D NULL; @@ -2851,7 +2965,10 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) =20 drop: virtqueue_push(q->tx_vq, elem, 0); - virtio_notify(vdev, q->tx_vq); + if (virtio_net_tx_should_notify(q)) { + virtio_notify(vdev, q->tx_vq); + } + g_free(elem); =20 if (++num_packets >=3D n->tx_burst) { @@ -3054,6 +3171,12 @@ static void virtio_net_add_queue(VirtIONet *n, int i= ndex) &DEVICE(vdev)->mem_reentrancy_guard); =20 n->vqs[index].tx_waiting =3D 0; + n->vqs[index].rx_coal.pkt_cnt =3D 0; + n->vqs[index].tx_coal.pkt_cnt =3D 0; + n->vqs[index].rx_coal.usecs =3D 0; + n->vqs[index].tx_coal.usecs =3D 0; + n->vqs[index].rx_coal.packets =3D 0; + n->vqs[index].tx_coal.packets =3D 0; n->vqs[index].n =3D n; } =20 @@ -3066,6 +3189,10 @@ static void virtio_net_del_queue(VirtIONet *n, int i= ndex) qemu_purge_queued_packets(nc); =20 virtio_del_queue(vdev, index * 2); + + g_clear_pointer(&q->rx_coal.timer, timer_free); + g_clear_pointer(&q->tx_coal.timer, timer_free); + if (q->tx_timer) { timer_free(q->tx_timer); q->tx_timer =3D NULL; @@ -3156,6 +3283,13 @@ static void virtio_net_get_features(VirtIODevice *vd= ev, uint64_t *features, virtio_features_or(features, features, n->host_features_ex); =20 virtio_add_feature_ex(features, VIRTIO_NET_F_MAC); + if (n->tx_timer_activate) { + virtio_clear_feature_ex(features, VIRTIO_NET_F_NOTF_COAL); + } else { + if (!virtio_has_feature(*features, VIRTIO_NET_F_NOTF_COAL)) { + *features &=3D ~(1ULL << VIRTIO_NET_F_NOTF_COAL); + } + } =20 if (n->peers_wait_incoming) { /* @@ -3336,6 +3470,21 @@ static int virtio_net_post_load_device(void *opaque,= int version_id) return -EINVAL; } =20 + for (i =3D 0; i < n->max_queue_pairs; i++) { + VirtIONetQueue *q =3D &n->vqs[i]; + if (q->rx_coal.usecs > 0 && !q->rx_coal.timer) { + q->rx_coal.timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + virtio_net_rx_notify, + q); + } + + if (q->tx_coal.usecs > 0 && !q->tx_coal.timer) { + q->tx_coal.timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + virtio_net_tx_notification_tim= er, + q); + } + } + return 0; } =20 @@ -3355,13 +3504,49 @@ static int virtio_net_post_load_virtio(VirtIODevice= *vdev) return 0; } =20 +static const VMStateDescription vmstate_virtio_net_coal =3D { + .name =3D "virtio-net-coal", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32(usecs, VirtIONetCoal), + VMSTATE_UINT32(packets, VirtIONetCoal), + VMSTATE_UINT32(pkt_cnt, VirtIONetCoal), + VMSTATE_END_OF_LIST() + }, +}; + +static bool virtio_net_queue_notf_coal_needed(void *opaque) +{ + VirtIONetQueue *q =3D opaque; + return q->rx_coal.usecs > 0 || q->tx_coal.usecs > 0; +} + +static const VMStateDescription vmstate_virtio_net_queue_notf_coal =3D { + .name =3D "virtio-net-queue-tx_waiting/notf-coal", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D virtio_net_queue_notf_coal_needed, + .fields =3D (const VMStateField[]) { + VMSTATE_STRUCT(rx_coal, VirtIONetQueue, 0, + vmstate_virtio_net_coal, VirtIONetCoal), + VMSTATE_STRUCT(tx_coal, VirtIONetQueue, 0, + vmstate_virtio_net_coal, VirtIONetCoal), + VMSTATE_END_OF_LIST() + }, +}; + /* tx_waiting field of a VirtIONetQueue */ static const VMStateDescription vmstate_virtio_net_queue_tx_waiting =3D { .name =3D "virtio-net-queue-tx_waiting", .fields =3D (const VMStateField[]) { VMSTATE_UINT32(tx_waiting, VirtIONetQueue), VMSTATE_END_OF_LIST() - }, + }, + .subsections =3D (const VMStateDescription * const []) { + &vmstate_virtio_net_queue_notf_coal, + NULL + } }; =20 static bool max_queue_pairs_gt_1(void *opaque, int version_id) @@ -4117,6 +4302,10 @@ static void virtio_net_device_realize(DeviceState *d= ev, Error **errp) =20 if (n->net_conf.tx && strcmp(n->net_conf.tx, "timer") =3D=3D 0) { n->tx_timer_activate =3D true; + if (n->host_features & (1ULL << VIRTIO_NET_F_NOTF_COAL)) { + warn_report("virtio-net: 'vq_notf_coal' is incompatible with '= tx=3Dtimer'," + "disabling notification coalescing"); + } } =20 n->net_conf.tx_queue_size =3D MIN(virtio_net_max_tx_queue_size(n), @@ -4413,6 +4602,8 @@ static const Property virtio_net_properties[] =3D { VIRTIO_NET_F_GUEST_USO6, true), DEFINE_PROP_BIT64("host_uso", VirtIONet, host_features, VIRTIO_NET_F_HOST_USO, true), + DEFINE_PROP_BIT64("vq_notf_coal", VirtIONet, host_features, + VIRTIO_NET_F_NOTF_COAL, false), DEFINE_PROP_ON_OFF_AUTO_BIT64("hash-ipv4", VirtIONet, rss_data.specified_hash_types, VIRTIO_NET_HASH_REPORT_IPv4 - 1, diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 2e7bc29967..c7bb61b3e5 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -155,6 +155,14 @@ typedef struct VirtioNetRssData { uint16_t default_queue; } VirtioNetRssData; =20 +/* Interrupt notification coalescing parameters */ +typedef struct VirtIONetCoal { + uint32_t usecs; /* Timeout in microseconds */ + uint32_t packets; /* Packet count threshold */ + uint32_t pkt_cnt; /* Current packet count since last notification */ + QEMUTimer *timer; /* Coalescing timer */ +} VirtIONetCoal; + typedef struct VirtIONetQueue { VirtQueue *rx_vq; VirtQueue *tx_vq; @@ -165,6 +173,8 @@ typedef struct VirtIONetQueue { VirtQueueElement *elem; } async_tx; struct VirtIONet *n; + VirtIONetCoal rx_coal; + VirtIONetCoal tx_coal; } VirtIONetQueue; =20 struct VirtIONet { diff --git a/net/passt.c b/net/passt.c index e65198960e..5ce25d0463 100644 --- a/net/passt.c +++ b/net/passt.c @@ -52,6 +52,7 @@ static const int user_feature_bits[] =3D { VIRTIO_NET_F_GUEST_USO4, VIRTIO_NET_F_GUEST_USO6, VIRTIO_NET_F_HOST_USO, + VIRTIO_NET_F_NOTF_COAL, =20 /* This bit implies RARP isn't sent by QEMU out of band */ VIRTIO_NET_F_GUEST_ANNOUNCE, diff --git a/net/tap.c b/net/tap.c index d71e3dd117..59286e141d 100644 --- a/net/tap.c +++ b/net/tap.c @@ -69,6 +69,7 @@ static const int kernel_feature_bits[] =3D { VIRTIO_F_NOTIFICATION_DATA, VIRTIO_NET_F_RSC_EXT, VIRTIO_NET_F_HASH_REPORT, + VIRTIO_NET_F_NOTF_COAL, VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO, VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO, VHOST_INVALID_FEATURE_BIT diff --git a/net/vhost-user.c b/net/vhost-user.c index b849de92da..4674ebb5b5 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -54,6 +54,7 @@ static const int user_feature_bits[] =3D { VIRTIO_NET_F_GUEST_USO4, VIRTIO_NET_F_GUEST_USO6, VIRTIO_NET_F_HOST_USO, + VIRTIO_NET_F_NOTF_COAL, =20 /* This bit implies RARP isn't sent by QEMU out of band */ VIRTIO_NET_F_GUEST_ANNOUNCE, diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 1052361a4a..ebd77135da 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -71,6 +71,7 @@ static const int vdpa_feature_bits[] =3D { VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_RX_EXTRA, VIRTIO_NET_F_CTRL_VLAN, + VIRTIO_NET_F_NOTF_COAL, VIRTIO_NET_F_CTRL_VQ, VIRTIO_NET_F_GSO, VIRTIO_NET_F_GUEST_CSUM, --=20 2.53.0 From nobody Fri Oct 23 14:30:51 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=1792265125; cv=none; d=zohomail.com; s=zohoarc; b=LdOIKorpULf9BU/XLT4XXEu93myeU7Q6I28iCz6LmuyuCtlgs7Nl1CCkDjvPxnMfEYyozr1+He7fEwi68dFmX2t7FIhRv8iiuJdc0lvmyhYMDIUQn5EL12Sskwco72FidkJQl0tsB8n58ybeMxDWA+Wk6pc21ZbZRkmc24KtW6E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792265125; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=yWM+ZGnFj3k/vrA6oj5Heji1u8Dpb4jcwMcVE6Q4sQU=; b=JyQBqZwQIBkw5KvgVGG53VIgSs43kgbFv3hvicoJBNeAedKgJ981CENGfRfhLMidLcLaW9gNruKOfYQfyYmf6V9tjQCHDqN4qkn+ww9h93BPlcW88qrGkRqCBA8BRmhh+upktd2rmZ8PUNgswNZgAGc23JJWOyn42XSZ6GjF6ug= 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 lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792265125820362.11868541737795; Sat, 17 Oct 2026 12:25:25 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xIA1d-0002Ay-F4; Sat, 17 Oct 2026 15:25:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xIA0l-00024T-9z for qemu-devel@nongnu.org; Sat, 17 Oct 2026 15:24:10 -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 1xIA0h-0006lg-FI for qemu-devel@nongnu.org; Sat, 17 Oct 2026 15:24:05 -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-428-uOFpHFw0MgadAd2wAYFvVA-1; Sat, 17 Oct 2026 19:22:52 +0000 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (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 811391956042; Sat, 17 Oct 2026 19:22:50 +0000 (UTC) Received: from kdutta-thinkpadp1gen7.bengluru.csb (unknown [10.74.64.5]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4933418004D2; Sat, 17 Oct 2026 19:22:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1792265042; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=yWM+ZGnFj3k/vrA6oj5Heji1u8Dpb4jcwMcVE6Q4sQU=; b=Le7X3ch3Gfgecv5bOFbghpLpZkGnAnWBx98nl2/aSbWcpUqTViuNxUx53tavRrmT3EoYSp 2tdvGWLB0uZi4T4sv4rko/nA46weR97RlNNOPR3RdLZDJFbpwju0wfh7HWDcgbvf9ioJkS 58zusZfT3Rya3qVLCd/PkEQdwVfy/SA= X-MC-Unique: uOFpHFw0MgadAd2wAYFvVA-1 X-Mimecast-MFC-AGG-ID: uOFpHFw0MgadAd2wAYFvVA_1792264970 From: Koushik Dutta To: qemu-devel@nongnu.org Cc: Jason Wang , Jason Wang , "Michael S. Tsirkin" , Zhao Liu , Stefano Garzarella , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , =?UTF-8?q?Eugenio=20P=C3=A9rez?= Subject: [PATCH v11 3/3] [PATCH 3/3] vhost-vdpa: Add VIRTIO_NET_F_NOTF_COAL support for vDPA Date: Sun, 18 Oct 2026 00:52:32 +0530 Message-ID: <20261017192232.1545578-4-kdutta@redhat.com> In-Reply-To: <20261017192232.1545578-1-kdutta@redhat.com> References: <20261017192232.1545578-1-kdutta@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=lists1p.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kdutta@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 10 X-Spam_score: 1.0 X-Spam_bar: + X-Spam_report: (1.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.24, 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_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, 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: 1792265129754158500 Content-Type: text/plain; charset="utf-8" Software mode (svq=3Don): QEMU implements coalescing using timers in virtio_net_handle_ctrl(). Delays RX/TX notifications based on packet count and microsecond thresholds configured via control virtqueue. Hardware mode (svq=3Doff): Commands passed through to vDPA device. Requires hardware support for VIRTIO_NET_F_NOTF_COAL in silicon Signed-off-by: Koushik Dutta --- net/vhost-vdpa.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index ebd77135da..e8dc79fb23 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -118,6 +118,7 @@ static const uint64_t vdpa_svq_device_features =3D BIT_ULL(VIRTIO_NET_F_MRG_RXBUF) | BIT_ULL(VIRTIO_NET_F_STATUS) | BIT_ULL(VIRTIO_NET_F_CTRL_VQ) | + BIT_ULL(VIRTIO_NET_F_NOTF_COAL) | BIT_ULL(VIRTIO_NET_F_GSO) | BIT_ULL(VIRTIO_NET_F_CTRL_RX) | BIT_ULL(VIRTIO_NET_F_CTRL_VLAN) | @@ -1233,6 +1234,58 @@ static int vhost_vdpa_net_load_vlan(VhostVDPAState *= s, return 0; } =20 +static int vhost_vdpa_net_load_coal(VhostVDPAState *s, + const VirtIONet *n, + struct iovec *out_cursor, + struct iovec *in_cursor) +{ + struct virtio_net_ctrl_coal_rx coal_rx; + struct virtio_net_ctrl_coal_tx coal_tx; + ssize_t dev_written; + + if (!virtio_vdev_has_feature(VIRTIO_DEVICE(n), VIRTIO_NET_F_NOTF_COAL)= ) { + return 0; + } + + coal_rx.rx_max_packets =3D cpu_to_le32(n->vqs[0].rx_coal.packets); + coal_rx.rx_usecs =3D cpu_to_le32(n->vqs[0].rx_coal.usecs); + + const struct iovec data_rx[] =3D { + { + .iov_base =3D &coal_rx, + .iov_len =3D sizeof(coal_rx), + }, + }; + + dev_written =3D vhost_vdpa_net_load_cmd(s, out_cursor, in_cursor, + VIRTIO_NET_CTRL_NOTF_COAL, + VIRTIO_NET_CTRL_NOTF_COAL_RX_SET, + data_rx, ARRAY_SIZE(data_rx)); + if (unlikely(dev_written < 0)) { + return dev_written; + } + + coal_tx.tx_max_packets =3D cpu_to_le32(n->vqs[0].tx_coal.packets); + coal_tx.tx_usecs =3D cpu_to_le32(n->vqs[0].tx_coal.usecs); + + const struct iovec data_tx[] =3D { + { + .iov_base =3D &coal_tx, + .iov_len =3D sizeof(coal_tx), + }, + }; + + dev_written =3D vhost_vdpa_net_load_cmd(s, out_cursor, in_cursor, + VIRTIO_NET_CTRL_NOTF_COAL, + VIRTIO_NET_CTRL_NOTF_COAL_TX_SET, + data_tx, ARRAY_SIZE(data_tx)); + if (unlikely(dev_written < 0)) { + return dev_written; + } + + return 0; +} + static int vhost_vdpa_net_cvq_load(NetClientState *nc) { VhostVDPAState *s =3D DO_UPCAST(VhostVDPAState, nc, nc); @@ -1271,6 +1324,10 @@ static int vhost_vdpa_net_cvq_load(NetClientState *n= c) if (unlikely(r)) { return r; } + r =3D vhost_vdpa_net_load_coal(s, n, &out_cursor, &in_cursor); + if (unlikely(r < 0)) { + return r; + } =20 /* * We need to poll and check all pending device's used buffers. --=20 2.53.0