Skip to content

Commit d34910e

Browse files
Tung Nguyendavem330
authored andcommitted
tipc: fix duplicate SYN messages under link congestion
Scenario: 1. A client socket initiates a SYN message to a listening socket. 2. The send link is congested, the SYN message is put in the send link and a wakeup message is put in wakeup queue. 3. The congestion situation is abated, the wakeup message is pulled out of the wakeup queue. Function tipc_sk_push_backlog() is called to send out delayed messages by Nagle. However, the client socket is still in CONNECTING state. So, it sends the SYN message in the socket write queue to the listening socket again. 4. The listening socket receives the first SYN message and creates first server socket. The client socket receives ACK- and establishes a connection to the first server socket. The client socket closes its connection with the first server socket. 5. The listening socket receives the second SYN message and creates second server socket. The second server socket sends ACK- to the client socket, but it has been closed. It results in connection reset error when reading from the server socket in user space. Solution: return from function tipc_sk_push_backlog() immediately if there is pending SYN message in the socket write queue. Fixes: c0bceb9 ("tipc: add smart nagle feature") Signed-off-by: Tung Nguyen <[email protected]> Acked-by: Jon Maloy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 12db3c8 commit d34910e

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

net/tipc/socket.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -540,12 +540,10 @@ static void __tipc_shutdown(struct socket *sock, int error)
540540
tipc_wait_for_cond(sock, &timeout, (!tsk->cong_link_cnt &&
541541
!tsk_conn_cong(tsk)));
542542

543-
/* Push out unsent messages or remove if pending SYN */
544-
skb = skb_peek(&sk->sk_write_queue);
545-
if (skb && !msg_is_syn(buf_msg(skb)))
546-
tipc_sk_push_backlog(tsk);
547-
else
548-
__skb_queue_purge(&sk->sk_write_queue);
543+
/* Push out delayed messages if in Nagle mode */
544+
tipc_sk_push_backlog(tsk);
545+
/* Remove pending SYN */
546+
__skb_queue_purge(&sk->sk_write_queue);
549547

550548
/* Reject all unreceived messages, except on an active connection
551549
* (which disconnects locally & sends a 'FIN+' to peer).
@@ -1248,9 +1246,14 @@ static void tipc_sk_push_backlog(struct tipc_sock *tsk)
12481246
struct sk_buff_head *txq = &tsk->sk.sk_write_queue;
12491247
struct net *net = sock_net(&tsk->sk);
12501248
u32 dnode = tsk_peer_node(tsk);
1249+
struct sk_buff *skb = skb_peek(txq);
12511250
int rc;
12521251

1253-
if (skb_queue_empty(txq) || tsk->cong_link_cnt)
1252+
if (!skb || tsk->cong_link_cnt)
1253+
return;
1254+
1255+
/* Do not send SYN again after congestion */
1256+
if (msg_is_syn(buf_msg(skb)))
12541257
return;
12551258

12561259
tsk->snt_unacked += tsk->snd_backlog;

0 commit comments

Comments
 (0)