aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:30:19 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:45:37 -0400
commitc2f42077bd06f300ae959204f3c007f820f5e769 (patch)
tree7e3d9c3c8b18f18b35a6ce19d84467ae8711521c
parent283fb4a5f39d1521d53e1044bff0ba2654acf145 (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 (previous patch), 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. It can thus serve other parts of the DCCP code as well. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
-rw-r--r--include/linux/dccp.h2
-rw-r--r--net/dccp/options.c24
-rw-r--r--net/dccp/output.c8
3 files changed, 30 insertions, 4 deletions
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 7187bd8a75f6..83197b601a4f 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -462,6 +462,7 @@ struct dccp_ackvec;
462 * @dccps_hc_rx_insert_options - receiver wants to add options when acking 462 * @dccps_hc_rx_insert_options - receiver wants to add options when acking
463 * @dccps_hc_tx_insert_options - sender wants to add options when sending 463 * @dccps_hc_tx_insert_options - sender wants to add options when sending
464 * @dccps_server_timewait - server holds timewait state on close (RFC 4340, 8.3) 464 * @dccps_server_timewait - server holds timewait state on close (RFC 4340, 8.3)
465 * @dccps_sync_scheduled - flag which signals "send out-of-band message soon"
465 * @dccps_xmit_timer - timer for when CCID is not ready to send 466 * @dccps_xmit_timer - timer for when CCID is not ready to send
466 * @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs) 467 * @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs)
467 */ 468 */
@@ -502,6 +503,7 @@ struct dccp_sock {
502 __u8 dccps_hc_rx_insert_options:1; 503 __u8 dccps_hc_rx_insert_options:1;
503 __u8 dccps_hc_tx_insert_options:1; 504 __u8 dccps_hc_tx_insert_options:1;
504 __u8 dccps_server_timewait:1; 505 __u8 dccps_server_timewait:1;
506 __u8 dccps_sync_scheduled:1;
505 struct timer_list dccps_xmit_timer; 507 struct timer_list dccps_xmit_timer;
506}; 508};
507 509
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