diff options
author | Arnaldo Carvalho de Melo <acme@mandriva.com> | 2005-08-09 23:30:56 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:55:18 -0400 |
commit | 27258ee54f8cd4a43d09319aa5448145afc2cb8d (patch) | |
tree | 4a52d16da47f7ab0777252169406ae85e53488b1 | |
parent | 0d48d93947dd9ea21c5cdc76a8581b06a4a39281 (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>
-rw-r--r-- | net/dccp/ccid.h | 8 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.c | 13 | ||||
-rw-r--r-- | net/dccp/dccp.h | 5 | ||||
-rw-r--r-- | net/dccp/output.c | 38 | ||||
-rw-r--r-- | net/dccp/proto.c | 65 |
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 { | |||
43 | unsigned char len, u16 idx, | 43 | unsigned char len, u16 idx, |
44 | unsigned char* value); | 44 | unsigned char* value); |
45 | int (*ccid_hc_tx_send_packet)(struct sock *sk, | 45 | int (*ccid_hc_tx_send_packet)(struct sock *sk, |
46 | struct sk_buff *skb, int len, | 46 | struct sk_buff *skb, int len); |
47 | long *delay); | ||
48 | void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more, int len); | 47 | void (*ccid_hc_tx_packet_sent)(struct sock *sk, int more, int len); |
49 | }; | 48 | }; |
50 | 49 | ||
@@ -60,12 +59,11 @@ static inline void __ccid_get(struct ccid *ccid) | |||
60 | } | 59 | } |
61 | 60 | ||
62 | static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk, | 61 | static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk, |
63 | struct sk_buff *skb, int len, | 62 | struct sk_buff *skb, int len) |
64 | long *delay) | ||
65 | { | 63 | { |
66 | int rc = 0; | 64 | int rc = 0; |
67 | if (ccid->ccid_hc_tx_send_packet != NULL) | 65 | if (ccid->ccid_hc_tx_send_packet != NULL) |
68 | rc = ccid->ccid_hc_tx_send_packet(sk, skb, len, delay); | 66 | rc = ccid->ccid_hc_tx_send_packet(sk, skb, len); |
69 | return rc; | 67 | return rc; |
70 | } | 68 | } |
71 | 69 | ||
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: | |||
977 | sock_put(sk); | 977 | sock_put(sk); |
978 | } | 978 | } |
979 | 979 | ||
980 | static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb, | 980 | static int ccid3_hc_tx_send_packet(struct sock *sk, |
981 | int len, long *delay) | 981 | struct sk_buff *skb, int len) |
982 | { | 982 | { |
983 | struct dccp_sock *dp = dccp_sk(sk); | 983 | struct dccp_sock *dp = dccp_sk(sk); |
984 | struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; | 984 | struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; |
985 | struct ccid3_tx_hist_entry *new_packet = NULL; | 985 | struct ccid3_tx_hist_entry *new_packet = NULL; |
986 | struct timeval now; | 986 | struct timeval now; |
987 | long delay; | ||
987 | int rc = -ENOTCONN; | 988 | int rc = -ENOTCONN; |
988 | 989 | ||
989 | // ccid3_pr_debug("%s, sk=%p, skb=%p, len=%d\n", dccp_role(sk), sk, skb, len); | 990 | // 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, | |||
1037 | break; | 1038 | break; |
1038 | case TFRC_SSTATE_NO_FBACK: | 1039 | case TFRC_SSTATE_NO_FBACK: |
1039 | case TFRC_SSTATE_FBACK: | 1040 | case TFRC_SSTATE_FBACK: |
1040 | *delay = (now_delta(hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta); | 1041 | delay = (now_delta(hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta); |
1041 | ccid3_pr_debug("send_packet delay=%ld\n",*delay); | 1042 | ccid3_pr_debug("send_packet delay=%ld\n", delay); |
1042 | *delay /= -1000; | 1043 | delay /= -1000; |
1043 | /* divide by -1000 is to convert to ms and get sign right */ | 1044 | /* divide by -1000 is to convert to ms and get sign right */ |
1044 | rc = *delay > 0 ? -EAGAIN : 0; | 1045 | rc = delay > 0 ? -EAGAIN : 0; |
1045 | break; | 1046 | break; |
1046 | default: | 1047 | default: |
1047 | printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", | 1048 | 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); | |||
122 | extern void dccp_send_delayed_ack(struct sock *sk); | 122 | extern void dccp_send_delayed_ack(struct sock *sk); |
123 | extern void dccp_send_sync(struct sock *sk, u64 seq); | 123 | extern void dccp_send_sync(struct sock *sk, u64 seq); |
124 | 124 | ||
125 | extern int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, | ||
126 | const int len); | ||
127 | |||
125 | extern void dccp_init_xmit_timers(struct sock *sk); | 128 | extern void dccp_init_xmit_timers(struct sock *sk); |
126 | static inline void dccp_clear_xmit_timers(struct sock *sk) | 129 | static inline void dccp_clear_xmit_timers(struct sock *sk) |
127 | { | 130 | { |
@@ -194,8 +197,6 @@ static inline void dccp_openreq_init(struct request_sock *req, | |||
194 | req->rcv_wnd = 0; | 197 | req->rcv_wnd = 0; |
195 | } | 198 | } |
196 | 199 | ||
197 | extern void dccp_v4_send_check(struct sock *sk, struct dccp_hdr *dh, int len, | ||
198 | struct sk_buff *skb); | ||
199 | extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb); | 200 | extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb); |
200 | 201 | ||
201 | extern struct sock *dccp_create_openreq_child(struct sock *sk, | 202 | 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) | |||
148 | return mss_now; | 148 | return mss_now; |
149 | } | 149 | } |
150 | 150 | ||
151 | int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, const int len) | ||
152 | { | ||
153 | const struct dccp_sock *dp = dccp_sk(sk); | ||
154 | int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, len); | ||
155 | |||
156 | if (err == 0) { | ||
157 | const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; | ||
158 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | ||
159 | |||
160 | if (sk->sk_state == DCCP_PARTOPEN) { | ||
161 | /* See 8.1.5. Handshake Completion */ | ||
162 | inet_csk_schedule_ack(sk); | ||
163 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, | ||
164 | inet_csk(sk)->icsk_rto, | ||
165 | DCCP_RTO_MAX); | ||
166 | dcb->dccpd_type = DCCP_PKT_DATAACK; | ||
167 | /* | ||
168 | * FIXME: we really should have a | ||
169 | * dccps_ack_pending or use icsk. | ||
170 | */ | ||
171 | } else if (inet_csk_ack_scheduled(sk) || | ||
172 | (dp->dccps_options.dccpo_send_ack_vector && | ||
173 | ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 && | ||
174 | ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)) | ||
175 | dcb->dccpd_type = DCCP_PKT_DATAACK; | ||
176 | else | ||
177 | dcb->dccpd_type = DCCP_PKT_DATA; | ||
178 | |||
179 | err = dccp_transmit_skb(sk, skb); | ||
180 | ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len); | ||
181 | } | ||
182 | |||
183 | return err; | ||
184 | } | ||
185 | |||
151 | int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | 186 | int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb) |
152 | { | 187 | { |
153 | if (inet_sk_rebuild_header(sk) != 0) | 188 | if (inet_sk_rebuild_header(sk) != 0) |
@@ -299,7 +334,8 @@ int dccp_connect(struct sock *sk) | |||
299 | DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS); | 334 | DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS); |
300 | 335 | ||
301 | /* Timer for repeating the REQUEST until an answer. */ | 336 | /* Timer for repeating the REQUEST until an answer. */ |
302 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); | 337 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, |
338 | icsk->icsk_rto, DCCP_RTO_MAX); | ||
303 | return 0; | 339 | return 0; |
304 | } | 340 | } |
305 | 341 | ||
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, | |||
182 | return -EMSGSIZE; | 182 | return -EMSGSIZE; |
183 | 183 | ||
184 | lock_sock(sk); | 184 | lock_sock(sk); |
185 | 185 | timeo = sock_sndtimeo(sk, noblock); | |
186 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); | ||
187 | 186 | ||
188 | /* | 187 | /* |
189 | * We have to use sk_stream_wait_connect here to set sk_write_pending, | 188 | * 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, | |||
192 | /* Wait for a connection to finish. */ | 191 | /* Wait for a connection to finish. */ |
193 | if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN | DCCPF_CLOSING)) | 192 | if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN | DCCPF_CLOSING)) |
194 | if ((rc = sk_stream_wait_connect(sk, &timeo)) != 0) | 193 | if ((rc = sk_stream_wait_connect(sk, &timeo)) != 0) |
195 | goto out_err; | 194 | goto out_release; |
196 | 195 | ||
197 | size = sk->sk_prot->max_header + len; | 196 | size = sk->sk_prot->max_header + len; |
198 | release_sock(sk); | 197 | release_sock(sk); |
199 | skb = sock_alloc_send_skb(sk, size, noblock, &rc); | 198 | skb = sock_alloc_send_skb(sk, size, noblock, &rc); |
200 | lock_sock(sk); | 199 | lock_sock(sk); |
201 | |||
202 | if (skb == NULL) | 200 | if (skb == NULL) |
203 | goto out_release; | 201 | goto out_release; |
204 | 202 | ||
205 | skb_reserve(skb, sk->sk_prot->max_header); | 203 | skb_reserve(skb, sk->sk_prot->max_header); |
206 | rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | 204 | rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); |
207 | if (rc == 0) { | 205 | if (rc != 0) |
208 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | 206 | goto out_discard; |
209 | const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; | ||
210 | long delay; | ||
211 | |||
212 | /* | ||
213 | * XXX: This is just to match the Waikato tree CA interaction | ||
214 | * points, after the CCID3 code is stable and I have a better | ||
215 | * understanding of behaviour I'll change this to look more like | ||
216 | * TCP. | ||
217 | */ | ||
218 | while (1) { | ||
219 | rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, | ||
220 | skb, len, &delay); | ||
221 | if (rc == 0) | ||
222 | break; | ||
223 | if (rc != -EAGAIN) | ||
224 | goto out_discard; | ||
225 | if (delay > timeo) | ||
226 | goto out_discard; | ||
227 | release_sock(sk); | ||
228 | delay = schedule_timeout(delay); | ||
229 | lock_sock(sk); | ||
230 | timeo -= delay; | ||
231 | if (signal_pending(current)) | ||
232 | goto out_interrupted; | ||
233 | rc = -EPIPE; | ||
234 | if (!(sk->sk_state == DCCP_PARTOPEN || sk->sk_state == DCCP_OPEN)) | ||
235 | goto out_discard; | ||
236 | } | ||
237 | 207 | ||
238 | if (sk->sk_state == DCCP_PARTOPEN) { | 208 | rc = dccp_write_xmit(sk, skb, len); |
239 | /* See 8.1.5. Handshake Completion */ | ||
240 | inet_csk_schedule_ack(sk); | ||
241 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, inet_csk(sk)->icsk_rto, TCP_RTO_MAX); | ||
242 | dcb->dccpd_type = DCCP_PKT_DATAACK; | ||
243 | /* FIXME: we really should have a dccps_ack_pending or use icsk */ | ||
244 | } else if (inet_csk_ack_scheduled(sk) || | ||
245 | (dp->dccps_options.dccpo_send_ack_vector && | ||
246 | ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 && | ||
247 | ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)) | ||
248 | dcb->dccpd_type = DCCP_PKT_DATAACK; | ||
249 | else | ||
250 | dcb->dccpd_type = DCCP_PKT_DATA; | ||
251 | dccp_transmit_skb(sk, skb); | ||
252 | ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len); | ||
253 | } else { | ||
254 | out_discard: | ||
255 | kfree_skb(skb); | ||
256 | } | ||
257 | out_release: | 209 | out_release: |
258 | release_sock(sk); | 210 | release_sock(sk); |
259 | return rc ? : len; | 211 | return rc ? : len; |
260 | out_err: | 212 | out_discard: |
261 | rc = sk_stream_error(sk, flags, rc); | 213 | kfree_skb(skb); |
262 | goto out_release; | 214 | goto out_release; |
263 | out_interrupted: | ||
264 | rc = sock_intr_errno(timeo); | ||
265 | goto out_discard; | ||
266 | } | 215 | } |
267 | 216 | ||
268 | EXPORT_SYMBOL(dccp_sendmsg); | 217 | EXPORT_SYMBOL(dccp_sendmsg); |