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

dccp tfrc/ccid-3: computing the loss rate from the Loss Event Rate

This adds a function to take care of the following, separate cases occurring in
the computation of the Loss Rate p:

* 1/(2^32-1) is mapped into 0% as per RFC 4342, 8.5;
* 1/0 is mapped into 100%, the maximum;
* to avoid that p = 1/x is rounded down to 0 when x is very large, since this
means accidentally re-entering slow-start indicated by p == 0, the minimum
resolution value of p is now returned instead;
* a bug in ccid3_hc_rx_getsockopt is fixed: 1/0 was mapped into ~0U.

Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>

+19 -5
+4 -5
net/dccp/ccids/ccid3.c
··· 400 400 401 401 /* Update loss event rate (which is scaled by 1e6) */ 402 402 pinv = opt_recv->ccid3or_loss_event_rate; 403 - if (pinv == ~0U || pinv == 0) /* see RFC 4342, 8.5 */ 403 + if (pinv == 0) 404 404 hc->tx_p = 0; 405 - else /* can not exceed 100% */ 406 - hc->tx_p = scaled_div(1, pinv); 405 + else 406 + hc->tx_p = tfrc_invert_loss_event_rate(pinv); 407 407 408 408 /* 409 409 * Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3 ··· 834 834 return -EINVAL; 835 835 rx_info.tfrcrx_x_recv = hc->rx_x_recv; 836 836 rx_info.tfrcrx_rtt = hc->rx_rtt; 837 - rx_info.tfrcrx_p = hc->rx_pinv == 0 ? ~0U : 838 - scaled_div(1, hc->rx_pinv); 837 + rx_info.tfrcrx_p = tfrc_invert_loss_event_rate(hc->rx_pinv); 839 838 len = sizeof(rx_info); 840 839 val = &rx_info; 841 840 break;
+1
net/dccp/ccids/lib/tfrc.h
··· 57 57 58 58 extern u32 tfrc_calc_x(u16 s, u32 R, u32 p); 59 59 extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue); 60 + extern u32 tfrc_invert_loss_event_rate(u32 loss_event_rate); 60 61 61 62 extern int tfrc_tx_packet_history_init(void); 62 63 extern void tfrc_tx_packet_history_exit(void);
+14
net/dccp/ccids/lib/tfrc_equation.c
··· 687 687 index = tfrc_binsearch(fvalue, 0); 688 688 return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE; 689 689 } 690 + 691 + /** 692 + * tfrc_invert_loss_event_rate - Compute p so that 10^6 corresponds to 100% 693 + * When @loss_event_rate is large, there is a chance that p is truncated to 0. 694 + * To avoid re-entering slow-start in that case, we set p = TFRC_SMALLEST_P > 0. 695 + */ 696 + u32 tfrc_invert_loss_event_rate(u32 loss_event_rate) 697 + { 698 + if (loss_event_rate == UINT_MAX) /* see RFC 4342, 8.5 */ 699 + return 0; 700 + if (unlikely(loss_event_rate == 0)) /* map 1/0 into 100% */ 701 + return 1000000; 702 + return max_t(u32, scaled_div(1, loss_event_rate), TFRC_SMALLEST_P); 703 + }