Skip to content

Commit e66f33b

Browse files
committed
Merge branch 'tcp-active-reset'
Jason Xing says: =================== tcp: completely support active reset This time the patch series finally covers all the cases in the active reset logic. After this, we can know the related exact reason(s). v4 Link: 1. revise the changelog to avoid future confusion in patch [5/7] (Eric) 2. revise the changelog of patch [6/7] like above. 3. add reviewed-by tags (Eric) v3 Link: https://lore.kernel.org/all/[email protected]/ 1. introduce TCP_DISCONNECT_WITH_DATA reason (Eric) 2. use a better name 'TCP_KEEPALIVE_TIMEOUT' (Eric) 3. add three reviewed-by tags (Eric) v2 Link: https://lore.kernel.org/all/[email protected]/ 1. use RFC 9293 in the comment and changelog instead of old RFC 793 2. correct the comment and changelog in patch 5 ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 2c14119 + ba0ca28 commit e66f33b

File tree

4 files changed

+54
-12
lines changed

4 files changed

+54
-12
lines changed

include/net/rstreason.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
FN(TCP_ABORT_ON_DATA) \
1818
FN(TCP_TIMEWAIT_SOCKET) \
1919
FN(INVALID_SYN) \
20+
FN(TCP_ABORT_ON_CLOSE) \
21+
FN(TCP_ABORT_ON_LINGER) \
22+
FN(TCP_ABORT_ON_MEMORY) \
23+
FN(TCP_STATE) \
24+
FN(TCP_KEEPALIVE_TIMEOUT) \
25+
FN(TCP_DISCONNECT_WITH_DATA) \
2026
FN(MPTCP_RST_EUNSPEC) \
2127
FN(MPTCP_RST_EMPTCP) \
2228
FN(MPTCP_RST_ERESOURCE) \
@@ -84,6 +90,39 @@ enum sk_rst_reason {
8490
* an error, send a reset"
8591
*/
8692
SK_RST_REASON_INVALID_SYN,
93+
/**
94+
* @SK_RST_REASON_TCP_ABORT_ON_CLOSE: abort on close
95+
* corresponding to LINUX_MIB_TCPABORTONCLOSE
96+
*/
97+
SK_RST_REASON_TCP_ABORT_ON_CLOSE,
98+
/**
99+
* @SK_RST_REASON_TCP_ABORT_ON_LINGER: abort on linger
100+
* corresponding to LINUX_MIB_TCPABORTONLINGER
101+
*/
102+
SK_RST_REASON_TCP_ABORT_ON_LINGER,
103+
/**
104+
* @SK_RST_REASON_TCP_ABORT_ON_MEMORY: abort on memory
105+
* corresponding to LINUX_MIB_TCPABORTONMEMORY
106+
*/
107+
SK_RST_REASON_TCP_ABORT_ON_MEMORY,
108+
/**
109+
* @SK_RST_REASON_TCP_STATE: abort on tcp state
110+
* Please see RFC 9293 for all possible reset conditions
111+
*/
112+
SK_RST_REASON_TCP_STATE,
113+
/**
114+
* @SK_RST_REASON_TCP_KEEPALIVE_TIMEOUT: time to timeout
115+
* When we have already run out of all the chances, which means
116+
* keepalive timeout, we have to reset the connection
117+
*/
118+
SK_RST_REASON_TCP_KEEPALIVE_TIMEOUT,
119+
/**
120+
* @SK_RST_REASON_TCP_DISCONNECT_WITH_DATA: disconnect when write
121+
* queue is not empty
122+
* It means user has written data into the write queue when doing
123+
* disconnecting, so we have to send an RST.
124+
*/
125+
SK_RST_REASON_TCP_DISCONNECT_WITH_DATA,
87126

88127
/* Copy from include/uapi/linux/mptcp.h.
89128
* These reset fields will not be changed since they adhere to

net/ipv4/tcp.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2833,7 +2833,7 @@ void __tcp_close(struct sock *sk, long timeout)
28332833
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE);
28342834
tcp_set_state(sk, TCP_CLOSE);
28352835
tcp_send_active_reset(sk, sk->sk_allocation,
2836-
SK_RST_REASON_NOT_SPECIFIED);
2836+
SK_RST_REASON_TCP_ABORT_ON_CLOSE);
28372837
} else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
28382838
/* Check zero linger _after_ checking for unread data. */
28392839
sk->sk_prot->disconnect(sk, 0);
@@ -2908,7 +2908,7 @@ void __tcp_close(struct sock *sk, long timeout)
29082908
if (READ_ONCE(tp->linger2) < 0) {
29092909
tcp_set_state(sk, TCP_CLOSE);
29102910
tcp_send_active_reset(sk, GFP_ATOMIC,
2911-
SK_RST_REASON_NOT_SPECIFIED);
2911+
SK_RST_REASON_TCP_ABORT_ON_LINGER);
29122912
__NET_INC_STATS(sock_net(sk),
29132913
LINUX_MIB_TCPABORTONLINGER);
29142914
} else {
@@ -2927,7 +2927,7 @@ void __tcp_close(struct sock *sk, long timeout)
29272927
if (tcp_check_oom(sk, 0)) {
29282928
tcp_set_state(sk, TCP_CLOSE);
29292929
tcp_send_active_reset(sk, GFP_ATOMIC,
2930-
SK_RST_REASON_NOT_SPECIFIED);
2930+
SK_RST_REASON_TCP_ABORT_ON_MEMORY);
29312931
__NET_INC_STATS(sock_net(sk),
29322932
LINUX_MIB_TCPABORTONMEMORY);
29332933
} else if (!check_net(sock_net(sk))) {
@@ -3025,13 +3025,16 @@ int tcp_disconnect(struct sock *sk, int flags)
30253025
inet_csk_listen_stop(sk);
30263026
} else if (unlikely(tp->repair)) {
30273027
WRITE_ONCE(sk->sk_err, ECONNABORTED);
3028-
} else if (tcp_need_reset(old_state) ||
3029-
(tp->snd_nxt != tp->write_seq &&
3030-
(1 << old_state) & (TCPF_CLOSING | TCPF_LAST_ACK))) {
3028+
} else if (tcp_need_reset(old_state)) {
3029+
tcp_send_active_reset(sk, gfp_any(), SK_RST_REASON_TCP_STATE);
3030+
WRITE_ONCE(sk->sk_err, ECONNRESET);
3031+
} else if (tp->snd_nxt != tp->write_seq &&
3032+
(1 << old_state) & (TCPF_CLOSING | TCPF_LAST_ACK)) {
30313033
/* The last check adjusts for discrepancy of Linux wrt. RFC
30323034
* states
30333035
*/
3034-
tcp_send_active_reset(sk, gfp_any(), SK_RST_REASON_NOT_SPECIFIED);
3036+
tcp_send_active_reset(sk, gfp_any(),
3037+
SK_RST_REASON_TCP_DISCONNECT_WITH_DATA);
30353038
WRITE_ONCE(sk->sk_err, ECONNRESET);
30363039
} else if (old_state == TCP_SYN_SENT)
30373040
WRITE_ONCE(sk->sk_err, ECONNRESET);
@@ -4649,7 +4652,7 @@ int tcp_abort(struct sock *sk, int err)
46494652
if (!sock_flag(sk, SOCK_DEAD)) {
46504653
if (tcp_need_reset(sk->sk_state))
46514654
tcp_send_active_reset(sk, GFP_ATOMIC,
4652-
SK_RST_REASON_NOT_SPECIFIED);
4655+
SK_RST_REASON_TCP_STATE);
46534656
tcp_done_with_error(sk, err);
46544657
}
46554658

net/ipv4/tcp_output.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3649,7 +3649,7 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority,
36493649
/* skb of trace_tcp_send_reset() keeps the skb that caused RST,
36503650
* skb here is different to the troublesome skb, so use NULL
36513651
*/
3652-
trace_tcp_send_reset(sk, NULL, SK_RST_REASON_NOT_SPECIFIED);
3652+
trace_tcp_send_reset(sk, NULL, reason);
36533653
}
36543654

36553655
/* Send a crossed SYN-ACK during socket establishment.

net/ipv4/tcp_timer.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ static int tcp_out_of_resources(struct sock *sk, bool do_reset)
125125
do_reset = true;
126126
if (do_reset)
127127
tcp_send_active_reset(sk, GFP_ATOMIC,
128-
SK_RST_REASON_NOT_SPECIFIED);
128+
SK_RST_REASON_TCP_ABORT_ON_MEMORY);
129129
tcp_done(sk);
130130
__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY);
131131
return 1;
@@ -779,7 +779,7 @@ static void tcp_keepalive_timer (struct timer_list *t)
779779
goto out;
780780
}
781781
}
782-
tcp_send_active_reset(sk, GFP_ATOMIC, SK_RST_REASON_NOT_SPECIFIED);
782+
tcp_send_active_reset(sk, GFP_ATOMIC, SK_RST_REASON_TCP_STATE);
783783
goto death;
784784
}
785785

@@ -807,7 +807,7 @@ static void tcp_keepalive_timer (struct timer_list *t)
807807
(user_timeout == 0 &&
808808
icsk->icsk_probes_out >= keepalive_probes(tp))) {
809809
tcp_send_active_reset(sk, GFP_ATOMIC,
810-
SK_RST_REASON_NOT_SPECIFIED);
810+
SK_RST_REASON_TCP_KEEPALIVE_TIMEOUT);
811811
tcp_write_err(sk);
812812
goto out;
813813
}

0 commit comments

Comments
 (0)