aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r--net/dccp/options.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 7743df00f5b1..dabd6ee34d45 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -427,6 +427,7 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
427{ 427{
428 struct dccp_sock *dp = dccp_sk(sk); 428 struct dccp_sock *dp = dccp_sk(sk);
429 struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; 429 struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
430 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
430 const u16 buflen = dccp_ackvec_buflen(av); 431 const u16 buflen = dccp_ackvec_buflen(av);
431 /* Figure out how many options do we need to represent the ackvec */ 432 /* Figure out how many options do we need to represent the ackvec */
432 const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN); 433 const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN);
@@ -435,10 +436,25 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
435 const unsigned char *tail, *from; 436 const unsigned char *tail, *from;
436 unsigned char *to; 437 unsigned char *to;
437 438
438 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) 439 if (dcb->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
440 DCCP_WARN("Lacking space for %u bytes on %s packet\n", len,
441 dccp_packet_name(dcb->dccpd_type));
439 return -1; 442 return -1;
440 443 }
441 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 444 /*
445 * Since Ack Vectors are variable-length, we can not always predict
446 * their size. To catch exception cases where the space is running out
447 * on the skb, a separate Sync is scheduled to carry the Ack Vector.
448 */
449 if (len > DCCPAV_MIN_OPTLEN &&
450 len + dcb->dccpd_opt_len + skb->len > dp->dccps_mss_cache) {
451 DCCP_WARN("No space left for Ack Vector (%u) on skb (%u+%u), "
452 "MPS=%u ==> reduce payload size?\n", len, skb->len,
453 dcb->dccpd_opt_len, dp->dccps_mss_cache);
454 dp->dccps_sync_scheduled = 1;
455 return 0;
456 }
457 dcb->dccpd_opt_len += len;
442 458
443 to = skb_push(skb, len); 459 to = skb_push(skb, len);
444 len = buflen; 460 len = buflen;
@@ -479,7 +495,7 @@ static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
479 /* 495 /*
480 * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340. 496 * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340.
481 */ 497 */
482 if (dccp_ackvec_update_records(av, DCCP_SKB_CB(skb)->dccpd_seq, nonce)) 498 if (dccp_ackvec_update_records(av, dcb->dccpd_seq, nonce))
483 return -ENOBUFS; 499 return -ENOBUFS;
484 return 0; 500 return 0;
485} 501}