From: Arnaldo Carvalho de Melo Date: Wed, 10 Aug 2005 03:30:56 +0000 (-0700) Subject: [DCCP]: Introduce dccp_write_xmit from code in dccp_sendmsg X-Git-Tag: v2.6.14-rc1~1035^2~124 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27258ee54f8cd4a43d09319aa5448145afc2cb8d;p=linux-2.6 [DCCP]: Introduce dccp_write_xmit from code in dccp_sendmsg This way it gets closer to the TCP flow, where congestion window checks are done, it seems we can map ccid_hc_tx_send_packet in dccp_write_xmit to tcp_snd_wnd_test in tcp_write_xmit, a CCID2 decision should just fit in here as well... Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 06105b2a61..469f9a14b4 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -43,8 +43,7 @@ struct ccid { unsigned char len, u16 idx, unsigned char* value); int (*ccid_hc_tx_send_packet)(struct sock *sk, - struct sk_buff *skb, int len, - long *delay); + struct sk_buff *skb, int len); void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more, int len); }; @@ -60,12 +59,11 @@ static inline void __ccid_get(struct ccid *ccid) } static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk, - struct sk_buff *skb, int len, - long *delay) + struct sk_buff *skb, int len) { int rc = 0; if (ccid->ccid_hc_tx_send_packet != NULL) - rc = ccid->ccid_hc_tx_send_packet(sk, skb, len, delay); + rc = ccid->ccid_hc_tx_send_packet(sk, skb, len); return rc; } diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 04299c7565..df4adfeaaf 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -977,13 +977,14 @@ out: sock_put(sk); } -static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb, - int len, long *delay) +static int ccid3_hc_tx_send_packet(struct sock *sk, + struct sk_buff *skb, int len) { struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; struct ccid3_tx_hist_entry *new_packet = NULL; struct timeval now; + long delay; int rc = -ENOTCONN; // ccid3_pr_debug("%s, sk=%p, skb=%p, len=%d\n", dccp_role(sk), sk, skb, len); @@ -1037,11 +1038,11 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb, break; case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: - *delay = (now_delta(hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta); - ccid3_pr_debug("send_packet delay=%ld\n",*delay); - *delay /= -1000; + delay = (now_delta(hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta); + ccid3_pr_debug("send_packet delay=%ld\n", delay); + delay /= -1000; /* divide by -1000 is to convert to ms and get sign right */ - rc = *delay > 0 ? -EAGAIN : 0; + rc = delay > 0 ? -EAGAIN : 0; break; default: printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 55b690ab61..8a0d7af649 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -122,6 +122,9 @@ extern void dccp_send_ack(struct sock *sk); extern void dccp_send_delayed_ack(struct sock *sk); extern void dccp_send_sync(struct sock *sk, u64 seq); +extern int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, + const int len); + extern void dccp_init_xmit_timers(struct sock *sk); static inline void dccp_clear_xmit_timers(struct sock *sk) { @@ -194,8 +197,6 @@ static inline void dccp_openreq_init(struct request_sock *req, req->rcv_wnd = 0; } -extern void dccp_v4_send_check(struct sock *sk, struct dccp_hdr *dh, int len, - struct sk_buff *skb); extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb); extern struct sock *dccp_create_openreq_child(struct sock *sk, diff --git a/net/dccp/output.c b/net/dccp/output.c index 4945eaa9d1..50292c0605 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -148,6 +148,41 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu) return mss_now; } +int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, const int len) +{ + const struct dccp_sock *dp = dccp_sk(sk); + int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, len); + + if (err == 0) { + const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; + struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); + + if (sk->sk_state == DCCP_PARTOPEN) { + /* See 8.1.5. Handshake Completion */ + inet_csk_schedule_ack(sk); + inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, + inet_csk(sk)->icsk_rto, + DCCP_RTO_MAX); + dcb->dccpd_type = DCCP_PKT_DATAACK; + /* + * FIXME: we really should have a + * dccps_ack_pending or use icsk. + */ + } else if (inet_csk_ack_scheduled(sk) || + (dp->dccps_options.dccpo_send_ack_vector && + ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 && + ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)) + dcb->dccpd_type = DCCP_PKT_DATAACK; + else + dcb->dccpd_type = DCCP_PKT_DATA; + + err = dccp_transmit_skb(sk, skb); + ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len); + } + + return err; +} + int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb) { if (inet_sk_rebuild_header(sk) != 0) @@ -299,7 +334,8 @@ int dccp_connect(struct sock *sk) DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS); /* Timer for repeating the REQUEST until an answer. */ - inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); + inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, + icsk->icsk_rto, DCCP_RTO_MAX); return 0; } diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 66c43fce17..877c1e0e3c 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -182,8 +182,7 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, return -EMSGSIZE; lock_sock(sk); - - timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); + timeo = sock_sndtimeo(sk, noblock); /* * We have to use sk_stream_wait_connect here to set sk_write_pending, @@ -192,77 +191,27 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, /* Wait for a connection to finish. */ if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN | DCCPF_CLOSING)) if ((rc = sk_stream_wait_connect(sk, &timeo)) != 0) - goto out_err; + goto out_release; size = sk->sk_prot->max_header + len; release_sock(sk); skb = sock_alloc_send_skb(sk, size, noblock, &rc); lock_sock(sk); - if (skb == NULL) goto out_release; skb_reserve(skb, sk->sk_prot->max_header); rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); - if (rc == 0) { - struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); - const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; - long delay; - - /* - * XXX: This is just to match the Waikato tree CA interaction - * points, after the CCID3 code is stable and I have a better - * understanding of behaviour I'll change this to look more like - * TCP. - */ - while (1) { - rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, - skb, len, &delay); - if (rc == 0) - break; - if (rc != -EAGAIN) - goto out_discard; - if (delay > timeo) - goto out_discard; - release_sock(sk); - delay = schedule_timeout(delay); - lock_sock(sk); - timeo -= delay; - if (signal_pending(current)) - goto out_interrupted; - rc = -EPIPE; - if (!(sk->sk_state == DCCP_PARTOPEN || sk->sk_state == DCCP_OPEN)) - goto out_discard; - } + if (rc != 0) + goto out_discard; - if (sk->sk_state == DCCP_PARTOPEN) { - /* See 8.1.5. Handshake Completion */ - inet_csk_schedule_ack(sk); - inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, inet_csk(sk)->icsk_rto, TCP_RTO_MAX); - dcb->dccpd_type = DCCP_PKT_DATAACK; - /* FIXME: we really should have a dccps_ack_pending or use icsk */ - } else if (inet_csk_ack_scheduled(sk) || - (dp->dccps_options.dccpo_send_ack_vector && - ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 && - ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)) - dcb->dccpd_type = DCCP_PKT_DATAACK; - else - dcb->dccpd_type = DCCP_PKT_DATA; - dccp_transmit_skb(sk, skb); - ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len); - } else { -out_discard: - kfree_skb(skb); - } + rc = dccp_write_xmit(sk, skb, len); out_release: release_sock(sk); return rc ? : len; -out_err: - rc = sk_stream_error(sk, flags, rc); +out_discard: + kfree_skb(skb); goto out_release; -out_interrupted: - rc = sock_intr_errno(timeo); - goto out_discard; } EXPORT_SYMBOL(dccp_sendmsg);