From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f170.google.com (mail-pf1-f170.google.com [209.85.210.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C454D1FCFFB for ; Thu, 5 Jun 2025 07:57:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.170 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749110269; cv=none; b=PFwdCyKDVIaQSSoR5IA0ArrN5mNtMg2y1mwfFPCMlTaJTpKx4Wieqcv0crjUwaqP44V052aRb04zB5B6he5NQUKkDtNNdU2FqY9ydZeN1eUcdjUROmlkjgTD/HVINNEnji2I4Yec3QJLr6fJbS+Nvt/YuBl043x6gGWfXAGPDSs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749110269; c=relaxed/simple; bh=lTA9zjNN3JRVFRXQw/iswVkI+O61SyCDwuvCfwwT6sA=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=WMcs3qWdFSQqTG3xp9erINuT1VliQTuMfafcwXr6NBfUshOpn3xNWv8DM7VhdTMFTTsO5RebYL3pA9H2Hjy4XcHdvWdk/nTd0bvwaKTTsGfOlofGme906cdF0pw2jsA25GZn65qtoKP6o97SqSETT6N8yet7ZcI59RY7MT43r8k= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=daynix.com; spf=pass smtp.mailfrom=daynix.com; dkim=pass (2048-bit key) header.d=daynix-com.20230601.gappssmtp.com header.i=@daynix-com.20230601.gappssmtp.com header.b=NXt9gKdx; arc=none smtp.client-ip=209.85.210.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=daynix.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=daynix.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=daynix-com.20230601.gappssmtp.com header.i=@daynix-com.20230601.gappssmtp.com header.b="NXt9gKdx" Received: by mail-pf1-f170.google.com with SMTP id d2e1a72fcca58-7399a2dc13fso829864b3a.2 for ; Thu, 05 Jun 2025 00:57:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20230601.gappssmtp.com; s=20230601; t=1749110265; x=1749715065; darn=vger.kernel.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=+zZl2dXMX0VDVWJAsL+cjXNr7Ok2fg0ZVvzGEGrTbrE=; b=NXt9gKdxkt0smYROeldepk+OBONg+wK+WS6irmFMbuM5Yh956ve7YzQQThj09ZtyLd tC0ohv+QpIcX54RX+u4zxAzBcKY8SCyY+zIDBrh+ArwSMgsS01HIWxXHImNzbSN3MfnN 2dLcfDCQIeCETU3DCYbUZjF/0/NEgsTXk6TqYlZuNIxZ42b9lLUEpUnK4nWl9gqY67BC w010AwWppj0xupGkvLBW6P2m4khin3x511BgNQlulo599MxmtuPR73Vwi2tUXeK0tvLF rohAoI9wro61NXLBho8oHW6/Ypts8waiCScBfnfs8jG+TXWqFQSDU3RR1fUJkbaGXkTS +xTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749110265; x=1749715065; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=+zZl2dXMX0VDVWJAsL+cjXNr7Ok2fg0ZVvzGEGrTbrE=; b=W3oDvKG/IBLeCVIlhJGmnx7l2LjvvoC3QnhtzJQZWnF2bKmwGQAC64BhUMwZLXycRf EivHVSYasHh6WxLPmqnsPnjH26gbNM/apOf43s7o18LDhaaHz0NIwKv2Gc2kUuWoVz6v 4efM0w/01FC+tw4P8kPeSnWOGD7pijxU1OzTQgs5zRbL3KhOTykA2iQCbdFVkG2X0u5R Q5Vs7GjUf74+cI+BTDuPCVegpgiQfyrSgS1ey8dWhXdYtpcaHnC5UxqPHm1450+jXK1e dmNysPujYvU6GWP78AyxeHeylGAo/QcJFCg0rchlfcmDY++Z1JnzoBfZsPSUiXVBdx23 Uq6Q== X-Forwarded-Encrypted: i=1; AJvYcCVTqQ/lIqGxHvT1xS8/9/Urxi4GR3wHxEnlv//+LjwdXRou4vP4JHd2J93SRweXQajFGx0t7aa+OYc=@vger.kernel.org X-Gm-Message-State: AOJu0YyEqQjsjcZ9tXhhs9aEW2glvsTMUG8riosGeHpw18RBpOIkTB6h 8FtOcLhkvKeiSB61ypFTnSGh5KBBf4MVDFzg/0HFr8MYHG77rIoTxTpPWWyOlhwCnSQ= X-Gm-Gg: ASbGncupGUzYHfmjYiErsEPKJvJs9TEZdBotcDI/Zpoygk6ScTh9kJCoDAsmH1P4qbq rf6s04IBDmLdVMqH8zS/8yn2QJBddWJaNm5G5xaM0lH38PuoM3UAq1rqov6H8uDYEmDHn1iBOjY R0nEyyf2U+tsAyHM1QYISm1tnJsHwrRlcUlSpjiTlNMdXz1DTDD/7+ovceRh0jdJtGJF4I0+gOS hJjHQoTdk4D+NYHaRmvjHr1KebVX8b3LyWRn2Bf6ADO2qGVTzW/nExjDHxvGLGHGD9A/8NgGmRu k2nZ//PYRke7lI36LpgDIst1gZ5PE3vjoFd1seHAF+UMydzYY3z2seYaPgexEvSq X-Google-Smtp-Source: AGHT+IFSoebIZPWJ4N4NNYcabgJf1nxLz3d3ke91Rf5CUCkTc2VJbpBBnWqg7beTFgdLDU7v3xdgJA== X-Received: by 2002:a05:6a00:3d13:b0:742:362c:d2e4 with SMTP id d2e1a72fcca58-7480b226180mr7583905b3a.5.1749110264898; Thu, 05 Jun 2025 00:57:44 -0700 (PDT) Received: from [157.82.203.223] ([157.82.203.223]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-747affcf703sm12228046b3a.129.2025.06.05.00.57.40 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 05 Jun 2025 00:57:44 -0700 (PDT) Message-ID: <75ef190e-49fc-48aa-abf2-579ea31e4d15@daynix.com> Date: Thu, 5 Jun 2025 16:57:39 +0900 Precedence: bulk X-Mailing-List: linux-doc@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH net-next v12 01/10] virtio_net: Add functions for hashing To: Jason Wang Cc: Jonathan Corbet , Willem de Bruijn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , "Michael S. Tsirkin" , Xuan Zhuo , Shuah Khan , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kselftest@vger.kernel.org, Yuri Benditovich , Andrew Melnychenko , Stephen Hemminger , gur.stavi@huawei.com, Lei Yang , Simon Horman References: <20250530-rss-v12-0-95d8b348de91@daynix.com> <20250530-rss-v12-1-95d8b348de91@daynix.com> <95cb2640-570d-4f51-8775-af5248c6bc5a@daynix.com> <4eaa7aaa-f677-4a31-bcc2-badcb5e2b9f6@daynix.com> Content-Language: en-US From: Akihiko Odaki In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 2025/06/05 10:53, Jason Wang wrote: > On Wed, Jun 4, 2025 at 3:20 PM Akihiko Odaki wrote: >> >> On 2025/06/04 10:18, Jason Wang wrote: >>> On Tue, Jun 3, 2025 at 1:31 PM Akihiko Odaki wrote: >>>> >>>> On 2025/06/03 12:19, Jason Wang wrote: >>>>> On Fri, May 30, 2025 at 12:50 PM Akihiko Odaki wrote: >>>>>> >>>>>> They are useful to implement VIRTIO_NET_F_RSS and >>>>>> VIRTIO_NET_F_HASH_REPORT. >>>>>> >>>>>> Signed-off-by: Akihiko Odaki >>>>>> Tested-by: Lei Yang >>>>>> --- >>>>>> include/linux/virtio_net.h | 188 +++++++++++++++++++++++++++++++++++++++++++++ >>>>>> 1 file changed, 188 insertions(+) >>>>>> >>>>>> diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h >>>>>> index 02a9f4dc594d..426f33b4b824 100644 >>>>>> --- a/include/linux/virtio_net.h >>>>>> +++ b/include/linux/virtio_net.h >>>>>> @@ -9,6 +9,194 @@ >>>>>> #include >>>>>> #include >>>>>> >>>>>> +struct virtio_net_hash { >>>>>> + u32 value; >>>>>> + u16 report; >>>>>> +}; >>>>>> + >>>>>> +struct virtio_net_toeplitz_state { >>>>>> + u32 hash; >>>>>> + const u32 *key; >>>>>> +}; >>>>>> + >>>>>> +#define VIRTIO_NET_SUPPORTED_HASH_TYPES (VIRTIO_NET_RSS_HASH_TYPE_IPv4 | \ >>>>>> + VIRTIO_NET_RSS_HASH_TYPE_TCPv4 | \ >>>>>> + VIRTIO_NET_RSS_HASH_TYPE_UDPv4 | \ >>>>>> + VIRTIO_NET_RSS_HASH_TYPE_IPv6 | \ >>>>>> + VIRTIO_NET_RSS_HASH_TYPE_TCPv6 | \ >>>>>> + VIRTIO_NET_RSS_HASH_TYPE_UDPv6) >>>>>> + >>>>>> +#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40 >>>>>> + >>>>>> +static inline void virtio_net_toeplitz_convert_key(u32 *input, size_t len) >>>>>> +{ >>>>>> + while (len >= sizeof(*input)) { >>>>>> + *input = be32_to_cpu((__force __be32)*input); >>>>>> + input++; >>>>>> + len -= sizeof(*input); >>>>>> + } >>>>>> +} >>>>>> + >>>>>> +static inline void virtio_net_toeplitz_calc(struct virtio_net_toeplitz_state *state, >>>>>> + const __be32 *input, size_t len) >>>>>> +{ >>>>>> + while (len >= sizeof(*input)) { >>>>>> + for (u32 map = be32_to_cpu(*input); map; map &= (map - 1)) { >>>>>> + u32 i = ffs(map); >>>>>> + >>>>>> + state->hash ^= state->key[0] << (32 - i) | >>>>>> + (u32)((u64)state->key[1] >> i); >>>>>> + } >>>>>> + >>>>>> + state->key++; >>>>>> + input++; >>>>>> + len -= sizeof(*input); >>>>>> + } >>>>>> +} >>>>>> + >>>>>> +static inline u8 virtio_net_hash_key_length(u32 types) >>>>>> +{ >>>>>> + size_t len = 0; >>>>>> + >>>>>> + if (types & VIRTIO_NET_HASH_REPORT_IPv4) >>>>>> + len = max(len, >>>>>> + sizeof(struct flow_dissector_key_ipv4_addrs)); >>>>>> + >>>>>> + if (types & >>>>>> + (VIRTIO_NET_HASH_REPORT_TCPv4 | VIRTIO_NET_HASH_REPORT_UDPv4)) >>>>>> + len = max(len, >>>>>> + sizeof(struct flow_dissector_key_ipv4_addrs) + >>>>>> + sizeof(struct flow_dissector_key_ports)); >>>>>> + >>>>>> + if (types & VIRTIO_NET_HASH_REPORT_IPv6) >>>>>> + len = max(len, >>>>>> + sizeof(struct flow_dissector_key_ipv6_addrs)); >>>>>> + >>>>>> + if (types & >>>>>> + (VIRTIO_NET_HASH_REPORT_TCPv6 | VIRTIO_NET_HASH_REPORT_UDPv6)) >>>>>> + len = max(len, >>>>>> + sizeof(struct flow_dissector_key_ipv6_addrs) + >>>>>> + sizeof(struct flow_dissector_key_ports)); >>>>>> + >>>>>> + return len + sizeof(u32); >>>>>> +} >>>>>> + >>>>>> +static inline u32 virtio_net_hash_report(u32 types, >>>>>> + const struct flow_keys_basic *keys) >>>>>> +{ >>>>>> + switch (keys->basic.n_proto) { >>>>>> + case cpu_to_be16(ETH_P_IP): >>>>>> + if (!(keys->control.flags & FLOW_DIS_IS_FRAGMENT)) { >>>>>> + if (keys->basic.ip_proto == IPPROTO_TCP && >>>>>> + (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4)) >>>>>> + return VIRTIO_NET_HASH_REPORT_TCPv4; >>>>>> + >>>>>> + if (keys->basic.ip_proto == IPPROTO_UDP && >>>>>> + (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4)) >>>>>> + return VIRTIO_NET_HASH_REPORT_UDPv4; >>>>>> + } >>>>>> + >>>>>> + if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) >>>>>> + return VIRTIO_NET_HASH_REPORT_IPv4; >>>>>> + >>>>>> + return VIRTIO_NET_HASH_REPORT_NONE; >>>>>> + >>>>>> + case cpu_to_be16(ETH_P_IPV6): >>>>>> + if (!(keys->control.flags & FLOW_DIS_IS_FRAGMENT)) { >>>>>> + if (keys->basic.ip_proto == IPPROTO_TCP && >>>>>> + (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv6)) >>>>>> + return VIRTIO_NET_HASH_REPORT_TCPv6; >>>>>> + >>>>>> + if (keys->basic.ip_proto == IPPROTO_UDP && >>>>>> + (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv6)) >>>>>> + return VIRTIO_NET_HASH_REPORT_UDPv6; >>>>>> + } >>>>>> + >>>>>> + if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv6) >>>>>> + return VIRTIO_NET_HASH_REPORT_IPv6; >>>>>> + >>>>>> + return VIRTIO_NET_HASH_REPORT_NONE; >>>>>> + >>>>>> + default: >>>>>> + return VIRTIO_NET_HASH_REPORT_NONE; >>>>>> + } >>>>>> +} >>>>>> + >>>>>> +static inline void virtio_net_hash_rss(const struct sk_buff *skb, >>>>>> + u32 types, const u32 *key, >>>>>> + struct virtio_net_hash *hash) >>>>>> +{ >>>>>> + struct virtio_net_toeplitz_state toeplitz_state = { .key = key }; >>>>>> + struct flow_keys flow; >>>>>> + struct flow_keys_basic flow_basic; >>>>>> + u16 report; >>>>>> + >>>>>> + if (!skb_flow_dissect_flow_keys(skb, &flow, 0)) { >>>>>> + hash->report = VIRTIO_NET_HASH_REPORT_NONE; >>>>>> + return; >>>>>> + } >>>>>> + >>>>>> + flow_basic = (struct flow_keys_basic) { >>>>>> + .control = flow.control, >>>>>> + .basic = flow.basic >>>>>> + }; >>>>>> + >>>>>> + report = virtio_net_hash_report(types, &flow_basic); >>>>>> + >>>>>> + switch (report) { >>>>>> + case VIRTIO_NET_HASH_REPORT_IPv4: >>>>>> + virtio_net_toeplitz_calc(&toeplitz_state, >>>>>> + (__be32 *)&flow.addrs.v4addrs, >>>>>> + sizeof(flow.addrs.v4addrs)); >>>>>> + break; >>>>>> + >>>>>> + case VIRTIO_NET_HASH_REPORT_TCPv4: >>>>>> + virtio_net_toeplitz_calc(&toeplitz_state, >>>>>> + (__be32 *)&flow.addrs.v4addrs, >>>>>> + sizeof(flow.addrs.v4addrs)); >>>>>> + virtio_net_toeplitz_calc(&toeplitz_state, &flow.ports.ports, >>>>>> + sizeof(flow.ports.ports)); >>>>>> + break; >>>>>> + >>>>>> + case VIRTIO_NET_HASH_REPORT_UDPv4: >>>>>> + virtio_net_toeplitz_calc(&toeplitz_state, >>>>>> + (__be32 *)&flow.addrs.v4addrs, >>>>>> + sizeof(flow.addrs.v4addrs)); >>>>>> + virtio_net_toeplitz_calc(&toeplitz_state, &flow.ports.ports, >>>>>> + sizeof(flow.ports.ports)); >>>>>> + break; >>>>>> + >>>>>> + case VIRTIO_NET_HASH_REPORT_IPv6: >>>>>> + virtio_net_toeplitz_calc(&toeplitz_state, >>>>>> + (__be32 *)&flow.addrs.v6addrs, >>>>>> + sizeof(flow.addrs.v6addrs)); >>>>>> + break; >>>>>> + >>>>>> + case VIRTIO_NET_HASH_REPORT_TCPv6: >>>>>> + virtio_net_toeplitz_calc(&toeplitz_state, >>>>>> + (__be32 *)&flow.addrs.v6addrs, >>>>>> + sizeof(flow.addrs.v6addrs)); >>>>>> + virtio_net_toeplitz_calc(&toeplitz_state, &flow.ports.ports, >>>>>> + sizeof(flow.ports.ports)); >>>>>> + break; >>>>>> + >>>>>> + case VIRTIO_NET_HASH_REPORT_UDPv6: >>>>>> + virtio_net_toeplitz_calc(&toeplitz_state, >>>>>> + (__be32 *)&flow.addrs.v6addrs, >>>>>> + sizeof(flow.addrs.v6addrs)); >>>>>> + virtio_net_toeplitz_calc(&toeplitz_state, &flow.ports.ports, >>>>>> + sizeof(flow.ports.ports)); >>>>>> + break; >>>>>> + >>>>>> + default: >>>>>> + hash->report = VIRTIO_NET_HASH_REPORT_NONE; >>>>>> + return; >>>>> >>>>> So I still think we need a comment here to explain why this is not an >>>>> issue if the device can report HASH_XXX_EX. Or we need to add the >>>>> support, since this is the code from the driver side, I don't think we >>>>> need to worry about the device implementation issues. >>>> >>>> This is on the device side, and don't report HASH_TYPE_XXX_EX. >>>> >>>>> >>>>> For the issue of the number of options, does the spec forbid fallback >>>>> to VIRTIO_NET_HASH_REPORT_NONE? If not, we can do that. >>>> >>>> 5.1.6.4.3.4 "IPv6 packets with extension header" says: >>>> > If VIRTIO_NET_HASH_TYPE_TCP_EX is set and the packet has a TCPv6 >>>> > header, the hash is calculated over the following fields: >>>> > - Home address from the home address option in the IPv6 destination >>>> > options header. If the extension header is not present, use the >>>> > Source IPv6 address. >>>> > - IPv6 address that is contained in the Routing-Header-Type-2 from the >>>> > associated extension header. If the extension header is not present, >>>> > use the Destination IPv6 address. >>>> > - Source TCP port >>>> > - Destination TCP port >>>> >>>> Therefore, if VIRTIO_NET_HASH_TYPE_TCP_EX is set, the packet has a TCPv6 >>>> and an home address option in the IPv6 destination options header is >>>> present, the hash is calculated over the home address. If the hash is >>>> not calculated over the home address in such a case, the device is >>>> contradicting with this section and violating the spec. The same goes >>>> for the other HASH_TYPE_XXX_EX types and Routing-Header-Type-2. >>> >>> Just to make sure we are one the same page. I meant: >>> >>> 1) If the hash is not calculated over the home address (in the case of >>> IPv6 destination destination), it can still report >>> VIRTIO_NET_RSS_HASH_TYPE_IPv6. This is what you implemented in your >>> series. So the device can simply fallback to e.g TCPv6 if it can't >>> understand all or part of the IPv6 options. >> >> The spec says it can fallback if "the extension header is not present", >> not if the device can't understand the extension header. > > I don't think so, > > 1) spec had a condition beforehand: > > """ > If VIRTIO_NET_HASH_TYPE_TCP_EX is set and the packet has a TCPv6 > header, the hash is calculated over the following fields: > ... > If the extension header is not present ... > """ > > So the device can choose not to set VIRTIO_NET_HASH_TYPE_TCP_EX as > spec doesn't say device MUST set VIRTIO_NET_HASH_TYPE_TCP_EX if ... > > 2) implementation wise, since device has limited resources, we can't > expect the device can parse arbitrary number of ipv6 options > > 3) if 1) and 2) not the case, we need fix the spec otherwise implement > a spec compliant device is impractical The statement is preceded by the following: > The device calculates the hash on IPv4 packets according to > ’Enabled hash types’ bitmask as follows: The 'Enabled hash types' bitmask is specified by the device. I think the spec needs amendment. I wonder if there are any people interested in the feature though. Looking at virtnet_set_hashflow() in drivers/net/virtio_net.c, the driver of Linux does not let users configure HASH_TYPE_XXX_EX. I suppose Windows supports HASH_TYPE_XXX_EX, but those who care network performance most would use Linux so HASH_TYPE_XXX_EX support without Linux driver's support may not be useful. > >> >>> 2) the VIRTIO_NET_SUPPORTED_HASH_TYPES is not checked against the >>> tun_vnet_ioctl_sethash(), so userspace may set >>> VIRTIO_NET_HASH_TYPE_TCP_EX regardless of what has been returned by >>> tun_vnet_ioctl_gethashtypes(). In this case they won't get >>> VIRTIO_NET_HASH_TYPE_TCP_EX. >> >> That's right. It's the responsibility of the userspace to set only the >> supported hash types. > > Well, the kernel should filter out the unsupported one to have a > robust uAPI. Otherwise, we give green light to the buggy userspace > which will have unexpected results. My reasoning was that it may be fine for some use cases other than VM (e.g., DPDK); in such a use case, it is fine as long as the UAPI works in the best-effort basis. For example, suppose a userspace program that processes TCP packets; the program can enable: HASH_TYPE_IPv4, HASH_TYPE_TCPv4, HASH_TYPE_IPv6, and HASH_TYPE_TCPv6. Ideally, the kernel should support all the hash types, but, even if e.g., HASH_TYPE_TCPv6 is not available, it will fall back to HASH_TYPE_IPv6, which still does something good and may be acceptable. That said, for a use case that involves VM and implements virtio-net (e.g., QEMU), setting an unsupported hash type here is definitely a bug. Catching the bug may outweigh the extra trouble for other use cases. > >> >>> 3) implementing part of the hash types might complicate the migration >>> or at least we need to describe the expectations of libvirt or other >>> management in this case. For example, do we plan to have a dedicated >>> Qemu command line like: >>> >>> -device virtio-net-pci,hash_report=on,supported_hash_types=X,Y,Z? >> >> I posted a patch series to implement such a command line for vDPA[1]. >> The patch series that wires this tuntap feature up[2] reuses the >> infrastructure so it doesn't bring additional complexity. >> >> [1] >> https://lore.kernel.org/qemu-devel/20250530-vdpa-v1-0-5af4109b1c19@daynix.com/ >> [2] >> https://lore.kernel.org/qemu-devel/20250530-hash-v5-0-343d7d7a8200@daynix.com/ > > I meant, if we implement a full hash report feature, it means a single > hash cmdline option is more than sufficient and so compatibility code > can just turn it off when dealing with machine types. This is much > more simpler than > > 1) having both hash as well as supported_hash_features > 2) dealing both hash as well as supported_hash_features in compatibility codes > 3) libvirt will be happy > > For [1], it seems it introduces a per has type option, this seems to > be a burden to the management layer as it need to learn new option > everytime a new hash type is supported Even with the command line you proposed (supported_hash_types=X,Y,Z), it is still necessary to know the values the supported_hash_types property accepts (X.Y,Z), so I don't think it makes difference. The burden to the management layer is already present for features, so it is an existing problem (or its mere extension). This problem was discussed in the following thread in the past, but no solution is implemented yet, and probably solving it will be difficult. https://lore.kernel.org/qemu-devel/20230731223148.1002258-5-yuri.benditovich@daynix.com/ Regards, Akihiko Odaki