Skip to content

Commit 9603d47

Browse files
sj-awskuba-moo
authored andcommitted
tcp: Reduce SYN resend delay if a suspicous ACK is received
When closing a connection, the two acks that required to change closing socket's status to FIN_WAIT_2 and then TIME_WAIT could be processed in reverse order. This is possible in RSS disabled environments such as a connection inside a host. For example, expected state transitions and required packets for the disconnection will be similar to below flow. 00 (Process A) (Process B) 01 ESTABLISHED ESTABLISHED 02 close() 03 FIN_WAIT_1 04 ---FIN--> 05 CLOSE_WAIT 06 <--ACK--- 07 FIN_WAIT_2 08 <--FIN/ACK--- 09 TIME_WAIT 10 ---ACK--> 11 LAST_ACK 12 CLOSED CLOSED In some cases such as LINGER option applied socket, the FIN and FIN/ACK will be substituted to RST and RST/ACK, but there is no difference in the main logic. The acks in lines 6 and 8 are the acks. If the line 8 packet is processed before the line 6 packet, it will be just ignored as it is not a expected packet, and the later process of the line 6 packet will change the status of Process A to FIN_WAIT_2, but as it has already handled line 8 packet, it will not go to TIME_WAIT and thus will not send the line 10 packet to Process B. Thus, Process B will left in CLOSE_WAIT status, as below. 00 (Process A) (Process B) 01 ESTABLISHED ESTABLISHED 02 close() 03 FIN_WAIT_1 04 ---FIN--> 05 CLOSE_WAIT 06 (<--ACK---) 07 (<--FIN/ACK---) 08 (fired in right order) 09 <--FIN/ACK--- 10 <--ACK--- 11 (processed in reverse order) 12 FIN_WAIT_2 Later, if the Process B sends SYN to Process A for reconnection using the same port, Process A will responds with an ACK for the last flow, which has no increased sequence number. Thus, Process A will send RST, wait for TIMEOUT_INIT (one second in default), and then try reconnection. If reconnections are frequent, the one second latency spikes can be a big problem. Below is a tcpdump results of the problem: 14.436259 IP 127.0.0.1.45150 > 127.0.0.1.4242: Flags [S], seq 2560603644 14.436266 IP 127.0.0.1.4242 > 127.0.0.1.45150: Flags [.], ack 5, win 512 14.436271 IP 127.0.0.1.45150 > 127.0.0.1.4242: Flags [R], seq 2541101298 /* ONE SECOND DELAY */ 15.464613 IP 127.0.0.1.45150 > 127.0.0.1.4242: Flags [S], seq 2560603644 This commit mitigates the problem by reducing the delay for the next SYN if the suspicous ACK is received while in SYN_SENT state. Following commit will add a selftest, which can be also helpful for understanding of this issue. Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: SeongJae Park <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent dff6bc1 commit 9603d47

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

net/ipv4/tcp_input.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5908,8 +5908,14 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
59085908
* the segment and return)"
59095909
*/
59105910
if (!after(TCP_SKB_CB(skb)->ack_seq, tp->snd_una) ||
5911-
after(TCP_SKB_CB(skb)->ack_seq, tp->snd_nxt))
5911+
after(TCP_SKB_CB(skb)->ack_seq, tp->snd_nxt)) {
5912+
/* Previous FIN/ACK or RST/ACK might be ignored. */
5913+
if (icsk->icsk_retransmits == 0)
5914+
inet_csk_reset_xmit_timer(sk,
5915+
ICSK_TIME_RETRANS,
5916+
TCP_TIMEOUT_MIN, TCP_RTO_MAX);
59125917
goto reset_and_undo;
5918+
}
59135919

59145920
if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
59155921
!between(tp->rx_opt.rcv_tsecr, tp->retrans_stamp,

0 commit comments

Comments
 (0)