aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/timer.c')
-rw-r--r--net/dccp/timer.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index 16359e29e7f5..54b3c7e9e016 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -87,6 +87,17 @@ static void dccp_retransmit_timer(struct sock *sk)
87{ 87{
88 struct inet_connection_sock *icsk = inet_csk(sk); 88 struct inet_connection_sock *icsk = inet_csk(sk);
89 89
90 /* retransmit timer is used for feature negotiation throughout
91 * connection. In this case, no packet is re-transmitted, but rather an
92 * ack is generated and pending changes are placed into its options.
93 */
94 if (sk->sk_send_head == NULL) {
95 dccp_pr_debug("feat negotiation retransmit timeout %p\n", sk);
96 if (sk->sk_state == DCCP_OPEN)
97 dccp_send_ack(sk);
98 goto backoff;
99 }
100
90 /* 101 /*
91 * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was 102 * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
92 * sent, no need to retransmit, this sock is dead. 103 * sent, no need to retransmit, this sock is dead.
@@ -115,6 +126,7 @@ static void dccp_retransmit_timer(struct sock *sk)
115 return; 126 return;
116 } 127 }
117 128
129backoff:
118 icsk->icsk_backoff++; 130 icsk->icsk_backoff++;
119 131
120 icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX); 132 icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
@@ -237,35 +249,32 @@ out:
237 sock_put(sk); 249 sock_put(sk);
238} 250}
239 251
240/** 252/* Transmit-delay timer: used by the CCIDs to delay actual send time */
241 * dccp_write_xmitlet - Workhorse for CCID packet dequeueing interface 253static void dccp_write_xmit_timer(unsigned long data)
242 * See the comments above %ccid_dequeueing_decision for supported modes.
243 */
244static void dccp_write_xmitlet(unsigned long data)
245{ 254{
246 struct sock *sk = (struct sock *)data; 255 struct sock *sk = (struct sock *)data;
256 struct dccp_sock *dp = dccp_sk(sk);
247 257
248 bh_lock_sock(sk); 258 bh_lock_sock(sk);
249 if (sock_owned_by_user(sk)) 259 if (sock_owned_by_user(sk))
250 sk_reset_timer(sk, &dccp_sk(sk)->dccps_xmit_timer, jiffies + 1); 260 sk_reset_timer(sk, &dp->dccps_xmit_timer, jiffies+1);
251 else 261 else
252 dccp_write_xmit(sk); 262 dccp_write_xmit(sk, 0);
253 bh_unlock_sock(sk); 263 bh_unlock_sock(sk);
264 sock_put(sk);
254} 265}
255 266
256static void dccp_write_xmit_timer(unsigned long data) 267static void dccp_init_write_xmit_timer(struct sock *sk)
257{ 268{
258 dccp_write_xmitlet(data); 269 struct dccp_sock *dp = dccp_sk(sk);
259 sock_put((struct sock *)data); 270
271 setup_timer(&dp->dccps_xmit_timer, dccp_write_xmit_timer,
272 (unsigned long)sk);
260} 273}
261 274
262void dccp_init_xmit_timers(struct sock *sk) 275void dccp_init_xmit_timers(struct sock *sk)
263{ 276{
264 struct dccp_sock *dp = dccp_sk(sk); 277 dccp_init_write_xmit_timer(sk);
265
266 tasklet_init(&dp->dccps_xmitlet, dccp_write_xmitlet, (unsigned long)sk);
267 setup_timer(&dp->dccps_xmit_timer, dccp_write_xmit_timer,
268 (unsigned long)sk);
269 inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer, 278 inet_csk_init_xmit_timers(sk, &dccp_write_timer, &dccp_delack_timer,
270 &dccp_keepalive_timer); 279 &dccp_keepalive_timer);
271} 280}
@@ -281,7 +290,8 @@ u32 dccp_timestamp(void)
281{ 290{
282 s64 delta = ktime_us_delta(ktime_get_real(), dccp_timestamp_seed); 291 s64 delta = ktime_us_delta(ktime_get_real(), dccp_timestamp_seed);
283 292
284 return div_u64(delta, DCCP_TIME_RESOLUTION); 293 do_div(delta, 10);
294 return delta;
285} 295}
286EXPORT_SYMBOL_GPL(dccp_timestamp); 296EXPORT_SYMBOL_GPL(dccp_timestamp);
287 297