Intel-Wired-Lan Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
To: "Dominik Dvořák" <241000@muni.cz>
Cc: "intel-wired-lan@lists.osuosl.org"
	<intel-wired-lan@lists.osuosl.org>,
	"netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	Tony Nguyen <anthony.l.nguyen@intel.com>,
	Przemek Kitszel <przemyslaw.kitszel@intel.com>
Subject: Re: [BUG] ice: rx_bytes inflated by up to 4 GiB per XDP_DROP (buffer length read after libeth_xdp_return_buff())
Date: Thu, 5 Nov 2026 12:19:41 +0100	[thread overview]
Message-ID: <auxmTcwi4J/k9Xb6@boxer> (raw)
In-Reply-To: <DB7PR03MB460158B90A64D025962670E0D5772@DB7PR03MB4601.eurprd03.prod.outlook.com>

On Thu, Nov 05, 2026 at 09:05:19AM +0000, Dominik Dvořák wrote:
> Hello,
> 
> after upgrading the kernel from 6.8 to 7.0 (Proxmox kernels
> 6.8.12-34-pve -> 7.0.14-26-pve), the software Rx byte counters of an E810
> started showing phantom jumps of hundreds of MB to several GB. Each jump
> is exactly one packet. The cause is a length read after the buffer has
> already been freed on the XDP_DROP path. The bug is still present in
> current master.
> 
> Setup
> -----
> - Intel E810-XXV for SFP (rev 02), FW 4.30 0x8001b891,
>   DDP ICE OS Default Package 1.3.43.0
> - in-tree ice, kernel 7.0.14 (Proxmox build 7.0.14-26-pve)
> - 2 ports in an 802.3ad bond, native XDP program attached to the bond.
>   The program returns XDP_DROP for blocklisted source IPs and XDP_PASS
>   for everything else.
> - 6.8 kernel with the same HW/FW and the same XDP program: not affected
> 
> What we see
> -----------
> One sample, 1 s interval, ethtool -S plus netdev stats:
> 
>   rx_queue_4_packets: 76843 -> 76844        (+1)
>   rx_queue_4_bytes:   32920496416 -> 33701427810  (+780931394)
>   rx_bytes.nic (HW) on the same port grew by 2222 bytes in that second
> 
> Only the queues that receive the blocklisted flows are affected (3 of 16
> here). All other queues show normal bytes per packet. Every jump is
> smaller than 4 GiB. 780931394 is 0x2E8C1142, which looks like the low
> 32 bits of a kernel address.
> 
> Root cause
> ----------
> In ice_clean_rx_irq() (drivers/net/ethernet/intel/ice/ice_txrx.c):
> 
>     xdp_verdict = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_desc);
>     if (xdp_verdict == ICE_XDP_PASS)
>             goto construct_skb;
> 
>     if (xdp_verdict & (ICE_XDP_TX | ICE_XDP_REDIR))
>             xdp_xmit |= xdp_verdict;
>     total_rx_bytes += xdp_get_buff_len(&xdp->base);
> 
> On XDP_DROP, XDP_ABORTED and a failed XDP_TX/XDP_REDIRECT, ice_run_xdp()
> has already called libeth_xdp_return_buff(xdp). That function frees the
> buffer and sets xdp->data = NULL. xdp_get_buff_len() then computes
> xdp->data_end - NULL, so the low 32 bits of a pointer get added to
> rx_bytes. For multi-buffer frames, xdp_get_shared_info_from_buff() would
> additionally read skb_shared_info from a page that has already been
> recycled.
> 
> This looks to have come in with "ice: switch to Page Pool"
> (93f53db9f9dc). The old Rx path did not clear xdp->data on drop.
> 
> Proposed fix (untested)
> -----------------------
> Take the length before running the program:
> 
> --- a/drivers/net/ethernet/intel/ice/ice_txrx.c
> +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
> @@ static int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
> -		unsigned int size;
> +		unsigned int size, len;
> @@
>  		if (ice_is_non_eop(rx_ring, rx_desc) ||
> unlikely(!xdp->data))
>  			continue;
>  
> +		/* ice_run_xdp() may free the buffer and clear xdp->data */
> +		len = xdp_get_buff_len(&xdp->base);
>  		xdp_verdict = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring,
> rx_desc);
>  		if (xdp_verdict == ICE_XDP_PASS)
>  			goto construct_skb;
>  
>  		if (xdp_verdict & (ICE_XDP_TX | ICE_XDP_REDIR))
>  			xdp_xmit |= xdp_verdict;
> -		total_rx_bytes += xdp_get_buff_len(&xdp->base);
> +		total_rx_bytes += len;
>  		total_rx_pkts++;
> 
> With this change TX/REDIRECT count the length before any
> bpf_xdp_adjust_head/tail. If you would rather keep counting the
> post-program length, the same thing can be done inside ice_run_xdp(),
> before the buffer is returned.
> 
> The root cause analysis and the proposed fix were done with the help of
> Claude Opus 5.5 (Anthropic). The symptoms and measurements come from our
> production firewall. I have checked the code paths described above
> against the v7.0 source.
> 
> I can test a patch on the affected box. The issue reproduces reliably:
> each XDP_DROP produces one phantom jump.

Please test and send a fix. You've done the root cause analysis so would
be nice if you get a credit for providing a fix to this issue.

I can then test this on my setup and give you an ACK.

Thanks!

> 
> Thanks,
> Dominik Dvořák
> Head of IT Services 
> 
> Masaryk University | Faculty of Economics and Administration
> IT Services
> A: Lipová 507/41a | 602 00 Brno 
> T: +420 549 493 183 | M: +420 739 487 807
> E: Dominik.Dvorak@econ.muni.cz
> 
> 



  reply	other threads:[~2026-11-05 11:19 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-05  9:05 [BUG] ice: rx_bytes inflated by up to 4 GiB per XDP_DROP (buffer length read after libeth_xdp_return_buff()) Dominik Dvořák
2026-11-05 11:19 ` Maciej Fijalkowski [this message]
2026-11-05 13:41   ` Dominik Dvořák

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=auxmTcwi4J/k9Xb6@boxer \
    --to=maciej.fijalkowski@intel.com \
    --cc=241000@muni.cz \
    --cc=anthony.l.nguyen@intel.com \
    --cc=intel-wired-lan@lists.osuosl.org \
    --cc=netdev@vger.kernel.org \
    --cc=przemyslaw.kitszel@intel.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