[Intel-wired-lan] [PATCH net v1] ice: fix IPIP and SIT TSO offload

Paul Menzel pmenzel at molgen.mpg.de
Sat Jan 15 07:54:52 UTC 2022


Dear Jesse,


Am 15.01.22 um 00:38 schrieb Jesse Brandeburg:
> The driver was avoiding offload for IPIP (at least) frames due to
> parsing the inner header offsets incorrectly when trying to check
> lengths.
> 
> This length check works for VXLAN frames but fails on IPIP frames
> because skb_transport_offset points to the inner header in IPIP
> frames, which meant the subtraction of transport_header from
> inner_network_header returns a negative value (-20).
> 
> With the code before this patch, everything continued to work, but GSO
> was being used to segment, causing throughputs of 1.5Gb/s per thread.
> After this patch, throughput is more like 10Gb/s per thread for IPIP
> traffic.

Would be nice to reflow for 75 characters per line.

> Fixes: e94d44786693 ("ice: Implement filter sync, NDO operations and bump version")

Wow present since Linux 4.17.

> Signed-off-by: Jesse Brandeburg <jesse.brandeburg at intel.com>
> --
> Testing Hints: test IPIP tunnel and VXLAN tunnel, both should use TSO.

Do you have a script to test it? Would be nice to have in the commit 
message.

> ---
>   .../net/ethernet/intel/ice/ice_lan_tx_rx.h    |  1 +
>   drivers/net/ethernet/intel/ice/ice_main.c     | 25 +++++++++++++------
>   2 files changed, 18 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
> index d981dc6f2323..85a612838a89 100644
> --- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
> +++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
> @@ -568,6 +568,7 @@ struct ice_tx_ctx_desc {
>   			(0x3FFFFULL << ICE_TXD_CTX_QW1_TSO_LEN_S)
>   
>   #define ICE_TXD_CTX_QW1_MSS_S	50
> +#define ICE_TXD_CTX_MIN_MSS	64
>   
>   #define ICE_TXD_CTX_QW1_VSI_S	50
>   #define ICE_TXD_CTX_QW1_VSI_M	(0x3FFULL << ICE_TXD_CTX_QW1_VSI_S)
> diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
> index 73c61cdb036f..105b62b5e7cb 100644
> --- a/drivers/net/ethernet/intel/ice/ice_main.c
> +++ b/drivers/net/ethernet/intel/ice/ice_main.c
> @@ -8540,6 +8540,7 @@ ice_features_check(struct sk_buff *skb,
>   		   struct net_device __always_unused *netdev,
>   		   netdev_features_t features)
>   {
> +	bool gso = skb_is_gso(skb);

Maybe name it `is_gso`, so it’s clear it’s a boolean, and make it const?

>   	size_t len;
>   
>   	/* No point in doing any of this if neither checksum nor GSO are
> @@ -8552,24 +8553,32 @@ ice_features_check(struct sk_buff *skb,
>   	/* We cannot support GSO if the MSS is going to be less than
>   	 * 64 bytes. If it is then we need to drop support for GSO.
>   	 */
> -	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
> +	if (gso && (skb_shinfo(skb)->gso_size < ICE_TXD_CTX_MIN_MSS))
>   		features &= ~NETIF_F_GSO_MASK;
>   
> -	len = skb_network_header(skb) - skb->data;
> +	len = skb_network_offset(skb);
>   	if (len > ICE_TXD_MACLEN_MAX || len & 0x1)
>   		goto out_rm_features;
>   
> -	len = skb_transport_header(skb) - skb_network_header(skb);
> +	len = skb_network_header_len(skb);

Ok, for networking unfamiliar, this is refactoring.

>   	if (len > ICE_TXD_IPLEN_MAX || len & 0x1)
>   		goto out_rm_features;
>   
>   	if (skb->encapsulation) {
> -		len = skb_inner_network_header(skb) - skb_transport_header(skb);
> -		if (len > ICE_TXD_L4LEN_MAX || len & 0x1)
> -			goto out_rm_features;
> +		/* this must work for vxlan frames AND IPIP/SIT frames, and in
> +		 * the case of IPIP frames, the transport header pointer is
> +		 * after the inner header! So check to make sure that this
> +		 * is a GRE or UDP_TUNNEL frame before doing that math.
> +		 */
> +		if (gso && (skb_shinfo(skb)->gso_type &
> +			    (SKB_GSO_GRE | SKB_GSO_UDP_TUNNEL))) {
> +			len = skb_inner_network_header(skb) -
> +			      skb_transport_header(skb);


> +			if (len > ICE_TXD_L4LEN_MAX || len & 0x1)
> +				goto out_rm_features;
> +		}
>   
> -		len = skb_inner_transport_header(skb) -
> -		      skb_inner_network_header(skb);
> +		len = skb_inner_network_header_len(skb);

Just refactoring.

>   		if (len > ICE_TXD_IPLEN_MAX || len & 0x1)
>   			goto out_rm_features;
>   	}

Next time, I’d prefer a separate patch doing the refactorings.

Reviewed-by: Paul Menzel <pmenzel at molgen.mpg.de>.


Kind regards,

Paul


PS: Is this also needed for i40e 
(`drivers/net/ethernet/intel/i40e/i40e_main.c`)?


More information about the Intel-wired-lan mailing list