aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/options.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2010-11-14 11:25:46 -0500
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2010-11-15 01:12:00 -0500
commitd83447f0944e73d690218d79c07762ffa4ceb9e4 (patch)
tree2a9adf943eee50d8c495ac9302692a277d862d92 /net/dccp/options.c
parent18219463c884bfdb7954d298b9edb5194b14d621 (diff)
dccp ccid-2: Schedule Sync as out-of-band mechanism
The problem with Ack Vectors is that i) their length is variable and can in principle grow quite large, ii) it is hard to predict exactly how large they will be. Due to the second point it seems not a good idea to reduce the MPS; in particular when on average there is enough room for the Ack Vector and an increase in length is momentarily due to some burst loss, after which the Ack Vector returns to its normal/average length. The solution taken by this patch is to subtract a minimum-expected Ack Vector length from the MPS, and to defer any larger Ack Vectors onto a separate Sync - but only if indeed there is no space left on the skb. This patch provides the infrastructure to schedule Sync-packets for transporting (urgent) out-of-band data. Its signalling is quicker than scheduling an Ack, since it does not need to wait for new application data. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
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}