From 1a924ab28fb51c64f3e66dc4cbc2dbafa0011f68 Mon Sep 17 00:00:00 2001 From: Jason Xing Date: Thu, 24 Sep 2026 23:25:29 +0800 Subject: [PATCH] tcp: preserve timestamps across receive queue collapse When tcp_collapse() rebuilds skbs under memory pressure, the copy process doesn't include the right tstamp and hwtstamp from the old skb. And memcpy(nskb->cb, skb->cb, ...) copies has_rxtstamp, but nskb->tstamp and hwtstamps are left at zero, so tcp_recv_timestamp() ends up emitting no cmsg at all. In net timestamping case, if such an skb happens to be the last one consumed in a recvmsg() call, the application receives no RX timestamp for that call. Fix this by copying both tstamp and hwtstamp of the last skb to the new skb, matching tcp_try_coalesce()/tcp_add_backlog(). Note that the has_rxtstamp flag can still be inherited through the cb memcpy from an skb that contributes no bytes (fully covered skb left in the ofo tree by the tcp_ooo_try_coalesce() -> coalesce_done path), so set TCP_SKB_CB(nskb)->has_rxtstamp to false which makes the new block the only place setting it. Signed-off-by: Jason Xing Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20260924152529.5689-1-kerneljasonxing@gmail.com Signed-off-by: Jakub Kicinski --- net/ipv4/tcp_input.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 892ff256e235..39f1ac73bd5e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5834,6 +5834,7 @@ skip_this: break; memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); + TCP_SKB_CB(nskb)->has_rxtstamp = false; skb_copy_decrypted(nskb, skb); TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start; if (list) @@ -5854,6 +5855,12 @@ skip_this: if (skb_copy_bits(skb, offset, skb_put(nskb, size), size)) BUG(); TCP_SKB_CB(nskb)->end_seq += size; + if (TCP_SKB_CB(skb)->has_rxtstamp) { + TCP_SKB_CB(nskb)->has_rxtstamp = true; + nskb->tstamp = skb->tstamp; + skb_hwtstamps(nskb)->hwtstamp = + skb_hwtstamps(skb)->hwtstamp; + } copy -= size; start += size; }