summaryrefslogtreecommitdiff
path: root/net/dccp
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@mandriva.com>2005-08-09 20:30:56 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 15:55:18 -0700
commit27258ee54f8cd4a43d09319aa5448145afc2cb8d (patch)
tree4a52d16da47f7ab0777252169406ae85e53488b1 /net/dccp
parent0d48d93947dd9ea21c5cdc76a8581b06a4a39281 (diff)
[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 <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/ccid.h8
-rw-r--r--net/dccp/ccids/ccid3.c13
-rw-r--r--net/dccp/dccp.h5
-rw-r--r--net/dccp/output.c38
-rw-r--r--net/dccp/proto.c65
5 files changed, 57 insertions, 72 deletions
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index 06105b2a613c..469f9a14b463 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 04299c7565f3..df4adfeaafac 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 55b690ab61ae..8a0d7af649e4 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 4945eaa9d1a4..50292c0605fb 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 66c43fce17a6..877c1e0e3c48 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);