[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>
This commit is contained in:
parent
0d48d93947
commit
27258ee54f
|
@ -43,8 +43,7 @@ struct ccid {
|
||||||
unsigned char len, u16 idx,
|
unsigned char len, u16 idx,
|
||||||
unsigned char* value);
|
unsigned char* value);
|
||||||
int (*ccid_hc_tx_send_packet)(struct sock *sk,
|
int (*ccid_hc_tx_send_packet)(struct sock *sk,
|
||||||
struct sk_buff *skb, int len,
|
struct sk_buff *skb, int len);
|
||||||
long *delay);
|
|
||||||
void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more, 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,
|
static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
|
||||||
struct sk_buff *skb, int len,
|
struct sk_buff *skb, int len)
|
||||||
long *delay)
|
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
if (ccid->ccid_hc_tx_send_packet != NULL)
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -977,13 +977,14 @@ out:
|
||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb,
|
static int ccid3_hc_tx_send_packet(struct sock *sk,
|
||||||
int len, long *delay)
|
struct sk_buff *skb, int len)
|
||||||
{
|
{
|
||||||
struct dccp_sock *dp = dccp_sk(sk);
|
struct dccp_sock *dp = dccp_sk(sk);
|
||||||
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
|
||||||
struct ccid3_tx_hist_entry *new_packet = NULL;
|
struct ccid3_tx_hist_entry *new_packet = NULL;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
long delay;
|
||||||
int rc = -ENOTCONN;
|
int rc = -ENOTCONN;
|
||||||
|
|
||||||
// ccid3_pr_debug("%s, sk=%p, skb=%p, len=%d\n", dccp_role(sk), sk, skb, len);
|
// 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;
|
break;
|
||||||
case TFRC_SSTATE_NO_FBACK:
|
case TFRC_SSTATE_NO_FBACK:
|
||||||
case TFRC_SSTATE_FBACK:
|
case TFRC_SSTATE_FBACK:
|
||||||
*delay = (now_delta(hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta);
|
delay = (now_delta(hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta);
|
||||||
ccid3_pr_debug("send_packet delay=%ld\n",*delay);
|
ccid3_pr_debug("send_packet delay=%ld\n", delay);
|
||||||
*delay /= -1000;
|
delay /= -1000;
|
||||||
/* divide by -1000 is to convert to ms and get sign right */
|
/* divide by -1000 is to convert to ms and get sign right */
|
||||||
rc = *delay > 0 ? -EAGAIN : 0;
|
rc = delay > 0 ? -EAGAIN : 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
|
printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
|
||||||
|
|
|
@ -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_delayed_ack(struct sock *sk);
|
||||||
extern void dccp_send_sync(struct sock *sk, u64 seq);
|
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);
|
extern void dccp_init_xmit_timers(struct sock *sk);
|
||||||
static inline void dccp_clear_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;
|
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 int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
|
||||||
|
|
||||||
extern struct sock *dccp_create_openreq_child(struct sock *sk,
|
extern struct sock *dccp_create_openreq_child(struct sock *sk,
|
||||||
|
|
|
@ -148,6 +148,41 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
|
||||||
return mss_now;
|
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)
|
int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
if (inet_sk_rebuild_header(sk) != 0)
|
if (inet_sk_rebuild_header(sk) != 0)
|
||||||
|
@ -299,7 +334,8 @@ int dccp_connect(struct sock *sk)
|
||||||
DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
|
DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
|
||||||
|
|
||||||
/* Timer for repeating the REQUEST until an answer. */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -182,8 +182,7 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
timeo = sock_sndtimeo(sk, noblock);
|
||||||
timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to use sk_stream_wait_connect here to set sk_write_pending,
|
* 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. */
|
/* Wait for a connection to finish. */
|
||||||
if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN | DCCPF_CLOSING))
|
if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN | DCCPF_CLOSING))
|
||||||
if ((rc = sk_stream_wait_connect(sk, &timeo)) != 0)
|
if ((rc = sk_stream_wait_connect(sk, &timeo)) != 0)
|
||||||
goto out_err;
|
goto out_release;
|
||||||
|
|
||||||
size = sk->sk_prot->max_header + len;
|
size = sk->sk_prot->max_header + len;
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
skb = sock_alloc_send_skb(sk, size, noblock, &rc);
|
skb = sock_alloc_send_skb(sk, size, noblock, &rc);
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
|
||||||
if (skb == NULL)
|
if (skb == NULL)
|
||||||
goto out_release;
|
goto out_release;
|
||||||
|
|
||||||
skb_reserve(skb, sk->sk_prot->max_header);
|
skb_reserve(skb, sk->sk_prot->max_header);
|
||||||
rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
|
rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
|
||||||
if (rc == 0) {
|
if (rc != 0)
|
||||||
struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
|
goto out_discard;
|
||||||
const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
|
|
||||||
long delay;
|
|
||||||
|
|
||||||
/*
|
rc = dccp_write_xmit(sk, skb, len);
|
||||||
* 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 (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);
|
|
||||||
}
|
|
||||||
out_release:
|
out_release:
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
return rc ? : len;
|
return rc ? : len;
|
||||||
out_err:
|
out_discard:
|
||||||
rc = sk_stream_error(sk, flags, rc);
|
kfree_skb(skb);
|
||||||
goto out_release;
|
goto out_release;
|
||||||
out_interrupted:
|
|
||||||
rc = sock_intr_errno(timeo);
|
|
||||||
goto out_discard;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(dccp_sendmsg);
|
EXPORT_SYMBOL(dccp_sendmsg);
|
||||||
|
|
Loading…
Reference in New Issue