]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
tcp: preserve const qualifier in tcp_sk()
authorEric Dumazet <edumazet@google.com>
Fri, 17 Mar 2023 15:55:39 +0000 (15:55 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 18 Mar 2023 12:23:34 +0000 (12:23 +0000)
We can change tcp_sk() to propagate its argument const qualifier,
thanks to container_of_const().

We have two places where a const sock pointer has to be upgraded
to a write one. We have been using const qualifier for lockless
listeners to clearly identify points where writes could happen.

Add tcp_sk_rw() helper to better document these.

tcp_inbound_md5_hash(), __tcp_grow_window(), tcp_reset_check()
and tcp_rack_reo_wnd() get an additional const qualififer
for their @tp local variables.

smc_check_reset_syn_req() also needs a similar change.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/tcp.h
include/net/tcp.h
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/tcp_recovery.c

index ca7f05a130d2d14d530207adcc1cc50b7b830c80..b4c08ac86983568a9511258708724da15d0b999e 100644 (file)
@@ -472,10 +472,12 @@ enum tsq_flags {
        TCPF_MTU_REDUCED_DEFERRED       = (1UL << TCP_MTU_REDUCED_DEFERRED),
 };
 
-static inline struct tcp_sock *tcp_sk(const struct sock *sk)
-{
-       return (struct tcp_sock *)sk;
-}
+#define tcp_sk(ptr) container_of_const(ptr, struct tcp_sock, inet_conn.icsk_inet.sk)
+
+/* Variant of tcp_sk() upgrading a const sock to a read/write tcp socket.
+ * Used in context of (lockless) tcp listeners.
+ */
+#define tcp_sk_rw(ptr) container_of(ptr, struct tcp_sock, inet_conn.icsk_inet.sk)
 
 struct tcp_timewait_sock {
        struct inet_timewait_sock tw_sk;
index db9f828e9d1ee4546951a408935b6c5f90851a93..a0a91a988272710470cd20f22e02e49476513239 100644 (file)
@@ -529,7 +529,7 @@ static inline void tcp_synq_overflow(const struct sock *sk)
 
        last_overflow = READ_ONCE(tcp_sk(sk)->rx_opt.ts_recent_stamp);
        if (!time_between32(now, last_overflow, last_overflow + HZ))
-               WRITE_ONCE(tcp_sk(sk)->rx_opt.ts_recent_stamp, now);
+               WRITE_ONCE(tcp_sk_rw(sk)->rx_opt.ts_recent_stamp, now);
 }
 
 /* syncookies: no recent synqueue overflow on this listening socket? */
index 01569de651b65aa5641fb0c06e0fb81dc40cd85a..fd68d49490f2849a41397be5bf78dbf07cadd7ff 100644 (file)
@@ -4570,7 +4570,7 @@ tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb,
        const __u8 *hash_location = NULL;
        struct tcp_md5sig_key *hash_expected;
        const struct tcphdr *th = tcp_hdr(skb);
-       struct tcp_sock *tp = tcp_sk(sk);
+       const struct tcp_sock *tp = tcp_sk(sk);
        int genhash, l3index;
        u8 newhash[16];
 
index 754ddbe0577f139d209032b4f15787392fe9a1d5..2b75cd9e2e92ea1b6e8e16485a8792790a905ade 100644 (file)
@@ -458,7 +458,7 @@ static void tcp_sndbuf_expand(struct sock *sk)
 static int __tcp_grow_window(const struct sock *sk, const struct sk_buff *skb,
                             unsigned int skbtruesize)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
+       const struct tcp_sock *tp = tcp_sk(sk);
        /* Optimize this! */
        int truesize = tcp_win_from_space(sk, skbtruesize) >> 1;
        int window = tcp_win_from_space(sk, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2])) >> 1;
@@ -5693,7 +5693,7 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, const struct tcphdr *t
  */
 static bool tcp_reset_check(const struct sock *sk, const struct sk_buff *skb)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
+       const struct tcp_sock *tp = tcp_sk(sk);
 
        return unlikely(TCP_SKB_CB(skb)->seq == (tp->rcv_nxt - 1) &&
                        (1 << sk->sk_state) & (TCPF_CLOSE_WAIT | TCPF_LAST_ACK |
index 9a7ef7732c24c94d4a01d5911ebe51f21371a457..dac0d62120e623ad3f206daa1785eddb39452fd6 100644 (file)
@@ -463,7 +463,7 @@ void tcp_ca_openreq_child(struct sock *sk, const struct dst_entry *dst)
 }
 EXPORT_SYMBOL_GPL(tcp_ca_openreq_child);
 
-static void smc_check_reset_syn_req(struct tcp_sock *oldtp,
+static void smc_check_reset_syn_req(const struct tcp_sock *oldtp,
                                    struct request_sock *req,
                                    struct tcp_sock *newtp)
 {
@@ -492,7 +492,8 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
        const struct inet_request_sock *ireq = inet_rsk(req);
        struct tcp_request_sock *treq = tcp_rsk(req);
        struct inet_connection_sock *newicsk;
-       struct tcp_sock *oldtp, *newtp;
+       const struct tcp_sock *oldtp;
+       struct tcp_sock *newtp;
        u32 seq;
 
        if (!newsk)
index b1e743b39a83c123b6ed9f9e5c535b56dcfbf417..cfe128b81a010339b486dd6a40b077cee9570d08 100644 (file)
@@ -4127,8 +4127,13 @@ int tcp_rtx_synack(const struct sock *sk, struct request_sock *req)
        if (!res) {
                TCP_INC_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS);
                NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSYNRETRANS);
-               if (unlikely(tcp_passive_fastopen(sk)))
-                       tcp_sk(sk)->total_retrans++;
+               if (unlikely(tcp_passive_fastopen(sk))) {
+                       /* sk has const attribute because listeners are lockless.
+                        * However in this case, we are dealing with a passive fastopen
+                        * socket thus we can change total_retrans value.
+                        */
+                       tcp_sk_rw(sk)->total_retrans++;
+               }
                trace_tcp_retransmit_synack(sk, req);
        }
        return res;
index 50abaa941387d3e7328b6859ea5118937fc12be4..acf4869c5d3b568227aca71d95a765493e452a85 100644 (file)
@@ -4,7 +4,7 @@
 
 static u32 tcp_rack_reo_wnd(const struct sock *sk)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
+       const struct tcp_sock *tp = tcp_sk(sk);
 
        if (!tp->reord_seen) {
                /* If reordering has not been observed, be aggressive during