aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/output.c')
-rw-r--r--net/dccp/output.c91
1 files changed, 65 insertions, 26 deletions
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 7409e4a3abdf..7102e3aed4ca 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -10,7 +10,6 @@
10 * 2 of the License, or (at your option) any later version. 10 * 2 of the License, or (at your option) any later version.
11 */ 11 */
12 12
13#include <linux/config.h>
14#include <linux/dccp.h> 13#include <linux/dccp.h>
15#include <linux/kernel.h> 14#include <linux/kernel.h>
16#include <linux/skbuff.h> 15#include <linux/skbuff.h>
@@ -199,7 +198,7 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
199 while (1) { 198 while (1) {
200 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); 199 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
201 200
202 if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) 201 if (sk->sk_err)
203 goto do_error; 202 goto do_error;
204 if (!*timeo) 203 if (!*timeo)
205 goto do_nonblock; 204 goto do_nonblock;
@@ -235,37 +234,72 @@ do_interrupted:
235 goto out; 234 goto out;
236} 235}
237 236
238int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo) 237static void dccp_write_xmit_timer(unsigned long data) {
238 struct sock *sk = (struct sock *)data;
239 struct dccp_sock *dp = dccp_sk(sk);
240
241 bh_lock_sock(sk);
242 if (sock_owned_by_user(sk))
243 sk_reset_timer(sk, &dp->dccps_xmit_timer, jiffies+1);
244 else
245 dccp_write_xmit(sk, 0);
246 bh_unlock_sock(sk);
247 sock_put(sk);
248}
249
250void dccp_write_xmit(struct sock *sk, int block)
239{ 251{
240 const struct dccp_sock *dp = dccp_sk(sk); 252 struct dccp_sock *dp = dccp_sk(sk);
241 int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, 253 struct sk_buff *skb;
254 long timeo = 30000; /* If a packet is taking longer than 2 secs
255 we have other issues */
256
257 while ((skb = skb_peek(&sk->sk_write_queue))) {
258 int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb,
242 skb->len); 259 skb->len);
243 260
244 if (err > 0) 261 if (err > 0) {
245 err = dccp_wait_for_ccid(sk, skb, timeo); 262 if (!block) {
263 sk_reset_timer(sk, &dp->dccps_xmit_timer,
264 msecs_to_jiffies(err)+jiffies);
265 break;
266 } else
267 err = dccp_wait_for_ccid(sk, skb, &timeo);
268 if (err) {
269 printk(KERN_CRIT "%s:err at dccp_wait_for_ccid"
270 " %d\n", __FUNCTION__, err);
271 dump_stack();
272 }
273 }
246 274
247 if (err == 0) { 275 skb_dequeue(&sk->sk_write_queue);
248 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); 276 if (err == 0) {
249 const int len = skb->len; 277 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
278 const int len = skb->len;
250 279
251 if (sk->sk_state == DCCP_PARTOPEN) { 280 if (sk->sk_state == DCCP_PARTOPEN) {
252 /* See 8.1.5. Handshake Completion */ 281 /* See 8.1.5. Handshake Completion */
253 inet_csk_schedule_ack(sk); 282 inet_csk_schedule_ack(sk);
254 inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 283 inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
255 inet_csk(sk)->icsk_rto, 284 inet_csk(sk)->icsk_rto,
256 DCCP_RTO_MAX); 285 DCCP_RTO_MAX);
257 dcb->dccpd_type = DCCP_PKT_DATAACK; 286 dcb->dccpd_type = DCCP_PKT_DATAACK;
258 } else if (dccp_ack_pending(sk)) 287 } else if (dccp_ack_pending(sk))
259 dcb->dccpd_type = DCCP_PKT_DATAACK; 288 dcb->dccpd_type = DCCP_PKT_DATAACK;
260 else 289 else
261 dcb->dccpd_type = DCCP_PKT_DATA; 290 dcb->dccpd_type = DCCP_PKT_DATA;
262 291
263 err = dccp_transmit_skb(sk, skb); 292 err = dccp_transmit_skb(sk, skb);
264 ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len); 293 ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len);
265 } else 294 if (err) {
266 kfree_skb(skb); 295 printk(KERN_CRIT "%s:err from "
267 296 "ccid_hc_tx_packet_sent %d\n",
268 return err; 297 __FUNCTION__, err);
298 dump_stack();
299 }
300 } else
301 kfree(skb);
302 }
269} 303}
270 304
271int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb) 305int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
@@ -427,6 +461,9 @@ static inline void dccp_connect_init(struct sock *sk)
427 dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss)); 461 dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
428 462
429 icsk->icsk_retransmits = 0; 463 icsk->icsk_retransmits = 0;
464 init_timer(&dp->dccps_xmit_timer);
465 dp->dccps_xmit_timer.data = (unsigned long)sk;
466 dp->dccps_xmit_timer.function = dccp_write_xmit_timer;
430} 467}
431 468
432int dccp_connect(struct sock *sk) 469int dccp_connect(struct sock *sk)
@@ -561,8 +598,10 @@ void dccp_send_close(struct sock *sk, const int active)
561 DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ; 598 DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ;
562 599
563 if (active) { 600 if (active) {
601 dccp_write_xmit(sk, 1);
564 dccp_skb_entail(sk, skb); 602 dccp_skb_entail(sk, skb);
565 dccp_transmit_skb(sk, skb_clone(skb, prio)); 603 dccp_transmit_skb(sk, skb_clone(skb, prio));
604 /* FIXME do we need a retransmit timer here? */
566 } else 605 } else
567 dccp_transmit_skb(sk, skb); 606 dccp_transmit_skb(sk, skb);
568} 607}