* [PATCH net] igb: only strip Rx timestamp header on the first buffer of a frame
@ 2026-06-12 8:05 Tjerk Kusters
2026-06-15 7:43 ` Kurt Kanzenbach
0 siblings, 1 reply; 2+ messages in thread
From: Tjerk Kusters @ 2026-06-12 8:05 UTC (permalink / raw)
To: netdev@vger.kernel.org
Cc: intel-wired-lan@lists.osuosl.org, anthony.l.nguyen@intel.com,
przemyslaw.kitszel@intel.com, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, richardcochran@gmail.com, kurt@linutronix.de,
hawk@kernel.org, stable@vger.kernel.org,
linux-kernel@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 2052 bytes --]
Hi,
The patch is attached (0001-igb-only-strip-Rx-timestamp-header-on-the-first-buff.patch)
as my mail setup cannot send it inline via git send-email; apologies for the
attachment.
Summary of the bug it fixes:
When Rx hardware timestamping is enabled (e.g. ptp4l, which configures
HWTSTAMP_FILTER_ALL), the igb NIC prepends a 16-byte timestamp header to the
first Rx buffer of every received frame. igb_clean_rx_irq() strips this header
inside its per-buffer loop, so for a frame that spans more than one Rx buffer
(a jumbo frame) the strip runs once per buffer.
The timestamp header only exists on the first buffer, but igb_ptp_rx_pktstamp()
is called for every buffer and only checks that PTP is enabled and that the
first 8 bytes (reserved dwords) are zero. On a continuation buffer whose
payload happens to begin with 8 zero bytes, both checks pass, the payload is
mistaken for a timestamp header, and 16 bytes of real data are stripped from
that buffer. A frame spanning N buffers whose continuation buffers start with
zero bytes loses 16 * (N - 1) bytes from its tail, silently.
This is easily triggered by a GigE Vision camera streaming dark frames (mostly
0x00 pixel data) over jumbo UDP with PTP active on the receiver: all-zero
frames arrive truncated, frames with non-zero content are fine.
The fix only attempts the strip on the first buffer of a frame (skb == NULL in
igb_clean_rx_irq), which is the only buffer that can contain a timestamp
header. A content-based check cannot reliably distinguish a continuation
buffer that begins with zero bytes from a real header.
Testing: reproduced on Linux 7.0.11 and 6.14.9 with an Intel I350-T2, MTU 8228,
ptp4l active. A random,zero,zero,random burst of 1024 jumbo UDP datagrams
captured on the receiver showed 512 of 1024 truncated (both all-zero bursts)
on the stock driver, and 0 truncated with this fix applied. The bug is still
present in mainline (checked v7.1-rc7).
Fixes: 5379260852b0 ("igb: Fix XDP with PTP enabled")
Thanks,
T Kusters
[-- Attachment #2: 0001-igb-only-strip-Rx-timestamp-header-on-the-first-buff.patch.txt --]
[-- Type: text/plain, Size: 3266 bytes --]
From fee3e3452dfcd7e109332369672a3e0090cadeb3 Mon Sep 17 00:00:00 2001
From: T Kusters <tkusters@aweta.nl>
Date: Tue, 9 Jun 2026 14:06:24 +0200
Subject: [PATCH net] igb: only strip Rx timestamp header on the first buffer
of a frame
When Rx hardware timestamping is enabled (e.g. ptp4l, which configures
HWTSTAMP_FILTER_ALL), the NIC prepends a 16-byte timestamp header to the
first Rx buffer of every received frame. igb_clean_rx_irq() strips this
header inside its per-buffer loop:
if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
ts_hdr_len = igb_ptp_rx_pktstamp(rx_ring->q_vector,
pktbuf, ×tamp);
pkt_offset += ts_hdr_len;
size -= ts_hdr_len;
}
For a frame that spans more than one Rx buffer (e.g. a jumbo frame), this
block runs once per buffer. The timestamp header only exists at the start
of the first buffer, but igb_ptp_rx_pktstamp() is called for every buffer.
On a continuation buffer the data is packet payload, not a timestamp
header. igb_ptp_rx_pktstamp() already has two guards against acting on a
non-header buffer: it returns 0 if PTP is disabled, and returns 0 if the
reserved dwords (the first 8 bytes) are non-zero. Neither is sufficient
here: PTP is enabled, and a continuation buffer whose payload happens to
begin with 8 zero bytes passes the reserved-dword check. In that case the
payload is mistaken for a valid timestamp header and igb_ptp_rx_pktstamp()
returns IGB_TS_HDR_LEN, so the caller strips 16 bytes of real data from
that buffer. A frame spanning N buffers whose continuation buffers start
with zero bytes therefore loses 16 * (N - 1) bytes from its tail.
This is easily triggered by a GigE Vision camera streaming dark frames
(mostly 0x00 pixel data) over jumbo UDP with PTP active on the receiver:
the all-zero frames arrive truncated while frames with non-zero content
are fine. There is no error indication.
No content-based check can reliably tell a continuation buffer that begins
with zero bytes from a real timestamp header, because both are all zero.
Fix it structurally instead: only attempt the strip on the first buffer of
a frame, which is the only buffer that can contain a timestamp header. In
igb_clean_rx_irq() skb is NULL until the first buffer has been processed,
so guarding the strip with !skb restricts it to the first buffer
regardless of payload content.
Fixes: 5379260852b0 ("igb: Fix XDP with PTP enabled")
Cc: stable@vger.kernel.org
Signed-off-by: T Kusters <tkusters@aweta.nl>
---
drivers/net/ethernet/intel/igb/igb_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index ce91dda00ec0..abb55cd589a9 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -9061,7 +9061,8 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset;
/* pull rx packet timestamp if available and valid */
- if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+ if (!skb &&
+ igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
int ts_hdr_len;
ts_hdr_len = igb_ptp_rx_pktstamp(rx_ring->q_vector,
--
2.27.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH net] igb: only strip Rx timestamp header on the first buffer of a frame
2026-06-12 8:05 [PATCH net] igb: only strip Rx timestamp header on the first buffer of a frame Tjerk Kusters
@ 2026-06-15 7:43 ` Kurt Kanzenbach
0 siblings, 0 replies; 2+ messages in thread
From: Kurt Kanzenbach @ 2026-06-15 7:43 UTC (permalink / raw)
To: Tjerk Kusters, netdev@vger.kernel.org
Cc: intel-wired-lan@lists.osuosl.org, anthony.l.nguyen@intel.com,
przemyslaw.kitszel@intel.com, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, richardcochran@gmail.com, hawk@kernel.org,
stable@vger.kernel.org, linux-kernel@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 3994 bytes --]
Hi,
On Fri Jun 12 2026, Tjerk Kusters wrote:
> Hi,
>
> The patch is attached (0001-igb-only-strip-Rx-timestamp-header-on-the-first-buff.patch)
> as my mail setup cannot send it inline via git send-email; apologies for the
> attachment.
b4 has a web submission endpoint. Maybe you can use that one:
https://b4.docs.kernel.org/en/latest/contributor/send.html
[snip]
> From fee3e3452dfcd7e109332369672a3e0090cadeb3 Mon Sep 17 00:00:00 2001
> From: T Kusters <tkusters@aweta.nl>
> Date: Tue, 9 Jun 2026 14:06:24 +0200
> Subject: [PATCH net] igb: only strip Rx timestamp header on the first buffer
> of a frame
>
> When Rx hardware timestamping is enabled (e.g. ptp4l, which configures
> HWTSTAMP_FILTER_ALL), the NIC prepends a 16-byte timestamp header to the
> first Rx buffer of every received frame. igb_clean_rx_irq() strips this
> header inside its per-buffer loop:
>
> if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
> ts_hdr_len = igb_ptp_rx_pktstamp(rx_ring->q_vector,
> pktbuf, ×tamp);
> pkt_offset += ts_hdr_len;
> size -= ts_hdr_len;
> }
>
> For a frame that spans more than one Rx buffer (e.g. a jumbo frame), this
> block runs once per buffer. The timestamp header only exists at the start
> of the first buffer, but igb_ptp_rx_pktstamp() is called for every buffer.
>
> On a continuation buffer the data is packet payload, not a timestamp
> header. igb_ptp_rx_pktstamp() already has two guards against acting on a
> non-header buffer: it returns 0 if PTP is disabled, and returns 0 if the
> reserved dwords (the first 8 bytes) are non-zero. Neither is sufficient
> here: PTP is enabled, and a continuation buffer whose payload happens to
> begin with 8 zero bytes passes the reserved-dword check. In that case the
> payload is mistaken for a valid timestamp header and igb_ptp_rx_pktstamp()
> returns IGB_TS_HDR_LEN, so the caller strips 16 bytes of real data from
> that buffer. A frame spanning N buffers whose continuation buffers start
> with zero bytes therefore loses 16 * (N - 1) bytes from its tail.
>
> This is easily triggered by a GigE Vision camera streaming dark frames
> (mostly 0x00 pixel data) over jumbo UDP with PTP active on the receiver:
> the all-zero frames arrive truncated while frames with non-zero content
> are fine. There is no error indication.
>
> No content-based check can reliably tell a continuation buffer that begins
> with zero bytes from a real timestamp header, because both are all zero.
> Fix it structurally instead: only attempt the strip on the first buffer of
> a frame, which is the only buffer that can contain a timestamp header. In
> igb_clean_rx_irq() skb is NULL until the first buffer has been processed,
> so guarding the strip with !skb restricts it to the first buffer
> regardless of payload content.
>
> Fixes: 5379260852b0 ("igb: Fix XDP with PTP enabled")
> Cc: stable@vger.kernel.org
> Signed-off-by: T Kusters <tkusters@aweta.nl>
Great explanation! igb_clean_rx_irq_zc() does not need the same
treatment, correct?
Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de>
> ---
> drivers/net/ethernet/intel/igb/igb_main.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
> index ce91dda00ec0..abb55cd589a9 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -9061,7 +9061,8 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
> pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset;
>
> /* pull rx packet timestamp if available and valid */
> - if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
> + if (!skb &&
> + igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
> int ts_hdr_len;
>
> ts_hdr_len = igb_ptp_rx_pktstamp(rx_ring->q_vector,
> --
> 2.27.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 861 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-15 7:53 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-12 8:05 [PATCH net] igb: only strip Rx timestamp header on the first buffer of a frame Tjerk Kusters
2026-06-15 7:43 ` Kurt Kanzenbach
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox