/*
* Recalculate t_ipi and delta (should be called whenever X changes)
*/
-static inline void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hctx)
+static void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hctx)
{
/* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
hctx->ccid3hctx_t_ipi = scaled_div32(((u64)hctx->ccid3hctx_s) << 6,
*
*/
static void ccid3_hc_tx_update_x(struct sock *sk, ktime_t *stamp)
-
{
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
__u64 min_rate = 2 * hctx->ccid3hctx_x_recv;
const __u64 old_x = hctx->ccid3hctx_x;
- ktime_t now = stamp? *stamp : ktime_get_real();
+ ktime_t now = stamp ? *stamp : ktime_get_real();
/*
* Handle IDLE periods: do not reduce below RFC3390 initial sending rate
ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk,
ccid3_tx_state_name(hctx->ccid3hctx_state));
- switch (hctx->ccid3hctx_state) {
- case TFRC_SSTATE_NO_FBACK:
- /* RFC 3448, 4.4: Halve send rate directly */
+ if (hctx->ccid3hctx_state == TFRC_SSTATE_FBACK)
+ ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
+ else if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK)
+ goto out;
+
+ /*
+ * Determine new allowed sending rate X as per draft rfc3448bis-00, 4.4
+ */
+ if (hctx->ccid3hctx_t_rto == 0 || /* no feedback received yet */
+ hctx->ccid3hctx_p == 0) {
+
+ /* halve send rate directly */
hctx->ccid3hctx_x = max(hctx->ccid3hctx_x / 2,
(((__u64)hctx->ccid3hctx_s) << 6) /
TFRC_T_MBI);
-
- ccid3_pr_debug("%s(%p, state=%s), updated tx rate to %u "
- "bytes/s\n", dccp_role(sk), sk,
- ccid3_tx_state_name(hctx->ccid3hctx_state),
- (unsigned)(hctx->ccid3hctx_x >> 6));
- /* The value of R is still undefined and so we can not recompute
- * the timeout value. Keep initial value as per [RFC 4342, 5]. */
- t_nfb = TFRC_INITIAL_TIMEOUT;
ccid3_update_send_interval(hctx);
- break;
- case TFRC_SSTATE_FBACK:
+ } else {
/*
- * Modify the cached value of X_recv [RFC 3448, 4.4]
+ * Modify the cached value of X_recv
*
- * If (p == 0 || X_calc > 2 * X_recv)
+ * If (X_calc > 2 * X_recv)
* X_recv = max(X_recv / 2, s / (2 * t_mbi));
* Else
* X_recv = X_calc / 4;
*/
BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc);
- if (hctx->ccid3hctx_p == 0 ||
- (hctx->ccid3hctx_x_calc > (hctx->ccid3hctx_x_recv >> 5))) {
-
+ if (hctx->ccid3hctx_x_calc > (hctx->ccid3hctx_x_recv >> 5))
hctx->ccid3hctx_x_recv =
max(hctx->ccid3hctx_x_recv / 2,
(((__u64)hctx->ccid3hctx_s) << 6) /
(2 * TFRC_T_MBI));
- } else {
+ else {
hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc;
hctx->ccid3hctx_x_recv <<= 4;
}
- /* Now recalculate X [RFC 3448, 4.3, step (4)] */
ccid3_hc_tx_update_x(sk, NULL);
- /*
- * Schedule no feedback timer to expire in
- * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi)
- * See comments in packet_recv() regarding the value of t_RTO.
- */
- t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
- break;
- case TFRC_SSTATE_NO_SENT:
- DCCP_BUG("%s(%p) - Illegal state NO_SENT", dccp_role(sk), sk);
- /* fall through */
- case TFRC_SSTATE_TERM:
- goto out;
}
+ ccid3_pr_debug("Reduced X to %llu/64 bytes/sec\n",
+ (unsigned long long)hctx->ccid3hctx_x);
+
+ /*
+ * Set new timeout for the nofeedback timer.
+ * See comments in packet_recv() regarding the value of t_RTO.
+ */
+ if (unlikely(hctx->ccid3hctx_t_rto == 0)) /* no feedback yet */
+ t_nfb = TFRC_INITIAL_TIMEOUT;
+ else
+ t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
restart_timer:
sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
if (pinv == ~0U || pinv == 0) /* see RFC 4342, 8.5 */
hctx->ccid3hctx_p = 0;
else /* can not exceed 100% */
- hctx->ccid3hctx_p = 1000000 / pinv;
+ hctx->ccid3hctx_p = scaled_div(1, pinv);
/*
* Validate new RTT sample and update moving average
*/
r_sample = dccp_sample_rtt(sk, r_sample);
hctx->ccid3hctx_rtt = tfrc_ewma(hctx->ccid3hctx_rtt, r_sample, 9);
-
+ /*
+ * Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3
+ */
if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {
- /*
- * Larger Initial Windows [RFC 4342, sec. 5]
- */
- hctx->ccid3hctx_x = rfc3390_initial_rate(sk);
- hctx->ccid3hctx_t_ld = now;
+ ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
- ccid3_update_send_interval(hctx);
+ if (hctx->ccid3hctx_t_rto == 0) {
+ /*
+ * Initial feedback packet: Larger Initial Windows (4.2)
+ */
+ hctx->ccid3hctx_x = rfc3390_initial_rate(sk);
+ hctx->ccid3hctx_t_ld = now;
- ccid3_pr_debug("%s(%p), s=%u, MSS=%u, "
- "R_sample=%uus, X=%u\n", dccp_role(sk),
- sk, hctx->ccid3hctx_s,
- dccp_sk(sk)->dccps_mss_cache, r_sample,
- (unsigned)(hctx->ccid3hctx_x >> 6));
+ ccid3_update_send_interval(hctx);
- ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
- } else {
+ goto done_computing_x;
+ } else if (hctx->ccid3hctx_p == 0) {
+ /*
+ * First feedback after nofeedback timer expiry (4.3)
+ */
+ goto done_computing_x;
+ }
+ }
- /* Update sending rate (step 4 of [RFC 3448, 4.3]) */
- if (hctx->ccid3hctx_p > 0)
- hctx->ccid3hctx_x_calc =
+ /* Update sending rate (step 4 of [RFC 3448, 4.3]) */
+ if (hctx->ccid3hctx_p > 0)
+ hctx->ccid3hctx_x_calc =
tfrc_calc_x(hctx->ccid3hctx_s,
hctx->ccid3hctx_rtt,
hctx->ccid3hctx_p);
- ccid3_hc_tx_update_x(sk, &now);
+ ccid3_hc_tx_update_x(sk, &now);
- ccid3_pr_debug("%s(%p), RTT=%uus (sample=%uus), s=%u, "
+done_computing_x:
+ ccid3_pr_debug("%s(%p), RTT=%uus (sample=%uus), s=%u, "
"p=%u, X_calc=%u, X_recv=%u, X=%u\n",
dccp_role(sk),
sk, hctx->ccid3hctx_rtt, r_sample,
hctx->ccid3hctx_x_calc,
(unsigned)(hctx->ccid3hctx_x_recv >> 6),
(unsigned)(hctx->ccid3hctx_x >> 6));
- }
/* unschedule no feedback timer */
sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);