Netdev List
 help / color / mirror / Atom feed
From: Jakub Kicinski <kuba@kernel.org>
To: anthony.l.nguyen@intel.com
Cc: Jakub Kicinski <kuba@kernel.org>,
	davem@davemloft.net, pabeni@redhat.com, edumazet@google.com,
	andrew+netdev@lunn.ch, netdev@vger.kernel.org, tactii@gmail.com,
	dima.ruinskiy@intel.com, aleksandr.loktionov@intel.com,
	pmenzel@molgen.mpg.de, michalx.cohen@intel.com
Subject: Re: [PATCH net-next 03/15] ice: use NETIF_F_HW_CSUM instead of IP/IPV6
Date: Mon, 10 Aug 2026 17:35:15 -0700	[thread overview]
Message-ID: <20260811003515.1056735-1-kuba@kernel.org> (raw)
In-Reply-To: <20260805213541.2281287-4-anthony.l.nguyen@intel.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
ice: use NETIF_F_HW_CSUM instead of IP/IPV6

This switches the ice netdev checksum offload advertisement from
NETIF_F_IP_CSUM/NETIF_F_IPV6_CSUM to NETIF_F_HW_CSUM, so IPv6 packets
carrying extension headers are no longer pushed down the software checksum
path.  It also removes the conditional NETIF_F_HW_CSUM advertisement for
GCS-capable parts and the TSO/GCS mutual exclusion check in
ice_set_features().

A few questions below.

> diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
> index cc30d8c73a41c..a5e9c3114706f 100644
> --- a/drivers/net/ethernet/intel/ice/ice_main.c
> +++ b/drivers/net/ethernet/intel/ice/ice_main.c
> @@ -3491,9 +3491,8 @@ void ice_set_netdev_features(struct net_device *netdev)
>  			NETIF_F_RXHASH;
>  
>  	csumo_features = NETIF_F_RXCSUM	  |
> -			 NETIF_F_IP_CSUM  |
>  			 NETIF_F_SCTP_CRC |
> -			 NETIF_F_IPV6_CSUM;
> +			 NETIF_F_HW_CSUM;

[Severity: Medium]
Should this hunk carry a Fixes: tag and be split out from the GCS/TSO
cleanup?

As far as I can tell this is not just an offload-advertisement cleanup, it
fixes a user-visible drop.  With only NETIF_F_IP_CSUM/NETIF_F_IPV6_CSUM set,
skb_csum_hwoffload_help() in net/core/dev.c forces the software path:

	if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
		if (vlan_get_protocol(skb) == htons(ETH_P_IPV6) &&
		    skb_network_header_len(skb) != sizeof(struct ipv6hdr))
			goto sw_checksum;

and skb_checksum_help() refuses GSO skbs:

	if (unlikely(skb_is_gso(skb))) {
		skb_warn_bad_offload(skb);
		return -EINVAL;
	}

Since ice advertises NETIF_F_TSO6, netif_needs_gso() is false and the skb
arrives still marked GSO, so validate_xmit_skb() takes the
out_kfree_skb path and the frame is dropped rather than de-offloaded.

That means TSO'd IPv6 traffic with an extension header (SRv6, HOPOPTS,
DSTOPTS) is dropped on every ice device on stable kernels containing the
skb_csum_hwoffload_help() change (04c20a9356f2, v6.13+).  The changelog only
hints at this with "To not drop such packets", and there is no Fixes: tag,
so it is hard to identify for backport.  Would it make sense to make this
one-liner a standalone patch with a Fixes: tag, and keep the GCS/TSO
mutual-exclusion removal (which depends on the earlier "ice: always do GCS
if hardware supports it" patch in this series) separate?

[Severity: Medium]
On non-GCS parts, is NETIF_F_HW_CSUM an accurate description of what the
legacy path in ice_tx_csum() (drivers/net/ethernet/intel/ice/ice_txrx.c)
implements?

NETIF_F_HW_CSUM promises the driver honours skb->csum_start /
skb->csum_offset for any protocol, and once it is set
skb_csum_hwoffload_help() returns 0 unconditionally, so the core no longer
checks that skb->csum_offset is offsetof(struct tcphdr, check) or
offsetof(struct udphdr, check).

The legacy branch of ice_tx_csum() derives the insertion point purely from
its own header parse and never looks at skb->csum_offset:

	switch (l4_proto) {
	case IPPROTO_TCP:
		cmd |= ICE_TX_DESC_CMD_L4T_EOFT_TCP;
		l4_len = l4.tcp->doff;
		offset |= l4_len << ICE_TX_DESC_LEN_L4_LEN_S;
		break;
	...
	default:
		goto checksum_sw_fb;
	}

So for a CHECKSUM_PARTIAL frame that parses as IPv4/IPv6 + TCP/UDP but asks
for a different csum_offset (virtio_net_hdr/tap or AF_PACKET with a vnet
header; skb_partial_csum_set() only checks that start/off lie inside the
linear area), hardware writes the checksum at the standard L4 offset while
the field the stack asked to be filled keeps the pseudo-header seed.  The
checksum_sw_fb fallback does not catch this, since it is only reached when
the network header is neither IPv4 nor IPv6 or when l4_proto hits the switch
default.

i40e has the same loose interpretation (it never references
skb->csum_offset either), so this may well be intended precedent - is that
the reasoning here?

>  
>  	vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER |
>  			 NETIF_F_HW_VLAN_CTAG_TX     |
> @@ -3555,12 +3554,6 @@ void ice_set_netdev_features(struct net_device *netdev)
>  	/* Allow core to manage IRQs affinity */
>  	netif_set_affinity_auto(netdev);
>  
> -	/* Mutual exclusivity for TSO and GCS is enforced by the set features
> -	 * ndo callback.
> -	 */
> -	if (ice_is_feature_supported(pf, ICE_F_GCS))
> -		netdev->hw_features |= NETIF_F_HW_CSUM;
> -

[Severity: High]
With NETIF_F_HW_CSUM now in csumo_features it is enabled by default
(netdev->features |= netdev->hw_features) and also propagated into
hw_enc_features and vlan_features.  On E830 that makes the GCS context
descriptor path in ice_tx_csum() the default Tx checksum path.  Can the
values programmed there be truncated?

	u16 csum_start = (skb->csum_start - skb->mac_header) / 2;
	u16 csum_offset = skb->csum_offset / 2;
	u16 gcs_params;

	gcs_params = FIELD_PREP(ICE_TX_GCS_DESC_START_M, csum_start) |
		     FIELD_PREP(ICE_TX_GCS_DESC_OFFSET_M, csum_offset) |

The descriptor fields in ice_lan_tx_rx.h are narrow:

	#define ICE_TX_GCS_DESC_START_M		GENMASK(7, 0)
	#define ICE_TX_GCS_DESC_OFFSET_M	GENMASK(11, 8)

i.e. at most 510 bytes of L2+L3 header and at most a 30-byte checksum
offset.  Neither value is range-checked, and FIELD_PREP()'s
__BF_FIELD_CHECK only rejects out-of-range constants, so a runtime value is
silently masked.

The driver's ndo_features_check, ice_features_check(), only bounds the two
lengths individually:

	len = skb_network_offset(skb);
	if (len > ICE_TXD_MACLEN_MAX || len & 0x1)
		goto out_rm_features;

	len = skb_network_header_len(skb);
	if (len > ICE_TXD_IPLEN_MAX || len & 0x1)
		goto out_rm_features;

That permits 254 + 508 = 762 combined bytes, well past the 510 bytes the
GCS start field can express.  An IPv6 frame with roughly 498..508 bytes of
header plus extension headers (a long HOPOPTS/DSTOPTS chain, or an SRv6 SRH
with many SIDs over a VLAN) passes both checks, yet
(csum_start - mac_header) / 2 = 259 becomes 3 after masking, so the NIC
sums the wrong byte range and inserts the result inside the MAC/IPv6
header.

The same masking applies to skb->csum_offset > 30, which
virtio_net_hdr_to_skb()/skb_partial_csum_set() allow (they only bound
start/off against skb_headlen()), and which the core no longer filters now
that NETIF_F_HW_CSUM is advertised.  Would a FIELD_MAX() check on both
values before taking the GCS branch, or an added combined-length check in
ice_features_check(), be appropriate here?

>  	netif_set_tso_max_size(netdev, ICE_MAX_TSO_SIZE);
>  }
>  
> @@ -6519,18 +6512,6 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
>  	if (changed & NETIF_F_LOOPBACK)
>  		ret = ice_set_loopback(vsi, !!(features & NETIF_F_LOOPBACK));
>  
> -	/* Due to E830 hardware limitations, TSO (NETIF_F_ALL_TSO) with GCS
> -	 * (NETIF_F_HW_CSUM) is not supported.
> -	 */
> -	if (ice_is_feature_supported(pf, ICE_F_GCS) &&
> -	    ((features & NETIF_F_HW_CSUM) && (features & NETIF_F_ALL_TSO))) {
> -		if (netdev->features & NETIF_F_HW_CSUM)
> -			dev_err(ice_pf_to_dev(pf), "To enable TSO, you must first disable HW checksum.\n");
> -		else
> -			dev_err(ice_pf_to_dev(pf), "To enable HW checksum, you must first disable TSO.\n");
> -		return -EIO;
> -	}
> -
>  	return ret;
>  }

  reply	other threads:[~2026-08-11  0:35 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-05 21:35 [PATCH net-next 00/15][pull request] Intel Wired LAN Driver Updates 2026-08-05 (ice, i40e, igc, e1000e) Tony Nguyen
2026-08-05 21:35 ` [PATCH net-next 01/15] ice: add support for unmanaged DPLL on E830 NIC Tony Nguyen
2026-08-11  0:33   ` Jakub Kicinski
2026-08-05 21:35 ` [PATCH net-next 02/15] ice: always do GCS if hardware supports it Tony Nguyen
2026-08-11  0:35   ` Jakub Kicinski
2026-08-05 21:35 ` [PATCH net-next 03/15] ice: use NETIF_F_HW_CSUM instead of IP/IPV6 Tony Nguyen
2026-08-11  0:35   ` Jakub Kicinski [this message]
2026-08-05 21:35 ` [PATCH net-next 04/15] virtchnl: add VIRTCHNL_VLAN_ETHERTYPE_88E7 support Tony Nguyen
2026-08-11  0:35   ` Jakub Kicinski
2026-08-05 21:35 ` [PATCH net-next 05/15] ice: add 0x88E7 handling to SW validation paths Tony Nguyen
2026-08-11  0:35   ` Jakub Kicinski
2026-08-05 21:35 ` [PATCH net-next 06/15] ice: reduce loglevel to debug for 'Can't delete DSCP' message Tony Nguyen
2026-08-05 21:35 ` [PATCH net-next 07/15] ice: use ice_fill_eth_hdr() in ice_fill_sw_rule() Tony Nguyen
2026-08-05 21:35 ` [PATCH net-next 08/15] ice: increase OICR interrupt moderation rate to 20K interrupts/sec Tony Nguyen
2026-08-05 21:35 ` [PATCH net-next 09/15] ice: add rx timestamp tracepoint for debugging Tony Nguyen
2026-08-05 21:35 ` [PATCH net-next 10/15] i40e: prepare for XDP metadata ops support Tony Nguyen
2026-08-11  0:35   ` Jakub Kicinski
2026-08-05 21:35 ` [PATCH net-next 11/15] i40e: add support for bpf_xdp_metadata_rx_hash() Tony Nguyen
2026-08-05 21:35 ` [PATCH net-next 12/15] i40e: add support for bpf_xdp_metadata_rx_vlan_tag() Tony Nguyen
2026-08-05 21:35 ` [PATCH net-next 13/15] i40e: Avoid repeating RX filter warning Tony Nguyen
2026-08-05 21:35 ` [PATCH net-next 14/15] igc: Support ACPI-based MAC pass-through Tony Nguyen
2026-08-11  0:35   ` Jakub Kicinski
2026-08-05 21:35 ` [PATCH net-next 15/15] e1000e: Avoid DMA re-mapping on RX copybreak Tony Nguyen
2026-08-11  0:35   ` Jakub Kicinski
2026-08-11  0:35 ` [PATCH net-next 00/15][pull request] Intel Wired LAN Driver Updates 2026-08-05 (ice, i40e, igc, e1000e) Jakub Kicinski

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=20260811003515.1056735-1-kuba@kernel.org \
    --to=kuba@kernel.org \
    --cc=aleksandr.loktionov@intel.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=anthony.l.nguyen@intel.com \
    --cc=davem@davemloft.net \
    --cc=dima.ruinskiy@intel.com \
    --cc=edumazet@google.com \
    --cc=michalx.cohen@intel.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=pmenzel@molgen.mpg.de \
    --cc=tactii@gmail.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