diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
| -rw-r--r-- | net/ipv4/tcp_input.c | 21 | 
1 files changed, 11 insertions, 10 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index ab5f0ea166f1..b85a9f755da4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3614,12 +3614,9 @@ bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb,  /* RFC 5961 7 [ACK Throttling] */  static void tcp_send_challenge_ack(struct sock *sk)  { -	/* unprotected vars, we dont care of overwrites */ -	static u32 challenge_timestamp; -	static unsigned int challenge_count;  	struct tcp_sock *tp = tcp_sk(sk);  	struct net *net = sock_net(sk); -	u32 count, now; +	u32 count, now, ack_limit;  	/* First check our per-socket dupack rate limit. */  	if (__tcp_oow_rate_limited(net, @@ -3627,18 +3624,22 @@ static void tcp_send_challenge_ack(struct sock *sk)  				   &tp->last_oow_ack_time))  		return; +	ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit); +	if (ack_limit == INT_MAX) +		goto send_ack; +  	/* Then check host-wide RFC 5961 rate limit. */  	now = jiffies / HZ; -	if (now != challenge_timestamp) { -		u32 ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit); +	if (now != READ_ONCE(net->ipv4.tcp_challenge_timestamp)) {  		u32 half = (ack_limit + 1) >> 1; -		challenge_timestamp = now; -		WRITE_ONCE(challenge_count, half + prandom_u32_max(ack_limit)); +		WRITE_ONCE(net->ipv4.tcp_challenge_timestamp, now); +		WRITE_ONCE(net->ipv4.tcp_challenge_count, half + prandom_u32_max(ack_limit));  	} -	count = READ_ONCE(challenge_count); +	count = READ_ONCE(net->ipv4.tcp_challenge_count);  	if (count > 0) { -		WRITE_ONCE(challenge_count, count - 1); +		WRITE_ONCE(net->ipv4.tcp_challenge_count, count - 1); +send_ack:  		NET_INC_STATS(net, LINUX_MIB_TCPCHALLENGEACK);  		tcp_send_ack(sk);  	}  | 
