diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/dccp/output.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'net/dccp/output.c')
-rw-r--r-- | net/dccp/output.c | 251 |
1 files changed, 149 insertions, 102 deletions
diff --git a/net/dccp/output.c b/net/dccp/output.c index aadbdb58758b..fab108e51e5a 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -43,7 +43,7 @@ static void dccp_skb_entail(struct sock *sk, struct sk_buff *skb) | |||
43 | static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | 43 | static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) |
44 | { | 44 | { |
45 | if (likely(skb != NULL)) { | 45 | if (likely(skb != NULL)) { |
46 | const struct inet_sock *inet = inet_sk(sk); | 46 | struct inet_sock *inet = inet_sk(sk); |
47 | const struct inet_connection_sock *icsk = inet_csk(sk); | 47 | const struct inet_connection_sock *icsk = inet_csk(sk); |
48 | struct dccp_sock *dp = dccp_sk(sk); | 48 | struct dccp_sock *dp = dccp_sk(sk); |
49 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | 49 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); |
@@ -136,14 +136,14 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | |||
136 | 136 | ||
137 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); | 137 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); |
138 | 138 | ||
139 | err = icsk->icsk_af_ops->queue_xmit(skb); | 139 | err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl); |
140 | return net_xmit_eval(err); | 140 | return net_xmit_eval(err); |
141 | } | 141 | } |
142 | return -ENOBUFS; | 142 | return -ENOBUFS; |
143 | } | 143 | } |
144 | 144 | ||
145 | /** | 145 | /** |
146 | * dccp_determine_ccmps - Find out about CCID-specfic packet-size limits | 146 | * dccp_determine_ccmps - Find out about CCID-specific packet-size limits |
147 | * We only consider the HC-sender CCID for setting the CCMPS (RFC 4340, 14.), | 147 | * We only consider the HC-sender CCID for setting the CCMPS (RFC 4340, 14.), |
148 | * since the RX CCID is restricted to feedback packets (Acks), which are small | 148 | * since the RX CCID is restricted to feedback packets (Acks), which are small |
149 | * in comparison with the data traffic. A value of 0 means "no current CCMPS". | 149 | * in comparison with the data traffic. A value of 0 means "no current CCMPS". |
@@ -209,108 +209,158 @@ 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; | ||
225 | 221 | ||
226 | do { | 222 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
227 | dccp_pr_debug("delayed send by %d msec\n", delay); | 223 | sk->sk_write_pending++; |
228 | jiffdelay = msecs_to_jiffies(delay); | 224 | release_sock(sk); |
229 | 225 | ||
230 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 226 | remaining = schedule_timeout(delay); |
231 | 227 | ||
232 | sk->sk_write_pending++; | 228 | lock_sock(sk); |
233 | release_sock(sk); | 229 | sk->sk_write_pending--; |
234 | schedule_timeout(jiffdelay); | 230 | finish_wait(sk_sleep(sk), &wait); |
235 | lock_sock(sk); | ||
236 | sk->sk_write_pending--; | ||
237 | 231 | ||
238 | if (sk->sk_err) | 232 | if (signal_pending(current) || sk->sk_err) |
239 | goto do_error; | 233 | return -1; |
240 | if (signal_pending(current)) | 234 | return remaining; |
241 | goto do_interrupted; | 235 | } |
242 | 236 | ||
243 | rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); | 237 | /** |
244 | } while ((delay = rc) > 0); | 238 | * dccp_xmit_packet - Send data packet under control of CCID |
245 | out: | 239 | * Transmits next-queued payload and informs CCID to account for the packet. |
246 | finish_wait(sk_sleep(sk), &wait); | 240 | */ |
247 | return rc; | 241 | static void dccp_xmit_packet(struct sock *sk) |
248 | 242 | { | |
249 | do_error: | 243 | int err, len; |
250 | rc = -EPIPE; | 244 | struct dccp_sock *dp = dccp_sk(sk); |
251 | goto out; | 245 | struct sk_buff *skb = dccp_qpolicy_pop(sk); |
252 | do_interrupted: | 246 | |
253 | rc = -EINTR; | 247 | if (unlikely(skb == NULL)) |
254 | goto out; | 248 | return; |
249 | len = skb->len; | ||
250 | |||
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 | } | ||
265 | |||
266 | inet_csk_schedule_ack(sk); | ||
267 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, | ||
268 | inet_csk(sk)->icsk_rto, | ||
269 | DCCP_RTO_MAX); | ||
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 | |||
287 | /* | ||
288 | * If the CCID needs to transfer additional header options out-of-band | ||
289 | * (e.g. Ack Vectors or feature-negotiation options), it activates this | ||
290 | * flag to schedule a Sync. The Sync will automatically incorporate all | ||
291 | * currently pending header options, thus clearing the backlog. | ||
292 | */ | ||
293 | if (dp->dccps_sync_scheduled) | ||
294 | dccp_send_sync(sk, dp->dccps_gsr, DCCP_PKT_SYNC); | ||
255 | } | 295 | } |
256 | 296 | ||
257 | void dccp_write_xmit(struct sock *sk, int block) | 297 | /** |
298 | * dccp_flush_write_queue - Drain queue at end of connection | ||
299 | * Since dccp_sendmsg queues packets without waiting for them to be sent, it may | ||
300 | * happen that the TX queue is not empty at the end of a connection. We give the | ||
301 | * HC-sender CCID a grace period of up to @time_budget jiffies. If this function | ||
302 | * returns with a non-empty write queue, it will be purged later. | ||
303 | */ | ||
304 | void dccp_flush_write_queue(struct sock *sk, long *time_budget) | ||
258 | { | 305 | { |
259 | struct dccp_sock *dp = dccp_sk(sk); | 306 | struct dccp_sock *dp = dccp_sk(sk); |
260 | struct sk_buff *skb; | 307 | struct sk_buff *skb; |
308 | long delay, rc; | ||
261 | 309 | ||
262 | while ((skb = skb_peek(&sk->sk_write_queue))) { | 310 | while (*time_budget > 0 && (skb = skb_peek(&sk->sk_write_queue))) { |
263 | int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); | 311 | 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 | 312 | ||
276 | skb_dequeue(&sk->sk_write_queue); | 313 | switch (ccid_packet_dequeue_eval(rc)) { |
277 | if (err == 0) { | 314 | case CCID_PACKET_WILL_DEQUEUE_LATER: |
278 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | 315 | /* |
279 | const int len = skb->len; | 316 | * If the CCID determines when to send, the next sending |
280 | 317 | * time is unknown or the CCID may not even send again | |
281 | if (sk->sk_state == DCCP_PARTOPEN) { | 318 | * (e.g. remote host crashes or lost Ack packets). |
282 | const u32 cur_mps = dp->dccps_mss_cache - DCCP_FEATNEG_OVERHEAD; | 319 | */ |
283 | /* | 320 | DCCP_WARN("CCID did not manage to send all packets\n"); |
284 | * See 8.1.5 - Handshake Completion. | 321 | return; |
285 | * | 322 | case CCID_PACKET_DELAY: |
286 | * For robustness we resend Confirm options until the client has | 323 | delay = msecs_to_jiffies(rc); |
287 | * entered OPEN. During the initial feature negotiation, the MPS | 324 | if (delay > *time_budget) |
288 | * is smaller than usual, reduced by the Change/Confirm options. | 325 | return; |
289 | */ | 326 | rc = dccp_wait_for_ccid(sk, delay); |
290 | if (!list_empty(&dp->dccps_featneg) && len > cur_mps) { | 327 | if (rc < 0) |
291 | DCCP_WARN("Payload too large (%d) for featneg.\n", len); | 328 | return; |
292 | dccp_send_ack(sk); | 329 | *time_budget -= (delay - rc); |
293 | dccp_feat_list_purge(&dp->dccps_featneg); | 330 | /* check again if we can send now */ |
294 | } | 331 | break; |
295 | 332 | case CCID_PACKET_SEND_AT_ONCE: | |
296 | inet_csk_schedule_ack(sk); | 333 | dccp_xmit_packet(sk); |
297 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, | 334 | break; |
298 | inet_csk(sk)->icsk_rto, | 335 | case CCID_PACKET_ERR: |
299 | DCCP_RTO_MAX); | 336 | skb_dequeue(&sk->sk_write_queue); |
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, 0, 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); | 337 | kfree_skb(skb); |
338 | dccp_pr_debug("packet discarded due to err=%ld\n", rc); | ||
339 | } | ||
340 | } | ||
341 | } | ||
342 | |||
343 | void dccp_write_xmit(struct sock *sk) | ||
344 | { | ||
345 | struct dccp_sock *dp = dccp_sk(sk); | ||
346 | struct sk_buff *skb; | ||
347 | |||
348 | while ((skb = dccp_qpolicy_top(sk))) { | ||
349 | int rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); | ||
350 | |||
351 | switch (ccid_packet_dequeue_eval(rc)) { | ||
352 | case CCID_PACKET_WILL_DEQUEUE_LATER: | ||
353 | return; | ||
354 | case CCID_PACKET_DELAY: | ||
355 | sk_reset_timer(sk, &dp->dccps_xmit_timer, | ||
356 | jiffies + msecs_to_jiffies(rc)); | ||
357 | return; | ||
358 | case CCID_PACKET_SEND_AT_ONCE: | ||
359 | dccp_xmit_packet(sk); | ||
360 | break; | ||
361 | case CCID_PACKET_ERR: | ||
362 | dccp_qpolicy_drop(sk, skb); | ||
363 | dccp_pr_debug("packet discarded due to err=%d\n", rc); | ||
314 | } | 364 | } |
315 | } | 365 | } |
316 | } | 366 | } |
@@ -474,8 +524,9 @@ int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code) | |||
474 | /* | 524 | /* |
475 | * Do all connect socket setups that can be done AF independent. | 525 | * Do all connect socket setups that can be done AF independent. |
476 | */ | 526 | */ |
477 | static inline void dccp_connect_init(struct sock *sk) | 527 | int dccp_connect(struct sock *sk) |
478 | { | 528 | { |
529 | struct sk_buff *skb; | ||
479 | struct dccp_sock *dp = dccp_sk(sk); | 530 | struct dccp_sock *dp = dccp_sk(sk); |
480 | struct dst_entry *dst = __sk_dst_get(sk); | 531 | struct dst_entry *dst = __sk_dst_get(sk); |
481 | struct inet_connection_sock *icsk = inet_csk(sk); | 532 | struct inet_connection_sock *icsk = inet_csk(sk); |
@@ -485,22 +536,12 @@ static inline void dccp_connect_init(struct sock *sk) | |||
485 | 536 | ||
486 | dccp_sync_mss(sk, dst_mtu(dst)); | 537 | dccp_sync_mss(sk, dst_mtu(dst)); |
487 | 538 | ||
488 | /* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */ | ||
489 | dp->dccps_gar = dp->dccps_iss; | ||
490 | |||
491 | icsk->icsk_retransmits = 0; | ||
492 | } | ||
493 | |||
494 | int dccp_connect(struct sock *sk) | ||
495 | { | ||
496 | struct sk_buff *skb; | ||
497 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
498 | |||
499 | /* do not connect if feature negotiation setup fails */ | 539 | /* do not connect if feature negotiation setup fails */ |
500 | if (dccp_feat_finalise_settings(dccp_sk(sk))) | 540 | if (dccp_feat_finalise_settings(dccp_sk(sk))) |
501 | return -EPROTO; | 541 | return -EPROTO; |
502 | 542 | ||
503 | dccp_connect_init(sk); | 543 | /* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */ |
544 | dp->dccps_gar = dp->dccps_iss; | ||
504 | 545 | ||
505 | skb = alloc_skb(sk->sk_prot->max_header, sk->sk_allocation); | 546 | skb = alloc_skb(sk->sk_prot->max_header, sk->sk_allocation); |
506 | if (unlikely(skb == NULL)) | 547 | if (unlikely(skb == NULL)) |
@@ -516,6 +557,7 @@ int dccp_connect(struct sock *sk) | |||
516 | DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS); | 557 | DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS); |
517 | 558 | ||
518 | /* Timer for repeating the REQUEST until an answer. */ | 559 | /* Timer for repeating the REQUEST until an answer. */ |
560 | icsk->icsk_retransmits = 0; | ||
519 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | 561 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, |
520 | icsk->icsk_rto, DCCP_RTO_MAX); | 562 | icsk->icsk_rto, DCCP_RTO_MAX); |
521 | return 0; | 563 | return 0; |
@@ -602,6 +644,12 @@ void dccp_send_sync(struct sock *sk, const u64 ackno, | |||
602 | DCCP_SKB_CB(skb)->dccpd_type = pkt_type; | 644 | DCCP_SKB_CB(skb)->dccpd_type = pkt_type; |
603 | DCCP_SKB_CB(skb)->dccpd_ack_seq = ackno; | 645 | DCCP_SKB_CB(skb)->dccpd_ack_seq = ackno; |
604 | 646 | ||
647 | /* | ||
648 | * Clear the flag in case the Sync was scheduled for out-of-band data, | ||
649 | * such as carrying a long Ack Vector. | ||
650 | */ | ||
651 | dccp_sk(sk)->dccps_sync_scheduled = 0; | ||
652 | |||
605 | dccp_transmit_skb(sk, skb); | 653 | dccp_transmit_skb(sk, skb); |
606 | } | 654 | } |
607 | 655 | ||
@@ -630,7 +678,6 @@ void dccp_send_close(struct sock *sk, const int active) | |||
630 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE; | 678 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE; |
631 | 679 | ||
632 | if (active) { | 680 | if (active) { |
633 | dccp_write_xmit(sk, 1); | ||
634 | dccp_skb_entail(sk, skb); | 681 | dccp_skb_entail(sk, skb); |
635 | dccp_transmit_skb(sk, skb_clone(skb, prio)); | 682 | dccp_transmit_skb(sk, skb_clone(skb, prio)); |
636 | /* | 683 | /* |