diff options
Diffstat (limited to 'net/dccp/output.c')
-rw-r--r-- | net/dccp/output.c | 209 |
1 files changed, 125 insertions, 84 deletions
diff --git a/net/dccp/output.c b/net/dccp/output.c index a988fe9ffcba..45b91853f5ae 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -209,108 +209,150 @@ void dccp_write_space(struct sock *sk) | |||
209 | } | 209 | } |
210 | 210 | ||
211 | /** | 211 | /** |
212 | * dccp_wait_for_ccid - Wait for ccid to tell us we can send a packet | 212 | * dccp_wait_for_ccid - Await CCID send permission |
213 | * @sk: socket to wait for | 213 | * @sk: socket to wait for |
214 | * @skb: current skb to pass on for waiting | 214 | * @delay: timeout in jiffies |
215 | * @delay: sleep timeout in milliseconds (> 0) | 215 | * This is used by CCIDs which need to delay the send time in process context. |
216 | * This function is called by default when the socket is closed, and | ||
217 | * when a non-zero linger time is set on the socket. For consistency | ||
218 | */ | 216 | */ |
219 | static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, int delay) | 217 | static int dccp_wait_for_ccid(struct sock *sk, unsigned long delay) |
220 | { | 218 | { |
221 | struct dccp_sock *dp = dccp_sk(sk); | ||
222 | DEFINE_WAIT(wait); | 219 | DEFINE_WAIT(wait); |
223 | unsigned long jiffdelay; | 220 | long remaining; |
224 | int rc; | 221 | |
222 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
223 | sk->sk_write_pending++; | ||
224 | release_sock(sk); | ||
225 | |||
226 | remaining = schedule_timeout(delay); | ||
227 | |||
228 | lock_sock(sk); | ||
229 | sk->sk_write_pending--; | ||
230 | finish_wait(sk_sleep(sk), &wait); | ||
231 | |||
232 | if (signal_pending(current) || sk->sk_err) | ||
233 | return -1; | ||
234 | return remaining; | ||
235 | } | ||
236 | |||
237 | /** | ||
238 | * dccp_xmit_packet - Send data packet under control of CCID | ||
239 | * Transmits next-queued payload and informs CCID to account for the packet. | ||
240 | */ | ||
241 | static void dccp_xmit_packet(struct sock *sk) | ||
242 | { | ||
243 | int err, len; | ||
244 | struct dccp_sock *dp = dccp_sk(sk); | ||
245 | struct sk_buff *skb = skb_dequeue(&sk->sk_write_queue); | ||
225 | 246 | ||
226 | do { | 247 | if (unlikely(skb == NULL)) |
227 | dccp_pr_debug("delayed send by %d msec\n", delay); | 248 | return; |
228 | jiffdelay = msecs_to_jiffies(delay); | 249 | len = skb->len; |
229 | 250 | ||
230 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 251 | if (sk->sk_state == DCCP_PARTOPEN) { |
252 | const u32 cur_mps = dp->dccps_mss_cache - DCCP_FEATNEG_OVERHEAD; | ||
253 | /* | ||
254 | * See 8.1.5 - Handshake Completion. | ||
255 | * | ||
256 | * For robustness we resend Confirm options until the client has | ||
257 | * entered OPEN. During the initial feature negotiation, the MPS | ||
258 | * is smaller than usual, reduced by the Change/Confirm options. | ||
259 | */ | ||
260 | if (!list_empty(&dp->dccps_featneg) && len > cur_mps) { | ||
261 | DCCP_WARN("Payload too large (%d) for featneg.\n", len); | ||
262 | dccp_send_ack(sk); | ||
263 | dccp_feat_list_purge(&dp->dccps_featneg); | ||
264 | } | ||
231 | 265 | ||
232 | sk->sk_write_pending++; | 266 | inet_csk_schedule_ack(sk); |
233 | release_sock(sk); | 267 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, |
234 | schedule_timeout(jiffdelay); | 268 | inet_csk(sk)->icsk_rto, |
235 | lock_sock(sk); | 269 | DCCP_RTO_MAX); |
236 | sk->sk_write_pending--; | 270 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_DATAACK; |
271 | } else if (dccp_ack_pending(sk)) { | ||
272 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_DATAACK; | ||
273 | } else { | ||
274 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_DATA; | ||
275 | } | ||
276 | |||
277 | err = dccp_transmit_skb(sk, skb); | ||
278 | if (err) | ||
279 | dccp_pr_debug("transmit_skb() returned err=%d\n", err); | ||
280 | /* | ||
281 | * Register this one as sent even if an error occurred. To the remote | ||
282 | * end a local packet drop is indistinguishable from network loss, i.e. | ||
283 | * any local drop will eventually be reported via receiver feedback. | ||
284 | */ | ||
285 | ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, len); | ||
286 | } | ||
237 | 287 | ||
238 | if (sk->sk_err) | 288 | /** |
239 | goto do_error; | 289 | * dccp_flush_write_queue - Drain queue at end of connection |
240 | if (signal_pending(current)) | 290 | * Since dccp_sendmsg queues packets without waiting for them to be sent, it may |
241 | goto do_interrupted; | 291 | * happen that the TX queue is not empty at the end of a connection. We give the |
292 | * HC-sender CCID a grace period of up to @time_budget jiffies. If this function | ||
293 | * returns with a non-empty write queue, it will be purged later. | ||
294 | */ | ||
295 | void dccp_flush_write_queue(struct sock *sk, long *time_budget) | ||
296 | { | ||
297 | struct dccp_sock *dp = dccp_sk(sk); | ||
298 | struct sk_buff *skb; | ||
299 | long delay, rc; | ||
242 | 300 | ||
301 | while (*time_budget > 0 && (skb = skb_peek(&sk->sk_write_queue))) { | ||
243 | rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); | 302 | rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); |
244 | } while ((delay = rc) > 0); | 303 | |
245 | out: | 304 | switch (ccid_packet_dequeue_eval(rc)) { |
246 | finish_wait(sk_sleep(sk), &wait); | 305 | case CCID_PACKET_WILL_DEQUEUE_LATER: |
247 | return rc; | 306 | /* |
248 | 307 | * If the CCID determines when to send, the next sending | |
249 | do_error: | 308 | * time is unknown or the CCID may not even send again |
250 | rc = -EPIPE; | 309 | * (e.g. remote host crashes or lost Ack packets). |
251 | goto out; | 310 | */ |
252 | do_interrupted: | 311 | DCCP_WARN("CCID did not manage to send all packets\n"); |
253 | rc = -EINTR; | 312 | return; |
254 | goto out; | 313 | case CCID_PACKET_DELAY: |
314 | delay = msecs_to_jiffies(rc); | ||
315 | if (delay > *time_budget) | ||
316 | return; | ||
317 | rc = dccp_wait_for_ccid(sk, delay); | ||
318 | if (rc < 0) | ||
319 | return; | ||
320 | *time_budget -= (delay - rc); | ||
321 | /* check again if we can send now */ | ||
322 | break; | ||
323 | case CCID_PACKET_SEND_AT_ONCE: | ||
324 | dccp_xmit_packet(sk); | ||
325 | break; | ||
326 | case CCID_PACKET_ERR: | ||
327 | skb_dequeue(&sk->sk_write_queue); | ||
328 | kfree_skb(skb); | ||
329 | dccp_pr_debug("packet discarded due to err=%ld\n", rc); | ||
330 | } | ||
331 | } | ||
255 | } | 332 | } |
256 | 333 | ||
257 | void dccp_write_xmit(struct sock *sk, int block) | 334 | void dccp_write_xmit(struct sock *sk) |
258 | { | 335 | { |
259 | struct dccp_sock *dp = dccp_sk(sk); | 336 | struct dccp_sock *dp = dccp_sk(sk); |
260 | struct sk_buff *skb; | 337 | struct sk_buff *skb; |
261 | 338 | ||
262 | while ((skb = skb_peek(&sk->sk_write_queue))) { | 339 | while ((skb = skb_peek(&sk->sk_write_queue))) { |
263 | int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); | 340 | int rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); |
264 | |||
265 | if (err > 0) { | ||
266 | if (!block) { | ||
267 | sk_reset_timer(sk, &dp->dccps_xmit_timer, | ||
268 | msecs_to_jiffies(err)+jiffies); | ||
269 | break; | ||
270 | } else | ||
271 | err = dccp_wait_for_ccid(sk, skb, err); | ||
272 | if (err && err != -EINTR) | ||
273 | DCCP_BUG("err=%d after dccp_wait_for_ccid", err); | ||
274 | } | ||
275 | 341 | ||
276 | skb_dequeue(&sk->sk_write_queue); | 342 | switch (ccid_packet_dequeue_eval(rc)) { |
277 | if (err == 0) { | 343 | case CCID_PACKET_WILL_DEQUEUE_LATER: |
278 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | 344 | return; |
279 | const int len = skb->len; | 345 | case CCID_PACKET_DELAY: |
280 | 346 | sk_reset_timer(sk, &dp->dccps_xmit_timer, | |
281 | if (sk->sk_state == DCCP_PARTOPEN) { | 347 | jiffies + msecs_to_jiffies(rc)); |
282 | const u32 cur_mps = dp->dccps_mss_cache - DCCP_FEATNEG_OVERHEAD; | 348 | return; |
283 | /* | 349 | case CCID_PACKET_SEND_AT_ONCE: |
284 | * See 8.1.5 - Handshake Completion. | 350 | dccp_xmit_packet(sk); |
285 | * | 351 | break; |
286 | * For robustness we resend Confirm options until the client has | 352 | case CCID_PACKET_ERR: |
287 | * entered OPEN. During the initial feature negotiation, the MPS | 353 | skb_dequeue(&sk->sk_write_queue); |
288 | * is smaller than usual, reduced by the Change/Confirm options. | ||
289 | */ | ||
290 | if (!list_empty(&dp->dccps_featneg) && len > cur_mps) { | ||
291 | DCCP_WARN("Payload too large (%d) for featneg.\n", len); | ||
292 | dccp_send_ack(sk); | ||
293 | dccp_feat_list_purge(&dp->dccps_featneg); | ||
294 | } | ||
295 | |||
296 | inet_csk_schedule_ack(sk); | ||
297 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, | ||
298 | inet_csk(sk)->icsk_rto, | ||
299 | DCCP_RTO_MAX); | ||
300 | dcb->dccpd_type = DCCP_PKT_DATAACK; | ||
301 | } else if (dccp_ack_pending(sk)) | ||
302 | dcb->dccpd_type = DCCP_PKT_DATAACK; | ||
303 | else | ||
304 | dcb->dccpd_type = DCCP_PKT_DATA; | ||
305 | |||
306 | err = dccp_transmit_skb(sk, skb); | ||
307 | ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, len); | ||
308 | if (err) | ||
309 | DCCP_BUG("err=%d after ccid_hc_tx_packet_sent", | ||
310 | err); | ||
311 | } else { | ||
312 | dccp_pr_debug("packet discarded due to err=%d\n", err); | ||
313 | kfree_skb(skb); | 354 | kfree_skb(skb); |
355 | dccp_pr_debug("packet discarded due to err=%d\n", rc); | ||
314 | } | 356 | } |
315 | } | 357 | } |
316 | } | 358 | } |
@@ -622,7 +664,6 @@ void dccp_send_close(struct sock *sk, const int active) | |||
622 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE; | 664 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE; |
623 | 665 | ||
624 | if (active) { | 666 | if (active) { |
625 | dccp_write_xmit(sk, 1); | ||
626 | dccp_skb_entail(sk, skb); | 667 | dccp_skb_entail(sk, skb); |
627 | dccp_transmit_skb(sk, skb_clone(skb, prio)); | 668 | dccp_transmit_skb(sk, skb_clone(skb, prio)); |
628 | /* | 669 | /* |