Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+37 -4
+2
include/linux/dccp.h
··· 462 462 * @dccps_hc_rx_insert_options - receiver wants to add options when acking 463 463 * @dccps_hc_tx_insert_options - sender wants to add options when sending 464 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 466 * @dccps_xmitlet - tasklet scheduled by the TX CCID to dequeue data packets 466 467 * @dccps_xmit_timer - used by the TX CCID to delay sending (rate-based pacing) 467 468 * @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs) ··· 504 503 __u8 dccps_hc_rx_insert_options:1; 505 504 __u8 dccps_hc_tx_insert_options:1; 506 505 __u8 dccps_server_timewait:1; 506 + __u8 dccps_sync_scheduled:1; 507 507 struct tasklet_struct dccps_xmitlet; 508 508 struct timer_list dccps_xmit_timer; 509 509 };
+20 -4
net/dccp/options.c
··· 427 427 { 428 428 struct dccp_sock *dp = dccp_sk(sk); 429 429 struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; 430 + struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); 430 431 const u16 buflen = dccp_ackvec_buflen(av); 431 432 /* Figure out how many options do we need to represent the ackvec */ 432 433 const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN); ··· 436 435 const unsigned char *tail, *from; 437 436 unsigned char *to; 438 437 439 - if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) 438 + if (dcb->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { 439 + DCCP_WARN("Lacking space for %u bytes on %s packet\n", len, 440 + dccp_packet_name(dcb->dccpd_type)); 440 441 return -1; 441 - 442 - DCCP_SKB_CB(skb)->dccpd_opt_len += len; 442 + } 443 + /* 444 + * Since Ack Vectors are variable-length, we can not always predict 445 + * their size. To catch exception cases where the space is running out 446 + * on the skb, a separate Sync is scheduled to carry the Ack Vector. 447 + */ 448 + if (len > DCCPAV_MIN_OPTLEN && 449 + len + dcb->dccpd_opt_len + skb->len > dp->dccps_mss_cache) { 450 + DCCP_WARN("No space left for Ack Vector (%u) on skb (%u+%u), " 451 + "MPS=%u ==> reduce payload size?\n", len, skb->len, 452 + dcb->dccpd_opt_len, dp->dccps_mss_cache); 453 + dp->dccps_sync_scheduled = 1; 454 + return 0; 455 + } 456 + dcb->dccpd_opt_len += len; 443 457 444 458 to = skb_push(skb, len); 445 459 len = buflen; ··· 495 479 /* 496 480 * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340. 497 481 */ 498 - if (dccp_ackvec_update_records(av, DCCP_SKB_CB(skb)->dccpd_seq, nonce)) 482 + if (dccp_ackvec_update_records(av, dcb->dccpd_seq, nonce)) 499 483 return -ENOBUFS; 500 484 return 0; 501 485 }
+15
net/dccp/output.c
··· 283 283 * any local drop will eventually be reported via receiver feedback. 284 284 */ 285 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); 286 295 } 287 296 288 297 /** ··· 644 635 skb_reserve(skb, sk->sk_prot->max_header); 645 636 DCCP_SKB_CB(skb)->dccpd_type = pkt_type; 646 637 DCCP_SKB_CB(skb)->dccpd_ack_seq = ackno; 638 + 639 + /* 640 + * Clear the flag in case the Sync was scheduled for out-of-band data, 641 + * such as carrying a long Ack Vector. 642 + */ 643 + dccp_sk(sk)->dccps_sync_scheduled = 0; 647 644 648 645 dccp_transmit_skb(sk, skb); 649 646 }