Blame view

net/dccp/timer.c 7.12 KB
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
1
2
  /*
   *  net/dccp/timer.c
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
3
   *
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
4
5
6
7
8
9
10
11
   *  An implementation of the DCCP protocol
   *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
12
13
  #include <linux/dccp.h>
  #include <linux/skbuff.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
14
  #include <linux/export.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
15
16
  
  #include "dccp.h"
2e2e9e92b   Gerrit Renker   [DCCP]: Add sysct...
17
18
19
20
  /* sysctl variables governing numbers of retransmission attempts */
  int  sysctl_dccp_request_retries	__read_mostly = TCP_SYN_RETRIES;
  int  sysctl_dccp_retries1		__read_mostly = TCP_RETR1;
  int  sysctl_dccp_retries2		__read_mostly = TCP_RETR2;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
21
22
23
24
  static void dccp_write_err(struct sock *sk)
  {
  	sk->sk_err = sk->sk_err_soft ? : ETIMEDOUT;
  	sk->sk_error_report(sk);
017487d7d   Arnaldo Carvalho de Melo   [DCCP]: Generaliz...
25
  	dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
26
  	dccp_done(sk);
aa62d76b6   Eric Dumazet   dccp: rename DCCP...
27
  	__DCCP_INC_STATS(DCCP_MIB_ABORTONTIMEOUT);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
28
29
30
31
32
33
34
35
36
37
  }
  
  /* A write timeout has occurred. Process the after effects. */
  static int dccp_write_timeout(struct sock *sk)
  {
  	const struct inet_connection_sock *icsk = inet_csk(sk);
  	int retry_until;
  
  	if (sk->sk_state == DCCP_REQUESTING || sk->sk_state == DCCP_PARTOPEN) {
  		if (icsk->icsk_retransmits != 0)
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
38
  			dst_negative_advice(sk);
2e2e9e92b   Gerrit Renker   [DCCP]: Add sysct...
39
40
  		retry_until = icsk->icsk_syn_retries ?
  			    : sysctl_dccp_request_retries;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
41
  	} else {
2e2e9e92b   Gerrit Renker   [DCCP]: Add sysct...
42
  		if (icsk->icsk_retransmits >= sysctl_dccp_retries1) {
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
43
44
  			/* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu
  			   black hole detection. :-(
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  
  			   It is place to make it. It is not made. I do not want
  			   to make it. It is disguisting. It does not work in any
  			   case. Let me to cite the same draft, which requires for
  			   us to implement this:
  
     "The one security concern raised by this memo is that ICMP black holes
     are often caused by over-zealous security administrators who block
     all ICMP messages.  It is vitally important that those who design and
     deploy security systems understand the impact of strict filtering on
     upper-layer protocols.  The safest web site in the world is worthless
     if most TCP implementations cannot transfer data from it.  It would
     be far nicer to have all of the black holes fixed rather than fixing
     all of the TCP implementations."
c9eaf1734   YOSHIFUJI Hideaki   [NET] DCCP: Fix w...
59
  			   Golden words :-).
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
60
  		   */
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
61
  			dst_negative_advice(sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
62
  		}
2e2e9e92b   Gerrit Renker   [DCCP]: Add sysct...
63
  		retry_until = sysctl_dccp_retries2;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
64
65
66
67
68
69
70
71
72
73
74
75
  		/*
  		 * FIXME: see tcp_write_timout and tcp_out_of_resources
  		 */
  	}
  
  	if (icsk->icsk_retransmits >= retry_until) {
  		/* Has it gone just too far? */
  		dccp_write_err(sk);
  		return 1;
  	}
  	return 0;
  }
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
76
77
78
79
80
81
82
83
  /*
   *	The DCCP retransmit timer.
   */
  static void dccp_retransmit_timer(struct sock *sk)
  {
  	struct inet_connection_sock *icsk = inet_csk(sk);
  
  	/*
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
84
85
86
87
  	 * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
  	 * sent, no need to retransmit, this sock is dead.
  	 */
  	if (dccp_write_timeout(sk))
59435444a   Gerrit Renker   dccp: Allow to di...
88
  		return;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
89
90
91
92
93
94
  
  	/*
  	 * We want to know the number of packets retransmitted, not the
  	 * total number of retransmissions of clones of original packets.
  	 */
  	if (icsk->icsk_retransmits == 0)
aa62d76b6   Eric Dumazet   dccp: rename DCCP...
95
  		__DCCP_INC_STATS(DCCP_MIB_TIMEOUTS);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
96

59435444a   Gerrit Renker   dccp: Allow to di...
97
  	if (dccp_retransmit_skb(sk) != 0) {
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
98
99
100
101
  		/*
  		 * Retransmission failed because of local congestion,
  		 * do not backoff.
  		 */
59435444a   Gerrit Renker   dccp: Allow to di...
102
  		if (--icsk->icsk_retransmits == 0)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
103
104
105
106
  			icsk->icsk_retransmits = 1;
  		inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
  					  min(icsk->icsk_rto,
  					      TCP_RESOURCE_PROBE_INTERVAL),
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
107
  					  DCCP_RTO_MAX);
59435444a   Gerrit Renker   dccp: Allow to di...
108
  		return;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
109
110
111
  	}
  
  	icsk->icsk_backoff++;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
112
113
  
  	icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
114
115
  	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto,
  				  DCCP_RTO_MAX);
2e2e9e92b   Gerrit Renker   [DCCP]: Add sysct...
116
  	if (icsk->icsk_retransmits > sysctl_dccp_retries1)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
117
  		__sk_dst_reset(sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
118
119
120
121
122
123
124
125
126
127
128
  }
  
  static void dccp_write_timer(unsigned long data)
  {
  	struct sock *sk = (struct sock *)data;
  	struct inet_connection_sock *icsk = inet_csk(sk);
  	int event = 0;
  
  	bh_lock_sock(sk);
  	if (sock_owned_by_user(sk)) {
  		/* Try again later */
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
129
130
  		sk_reset_timer(sk, &icsk->icsk_retransmit_timer,
  			       jiffies + (HZ / 20));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
131
132
133
134
135
136
137
  		goto out;
  	}
  
  	if (sk->sk_state == DCCP_CLOSED || !icsk->icsk_pending)
  		goto out;
  
  	if (time_after(icsk->icsk_timeout, jiffies)) {
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
138
139
  		sk_reset_timer(sk, &icsk->icsk_retransmit_timer,
  			       icsk->icsk_timeout);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  		goto out;
  	}
  
  	event = icsk->icsk_pending;
  	icsk->icsk_pending = 0;
  
  	switch (event) {
  	case ICSK_TIME_RETRANS:
  		dccp_retransmit_timer(sk);
  		break;
  	}
  out:
  	bh_unlock_sock(sk);
  	sock_put(sk);
  }
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
155
156
157
  static void dccp_keepalive_timer(unsigned long data)
  {
  	struct sock *sk = (struct sock *)data;
fa76ce732   Eric Dumazet   inet: get rid of ...
158
159
  	pr_err("dccp should not use a keepalive timer !
  ");
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
160
161
  	sock_put(sk);
  }
4ed800d02   Gerrit Renker   [DCCP]: Remove fo...
162
163
164
165
166
167
168
169
170
171
172
  
  /* This is the same as tcp_delack_timer, sans prequeue & mem_reclaim stuff */
  static void dccp_delack_timer(unsigned long data)
  {
  	struct sock *sk = (struct sock *)data;
  	struct inet_connection_sock *icsk = inet_csk(sk);
  
  	bh_lock_sock(sk);
  	if (sock_owned_by_user(sk)) {
  		/* Try again later. */
  		icsk->icsk_ack.blocked = 1;
02a1d6e7a   Eric Dumazet   net: rename NET_{...
173
  		__NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED);
4ed800d02   Gerrit Renker   [DCCP]: Remove fo...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  		sk_reset_timer(sk, &icsk->icsk_delack_timer,
  			       jiffies + TCP_DELACK_MIN);
  		goto out;
  	}
  
  	if (sk->sk_state == DCCP_CLOSED ||
  	    !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
  		goto out;
  	if (time_after(icsk->icsk_ack.timeout, jiffies)) {
  		sk_reset_timer(sk, &icsk->icsk_delack_timer,
  			       icsk->icsk_ack.timeout);
  		goto out;
  	}
  
  	icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER;
  
  	if (inet_csk_ack_scheduled(sk)) {
  		if (!icsk->icsk_ack.pingpong) {
  			/* Delayed ACK missed: inflate ATO. */
  			icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1,
  						 icsk->icsk_rto);
  		} else {
  			/* Delayed ACK missed: leave pingpong mode and
  			 * deflate ATO.
  			 */
  			icsk->icsk_ack.pingpong = 0;
  			icsk->icsk_ack.ato = TCP_ATO_MIN;
  		}
  		dccp_send_ack(sk);
02a1d6e7a   Eric Dumazet   net: rename NET_{...
203
  		__NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKS);
4ed800d02   Gerrit Renker   [DCCP]: Remove fo...
204
205
206
207
208
  	}
  out:
  	bh_unlock_sock(sk);
  	sock_put(sk);
  }
dc841e30e   Gerrit Renker   dccp: Extend CCID...
209
210
211
212
213
  /**
   * dccp_write_xmitlet  -  Workhorse for CCID packet dequeueing interface
   * See the comments above %ccid_dequeueing_decision for supported modes.
   */
  static void dccp_write_xmitlet(unsigned long data)
aabb601b0   Gerrit Renker   [DCCP]: Initialis...
214
215
  {
  	struct sock *sk = (struct sock *)data;
aabb601b0   Gerrit Renker   [DCCP]: Initialis...
216
217
218
  
  	bh_lock_sock(sk);
  	if (sock_owned_by_user(sk))
dc841e30e   Gerrit Renker   dccp: Extend CCID...
219
  		sk_reset_timer(sk, &dccp_sk(sk)->dccps_xmit_timer, jiffies + 1);
aabb601b0   Gerrit Renker   [DCCP]: Initialis...
220
  	else
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
221
  		dccp_write_xmit(sk);
aabb601b0   Gerrit Renker   [DCCP]: Initialis...
222
  	bh_unlock_sock(sk);
aabb601b0   Gerrit Renker   [DCCP]: Initialis...
223
  }
dc841e30e   Gerrit Renker   dccp: Extend CCID...
224
  static void dccp_write_xmit_timer(unsigned long data)
aabb601b0   Gerrit Renker   [DCCP]: Initialis...
225
  {
dc841e30e   Gerrit Renker   dccp: Extend CCID...
226
227
  	dccp_write_xmitlet(data);
  	sock_put((struct sock *)data);
aabb601b0   Gerrit Renker   [DCCP]: Initialis...
228
  }
4ed800d02   Gerrit Renker   [DCCP]: Remove fo...
229
230
  void dccp_init_xmit_timers(struct sock *sk)
  {
dc841e30e   Gerrit Renker   dccp: Extend CCID...
231
232
233
234
235
  	struct dccp_sock *dp = dccp_sk(sk);
  
  	tasklet_init(&dp->dccps_xmitlet, dccp_write_xmitlet, (unsigned long)sk);
  	setup_timer(&dp->dccps_xmit_timer, dccp_write_xmit_timer,
  							     (unsigned long)sk);
4ed800d02   Gerrit Renker   [DCCP]: Remove fo...
236
237
238
  	inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer,
  				  &dccp_keepalive_timer);
  }
4c70f383e   Gerrit Renker   [DCCP]: Provide 1...
239
240
241
242
243
244
245
246
247
248
  
  static ktime_t dccp_timestamp_seed;
  /**
   * dccp_timestamp  -  10s of microseconds time source
   * Returns the number of 10s of microseconds since loading DCCP. This is native
   * DCCP time difference format (RFC 4340, sec. 13).
   * Please note: This will wrap around about circa every 11.9 hours.
   */
  u32 dccp_timestamp(void)
  {
5c4a43b02   Chen Gang   net/dccp/timer.c:...
249
  	u64 delta = (u64)ktime_us_delta(ktime_get_real(), dccp_timestamp_seed);
4c70f383e   Gerrit Renker   [DCCP]: Provide 1...
250
251
252
253
254
255
256
257
258
259
  
  	do_div(delta, 10);
  	return delta;
  }
  EXPORT_SYMBOL_GPL(dccp_timestamp);
  
  void __init dccp_timestamping_init(void)
  {
  	dccp_timestamp_seed = ktime_get_real();
  }