> -----Original Message-----
> From: Intel-wired-lan <[email protected]> On Behalf
> Of Tjerk Kusters via B4 Relay
> Sent: Friday, June 19, 2026 9:15 AM
> To: Nguyen, Anthony L <[email protected]>; Kitszel,
> Przemyslaw <[email protected]>; Andrew Lunn
> <[email protected]>; David S. Miller <[email protected]>; Eric
> Dumazet <[email protected]>; Jakub Kicinski <[email protected]>; Paolo
> Abeni <[email protected]>; Richard Cochran <[email protected]>;
> Jesper Dangaard Brouer <[email protected]>; Kurt Kanzenbach
> <[email protected]>
> Cc: [email protected]; [email protected]; linux-
> [email protected]; [email protected]; Tjerk Kusters
> <[email protected]>
> Subject: [Intel-wired-lan] [PATCH net v2] igb: only strip Rx timestamp
> header on the first buffer of a frame
> 
> From: Tjerk Kusters <[email protected]>
> 
> 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, &timestamp);
>               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: [email protected]
> Reviewed-by: Kurt Kanzenbach <[email protected]>
> Signed-off-by: Tjerk Kusters <[email protected]>
> ---
> Changes in v2:
>  - resend via b4 (v1 was sent with a mail client)
>  - use full author name "Tjerk Kusters" (Jacob Keller)
>  - add Reviewed-by from Kurt Kanzenbach
>  - no functional change
> 
> Link to v1:
> https://lore.kernel.org/all/PAWPR05MB1069106D52F4E17F1EDB99C67B9182@PA
> WPR05MB10691.eurprd05.prod.outlook.com/
> ---
>  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,
> 
> ---
> base-commit: 2d3090a8aeb596a26935db0955d46c9a5db5c6ce
> change-id: 20260619-igb-rx-ts-fix-cd70585ee316
> 
> Best regards,
> --
> Tjerk Kusters <[email protected]>
> 

Reviewed-by: Aleksandr Loktionov <[email protected]>

Reply via email to