diff options
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/options.c | 24 | ||||
-rw-r--r-- | net/dccp/output.c | 8 |
2 files changed, 28 insertions, 4 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c index b11d7b7167f0..791e07853a79 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -430,6 +430,7 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | |||
430 | { | 430 | { |
431 | struct dccp_sock *dp = dccp_sk(sk); | 431 | struct dccp_sock *dp = dccp_sk(sk); |
432 | struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; | 432 | struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; |
433 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | ||
433 | const u16 buflen = dccp_ackvec_buflen(av); | 434 | const u16 buflen = dccp_ackvec_buflen(av); |
434 | /* Figure out how many options do we need to represent the ackvec */ | 435 | /* Figure out how many options do we need to represent the ackvec */ |
435 | const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN); | 436 | const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN); |
@@ -438,10 +439,25 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | |||
438 | const unsigned char *tail, *from; | 439 | const unsigned char *tail, *from; |
439 | unsigned char *to; | 440 | unsigned char *to; |
440 | 441 | ||
441 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) | 442 | if (dcb->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { |
443 | DCCP_WARN("Lacking space for %u bytes on %s packet\n", len, | ||
444 | dccp_packet_name(dcb->dccpd_type)); | ||
442 | return -1; | 445 | return -1; |
443 | 446 | } | |
444 | DCCP_SKB_CB(skb)->dccpd_opt_len += len; | 447 | /* |
448 | * Since Ack Vectors are variable-length, we can not always predict | ||
449 | * their size. To catch exception cases where the space is running out | ||
450 | * on the skb, a separate Sync is scheduled to carry the Ack Vector. | ||
451 | */ | ||
452 | if (len > DCCPAV_MIN_OPTLEN && | ||
453 | len + dcb->dccpd_opt_len + skb->len > dp->dccps_mss_cache) { | ||
454 | DCCP_WARN("No space left for Ack Vector (%u) on skb (%u+%u), " | ||
455 | "MPS=%u ==> reduce payload size?\n", len, skb->len, | ||
456 | dcb->dccpd_opt_len, dp->dccps_mss_cache); | ||
457 | dp->dccps_sync_scheduled = 1; | ||
458 | return 0; | ||
459 | } | ||
460 | dcb->dccpd_opt_len += len; | ||
445 | 461 | ||
446 | to = skb_push(skb, len); | 462 | to = skb_push(skb, len); |
447 | len = buflen; | 463 | len = buflen; |
@@ -482,7 +498,7 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | |||
482 | /* | 498 | /* |
483 | * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340. | 499 | * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340. |
484 | */ | 500 | */ |
485 | if (dccp_ackvec_update_records(av, DCCP_SKB_CB(skb)->dccpd_seq, nonce)) | 501 | if (dccp_ackvec_update_records(av, dcb->dccpd_seq, nonce)) |
486 | return -ENOBUFS; | 502 | return -ENOBUFS; |
487 | return 0; | 503 | return 0; |
488 | } | 504 | } |
diff --git a/net/dccp/output.c b/net/dccp/output.c index 1b3168307586..bfda071559f4 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -305,6 +305,8 @@ void dccp_write_xmit(struct sock *sk, int block) | |||
305 | if (err) | 305 | if (err) |
306 | DCCP_BUG("err=%d after ccid_hc_tx_packet_sent", | 306 | DCCP_BUG("err=%d after ccid_hc_tx_packet_sent", |
307 | err); | 307 | err); |
308 | if (dp->dccps_sync_scheduled) | ||
309 | dccp_send_sync(sk, dp->dccps_gsr, DCCP_PKT_SYNC); | ||
308 | } else { | 310 | } else { |
309 | dccp_pr_debug("packet discarded due to err=%d\n", err); | 311 | dccp_pr_debug("packet discarded due to err=%d\n", err); |
310 | kfree_skb(skb); | 312 | kfree_skb(skb); |
@@ -591,6 +593,12 @@ void dccp_send_sync(struct sock *sk, const u64 ackno, | |||
591 | DCCP_SKB_CB(skb)->dccpd_type = pkt_type; | 593 | DCCP_SKB_CB(skb)->dccpd_type = pkt_type; |
592 | DCCP_SKB_CB(skb)->dccpd_ack_seq = ackno; | 594 | DCCP_SKB_CB(skb)->dccpd_ack_seq = ackno; |
593 | 595 | ||
596 | /* | ||
597 | * Clear the flag in case the Sync was scheduled for out-of-band data, | ||
598 | * such as carrying a long Ack Vector. | ||
599 | */ | ||
600 | dccp_sk(sk)->dccps_sync_scheduled = 0; | ||
601 | |||
594 | dccp_transmit_skb(sk, skb); | 602 | dccp_transmit_skb(sk, skb); |
595 | } | 603 | } |
596 | 604 | ||