diff options
Diffstat (limited to 'net/dccp/proto.c')
| -rw-r--r-- | net/dccp/proto.c | 21 | 
1 files changed, 20 insertions, 1 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 7e5fc04eb6d..ef343d53fce 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -726,7 +726,13 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,  		goto out_discard;  	skb_queue_tail(&sk->sk_write_queue, skb); -	dccp_write_xmit(sk,0); +	/* +	 * The xmit_timer is set if the TX CCID is rate-based and will expire +	 * when congestion control permits to release further packets into the +	 * network. Window-based CCIDs do not use this timer. +	 */ +	if (!timer_pending(&dp->dccps_xmit_timer)) +		dccp_write_xmit(sk);  out_release:  	release_sock(sk);  	return rc ? : len; @@ -951,9 +957,22 @@ void dccp_close(struct sock *sk, long timeout)  		/* Check zero linger _after_ checking for unread data. */  		sk->sk_prot->disconnect(sk, 0);  	} else if (sk->sk_state != DCCP_CLOSED) { +		/* +		 * Normal connection termination. May need to wait if there are +		 * still packets in the TX queue that are delayed by the CCID. +		 */ +		dccp_flush_write_queue(sk, &timeout);  		dccp_terminate_connection(sk);  	} +	/* +	 * Flush write queue. This may be necessary in several cases: +	 * - we have been closed by the peer but still have application data; +	 * - abortive termination (unread data or zero linger time), +	 * - normal termination but queue could not be flushed within time limit +	 */ +	__skb_queue_purge(&sk->sk_write_queue); +  	sk_stream_wait_close(sk, timeout);  adjudge_to_death:  |