tcp: rstreason: introduce SK_RST_REASON_TCP_STATE for active reset
authorJason Xing <kernelxing@tencent.com>
Fri, 2 Aug 2024 10:21:09 +0000 (18:21 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 7 Aug 2024 09:24:45 +0000 (10:24 +0100)
Introducing a new type TCP_STATE to handle some reset conditions
appearing in RFC 793 due to its socket state. Actually, we can look
into RFC 9293 which has no discrepancy about this part.

Signed-off-by: Jason Xing <kernelxing@tencent.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/rstreason.h
net/ipv4/tcp.c
net/ipv4/tcp_timer.c

index eef658d..bbf20d0 100644 (file)
@@ -20,6 +20,7 @@
        FN(TCP_ABORT_ON_CLOSE)          \
        FN(TCP_ABORT_ON_LINGER)         \
        FN(TCP_ABORT_ON_MEMORY)         \
+       FN(TCP_STATE)                   \
        FN(MPTCP_RST_EUNSPEC)           \
        FN(MPTCP_RST_EMPTCP)            \
        FN(MPTCP_RST_ERESOURCE)         \
@@ -102,6 +103,11 @@ enum sk_rst_reason {
         * corresponding to LINUX_MIB_TCPABORTONMEMORY
         */
        SK_RST_REASON_TCP_ABORT_ON_MEMORY,
+       /**
+        * @SK_RST_REASON_TCP_STATE: abort on tcp state
+        * Please see RFC 9293 for all possible reset conditions
+        */
+       SK_RST_REASON_TCP_STATE,
 
        /* Copy from include/uapi/linux/mptcp.h.
         * These reset fields will not be changed since they adhere to
index fd928c4..24777e4 100644 (file)
@@ -3025,9 +3025,11 @@ int tcp_disconnect(struct sock *sk, int flags)
                inet_csk_listen_stop(sk);
        } else if (unlikely(tp->repair)) {
                WRITE_ONCE(sk->sk_err, ECONNABORTED);
-       } else if (tcp_need_reset(old_state) ||
-                  (tp->snd_nxt != tp->write_seq &&
-                   (1 << old_state) & (TCPF_CLOSING | TCPF_LAST_ACK))) {
+       } else if (tcp_need_reset(old_state)) {
+               tcp_send_active_reset(sk, gfp_any(), SK_RST_REASON_TCP_STATE);
+               WRITE_ONCE(sk->sk_err, ECONNRESET);
+       } else if (tp->snd_nxt != tp->write_seq &&
+                  (1 << old_state) & (TCPF_CLOSING | TCPF_LAST_ACK)) {
                /* The last check adjusts for discrepancy of Linux wrt. RFC
                 * states
                 */
@@ -4649,7 +4651,7 @@ int tcp_abort(struct sock *sk, int err)
        if (!sock_flag(sk, SOCK_DEAD)) {
                if (tcp_need_reset(sk->sk_state))
                        tcp_send_active_reset(sk, GFP_ATOMIC,
-                                             SK_RST_REASON_NOT_SPECIFIED);
+                                             SK_RST_REASON_TCP_STATE);
                tcp_done_with_error(sk, err);
        }
 
index 0fba4a4..3910f6d 100644 (file)
@@ -779,7 +779,7 @@ static void tcp_keepalive_timer (struct timer_list *t)
                                goto out;
                        }
                }
-               tcp_send_active_reset(sk, GFP_ATOMIC, SK_RST_REASON_NOT_SPECIFIED);
+               tcp_send_active_reset(sk, GFP_ATOMIC, SK_RST_REASON_TCP_STATE);
                goto death;
        }