From nobody Tue Apr 7 19:40:29 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=1773299792; cv=none; d=zohomail.com; s=zohoarc; b=YhZDG6BebIJ4MPcpCcVrUw+S4tgL/uVZ7WiCTDEIKtX9UIbXQHw5nNxdrGPTsKCcuORH7vpLkBbr2OYISw07q4IPAR8SR+lrfZ3fHSij4pwQIq/a3X7mXACl7IC2dgXekTJWCfEgexgbVnT34XDpbGjAuOvu3mWkgLCfquGNqmQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773299792; 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=zoqm4IOr0n5qGBJHI6uKZ5VJOLDmV3ZKkec2FGaY77A=; b=I6BJ/i7xQjJf8BSnKZKCZuctaesEFpoWAzgizmUx8Yf1MEh2GW0MBTRsQsEBZfIox29T29zWIE2ILnCBzscIXBB5DeHo9Gr0impe6BB5J90Z9aEdiEAA73sADfbToRMgy8QySQeYdJ5Zd5zopF7Mbv/HFd7hn1CPIW7YM9+KlZE= 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 1773299792178108.45610876553519; Thu, 12 Mar 2026 00:16:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w0aH1-00068h-I8; Thu, 12 Mar 2026 03:15:59 -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 1w0aGv-00060N-OS for qemu-devel@nongnu.org; Thu, 12 Mar 2026 03:15:54 -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 1w0aGt-0001di-9P for qemu-devel@nongnu.org; Thu, 12 Mar 2026 03:15:53 -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-152-vRqcH31sPCKHzxgcGVGJ0A-1; Thu, 12 Mar 2026 03:15:48 -0400 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 7A5CA195609E; Thu, 12 Mar 2026 07:15:47 +0000 (UTC) Received: from S2.redhat.com (unknown [10.72.112.170]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E6F181800107; Thu, 12 Mar 2026 07:15:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1773299750; 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=zoqm4IOr0n5qGBJHI6uKZ5VJOLDmV3ZKkec2FGaY77A=; b=VzDjnj6Kr6cgj785WQ6UggAi3YBbXVaJ8LgFn7I06ubWrNceVDO67Xo6AUHykyxKniM57n dE5OSJSe3n5GhWMwqel3LHy7LLZKoLjJ4vPhm3D4x5pXvC991a/eOY8Mm9dGR/bx4f7yje BBGdJ3W+oatv3yLlf3m1Llh5wPS+zTw= X-MC-Unique: vRqcH31sPCKHzxgcGVGJ0A-1 X-Mimecast-MFC-AGG-ID: vRqcH31sPCKHzxgcGVGJ0A_1773299747 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 v2 8/9] virtio-net: handle short vnet headers on replay RX Date: Thu, 12 Mar 2026 15:09:36 +0800 Message-ID: <20260312071415.1836655-9-lulu@redhat.com> In-Reply-To: <20260312071415.1836655-1-lulu@redhat.com> References: <20260312071415.1836655-1-lulu@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=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: -3 X-Spam_score: -0.4 X-Spam_bar: / X-Spam_report: (-0.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, 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_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.819, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.903, 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: 1773299816811154100 Content-Type: text/plain; charset="utf-8" During switchover replay, packets injected through AF_PACKET can come back from the bridge with a 10-byte virtio_net_hdr even though QEMU expects a 12-byte merged-rxbuf header. The missing two bytes shift the Ethernet frame and corrupt the packet seen by the guest. Detect this case by comparing the EtherType at the expected position with the value two bytes earlier. When only the shifted position contains a recognized protocol, reduce the effective host header length by two for this packet. Only apply the heuristic while vhost is running, and carry the adjusted header length through the normal receive path without copying the buffer. Signed-off-by: Cindy Lu --- hw/net/virtio-net.c | 54 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 616590fb82..29dbe3d8d5 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -144,6 +144,36 @@ static int vq2q(int queue_index) return queue_index / 2; } =20 +static bool virtio_net_rx_known_ethertype(uint16_t proto) +{ + if (proto <=3D 1500) { + /* IEEE 802.3 length field */ + return true; + } + + switch (proto) { + case ETH_P_IP: + case ETH_P_IPV6: + case ETH_P_ARP: + case ETH_P_VLAN: + case ETH_P_DVLAN: + case 0x0842: /* Wake-on-LAN */ + case 0x22f0: /* IEEE 802.1Qbe / TSN */ + case 0x8809: /* Slow protocols / LACP */ + case 0x8863: /* PPPoE discovery */ + case 0x8864: /* PPPoE session */ + case 0x8906: /* FCoE */ + case 0x8914: /* FCoE Init */ + case 0x88cc: /* LLDP */ + case 0x88e1: /* HomePlug AV */ + case 0x88f7: /* PTP */ + case 0x8915: /* RoCE */ + return true; + default: + return false; + } +} + static void flush_or_purge_queued_packets(NetClientState *nc) { if (!nc->peer) { @@ -1780,7 +1810,8 @@ static void receive_header(VirtIONet *n, const struct= iovec *iov, int iov_cnt, } } =20 -static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) +static int receive_filter(VirtIONet *n, const uint8_t *buf, int size, + size_t host_hdr_len) { static const uint8_t bcast[] =3D {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; static const uint8_t vlan[] =3D {0x81, 0x00}; @@ -1790,7 +1821,7 @@ static int receive_filter(VirtIONet *n, const uint8_t= *buf, int size) if (n->promisc) return 1; =20 - ptr +=3D n->host_hdr_len; + ptr +=3D host_hdr_len; =20 if (!memcmp(&ptr[12], vlan, sizeof(vlan))) { int vid =3D lduw_be_p(ptr + 14) & 0xfff; @@ -1955,12 +1986,25 @@ static ssize_t virtio_net_receive_rcu(NetClientStat= e *nc, const uint8_t *buf, QEMU_UNINITIALIZED size_t lens[VIRTQUEUE_MAX_SIZE]; QEMU_UNINITIALIZED struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE]; struct virtio_net_hdr_v1_hash extra_hdr; + size_t host_hdr_len =3D n->host_hdr_len; unsigned mhdr_cnt =3D 0; size_t offset, i, guest_offset, j; ssize_t err; =20 memset(&extra_hdr, 0, sizeof(extra_hdr)); =20 + if (n->vhost_started && + host_hdr_len >=3D 12 && + size >=3D host_hdr_len + ETH_HLEN) { + uint16_t et_at_host =3D lduw_be_p(buf + host_hdr_len + 12); + uint16_t et_at_m2 =3D lduw_be_p(buf + host_hdr_len + 10); + + if (!virtio_net_rx_known_ethertype(et_at_host) && + virtio_net_rx_known_ethertype(et_at_m2)) { + host_hdr_len -=3D 2; + } + } + if (n->rss_data.enabled && n->rss_data.enabled_software_rss) { int index =3D virtio_net_process_rss(nc, buf, size, &extra_hdr); if (index >=3D 0) { @@ -1975,11 +2019,11 @@ static ssize_t virtio_net_receive_rcu(NetClientStat= e *nc, const uint8_t *buf, q =3D virtio_net_get_subqueue(nc); =20 /* hdr_len refers to the header we supply to the guest */ - if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_l= en)) { + if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - host_hdr_len)= ) { return 0; } =20 - if (!receive_filter(n, buf, size)) + if (!receive_filter(n, buf, size, host_hdr_len)) return size; =20 offset =3D i =3D 0; @@ -2041,7 +2085,7 @@ static ssize_t virtio_net_receive_rcu(NetClientState = *nc, const uint8_t *buf, sizeof(extra_hdr.hash_value) + sizeof(extra_hdr.hash_report)); } - offset =3D n->host_hdr_len; + offset =3D host_hdr_len; total +=3D n->guest_hdr_len; guest_offset =3D n->guest_hdr_len; } else { --=20 2.52.0