aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@mandriva.com>2005-08-09 23:30:56 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:55:18 -0400
commit27258ee54f8cd4a43d09319aa5448145afc2cb8d (patch)
tree4a52d16da47f7ab0777252169406ae85e53488b1
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>
-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 {
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
62static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk, 61static 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
980static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb, 980static 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);
122extern void dccp_send_delayed_ack(struct sock *sk); 122extern void dccp_send_delayed_ack(struct sock *sk);
123extern void dccp_send_sync(struct sock *sk, u64 seq); 123extern void dccp_send_sync(struct sock *sk, u64 seq);
124 124
125extern int dccp_write_xmit(struct sock *sk, struct sk_buff *skb,
126 const int len);
127
125extern void dccp_init_xmit_timers(struct sock *sk); 128extern void dccp_init_xmit_timers(struct sock *sk);
126static inline void dccp_clear_xmit_timers(struct sock *sk) 129static 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
197extern void dccp_v4_send_check(struct sock *sk, struct dccp_hdr *dh, int len,
198 struct sk_buff *skb);
199extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb); 200extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
200 201
201extern struct sock *dccp_create_openreq_child(struct sock *sk, 202extern 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
151int 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
151int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb) 186int 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 {
254out_discard:
255 kfree_skb(skb);
256 }
257out_release: 209out_release:
258 release_sock(sk); 210 release_sock(sk);
259 return rc ? : len; 211 return rc ? : len;
260out_err: 212out_discard:
261 rc = sk_stream_error(sk, flags, rc); 213 kfree_skb(skb);
262 goto out_release; 214 goto out_release;
263out_interrupted:
264 rc = sock_intr_errno(timeo);
265 goto out_discard;
266} 215}
267 216
268EXPORT_SYMBOL(dccp_sendmsg); 217EXPORT_SYMBOL(dccp_sendmsg);