Netdev List
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: shshitrit@nvidia.com
Cc: netdev@vger.kernel.org, mst@redhat.com, jasowang@redhat.com,
	pabeni@redhat.com, virtualization@lists.linux.dev,
	parav@nvidia.com, yohadt@nvidia.com, xuanzhuo@linux.alibaba.com,
	eperezma@redhat.com, jgg@ziepe.ca, kevin.tian@intel.com,
	kuba@kernel.org, andrew+netdev@lunn.ch, edumazet@google.com,
	danielj@nvidia.com
Subject: Re: [net-next,v23,12/14] virtio_net: Add support for IPv6 ethtool steering
Date: Wed, 02 Sep 2026 13:12:30 +0000	[thread overview]
Message-ID: <178835475012.3394541.15260297346389800429@kernel.org> (raw)
In-Reply-To: <20260831161109.2999926-13-shshitrit@nvidia.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issue(s) to consider:

Critical: 0 · High: 0 · Medium: 1 · Low: 1

- [Medium] The new IPv6 code overlays `struct ipv6hdr` (alignment 4, from
  the embedded struct in6_addr / __be32 s6_addr32[]) on byte-packed…
- [Low] Commit message claims "Implement support for IPV6_USER_FLOW type
  rules" but the implementation only supports src-ip/dst-ip matching:…

--

virtio_net: Add support for IPv6 ethtool steering

This adds IPV6_USER_FLOW support to the virtio_net ethtool flow filter
code: a new validate_ip6_mask() for the IPv6 selector mask, a new
parse_ip6() to build the key/mask pair, and IPv6 handling in
setup_ip_key_mask(), supported_flow_type() and calculate_flow_sizes().

Two questions below, one about alignment of the new IPv6 accesses and one
about the scope described in the changelog.

> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index c33bbdda75590..bfe8f0bc2581a 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -5843,6 +5843,40 @@ static bool validate_ip4_mask(const struct virtnet_ff *ff,
>  	return true;
>  }
>  
> +static bool validate_ip6_mask(const struct virtnet_ff *ff,
> +			      const struct virtio_net_ff_selector *sel,
> +			      const struct virtio_net_ff_selector *sel_cap)
> +{
> +	bool partial_mask = !!(sel_cap->flags & VIRTIO_NET_FF_MASK_F_PARTIAL_MASK);
> +	struct in6_addr tmp;
> +	struct ipv6hdr *cap, *mask;
> +
> +	cap = (struct ipv6hdr *)&sel_cap->mask;
> +	mask = (struct ipv6hdr *)&sel->mask;
> +
> +	/* mask->saddr/daddr may be unaligned; copy to aligned tmp for
> +	 * ipv6_addr_any().
> +	 */
> +	memcpy(&tmp, &mask->saddr, sizeof(tmp));
> +	if (!ipv6_addr_any(&tmp) &&
> +	    !check_mask_vs_cap(&mask->saddr, &cap->saddr,
> +			       sizeof(cap->saddr), partial_mask))
> +		return false;
> +
> +	memcpy(&tmp, &mask->daddr, sizeof(tmp));
> +	if (!ipv6_addr_any(&tmp) &&
> +	    !check_mask_vs_cap(&mask->daddr, &cap->daddr,
> +			       sizeof(cap->daddr), partial_mask))
> +		return false;
> +
> +	if (mask->nexthdr &&
> +	    !check_mask_vs_cap(&mask->nexthdr, &cap->nexthdr,
> +			       sizeof(cap->nexthdr), partial_mask))
> +		return false;
> +
> +	return true;
> +}
> +

[ ... ]

> @@ -5884,11 +5921,33 @@ static void parse_ip4(struct iphdr *mask, struct iphdr *key,
>  	}
>  }
>  
> +static void parse_ip6(struct ipv6hdr *mask, struct ipv6hdr *key,
> +		      const struct ethtool_rx_flow_spec *fs)
> +{
> +	const struct ethtool_usrip6_spec *l3_mask = &fs->m_u.usr_ip6_spec;
> +	const struct ethtool_usrip6_spec *l3_val  = &fs->h_u.usr_ip6_spec;
> +
> +	if (!ipv6_addr_any((struct in6_addr *)l3_mask->ip6src)) {
> +		memcpy(&mask->saddr, l3_mask->ip6src, sizeof(mask->saddr));
> +		memcpy(&key->saddr, l3_val->ip6src, sizeof(key->saddr));
> +	}
> +
> +	if (!ipv6_addr_any((struct in6_addr *)l3_mask->ip6dst)) {
> +		memcpy(&mask->daddr, l3_mask->ip6dst, sizeof(mask->daddr));
> +		memcpy(&key->daddr, l3_val->ip6dst, sizeof(key->daddr));
> +	}
> +}

[Severity: Medium]
Are the destinations of these copies guaranteed to be 4-byte aligned?

struct in6_addr contains __be32 s6_addr32[4], so struct ipv6hdr has
4-byte alignment, but the buffers these pointers overlay are byte packed
in the virtio flow filter layout:

  build_and_insert() -> setup_ip_key_mask(next_selector(selector),
                                          key + sizeof(struct ethhdr), fs)

For the classifier mask, the first selector is an 8-byte
struct virtio_net_ff_selector header plus a 14-byte struct ethhdr mask,
so the second selector starts at obj+30 and its mask[] at obj+38, which
makes &v6_m->saddr land at obj+46, i.e. 2 mod 4. The key buffer is the
same: it is offset by sizeof(struct ethhdr), so &v6_k->saddr is
base+22, again 2 mod 4.

The IPv4 sibling in the same file goes through the unaligned helpers for
exactly these members:

drivers/net/virtio_net.c:parse_ip4() {
	if (l3_mask->ip4src) {
		put_unaligned(l3_mask->ip4src, &mask->saddr);
		put_unaligned(l3_val->ip4src, &key->saddr);
	}
	...
}

and validate_ip4_mask() uses get_unaligned(&mask->saddr) for the read
side. Since the pointer expressions here are typed struct in6_addr *,
can the compiler expand these 16-byte copies into word or multi-word
accesses (for example LDRD/STRD or LDM/STM on 32-bit ARM) on an address
that is 2 mod 4, and fault on strict-alignment architectures?

The comment in validate_ip6_mask() already notes "mask->saddr/daddr may
be unaligned", but the aligned tmp only fixes the destination of that one
copy; the source (&mask->saddr) and the copies in parse_ip6() are still
misaligned accesses through a 4-byte-aligned pointer type. Would using
the unaligned accessors, or plain u8 pointers, for these fields keep the
IPv6 path consistent with the IPv4 one?

[ ... ]

> @@ -6114,20 +6179,38 @@ static int setup_ip_key_mask(struct virtio_net_ff_selector *selector,
>  			     u8 *key,
>  			     const struct ethtool_rx_flow_spec *fs)
>  {
> +	struct ipv6hdr *v6_m = (struct ipv6hdr *)&selector->mask;
>  	struct iphdr *v4_m = (struct iphdr *)&selector->mask;
> +	struct ipv6hdr *v6_k = (struct ipv6hdr *)key;
>  	struct iphdr *v4_k = (struct iphdr *)key;
>  
> -	selector->type = VIRTIO_NET_FF_MASK_TYPE_IPV4;
> -	selector->length = sizeof(struct iphdr);
> +	if (has_ipv6(fs->flow_type)) {
> +		selector->type = VIRTIO_NET_FF_MASK_TYPE_IPV6;
> +		selector->length = sizeof(struct ipv6hdr);
> +
> +		/* exclude tclass, it's not exposed directly in struct ipv6hdr */
> +		if (fs->h_u.usr_ip6_spec.l4_4_bytes ||
> +		    fs->m_u.usr_ip6_spec.l4_4_bytes ||
> +		    fs->h_u.usr_ip6_spec.tclass ||
> +		    fs->m_u.usr_ip6_spec.tclass ||
> +		    fs->h_u.usr_ip6_spec.l4_proto ||
> +		    fs->m_u.usr_ip6_spec.l4_proto)
> +			return -EINVAL;
>  
> -	if (fs->h_u.usr_ip4_spec.l4_4_bytes ||
> -	    fs->h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4 ||
> -	    fs->m_u.usr_ip4_spec.l4_4_bytes ||
> -	    fs->m_u.usr_ip4_spec.ip_ver ||
> -	    fs->m_u.usr_ip4_spec.proto)
> -		return -EINVAL;
> +		parse_ip6(v6_m, v6_k, fs);

[Severity: Low]
This isn't a bug, but should the changelog say which ip6 match fields are
actually implemented?

The commit message says:

    Implement support for IPV6_USER_FLOW type rules.

but setup_ip_key_mask() rejects any non-zero tclass, l4_proto or
l4_4_bytes, in the value as well as in the mask, and parse_ip6() only
ever fills in saddr/daddr. So of the struct ethtool_usrip6_spec fields
only the addresses work, while supported_flow_type() advertises
IPV6_USER_FLOW as a whole:

	case IPV6_USER_FLOW:
		return true;

A request such as:

    ethtool -U ens9 flow-type ip6 src-ip fe80::2 tclass 8 action 3

fails with "Invalid argument" and there is nothing in the log describing
the limitation.

There is also an asymmetry with the IPv4 support added in the previous
patch: parse_ip4() does translate the IPv4 tos field:

	if (l3_mask->tos) {
		mask->tos = l3_mask->tos;
		key->tos = l3_val->tos;
	}

while the IPv6 path refuses the equivalent tclass, even though
struct ipv6hdr carries the traffic class in the priority/flow_lbl bits.
Could the changelog mention that only src-ip/dst-ip matching is
supported for ip6 flows, and why tclass parity with the IPv4 path is not
provided?

> +	} else {
> +		selector->type = VIRTIO_NET_FF_MASK_TYPE_IPV4;
> +		selector->length = sizeof(struct iphdr);

[ ... ]

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260831161109.2999926-1-shshitrit%40nvidia.com

  reply	other threads:[~2026-09-02 13:12 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31 16:10 [PATCH net-next v23 00/14] virtio_net: Add ethtool flow rules support Shahar Shitrit
2026-08-31 16:10 ` [PATCH net-next v23 01/14] virtio_pci: Remove supported_caps cache and build assert Shahar Shitrit
2026-08-31 16:10 ` [PATCH net-next v23 02/14] virtio_pci: Fix sleeping under spinlock in admin command path Shahar Shitrit
2026-09-02 13:12   ` [net-next,v23,02/14] " netdev-bot+sashiko
2026-09-03  9:25     ` Paolo Abeni
2026-08-31 16:10 ` [PATCH net-next v23 03/14] virtio: Add config_op for admin commands Shahar Shitrit
2026-09-02 13:12   ` [net-next,v23,03/14] " netdev-bot+sashiko
2026-08-31 16:10 ` [PATCH net-next v23 04/14] virtio: Expose generic device capability operations Shahar Shitrit
2026-09-02 13:12   ` [net-next,v23,04/14] " netdev-bot+sashiko
2026-08-31 16:11 ` [PATCH net-next v23 05/14] virtio: Expose object create and destroy API Shahar Shitrit
2026-09-02 13:12   ` [net-next,v23,05/14] " netdev-bot+sashiko
2026-08-31 16:11 ` [PATCH net-next v23 06/14] virtio_net: Query and set flow filter caps Shahar Shitrit
2026-09-02 13:12   ` [net-next,v23,06/14] " netdev-bot+sashiko
2026-08-31 16:11 ` [PATCH net-next v23 07/14] virtio_net: Create a FF group for ethtool steering Shahar Shitrit
2026-09-02 13:12   ` [net-next,v23,07/14] " netdev-bot+sashiko
2026-08-31 16:11 ` [PATCH net-next v23 08/14] ethtool: Introduce ethtool_flow_type_mask() Shahar Shitrit
2026-08-31 16:11 ` [PATCH net-next v23 09/14] virtio_net: Implement layer 2 ethtool flow rules Shahar Shitrit
2026-09-02 13:12   ` [net-next,v23,09/14] " netdev-bot+sashiko
2026-08-31 16:11 ` [PATCH net-next v23 10/14] virtio_net: Use existing classifier if possible Shahar Shitrit
2026-09-02 13:12   ` [net-next,v23,10/14] " netdev-bot+sashiko
2026-08-31 16:11 ` [PATCH net-next v23 11/14] virtio_net: Implement IPv4 ethtool flow rules Shahar Shitrit
2026-09-02 13:12   ` [net-next,v23,11/14] " netdev-bot+sashiko
2026-08-31 16:11 ` [PATCH net-next v23 12/14] virtio_net: Add support for IPv6 ethtool steering Shahar Shitrit
2026-09-02 13:12   ` netdev-bot+sashiko [this message]
2026-08-31 16:11 ` [PATCH net-next v23 13/14] virtio_net: Add support for TCP and UDP ethtool rules Shahar Shitrit
2026-08-31 16:11 ` [PATCH net-next v23 14/14] virtio_net: Add get ethtool flow rules ops Shahar Shitrit
2026-09-02 13:12   ` [net-next,v23,14/14] " netdev-bot+sashiko
2026-08-31 16:37 ` [PATCH net-next v23 00/14] virtio_net: Add ethtool flow rules support Michael S. Tsirkin
2026-08-31 19:45 ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178835475012.3394541.15260297346389800429@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=danielj@nvidia.com \
    --cc=edumazet@google.com \
    --cc=eperezma@redhat.com \
    --cc=jasowang@redhat.com \
    --cc=jgg@ziepe.ca \
    --cc=kevin.tian@intel.com \
    --cc=kuba@kernel.org \
    --cc=mst@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=parav@nvidia.com \
    --cc=shshitrit@nvidia.com \
    --cc=virtualization@lists.linux.dev \
    --cc=xuanzhuo@linux.alibaba.com \
    --cc=yohadt@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox