The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/cc/cc_htcp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2007-2008
    5  *      Swinburne University of Technology, Melbourne, Australia
    6  * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
    7  * Copyright (c) 2010 The FreeBSD Foundation
    8  * All rights reserved.
    9  *
   10  * This software was developed at the Centre for Advanced Internet
   11  * Architectures, Swinburne University of Technology, by Lawrence Stewart and
   12  * James Healy, made possible in part by a grant from the Cisco University
   13  * Research Program Fund at Community Foundation Silicon Valley.
   14  *
   15  * Portions of this software were developed at the Centre for Advanced
   16  * Internet Architectures, Swinburne University of Technology, Melbourne,
   17  * Australia by David Hayes under sponsorship from the FreeBSD Foundation.
   18  *
   19  * Redistribution and use in source and binary forms, with or without
   20  * modification, are permitted provided that the following conditions
   21  * are met:
   22  * 1. Redistributions of source code must retain the above copyright
   23  *    notice, this list of conditions and the following disclaimer.
   24  * 2. Redistributions in binary form must reproduce the above copyright
   25  *    notice, this list of conditions and the following disclaimer in the
   26  *    documentation and/or other materials provided with the distribution.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   38  * SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * An implementation of the H-TCP congestion control algorithm for FreeBSD,
   43  * based on the Internet Draft "draft-leith-tcp-htcp-06.txt" by Leith and
   44  * Shorten. Originally released as part of the NewTCP research project at
   45  * Swinburne University of Technology's Centre for Advanced Internet
   46  * Architectures, Melbourne, Australia, which was made possible in part by a
   47  * grant from the Cisco University Research Program Fund at Community Foundation
   48  * Silicon Valley. More details are available at:
   49  *   http://caia.swin.edu.au/urp/newtcp/
   50  */
   51 
   52 #include <sys/cdefs.h>
   53 __FBSDID("$FreeBSD$");
   54 
   55 #include <sys/param.h>
   56 #include <sys/kernel.h>
   57 #include <sys/limits.h>
   58 #include <sys/malloc.h>
   59 #include <sys/module.h>
   60 #include <sys/socket.h>
   61 #include <sys/socketvar.h>
   62 #include <sys/sysctl.h>
   63 #include <sys/systm.h>
   64 
   65 #include <net/vnet.h>
   66 
   67 #include <net/route.h>
   68 #include <net/route/nhop.h>
   69 
   70 #include <netinet/in_pcb.h>
   71 #include <netinet/tcp.h>
   72 #include <netinet/tcp_seq.h>
   73 #include <netinet/tcp_timer.h>
   74 #include <netinet/tcp_var.h>
   75 #include <netinet/cc/cc.h>
   76 #include <netinet/cc/cc_module.h>
   77 
   78 /* Fixed point math shifts. */
   79 #define HTCP_SHIFT 8
   80 #define HTCP_ALPHA_INC_SHIFT 4
   81 
   82 #define HTCP_INIT_ALPHA 1
   83 #define HTCP_DELTA_L hz         /* 1 sec in ticks. */
   84 #define HTCP_MINBETA 128        /* 0.5 << HTCP_SHIFT. */
   85 #define HTCP_MAXBETA 204        /* ~0.8 << HTCP_SHIFT. */
   86 #define HTCP_MINROWE 26         /* ~0.1 << HTCP_SHIFT. */
   87 #define HTCP_MAXROWE 512        /* 2 << HTCP_SHIFT. */
   88 
   89 /* RTT_ref (ms) used in the calculation of alpha if RTT scaling is enabled. */
   90 #define HTCP_RTT_REF 100
   91 
   92 /* Don't trust SRTT until this many samples have been taken. */
   93 #define HTCP_MIN_RTT_SAMPLES 8
   94 
   95 /*
   96  * HTCP_CALC_ALPHA performs a fixed point math calculation to determine the
   97  * value of alpha, based on the function defined in the HTCP spec.
   98  *
   99  * i.e. 1 + 10(delta - delta_l) + ((delta - delta_l) / 2) ^ 2
  100  *
  101  * "diff" is passed in to the macro as "delta - delta_l" and is expected to be
  102  * in units of ticks.
  103  *
  104  * The joyousnous of fixed point maths means our function implementation looks a
  105  * little funky...
  106  *
  107  * In order to maintain some precision in the calculations, a fixed point shift
  108  * HTCP_ALPHA_INC_SHIFT is used to ensure the integer divisions don't
  109  * truncate the results too badly.
  110  *
  111  * The "16" value is the "1" term in the alpha function shifted up by
  112  * HTCP_ALPHA_INC_SHIFT
  113  *
  114  * The "160" value is the "10" multiplier in the alpha function multiplied by
  115  * 2^HTCP_ALPHA_INC_SHIFT
  116  *
  117  * Specifying these as constants reduces the computations required. After
  118  * up-shifting all the terms in the function and performing the required
  119  * calculations, we down-shift the final result by HTCP_ALPHA_INC_SHIFT to
  120  * ensure it is back in the correct range.
  121  *
  122  * The "hz" terms are required as kernels can be configured to run with
  123  * different tick timers, which we have to adjust for in the alpha calculation
  124  * (which originally was defined in terms of seconds).
  125  *
  126  * We also have to be careful to constrain the value of diff such that it won't
  127  * overflow whilst performing the calculation. The middle term i.e. (160 * diff)
  128  * / hz is the limiting factor in the calculation. We must constrain diff to be
  129  * less than the max size of an int divided by the constant 160 figure
  130  * i.e. diff < INT_MAX / 160
  131  *
  132  * NB: Changing HTCP_ALPHA_INC_SHIFT will require you to MANUALLY update the
  133  * constants used in this function!
  134  */
  135 #define HTCP_CALC_ALPHA(diff) \
  136 ((\
  137         (16) + \
  138         ((160 * (diff)) / hz) + \
  139         (((diff) / hz) * (((diff) << HTCP_ALPHA_INC_SHIFT) / (4 * hz))) \
  140 ) >> HTCP_ALPHA_INC_SHIFT)
  141 
  142 static void     htcp_ack_received(struct cc_var *ccv, uint16_t type);
  143 static void     htcp_cb_destroy(struct cc_var *ccv);
  144 static int      htcp_cb_init(struct cc_var *ccv, void *ptr);
  145 static void     htcp_cong_signal(struct cc_var *ccv, uint32_t type);
  146 static int      htcp_mod_init(void);
  147 static void     htcp_post_recovery(struct cc_var *ccv);
  148 static void     htcp_recalc_alpha(struct cc_var *ccv);
  149 static void     htcp_recalc_beta(struct cc_var *ccv);
  150 static void     htcp_record_rtt(struct cc_var *ccv);
  151 static void     htcp_ssthresh_update(struct cc_var *ccv);
  152 static size_t   htcp_data_sz(void);
  153 
  154 struct htcp {
  155         /* cwnd before entering cong recovery. */
  156         unsigned long   prev_cwnd;
  157         /* cwnd additive increase parameter. */
  158         int             alpha;
  159         /* cwnd multiplicative decrease parameter. */
  160         int             beta;
  161         /* Largest rtt seen for the flow. */
  162         int             maxrtt;
  163         /* Shortest rtt seen for the flow. */
  164         int             minrtt;
  165         /* Time of last congestion event in ticks. */
  166         int             t_last_cong;
  167 };
  168 
  169 static int htcp_rtt_ref;
  170 /*
  171  * The maximum number of ticks the value of diff can reach in
  172  * htcp_recalc_alpha() before alpha will stop increasing due to overflow.
  173  * See comment above HTCP_CALC_ALPHA for more info.
  174  */
  175 static int htcp_max_diff = INT_MAX / ((1 << HTCP_ALPHA_INC_SHIFT) * 10);
  176 
  177 /* Per-netstack vars. */
  178 VNET_DEFINE_STATIC(u_int, htcp_adaptive_backoff) = 0;
  179 VNET_DEFINE_STATIC(u_int, htcp_rtt_scaling) = 0;
  180 #define V_htcp_adaptive_backoff    VNET(htcp_adaptive_backoff)
  181 #define V_htcp_rtt_scaling    VNET(htcp_rtt_scaling)
  182 
  183 struct cc_algo htcp_cc_algo = {
  184         .name = "htcp",
  185         .ack_received = htcp_ack_received,
  186         .cb_destroy = htcp_cb_destroy,
  187         .cb_init = htcp_cb_init,
  188         .cong_signal = htcp_cong_signal,
  189         .mod_init = htcp_mod_init,
  190         .post_recovery = htcp_post_recovery,
  191         .cc_data_sz = htcp_data_sz,
  192         .after_idle = newreno_cc_after_idle,
  193 };
  194 
  195 static void
  196 htcp_ack_received(struct cc_var *ccv, uint16_t type)
  197 {
  198         struct htcp *htcp_data;
  199 
  200         htcp_data = ccv->cc_data;
  201         htcp_record_rtt(ccv);
  202 
  203         /*
  204          * Regular ACK and we're not in cong/fast recovery and we're cwnd
  205          * limited and we're either not doing ABC or are slow starting or are
  206          * doing ABC and we've sent a cwnd's worth of bytes.
  207          */
  208         if (type == CC_ACK && !IN_RECOVERY(CCV(ccv, t_flags)) &&
  209             (ccv->flags & CCF_CWND_LIMITED) && (!V_tcp_do_rfc3465 ||
  210             CCV(ccv, snd_cwnd) <= CCV(ccv, snd_ssthresh) ||
  211             (V_tcp_do_rfc3465 && ccv->flags & CCF_ABC_SENTAWND))) {
  212                 htcp_recalc_beta(ccv);
  213                 htcp_recalc_alpha(ccv);
  214                 /*
  215                  * Use the logic in NewReno ack_received() for slow start and
  216                  * for the first HTCP_DELTA_L ticks after either the flow starts
  217                  * or a congestion event (when alpha equals 1).
  218                  */
  219                 if (htcp_data->alpha == 1 ||
  220                     CCV(ccv, snd_cwnd) <= CCV(ccv, snd_ssthresh))
  221                         newreno_cc_ack_received(ccv, type);
  222                 else {
  223                         if (V_tcp_do_rfc3465) {
  224                                 /* Increment cwnd by alpha segments. */
  225                                 CCV(ccv, snd_cwnd) += htcp_data->alpha *
  226                                     CCV(ccv, t_maxseg);
  227                                 ccv->flags &= ~CCF_ABC_SENTAWND;
  228                         } else
  229                                 /*
  230                                  * Increment cwnd by alpha/cwnd segments to
  231                                  * approximate an increase of alpha segments
  232                                  * per RTT.
  233                                  */
  234                                 CCV(ccv, snd_cwnd) += (((htcp_data->alpha <<
  235                                     HTCP_SHIFT) / (CCV(ccv, snd_cwnd) /
  236                                     CCV(ccv, t_maxseg))) * CCV(ccv, t_maxseg))
  237                                     >> HTCP_SHIFT;
  238                 }
  239         }
  240 }
  241 
  242 static void
  243 htcp_cb_destroy(struct cc_var *ccv)
  244 {
  245         free(ccv->cc_data, M_CC_MEM);
  246 }
  247 
  248 static size_t
  249 htcp_data_sz(void)
  250 {
  251         return(sizeof(struct htcp));
  252 }
  253 
  254 static int
  255 htcp_cb_init(struct cc_var *ccv, void *ptr)
  256 {
  257         struct htcp *htcp_data;
  258 
  259         INP_WLOCK_ASSERT(tptoinpcb(ccv->ccvc.tcp));
  260         if (ptr == NULL) {
  261                 htcp_data = malloc(sizeof(struct htcp), M_CC_MEM, M_NOWAIT);
  262                 if (htcp_data == NULL)
  263                         return (ENOMEM);
  264         } else
  265                 htcp_data = ptr;
  266 
  267         /* Init some key variables with sensible defaults. */
  268         htcp_data->alpha = HTCP_INIT_ALPHA;
  269         htcp_data->beta = HTCP_MINBETA;
  270         htcp_data->maxrtt = TCPTV_SRTTBASE;
  271         htcp_data->minrtt = TCPTV_SRTTBASE;
  272         htcp_data->prev_cwnd = 0;
  273         htcp_data->t_last_cong = ticks;
  274 
  275         ccv->cc_data = htcp_data;
  276 
  277         return (0);
  278 }
  279 
  280 /*
  281  * Perform any necessary tasks before we enter congestion recovery.
  282  */
  283 static void
  284 htcp_cong_signal(struct cc_var *ccv, uint32_t type)
  285 {
  286         struct htcp *htcp_data;
  287         u_int mss;
  288 
  289         htcp_data = ccv->cc_data;
  290         mss = tcp_maxseg(ccv->ccvc.tcp);
  291 
  292         switch (type) {
  293         case CC_NDUPACK:
  294                 if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) {
  295                         if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
  296                                 /*
  297                                  * Apply hysteresis to maxrtt to ensure
  298                                  * reductions in the RTT are reflected in our
  299                                  * measurements.
  300                                  */
  301                                 htcp_data->maxrtt = (htcp_data->minrtt +
  302                                     (htcp_data->maxrtt - htcp_data->minrtt) *
  303                                     95) / 100;
  304                                 htcp_ssthresh_update(ccv);
  305                                 htcp_data->t_last_cong = ticks;
  306                                 htcp_data->prev_cwnd = CCV(ccv, snd_cwnd);
  307                         }
  308                         ENTER_RECOVERY(CCV(ccv, t_flags));
  309                 }
  310                 break;
  311 
  312         case CC_ECN:
  313                 if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
  314                         /*
  315                          * Apply hysteresis to maxrtt to ensure reductions in
  316                          * the RTT are reflected in our measurements.
  317                          */
  318                         htcp_data->maxrtt = (htcp_data->minrtt + (htcp_data->maxrtt -
  319                             htcp_data->minrtt) * 95) / 100;
  320                         htcp_ssthresh_update(ccv);
  321                         CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh);
  322                         htcp_data->t_last_cong = ticks;
  323                         htcp_data->prev_cwnd = CCV(ccv, snd_cwnd);
  324                         ENTER_CONGRECOVERY(CCV(ccv, t_flags));
  325                 }
  326                 break;
  327 
  328         case CC_RTO:
  329                 CCV(ccv, snd_ssthresh) = max(min(CCV(ccv, snd_wnd),
  330                                                  CCV(ccv, snd_cwnd)) / 2 / mss,
  331                                              2) * mss;
  332                 CCV(ccv, snd_cwnd) = mss;
  333                 /*
  334                  * Grab the current time and record it so we know when the
  335                  * most recent congestion event was. Only record it when the
  336                  * timeout has fired more than once, as there is a reasonable
  337                  * chance the first one is a false alarm and may not indicate
  338                  * congestion.
  339                  */
  340                 if (CCV(ccv, t_rxtshift) >= 2)
  341                         htcp_data->t_last_cong = ticks;
  342                 break;
  343         }
  344 }
  345 
  346 static int
  347 htcp_mod_init(void)
  348 {
  349         /*
  350          * HTCP_RTT_REF is defined in ms, and t_srtt in the tcpcb is stored in
  351          * units of TCP_RTT_SCALE*hz. Scale HTCP_RTT_REF to be in the same units
  352          * as t_srtt.
  353          */
  354         htcp_rtt_ref = (HTCP_RTT_REF * TCP_RTT_SCALE * hz) / 1000;
  355         return (0);
  356 }
  357 
  358 /*
  359  * Perform any necessary tasks before we exit congestion recovery.
  360  */
  361 static void
  362 htcp_post_recovery(struct cc_var *ccv)
  363 {
  364         int pipe;
  365         struct htcp *htcp_data;
  366 
  367         pipe = 0;
  368         htcp_data = ccv->cc_data;
  369 
  370         if (IN_FASTRECOVERY(CCV(ccv, t_flags))) {
  371                 /*
  372                  * If inflight data is less than ssthresh, set cwnd
  373                  * conservatively to avoid a burst of data, as suggested in the
  374                  * NewReno RFC. Otherwise, use the HTCP method.
  375                  *
  376                  * XXXLAS: Find a way to do this without needing curack
  377                  */
  378                 if (V_tcp_do_newsack)
  379                         pipe = tcp_compute_pipe(ccv->ccvc.tcp);
  380                 else
  381                         pipe = CCV(ccv, snd_max) - ccv->curack;
  382 
  383                 if (pipe < CCV(ccv, snd_ssthresh))
  384                         /*
  385                          * Ensure that cwnd down not collape to 1 MSS under
  386                          * adverse conditions. Implements RFC6582
  387                          */
  388                         CCV(ccv, snd_cwnd) = max(pipe, CCV(ccv, t_maxseg)) +
  389                             CCV(ccv, t_maxseg);
  390                 else
  391                         CCV(ccv, snd_cwnd) = max(1, ((htcp_data->beta *
  392                             htcp_data->prev_cwnd / CCV(ccv, t_maxseg))
  393                             >> HTCP_SHIFT)) * CCV(ccv, t_maxseg);
  394         }
  395 }
  396 
  397 static void
  398 htcp_recalc_alpha(struct cc_var *ccv)
  399 {
  400         struct htcp *htcp_data;
  401         int alpha, diff, now;
  402 
  403         htcp_data = ccv->cc_data;
  404         now = ticks;
  405 
  406         /*
  407          * If ticks has wrapped around (will happen approximately once every 49
  408          * days on a machine with the default kern.hz=1000) and a flow straddles
  409          * the wrap point, our alpha calcs will be completely wrong. We cut our
  410          * losses and restart alpha from scratch by setting t_last_cong = now -
  411          * HTCP_DELTA_L.
  412          *
  413          * This does not deflate our cwnd at all. It simply slows the rate cwnd
  414          * is growing by until alpha regains the value it held prior to taking
  415          * this drastic measure.
  416          */
  417         if (now < htcp_data->t_last_cong)
  418                 htcp_data->t_last_cong = now - HTCP_DELTA_L;
  419 
  420         diff = now - htcp_data->t_last_cong - HTCP_DELTA_L;
  421 
  422         /* Cap alpha if the value of diff would overflow HTCP_CALC_ALPHA(). */
  423         if (diff < htcp_max_diff) {
  424                 /*
  425                  * If it has been more than HTCP_DELTA_L ticks since congestion,
  426                  * increase alpha according to the function defined in the spec.
  427                  */
  428                 if (diff > 0) {
  429                         alpha = HTCP_CALC_ALPHA(diff);
  430 
  431                         /*
  432                          * Adaptive backoff fairness adjustment:
  433                          * 2 * (1 - beta) * alpha_raw
  434                          */
  435                         if (V_htcp_adaptive_backoff)
  436                                 alpha = max(1, (2 * ((1 << HTCP_SHIFT) -
  437                                     htcp_data->beta) * alpha) >> HTCP_SHIFT);
  438 
  439                         /*
  440                          * RTT scaling: (RTT / RTT_ref) * alpha
  441                          * alpha will be the raw value from HTCP_CALC_ALPHA() if
  442                          * adaptive backoff is off, or the adjusted value if
  443                          * adaptive backoff is on.
  444                          */
  445                         if (V_htcp_rtt_scaling)
  446                                 alpha = max(1, (min(max(HTCP_MINROWE,
  447                                     (CCV(ccv, t_srtt) << HTCP_SHIFT) /
  448                                     htcp_rtt_ref), HTCP_MAXROWE) * alpha)
  449                                     >> HTCP_SHIFT);
  450 
  451                 } else
  452                         alpha = 1;
  453 
  454                 htcp_data->alpha = alpha;
  455         }
  456 }
  457 
  458 static void
  459 htcp_recalc_beta(struct cc_var *ccv)
  460 {
  461         struct htcp *htcp_data;
  462 
  463         htcp_data = ccv->cc_data;
  464 
  465         /*
  466          * TCPTV_SRTTBASE is the initialised value of each connection's SRTT, so
  467          * we only calc beta if the connection's SRTT has been changed from its
  468          * initial value. beta is bounded to ensure it is always between
  469          * HTCP_MINBETA and HTCP_MAXBETA.
  470          */
  471         if (V_htcp_adaptive_backoff && htcp_data->minrtt != TCPTV_SRTTBASE &&
  472             htcp_data->maxrtt != TCPTV_SRTTBASE)
  473                 htcp_data->beta = min(max(HTCP_MINBETA,
  474                     (htcp_data->minrtt << HTCP_SHIFT) / htcp_data->maxrtt),
  475                     HTCP_MAXBETA);
  476         else
  477                 htcp_data->beta = HTCP_MINBETA;
  478 }
  479 
  480 /*
  481  * Record the minimum and maximum RTT seen for the connection. These are used in
  482  * the calculation of beta if adaptive backoff is enabled.
  483  */
  484 static void
  485 htcp_record_rtt(struct cc_var *ccv)
  486 {
  487         struct htcp *htcp_data;
  488 
  489         htcp_data = ccv->cc_data;
  490 
  491         /* XXXLAS: Should there be some hysteresis for minrtt? */
  492 
  493         /*
  494          * Record the current SRTT as our minrtt if it's the smallest we've seen
  495          * or minrtt is currently equal to its initialised value. Ignore SRTT
  496          * until a min number of samples have been taken.
  497          */
  498         if ((CCV(ccv, t_srtt) < htcp_data->minrtt ||
  499             htcp_data->minrtt == TCPTV_SRTTBASE) &&
  500             (CCV(ccv, t_rttupdated) >= HTCP_MIN_RTT_SAMPLES))
  501                 htcp_data->minrtt = CCV(ccv, t_srtt);
  502 
  503         /*
  504          * Record the current SRTT as our maxrtt if it's the largest we've
  505          * seen. Ignore SRTT until a min number of samples have been taken.
  506          */
  507         if (CCV(ccv, t_srtt) > htcp_data->maxrtt
  508             && CCV(ccv, t_rttupdated) >= HTCP_MIN_RTT_SAMPLES)
  509                 htcp_data->maxrtt = CCV(ccv, t_srtt);
  510 }
  511 
  512 /*
  513  * Update the ssthresh in the event of congestion.
  514  */
  515 static void
  516 htcp_ssthresh_update(struct cc_var *ccv)
  517 {
  518         struct htcp *htcp_data;
  519 
  520         htcp_data = ccv->cc_data;
  521 
  522         /*
  523          * On the first congestion event, set ssthresh to cwnd * 0.5, on
  524          * subsequent congestion events, set it to cwnd * beta.
  525          */
  526         if (CCV(ccv, snd_ssthresh) == TCP_MAXWIN << TCP_MAX_WINSHIFT)
  527                 CCV(ccv, snd_ssthresh) = ((u_long)CCV(ccv, snd_cwnd) *
  528                     HTCP_MINBETA) >> HTCP_SHIFT;
  529         else {
  530                 htcp_recalc_beta(ccv);
  531                 CCV(ccv, snd_ssthresh) = ((u_long)CCV(ccv, snd_cwnd) *
  532                     htcp_data->beta) >> HTCP_SHIFT;
  533         }
  534 }
  535 
  536 SYSCTL_DECL(_net_inet_tcp_cc_htcp);
  537 SYSCTL_NODE(_net_inet_tcp_cc, OID_AUTO, htcp, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
  538     "H-TCP related settings");
  539 SYSCTL_UINT(_net_inet_tcp_cc_htcp, OID_AUTO, adaptive_backoff,
  540     CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(htcp_adaptive_backoff), 0,
  541     "enable H-TCP adaptive backoff");
  542 SYSCTL_UINT(_net_inet_tcp_cc_htcp, OID_AUTO, rtt_scaling,
  543     CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(htcp_rtt_scaling), 0,
  544     "enable H-TCP RTT scaling");
  545 
  546 DECLARE_CC_MODULE(htcp, &htcp_cc_algo);
  547 MODULE_VERSION(htcp, 2);

Cache object: a179fe960e95adf449c4c4c4fcfe766d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.