See below.

> -----Original Message-----
> From: Tung Nguyen <tung.q.ngu...@dektech.com.au>
> Sent: 14-Nov-19 03:28
> To: tipc-discussion@lists.sourceforge.net; Jon Maloy 
> <jon.ma...@ericsson.com>; ma...@donjonn.com;
> ying....@windriver.com
> Subject: [tipc-discussion] [net v2 1/1] 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
> refuse 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.
> 
> v2: use Jon's suggestion.
> 
> Fixes: c0bceb97db9e ("tipc: add smart nagle feature")
> Signed-off-by: Tung Nguyen <tung.q.ngu...@dektech.com.au>
> ---
>  net/tipc/socket.c | 16 ++++++++++------
>  1 file changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/net/tipc/socket.c b/net/tipc/socket.c
> index 5d7859a..7a402ee 100644
> --- a/net/tipc/socket.c
> +++ b/net/tipc/socket.c
> @@ -540,12 +540,10 @@ static void __tipc_shutdown(struct socket *sock, int 
> error)
>       tipc_wait_for_cond(sock, &timeout, (!tsk->cong_link_cnt &&
>                                           !tsk_conn_cong(tsk)));
> 
> -     /* Push out unsent messages or remove if pending SYN */
> -     skb = skb_peek(&sk->sk_write_queue);
> -     if (skb && !msg_is_syn(buf_msg(skb)))
> -             tipc_sk_push_backlog(tsk);
> -     else
> -             __skb_queue_purge(&sk->sk_write_queue);
> +     /* Push out delayed messages if in Nagle mode */
> +     tipc_sk_push_backlog(tsk);
> +     /* Remove pending SYN */
> +     __skb_queue_purge(&sk->sk_write_queue);
> 
>       /* Reject all unreceived messages, except on an active connection
>        * (which disconnects locally & sends a 'FIN+' to peer).
> @@ -1248,11 +1246,17 @@ static void tipc_sk_push_backlog(struct tipc_sock 
> *tsk)
>       struct sk_buff_head *txq = &tsk->sk.sk_write_queue;
>       struct net *net = sock_net(&tsk->sk);
>       u32 dnode = tsk_peer_node(tsk);
> +     struct sk_buff *skb;
>       int rc;
> 
>       if (skb_queue_empty(txq) || tsk->cong_link_cnt)
>               return;
> 
> +     skb = skb_peek(txq);

Move this line to before the if() clause.Then test for if (!skb ||...) instead 
of skb_queue_empty().
This way we should save a couple of instructions.

Acked-by:jon



> +     /* Do not send SYN again after congestion */
> +     if (msg_is_syn(buf_msg(skb)))
> +             return;
> +
>       tsk->snt_unacked += tsk->snd_backlog;
>       tsk->snd_backlog = 0;
>       tsk->expect_ack = true;
> --
> 2.1.4


_______________________________________________
tipc-discussion mailing list
tipc-discussion@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tipc-discussion

Reply via email to