dccp ccid-3: Preventing Oscillations
[deliverable/linux.git] / net / dccp / ccids / ccid3.c
index 7cd76c6c790c1cb53b36d81a2480e4e910ad4174..06cfdad84a6a5518098259e3a450cf0498bf8ca0 100644 (file)
@@ -49,6 +49,8 @@ static int ccid3_debug;
 /*
  *     Transmitter Half-Connection Routines
  */
+/* Oscillation Prevention/Reduction: recommended by rfc3448bis, on by default */
+static int do_osc_prev = true;
 
 /*
  * Compute the initial sending rate X_init in the manner of RFC 3390:
@@ -296,6 +298,9 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
                hctx->s = ccid3_hc_tx_measure_packet_size(sk, skb->len);
                ccid3_update_send_interval(hctx);
 
+               /* Seed value for Oscillation Prevention (sec. 4.5) */
+               hctx->r_sqmean = tfrc_scaled_sqrt(hctx->rtt);
+
        } else {
                delay = ktime_us_delta(hctx->t_nom, now);
                ccid3_pr_debug("delay=%ld\n", (long)delay);
@@ -400,6 +405,38 @@ done_computing_x:
                               hctx->s, hctx->p, hctx->x_calc,
                               (unsigned)(hctx->x_recv >> 6),
                               (unsigned)(hctx->x >> 6));
+       /*
+        * Oscillation Reduction (RFC 3448, 4.5) - modifying t_ipi according to
+        * RTT changes, multiplying by X/X_inst = sqrt(R_sample)/R_sqmean. This
+        * can be useful if few connections share a link, avoiding that buffer
+        * fill levels (RTT) oscillate as a result of frequent adjustments to X.
+        * A useful presentation with background information is in
+        *    Joerg Widmer, "Equation-Based Congestion Control",
+        *    MSc Thesis, University of Mannheim, Germany, 2000
+        * (sec. 3.6.4), who calls this ISM ("Inter-packet Space Modulation").
+        */
+       if (do_osc_prev) {
+               r_sample = tfrc_scaled_sqrt(r_sample);
+               /*
+                * The modulation can work in both ways: increase/decrease t_ipi
+                * according to long-term increases/decreases of the RTT. The
+                * former is a useful measure, since it works against queue
+                * build-up. The latter temporarily increases the sending rate,
+                * so that buffers fill up more quickly. This in turn causes
+                * the RTT to increase, so that either later reduction becomes
+                * necessary or the RTT stays at a very high level. Decreasing
+                * t_ipi is therefore not supported.
+                * Furthermore, during the initial slow-start phase the RTT
+                * naturally increases, where using the algorithm would cause
+                * delays. Hence it is disabled during the initial slow-start.
+                */
+               if (r_sample > hctx->r_sqmean && hctx->p > 0)
+                       hctx->t_ipi = div_u64((u64)hctx->t_ipi * (u64)r_sample,
+                                             hctx->r_sqmean);
+               hctx->t_ipi = min_t(u32, hctx->t_ipi, TFRC_T_MBI);
+               /* update R_sqmean _after_ computing the modulation factor */
+               hctx->r_sqmean = tfrc_ewma(hctx->r_sqmean, r_sample, 9);
+       }
 
        /* unschedule no feedback timer */
        sk_stop_timer(sk, &hctx->no_feedback_timer);
@@ -749,6 +786,9 @@ static struct ccid_operations ccid3 = {
        .ccid_hc_tx_getsockopt     = ccid3_hc_tx_getsockopt,
 };
 
+module_param(do_osc_prev, bool, 0644);
+MODULE_PARM_DESC(do_osc_prev, "Use Oscillation Prevention (RFC 3448, 4.5)");
+
 #ifdef CONFIG_IP_DCCP_CCID3_DEBUG
 module_param(ccid3_debug, bool, 0644);
 MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
This page took 0.038664 seconds and 5 git commands to generate.