mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
To: <tkusters@aweta.nl>
Cc: Tony Nguyen <anthony.l.nguyen@intel.com>,
	Przemek Kitszel <przemyslaw.kitszel@intel.com>,
	Andrew Lunn <andrew+netdev@lunn.ch>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	"Jakub Kicinski" <kuba@kernel.org>,
	Paolo Abeni <pabeni@redhat.com>,
	"Alexei Starovoitov" <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	"Jesper Dangaard Brouer" <hawk@kernel.org>,
	John Fastabend <john.fastabend@gmail.com>,
	Stanislav Fomichev <sdf@fomichev.me>,
	Sven Auhagen <sven.auhagen@voleatech.de>,
	Richard Cochran <richardcochran@gmail.com>,
	"Kurt Kanzenbach" <kurt@linutronix.de>,
	Sriram Yagnaraman <sriram.yagnaraman@ericsson.com>,
	<intel-wired-lan@lists.osuosl.org>, <netdev@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, <bpf@vger.kernel.org>,
	Paul Moses <p@1g4.org>, <stable@vger.kernel.org>
Subject: Re: [PATCH net v5 3/4] igb: do not split AF_XDP zero-copy frames over several Rx buffers
Date: Sat, 7 Nov 2026 17:37:53 +0100	[thread overview]
Message-ID: <au9T4Y1rpxvuEuFv@boxer> (raw)
In-Reply-To: <20261104-igb-rx-ts-fix-v5-3-bf4b4367129a@aweta.nl>

On Wed, Nov 04, 2026 at 07:40:04AM +0100, Tjerk Kusters via B4 Relay wrote:
> From: Tjerk Kusters <tkusters@aweta.nl>
> 
> SRRCTL.BSIZEPKT has a granularity of 1 KiB. For AF_XDP zero-copy rings,
> igb_setup_srrctl() programs xsk_pool_get_rx_frame_size(), which is
> rounded down. With 2 KiB UMEM chunks and the default headroom this is
> 1792 bytes, so the hardware buffer becomes 1 KiB and a full-size frame
> spans two Rx buffers. igb_clean_rx_irq_zc() handles every descriptor as
> a complete frame, so the AF_XDP socket gets such a frame as two
> packets, the second one without headers. With Rx timestamping enabled,
> the timestamp header is also stripped from the second buffer, and a
> short final buffer makes the size wrap.
> 
> Program the same buffer size as for the other rings, 2 KiB or 3 KiB.
> This depends on "igb: do not let XDP frames span more than one Rx
> buffer": the receive length limit set there while XDP is attached keeps
> the hardware from writing more than the frame plus the timestamp header
> into the larger buffer. Without it, the hardware can write past the XSK
> frame.
> 
> Refuse an XSK pool whose frame size cannot hold that, and an MTU change
> that would no longer fit a bound pool, also while no XDP program is
> attached. The current MTU is checked rather than the largest XDP MTU,
> as igb allows XDP up to MTU 3030 and that would rule out 2 KiB chunks.
> A pool that still does not fit when the ring is configured, for example
> because its queue was hidden by SR-IOV during an MTU change, is not used
> in zero-copy mode, see igb_xsk_pool(); its Tx then fails with EINVAL
> until the pool is bound again.

I would rather return -EBUSY when enabling VFs on queues with active
xsk_pool. Seems igb sort of steal queues from PF?

We do this in core when xsk_pool enabled queue would get wiped out via
ethtool -L shrinking the queue count.

> 
> This is the igb counterpart of the igc XSK buffer change.
> 
> Tested on an I350 with xdpsock from bpf-examples in rxdrop zero-copy
> mode on one queue, Rx timestamping on and 1514-byte frames from the
> peer. With 2 KiB chunks, the receive descriptors went from about two
> per frame to one per frame; 98-byte frames and 4 KiB chunks were one
> per frame with and without this patch. At MTU 3000, 4 KiB chunks
> receive 3014-byte frames in one buffer. A 2 KiB chunk pool at MTU 3000
> was refused by the new check on the 6.14.9 test kernel; current kernels
> already refuse it in xp_assign_dev(). There, with 2 KiB chunks and the
> default headroom, the new check refuses MTU 1751 to 1766, which the core
> accepts.
> 
> Link: https://lore.kernel.org/all/20261028083344.3047350-3-p@1g4.org/
> Fixes: 2c6196013f84 ("igb: Add AF_XDP zero-copy Rx support")
> Cc: stable@vger.kernel.org
> Suggested-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
> Signed-off-by: Tjerk Kusters <tkusters@aweta.nl>
> ---
>  drivers/net/ethernet/intel/igb/igb.h      |  9 +++++++++
>  drivers/net/ethernet/intel/igb/igb_main.c | 28 +++++++++++++++++++++++++---
>  drivers/net/ethernet/intel/igb/igb_xsk.c  | 19 ++++++++++++++++++-
>  3 files changed, 52 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
> index 0fff1df81b7b..0495c02544d6 100644
> --- a/drivers/net/ethernet/intel/igb/igb.h
> +++ b/drivers/net/ethernet/intel/igb/igb.h
> @@ -856,6 +856,15 @@ int igb_add_mac_steering_filter(struct igb_adapter *adapter,
>  int igb_del_mac_steering_filter(struct igb_adapter *adapter,
>  				const u8 *addr, u8 queue, u8 flags);
>  
> +/* XDP does not support frames that span more than one Rx buffer, so a
> + * frame plus the inline Rx timestamp header must fit in one XSK buffer.
> + */
> +static inline bool igb_xsk_frame_fits(struct xsk_buff_pool *pool,
> +				      int max_frame)
> +{
> +	return max_frame + IGB_TS_HDR_LEN <= xsk_pool_get_rx_frame_size(pool);
> +}
> +
>  struct xsk_buff_pool *igb_xsk_pool(struct igb_adapter *adapter,
>  				   struct igb_ring *ring);
>  int igb_xsk_pool_setup(struct igb_adapter *adapter,
> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
> index cf9911137bd3..b286adedad5d 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -4833,9 +4833,13 @@ void igb_setup_srrctl(struct igb_adapter *adapter, struct igb_ring *ring)
>  	u32 srrctl = 0;
>  	u32 buf_size;
>  
> -	if (ring->xsk_pool)
> -		buf_size = xsk_pool_get_rx_frame_size(ring->xsk_pool);
> -	else if (ring_uses_large_buffer(ring))
> +	/* SRRCTL.BSIZEPKT has a 1 KiB granularity, so programming the XSK
> +	 * frame size would round it down and split frames over several
> +	 * buffers. XSK rings use the same buffer size as the other rings.
> +	 * While XDP is attached, the receive length limit keeps frames
> +	 * within the XSK frame, see igb_xsk_frame_fits().
> +	 */
> +	if (ring_uses_large_buffer(ring))
>  		buf_size = IGB_RXBUFFER_3072;
>  	else
>  		buf_size = IGB_RXBUFFER_2048;
> @@ -6775,6 +6779,7 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
>  {
>  	struct igb_adapter *adapter = netdev_priv(netdev);
>  	int max_frame = new_mtu + IGB_ETH_PKT_HDR_PAD;
> +	int i;
>  
>  	if (igb_xdp_is_enabled(adapter) &&
>  	    !igb_xdp_frame_fits(adapter, max_frame)) {
> @@ -6788,6 +6793,23 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
>  	if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))
>  		max_frame = ETH_FRAME_LEN + ETH_FCS_LEN;
>  
> +	/* the frame must fit the buffers of a bound XSK pool, also while no
> +	 * XDP program is attached, as attaching one does not check it again
> +	 */
> +	for (i = 0; i < adapter->num_rx_queues; i++) {
> +		struct xsk_buff_pool *pool = xsk_get_pool_from_qid(netdev, i);
> +
> +		if (!pool || !pool->dev)
> +			continue;
> +
> +		if (!igb_xsk_frame_fits(pool, max_frame)) {
> +			netdev_warn(adapter->netdev,
> +				    "Requested MTU size is not supported with AF_XDP. Frame size is %d\n",
> +				    max_frame);
> +			return -EINVAL;
> +		}
> +	}
> +
>  	while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
>  		usleep_range(1000, 2000);
>  
> diff --git a/drivers/net/ethernet/intel/igb/igb_xsk.c b/drivers/net/ethernet/intel/igb/igb_xsk.c
> index ce4a7b58cad2..fb04df82272a 100644
> --- a/drivers/net/ethernet/intel/igb/igb_xsk.c
> +++ b/drivers/net/ethernet/intel/igb/igb_xsk.c
> @@ -91,7 +91,20 @@ struct xsk_buff_pool *igb_xsk_pool(struct igb_adapter *adapter,
>  	if (!igb_xdp_is_enabled(adapter))
>  		return NULL;
>  
> -	return (pool && pool->dev) ? pool : NULL;
> +	if (!pool || !pool->dev)
> +		return NULL;
> +
> +	/* the MTU check in igb_change_mtu() does not see a pool on a queue
> +	 * that was hidden at the time, for example by SR-IOV
> +	 */
> +	if (!igb_xsk_frame_fits(pool, adapter->max_frame_size)) {
> +		netdev_warn_once(adapter->netdev,
> +				 "XSK frame size is too small for the MTU, queue %d is not used in zero-copy mode\n",
> +				 qid);
> +		return NULL;
> +	}
> +
> +	return pool;
>  }
>  
>  static int igb_xsk_pool_enable(struct igb_adapter *adapter,
> @@ -110,6 +123,10 @@ static int igb_xsk_pool_enable(struct igb_adapter *adapter,
>  	    qid >= netdev->real_num_tx_queues)
>  		return -EINVAL;
>  
> +	/* igb_change_mtu() keeps this true while the pool is bound */
> +	if (!igb_xsk_frame_fits(pool, adapter->max_frame_size))
> +		return -EOPNOTSUPP;
> +
>  	err = xsk_pool_dma_map(pool, &adapter->pdev->dev, IGB_RX_DMA_ATTR);
>  	if (err)
>  		return err;
> 
> -- 
> 2.27.0
> 
> 

  reply	other threads:[~2026-11-07 16:38 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-04  6:40 [PATCH net v5 0/4] igb: only strip the Rx timestamp header from the first buffer of a frame Tjerk Kusters via B4 Relay
2026-11-04  6:40 ` [PATCH net v5 1/4] igb: do not let XDP frames span more than one Rx buffer Tjerk Kusters via B4 Relay
2026-11-04  6:40 ` [PATCH net v5 2/4] igb: only strip Rx timestamp header on the first buffer of a frame Tjerk Kusters via B4 Relay
2026-11-04  6:40 ` [PATCH net v5 3/4] igb: do not split AF_XDP zero-copy frames over several Rx buffers Tjerk Kusters via B4 Relay
2026-11-07 16:37   ` Maciej Fijalkowski [this message]
2026-11-04  6:40 ` [PATCH net v5 4/4] igb: drop AF_XDP zero-copy frames that span " Tjerk Kusters via B4 Relay
2026-11-07 16:00   ` Maciej Fijalkowski

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=au9T4Y1rpxvuEuFv@boxer \
    --to=maciej.fijalkowski@intel.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=anthony.l.nguyen@intel.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=hawk@kernel.org \
    --cc=intel-wired-lan@lists.osuosl.org \
    --cc=john.fastabend@gmail.com \
    --cc=kuba@kernel.org \
    --cc=kurt@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=p@1g4.org \
    --cc=pabeni@redhat.com \
    --cc=przemyslaw.kitszel@intel.com \
    --cc=richardcochran@gmail.com \
    --cc=sdf@fomichev.me \
    --cc=sriram.yagnaraman@ericsson.com \
    --cc=stable@vger.kernel.org \
    --cc=sven.auhagen@voleatech.de \
    --cc=tkusters@aweta.nl \
    /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

all inboxes | Powered by JetHome®