net-timestamp: support TCP GSO case for a few missing flags
authorJason Xing <kerneljasonxing@gmail.com>
Tue, 4 Mar 2025 00:44:29 +0000 (08:44 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 5 Mar 2025 13:34:38 +0000 (13:34 +0000)
When I read through the TSO codes, I found out that we probably
miss initializing the tx_flags of last seg when TSO is turned
off, which means at the following points no more timestamp
(for this last one) will be generated. There are three flags
to be handled in this patch:
1. SKBTX_HW_TSTAMP
2. SKBTX_BPF
3. SKBTX_SCHED_TSTAMP
Note that SKBTX_BPF[1] was added in 6.14.0-rc2 by commit
6b98ec7e882af ("bpf: Add BPF_SOCK_OPS_TSTAMP_SCHED_CB callback")
and only belongs to net-next branch material for now. The common
issue of the above three flags can be fixed by this single patch.

This patch initializes the tx_flags to SKBTX_ANY_TSTAMP like what
the UDP GSO does to make the newly segmented last skb inherit the
tx_flags so that requested timestamp will be generated in each
certain layer, or else that last one has zero value of tx_flags
which leads to no timestamp at all.

Fixes: 4ed2d765dfacc ("net-timestamp: TCP timestamping")
Signed-off-by: Jason Xing <kerneljasonxing@gmail.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/tcp_offload.c

index 2308665b51c5388814e5b61a262a1636d897c4a9..2dfac79dc78b8b8e7cd89c7b50ccd97c0a870132 100644 (file)
 #include <net/tcp.h>
 #include <net/protocol.h>
 
-static void tcp_gso_tstamp(struct sk_buff *skb, unsigned int ts_seq,
+static void tcp_gso_tstamp(struct sk_buff *skb, struct sk_buff *gso_skb,
                           unsigned int seq, unsigned int mss)
 {
+       u32 flags = skb_shinfo(gso_skb)->tx_flags & SKBTX_ANY_TSTAMP;
+       u32 ts_seq = skb_shinfo(gso_skb)->tskey;
+
        while (skb) {
                if (before(ts_seq, seq + mss)) {
-                       skb_shinfo(skb)->tx_flags |= SKBTX_SW_TSTAMP;
+                       skb_shinfo(skb)->tx_flags |= flags;
                        skb_shinfo(skb)->tskey = ts_seq;
                        return;
                }
@@ -193,8 +196,8 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
        th = tcp_hdr(skb);
        seq = ntohl(th->seq);
 
-       if (unlikely(skb_shinfo(gso_skb)->tx_flags & SKBTX_SW_TSTAMP))
-               tcp_gso_tstamp(segs, skb_shinfo(gso_skb)->tskey, seq, mss);
+       if (unlikely(skb_shinfo(gso_skb)->tx_flags & SKBTX_ANY_TSTAMP))
+               tcp_gso_tstamp(segs, gso_skb, seq, mss);
 
        newcheck = ~csum_fold(csum_add(csum_unfold(th->check), delta));