diff options
Diffstat (limited to 'net/dccp/timer.c')
-rw-r--r-- | net/dccp/timer.c | 134 |
1 files changed, 68 insertions, 66 deletions
diff --git a/net/dccp/timer.c b/net/dccp/timer.c index 8447742f5615..e8f519e7f481 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c | |||
@@ -15,15 +15,10 @@ | |||
15 | 15 | ||
16 | #include "dccp.h" | 16 | #include "dccp.h" |
17 | 17 | ||
18 | static void dccp_write_timer(unsigned long data); | 18 | /* sysctl variables governing numbers of retransmission attempts */ |
19 | static void dccp_keepalive_timer(unsigned long data); | 19 | int sysctl_dccp_request_retries __read_mostly = TCP_SYN_RETRIES; |
20 | static void dccp_delack_timer(unsigned long data); | 20 | int sysctl_dccp_retries1 __read_mostly = TCP_RETR1; |
21 | 21 | int sysctl_dccp_retries2 __read_mostly = TCP_RETR2; | |
22 | void dccp_init_xmit_timers(struct sock *sk) | ||
23 | { | ||
24 | inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer, | ||
25 | &dccp_keepalive_timer); | ||
26 | } | ||
27 | 22 | ||
28 | static void dccp_write_err(struct sock *sk) | 23 | static void dccp_write_err(struct sock *sk) |
29 | { | 24 | { |
@@ -44,11 +39,10 @@ static int dccp_write_timeout(struct sock *sk) | |||
44 | if (sk->sk_state == DCCP_REQUESTING || sk->sk_state == DCCP_PARTOPEN) { | 39 | if (sk->sk_state == DCCP_REQUESTING || sk->sk_state == DCCP_PARTOPEN) { |
45 | if (icsk->icsk_retransmits != 0) | 40 | if (icsk->icsk_retransmits != 0) |
46 | dst_negative_advice(&sk->sk_dst_cache); | 41 | dst_negative_advice(&sk->sk_dst_cache); |
47 | retry_until = icsk->icsk_syn_retries ? : | 42 | retry_until = icsk->icsk_syn_retries ? |
48 | /* FIXME! */ 3 /* FIXME! sysctl_tcp_syn_retries */; | 43 | : sysctl_dccp_request_retries; |
49 | } else { | 44 | } else { |
50 | if (icsk->icsk_retransmits >= | 45 | if (icsk->icsk_retransmits >= sysctl_dccp_retries1) { |
51 | /* FIXME! sysctl_tcp_retries1 */ 5 /* FIXME! */) { | ||
52 | /* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu | 46 | /* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu |
53 | black hole detection. :-( | 47 | black hole detection. :-( |
54 | 48 | ||
@@ -72,7 +66,7 @@ static int dccp_write_timeout(struct sock *sk) | |||
72 | dst_negative_advice(&sk->sk_dst_cache); | 66 | dst_negative_advice(&sk->sk_dst_cache); |
73 | } | 67 | } |
74 | 68 | ||
75 | retry_until = /* FIXME! */ 15 /* FIXME! sysctl_tcp_retries2 */; | 69 | retry_until = sysctl_dccp_retries2; |
76 | /* | 70 | /* |
77 | * FIXME: see tcp_write_timout and tcp_out_of_resources | 71 | * FIXME: see tcp_write_timout and tcp_out_of_resources |
78 | */ | 72 | */ |
@@ -86,53 +80,6 @@ static int dccp_write_timeout(struct sock *sk) | |||
86 | return 0; | 80 | return 0; |
87 | } | 81 | } |
88 | 82 | ||
89 | /* This is the same as tcp_delack_timer, sans prequeue & mem_reclaim stuff */ | ||
90 | static void dccp_delack_timer(unsigned long data) | ||
91 | { | ||
92 | struct sock *sk = (struct sock *)data; | ||
93 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
94 | |||
95 | bh_lock_sock(sk); | ||
96 | if (sock_owned_by_user(sk)) { | ||
97 | /* Try again later. */ | ||
98 | icsk->icsk_ack.blocked = 1; | ||
99 | NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKLOCKED); | ||
100 | sk_reset_timer(sk, &icsk->icsk_delack_timer, | ||
101 | jiffies + TCP_DELACK_MIN); | ||
102 | goto out; | ||
103 | } | ||
104 | |||
105 | if (sk->sk_state == DCCP_CLOSED || | ||
106 | !(icsk->icsk_ack.pending & ICSK_ACK_TIMER)) | ||
107 | goto out; | ||
108 | if (time_after(icsk->icsk_ack.timeout, jiffies)) { | ||
109 | sk_reset_timer(sk, &icsk->icsk_delack_timer, | ||
110 | icsk->icsk_ack.timeout); | ||
111 | goto out; | ||
112 | } | ||
113 | |||
114 | icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER; | ||
115 | |||
116 | if (inet_csk_ack_scheduled(sk)) { | ||
117 | if (!icsk->icsk_ack.pingpong) { | ||
118 | /* Delayed ACK missed: inflate ATO. */ | ||
119 | icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1, | ||
120 | icsk->icsk_rto); | ||
121 | } else { | ||
122 | /* Delayed ACK missed: leave pingpong mode and | ||
123 | * deflate ATO. | ||
124 | */ | ||
125 | icsk->icsk_ack.pingpong = 0; | ||
126 | icsk->icsk_ack.ato = TCP_ATO_MIN; | ||
127 | } | ||
128 | dccp_send_ack(sk); | ||
129 | NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKS); | ||
130 | } | ||
131 | out: | ||
132 | bh_unlock_sock(sk); | ||
133 | sock_put(sk); | ||
134 | } | ||
135 | |||
136 | /* | 83 | /* |
137 | * The DCCP retransmit timer. | 84 | * The DCCP retransmit timer. |
138 | */ | 85 | */ |
@@ -142,7 +89,7 @@ static void dccp_retransmit_timer(struct sock *sk) | |||
142 | 89 | ||
143 | /* retransmit timer is used for feature negotiation throughout | 90 | /* retransmit timer is used for feature negotiation throughout |
144 | * connection. In this case, no packet is re-transmitted, but rather an | 91 | * connection. In this case, no packet is re-transmitted, but rather an |
145 | * ack is generated and pending changes are splaced into its options. | 92 | * ack is generated and pending changes are placed into its options. |
146 | */ | 93 | */ |
147 | if (sk->sk_send_head == NULL) { | 94 | if (sk->sk_send_head == NULL) { |
148 | dccp_pr_debug("feat negotiation retransmit timeout %p\n", sk); | 95 | dccp_pr_debug("feat negotiation retransmit timeout %p\n", sk); |
@@ -154,9 +101,11 @@ static void dccp_retransmit_timer(struct sock *sk) | |||
154 | /* | 101 | /* |
155 | * sk->sk_send_head has to have one skb with | 102 | * sk->sk_send_head has to have one skb with |
156 | * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP | 103 | * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP |
157 | * packet types (REQUEST, RESPONSE, the ACK in the 3way handshake | 104 | * packet types. The only packets eligible for retransmission are: |
158 | * (PARTOPEN timer), etc). | 105 | * -- Requests in client-REQUEST state (sec. 8.1.1) |
159 | */ | 106 | * -- Acks in client-PARTOPEN state (sec. 8.1.5) |
107 | * -- CloseReq in server-CLOSEREQ state (sec. 8.3) | ||
108 | * -- Close in node-CLOSING state (sec. 8.3) */ | ||
160 | BUG_TRAP(sk->sk_send_head != NULL); | 109 | BUG_TRAP(sk->sk_send_head != NULL); |
161 | 110 | ||
162 | /* | 111 | /* |
@@ -194,7 +143,7 @@ backoff: | |||
194 | icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX); | 143 | icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX); |
195 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, | 144 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, |
196 | DCCP_RTO_MAX); | 145 | DCCP_RTO_MAX); |
197 | if (icsk->icsk_retransmits > 3 /* FIXME: sysctl_dccp_retries1 */) | 146 | if (icsk->icsk_retransmits > sysctl_dccp_retries1) |
198 | __sk_dst_reset(sk); | 147 | __sk_dst_reset(sk); |
199 | out:; | 148 | out:; |
200 | } | 149 | } |
@@ -264,3 +213,56 @@ out: | |||
264 | bh_unlock_sock(sk); | 213 | bh_unlock_sock(sk); |
265 | sock_put(sk); | 214 | sock_put(sk); |
266 | } | 215 | } |
216 | |||
217 | /* This is the same as tcp_delack_timer, sans prequeue & mem_reclaim stuff */ | ||
218 | static void dccp_delack_timer(unsigned long data) | ||
219 | { | ||
220 | struct sock *sk = (struct sock *)data; | ||
221 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
222 | |||
223 | bh_lock_sock(sk); | ||
224 | if (sock_owned_by_user(sk)) { | ||
225 | /* Try again later. */ | ||
226 | icsk->icsk_ack.blocked = 1; | ||
227 | NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKLOCKED); | ||
228 | sk_reset_timer(sk, &icsk->icsk_delack_timer, | ||
229 | jiffies + TCP_DELACK_MIN); | ||
230 | goto out; | ||
231 | } | ||
232 | |||
233 | if (sk->sk_state == DCCP_CLOSED || | ||
234 | !(icsk->icsk_ack.pending & ICSK_ACK_TIMER)) | ||
235 | goto out; | ||
236 | if (time_after(icsk->icsk_ack.timeout, jiffies)) { | ||
237 | sk_reset_timer(sk, &icsk->icsk_delack_timer, | ||
238 | icsk->icsk_ack.timeout); | ||
239 | goto out; | ||
240 | } | ||
241 | |||
242 | icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER; | ||
243 | |||
244 | if (inet_csk_ack_scheduled(sk)) { | ||
245 | if (!icsk->icsk_ack.pingpong) { | ||
246 | /* Delayed ACK missed: inflate ATO. */ | ||
247 | icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1, | ||
248 | icsk->icsk_rto); | ||
249 | } else { | ||
250 | /* Delayed ACK missed: leave pingpong mode and | ||
251 | * deflate ATO. | ||
252 | */ | ||
253 | icsk->icsk_ack.pingpong = 0; | ||
254 | icsk->icsk_ack.ato = TCP_ATO_MIN; | ||
255 | } | ||
256 | dccp_send_ack(sk); | ||
257 | NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKS); | ||
258 | } | ||
259 | out: | ||
260 | bh_unlock_sock(sk); | ||
261 | sock_put(sk); | ||
262 | } | ||
263 | |||
264 | void dccp_init_xmit_timers(struct sock *sk) | ||
265 | { | ||
266 | inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer, | ||
267 | &dccp_keepalive_timer); | ||
268 | } | ||