From a3cbdde8e9c38b66b4f13ac5d6ff1939ded0ff20 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Thu, 4 Sep 2008 07:30:19 +0200 Subject: dccp ccid-3: Preventing Oscillations This implements [RFC 3448, 4.5], which performs congestion avoidance behaviour by reducing the transmit rate as the queueing delay (measured in terms of long-term RTT) increases. Oscillation can be turned on/off via a module option (do_osc_prev) and via sysfs (using mode 0644), the default is off. Overflow analysis: ------------------ * oscillation prevention is done after update_x(), so that t_ipi <= 64000; * hence the multiplication "t_ipi * sqrt(R_sample)" needs 64 bits; * done using u64 for sqrt_sample and explicit typecast of t_ipi; * the divisor, R_sqmean, is non-zero because oscillation prevention is first called when receiving the second feedback packet, and tfrc_scaled_rtt() > 0. A detailed discussion of the algorithm (with plots) is on http://www.erg.abdn.ac.uk/users/gerrit/dccp/notes/ccid3/sender_notes/oscillation_prevention/ The algorithm has negative side effects: * when allowing to decrease t_ipi (leads to a large RTT) and * when using it during slow-start; both uses are therefore disabled. Signed-off-by: Gerrit Renker --- net/dccp/ccids/ccid3.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'net/dccp/ccids/ccid3.c') diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 7cd76c6..06cfdad 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -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"); -- cgit v1.1