From c60168256a1befccf10172afc192f702cd39968c Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Tue, 31 Mar 2026 04:28:41 +0000 Subject: [PATCH] net_util: Tolerate some unsupported command classes Windows NetKVM driver (>= 0.1.271) issues unsupported command classes even when they are not even advertised. According to the Virtio 1.2 specification: RX, VLAN, and ANNOUNCE control paths are only meaningful when their corresponding features are negotiated in sections 5.1.3.1, 5.1.6.5.1.2, 5.1.6.5.2.2, and 5.1.6.5.4.1. RX and VLAN are explicitly described as best-effort in sections 5.1.6.5.1 and 5.1.6.5.3. Instead of returning an error to the guest, return success to the guest. Fixes: #7925 Signed-off-by: Wei Liu --- net_util/src/ctrl_queue.rs | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/net_util/src/ctrl_queue.rs b/net_util/src/ctrl_queue.rs index 284b6ec4e..f449d5527 100644 --- a/net_util/src/ctrl_queue.rs +++ b/net_util/src/ctrl_queue.rs @@ -2,12 +2,16 @@ // // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause -use log::{error, info, warn}; +use log::{debug, error, info, warn}; use thiserror::Error; use virtio_bindings::virtio_net::{ - VIRTIO_NET_CTRL_GUEST_OFFLOADS, VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET, VIRTIO_NET_CTRL_MQ, - VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN, - VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, VIRTIO_NET_ERR, VIRTIO_NET_OK, + VIRTIO_NET_CTRL_ANNOUNCE, VIRTIO_NET_CTRL_ANNOUNCE_ACK, VIRTIO_NET_CTRL_GUEST_OFFLOADS, + VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET, VIRTIO_NET_CTRL_MQ, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, + VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, VIRTIO_NET_CTRL_RX, + VIRTIO_NET_CTRL_RX_ALLMULTI, VIRTIO_NET_CTRL_RX_ALLUNI, VIRTIO_NET_CTRL_RX_NOBCAST, + VIRTIO_NET_CTRL_RX_NOMULTI, VIRTIO_NET_CTRL_RX_NOUNI, VIRTIO_NET_CTRL_RX_PROMISC, + VIRTIO_NET_CTRL_VLAN, VIRTIO_NET_CTRL_VLAN_ADD, VIRTIO_NET_CTRL_VLAN_DEL, VIRTIO_NET_ERR, + VIRTIO_NET_OK, }; use virtio_queue::{Queue, QueueT}; use vm_memory::{ByteValued, Bytes, GuestMemoryError}; @@ -53,6 +57,26 @@ pub struct ControlHeader { // SAFETY: ControlHeader only contains a series of integers unsafe impl ByteValued for ControlHeader {} +fn is_tolerated_ctrl_command(ctrl_hdr: ControlHeader) -> bool { + match u32::from(ctrl_hdr.class) { + VIRTIO_NET_CTRL_RX => matches!( + u32::from(ctrl_hdr.cmd), + VIRTIO_NET_CTRL_RX_PROMISC + | VIRTIO_NET_CTRL_RX_ALLMULTI + | VIRTIO_NET_CTRL_RX_ALLUNI + | VIRTIO_NET_CTRL_RX_NOMULTI + | VIRTIO_NET_CTRL_RX_NOUNI + | VIRTIO_NET_CTRL_RX_NOBCAST + ), + VIRTIO_NET_CTRL_VLAN => matches!( + u32::from(ctrl_hdr.cmd), + VIRTIO_NET_CTRL_VLAN_ADD | VIRTIO_NET_CTRL_VLAN_DEL + ), + VIRTIO_NET_CTRL_ANNOUNCE => u32::from(ctrl_hdr.cmd) == VIRTIO_NET_CTRL_ANNOUNCE_ACK, + _ => false, + } +} + pub struct CtrlQueue { pub taps: Vec, } @@ -128,6 +152,10 @@ impl CtrlQueue { false } } + _ if is_tolerated_ctrl_command(ctrl_hdr) => { + debug!("Ignoring unsupported but tolerated control command {ctrl_hdr:?}"); + true + } _ => { warn!("Unsupported command {ctrl_hdr:?}"); false