On Wed, Jul 29, 2026 at 01:49:16PM +0800, Chenguang Zhao wrote:
> From: Chenguang Zhao <[email protected]>
> 
> Replace the driver-local i40e_construct_skb_zc() with the common
> helper xdp_build_skb_from_zc(). On failure, free the xdp buff in
> the caller.
> 
> xdp_build_skb_from_zc() already calls skb_record_rx_queue() and
> eth_type_trans(), so pull the remaining descriptor field setup into
> __i40e_process_skb_fields() and use that on the XDP_PASS path.
> Briefly restore the Ethernet header around eth_skb_pad() so padding
> sees the full L2 frame length.
> 
> Signed-off-by: Chenguang Zhao <[email protected]>
> ---
> v2:
> - Extract descriptor field setup into __i40e_process_skb_fields() and
>   use it on the XDP_PASS path, so skb_record_rx_queue()/eth_type_trans()
>   are not repeated after xdp_build_skb_from_zc().
> - Keep a brief __skb_push()/__skb_pull() around eth_skb_pad() so padding
>   still sees the full L2 frame length.
> 
> v1:
>  - 
> https://lore.kernel.org/all/[email protected]/
> ---
>  drivers/net/ethernet/intel/i40e/i40e_txrx.c   | 32 ++++++--
>  .../ethernet/intel/i40e/i40e_txrx_common.h    |  2 +
>  drivers/net/ethernet/intel/i40e/i40e_xsk.c    | 76 +++----------------
>  3 files changed, 36 insertions(+), 74 deletions(-)
> 

[...]

>  static void i40e_handle_xdp_result_zc(struct i40e_ring *rx_ring,
>                                     struct xdp_buff *xdp_buff,
>                                     union i40e_rx_desc *rx_desc,
> @@ -372,21 +309,28 @@ static void i40e_handle_xdp_result_zc(struct i40e_ring 
> *rx_ring,
>                * BIT(I40E_RXD_QW1_ERROR_SHIFT). This is due to that
>                * SBP is *not* set in PRT_SBPVSI (default not set).
>                */
> -             skb = i40e_construct_skb_zc(rx_ring, xdp_buff);
> +             skb = xdp_build_skb_from_zc(xdp_buff);
>               if (!skb) {
> +                     xsk_buff_free(xdp_buff);
>                       rx_ring->rx_stats.alloc_buff_failed++;
>                       *rx_packets = 0;
>                       *rx_bytes = 0;
>                       return;
>               }
>  
> +             /* xdp_build_skb_from_zc() already ran eth_type_trans() and
> +              * skb_record_rx_queue(). Restore the Ethernet header only for
> +              * eth_skb_pad(), then pull it back.
> +              */
> +             __skb_push(skb, ETH_HLEN);
>               if (eth_skb_pad(skb)) {
>                       *rx_packets = 0;
>                       *rx_bytes = 0;
>                       return;
>               }
> +             __skb_pull(skb, ETH_HLEN);

I am pretty sure that eth_skb_pad() is not needed on Rx, network stack handles 
small skbs just fine, and no other vendor does this. We were trying to figure 
out the historical reasons for eth_skb_pad() being there in the intel drivers, 
but with no luck.

>  
> -             i40e_process_skb_fields(rx_ring, rx_desc, skb);
> +             __i40e_process_skb_fields(rx_ring, rx_desc, skb);
>               napi_gro_receive(&rx_ring->q_vector->napi, skb);
>               return;
>       }
> -- 
> 2.25.1
> 
> 

Reply via email to