LCOV - code coverage report
Current view: top level - netwerk/sctp/src/netinet - sctp_cc_functions.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 865 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 45 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
       3             :  * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
       4             :  * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions are met:
       8             :  *
       9             :  * a) Redistributions of source code must retain the above copyright notice,
      10             :  *    this list of conditions and the following disclaimer.
      11             :  *
      12             :  * b) Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in
      14             :  *    the documentation and/or other materials provided with the distribution.
      15             :  *
      16             :  * c) Neither the name of Cisco Systems, Inc. nor the names of its
      17             :  *    contributors may be used to endorse or promote products derived
      18             :  *    from this software without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
      22             :  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23             :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      24             :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      30             :  * THE POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : 
      33             : #ifdef __FreeBSD__
      34             : #include <sys/cdefs.h>
      35             : __FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 279859 2015-03-10 19:49:25Z tuexen $");
      36             : #endif
      37             : 
      38             : #include <netinet/sctp_os.h>
      39             : #include <netinet/sctp_var.h>
      40             : #include <netinet/sctp_sysctl.h>
      41             : #include <netinet/sctp_pcb.h>
      42             : #include <netinet/sctp_header.h>
      43             : #include <netinet/sctputil.h>
      44             : #include <netinet/sctp_output.h>
      45             : #include <netinet/sctp_input.h>
      46             : #include <netinet/sctp_indata.h>
      47             : #include <netinet/sctp_uio.h>
      48             : #include <netinet/sctp_timer.h>
      49             : #include <netinet/sctp_auth.h>
      50             : #include <netinet/sctp_asconf.h>
      51             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
      52             : #include <netinet/sctp_dtrace_declare.h>
      53             : #endif
      54             : 
      55             : #define SHIFT_MPTCP_MULTI_N 40
      56             : #define SHIFT_MPTCP_MULTI_Z 16
      57             : #define SHIFT_MPTCP_MULTI 8
      58             : 
      59             : static void
      60           0 : sctp_enforce_cwnd_limit(struct sctp_association *assoc, struct sctp_nets *net)
      61             : {
      62           0 :         if ((assoc->max_cwnd > 0) &&
      63           0 :             (net->cwnd > assoc->max_cwnd) &&
      64           0 :             (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
      65           0 :                 net->cwnd = assoc->max_cwnd ;
      66           0 :                 if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
      67           0 :                         net->cwnd = net->mtu - sizeof(struct sctphdr);
      68             :                 }
      69             :         }
      70           0 : }
      71             : 
      72             : static void
      73           0 : sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
      74             : {
      75             :         struct sctp_association *assoc;
      76             :         uint32_t cwnd_in_mtu;
      77             : 
      78           0 :         assoc = &stcb->asoc;
      79           0 :         cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
      80           0 :         if (cwnd_in_mtu == 0) {
      81             :                 /* Using 0 means that the value of RFC 4960 is used. */
      82           0 :                 net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
      83             :         } else {
      84             :                 /*
      85             :                  * We take the minimum of the burst limit and the
      86             :                  * initial congestion window.
      87             :                  */
      88           0 :                 if ((assoc->max_burst > 0) && (cwnd_in_mtu > assoc->max_burst))
      89           0 :                         cwnd_in_mtu = assoc->max_burst;
      90           0 :                 net->cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
      91             :         }
      92           0 :         if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
      93           0 :             (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
      94             :                 /* In case of resource pooling initialize appropriately */
      95           0 :                 net->cwnd /= assoc->numnets;
      96           0 :                 if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
      97           0 :                         net->cwnd = net->mtu - sizeof(struct sctphdr);
      98             :                 }
      99             :         }
     100           0 :         sctp_enforce_cwnd_limit(assoc, net);
     101           0 :         net->ssthresh = assoc->peers_rwnd;
     102             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     103             :         SDT_PROBE(sctp, cwnd, net, init,
     104             :                   stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
     105             :                   0, net->cwnd);
     106             : #endif
     107           0 :         if (SCTP_BASE_SYSCTL(sctp_logging_level) &
     108             :             (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) {
     109           0 :                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
     110             :         }
     111           0 : }
     112             : 
     113             : static void
     114           0 : sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
     115             :                           struct sctp_association *asoc)
     116             : {
     117             :         struct sctp_nets *net;
     118             :         uint32_t t_ssthresh, t_cwnd;
     119             :         uint64_t t_ucwnd_sbw;
     120             : 
     121             :         /* MT FIXME: Don't compute this over and over again */
     122           0 :         t_ssthresh = 0;
     123           0 :         t_cwnd = 0;
     124           0 :         t_ucwnd_sbw = 0;
     125           0 :         if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
     126           0 :             (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
     127           0 :                 TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
     128           0 :                         t_ssthresh += net->ssthresh;
     129           0 :                         t_cwnd += net->cwnd;
     130           0 :                         if (net->lastsa > 0) {
     131           0 :                                 t_ucwnd_sbw += (uint64_t)net->cwnd / (uint64_t)net->lastsa;
     132             :                         }
     133             :                 }
     134           0 :                 if (t_ucwnd_sbw == 0) {
     135           0 :                         t_ucwnd_sbw = 1;
     136             :                 }
     137             :         }
     138             : 
     139             :         /*-
     140             :          * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
     141             :          * (net->fast_retran_loss_recovery == 0)))
     142             :          */
     143           0 :         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
     144           0 :                 if ((asoc->fast_retran_loss_recovery == 0) ||
     145           0 :                     (asoc->sctp_cmt_on_off > 0)) {
     146             :                         /* out of a RFC2582 Fast recovery window? */
     147           0 :                         if (net->net_ack > 0) {
     148             :                                 /*
     149             :                                  * per section 7.2.3, are there any
     150             :                                  * destinations that had a fast retransmit
     151             :                                  * to them. If so what we need to do is
     152             :                                  * adjust ssthresh and cwnd.
     153             :                                  */
     154             :                                 struct sctp_tmit_chunk *lchk;
     155           0 :                                 int old_cwnd = net->cwnd;
     156             : 
     157           0 :                                 if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
     158           0 :                                     (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
     159           0 :                                         if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) {
     160           0 :                                                 net->ssthresh = (uint32_t)(((uint64_t)4 *
     161           0 :                                                                             (uint64_t)net->mtu *
     162           0 :                                                                             (uint64_t)net->ssthresh) /
     163           0 :                                                                            (uint64_t)t_ssthresh);
     164             : 
     165             :                                         }
     166           0 :                                         if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2) {
     167             :                                                 uint32_t srtt;
     168             : 
     169           0 :                                                 srtt = net->lastsa;
     170             :                                                 /* lastsa>>3;  we don't need to devide ...*/
     171           0 :                                                 if (srtt == 0) {
     172           0 :                                                         srtt = 1;
     173             :                                                 }
     174             :                                                 /* Short Version => Equal to Contel Version MBe */
     175           0 :                                                 net->ssthresh = (uint32_t) (((uint64_t)4 *
     176           0 :                                                                              (uint64_t)net->mtu *
     177           0 :                                                                              (uint64_t)net->cwnd) /
     178           0 :                                                                             ((uint64_t)srtt *
     179             :                                                                              t_ucwnd_sbw));
     180             :                                                                              /* INCREASE FACTOR */;
     181             :                                         }
     182           0 :                                         if ((net->cwnd > t_cwnd / 2) &&
     183           0 :                                             (net->ssthresh < net->cwnd - t_cwnd / 2)) {
     184           0 :                                                 net->ssthresh = net->cwnd - t_cwnd / 2;
     185             :                                         }
     186           0 :                                         if (net->ssthresh < net->mtu) {
     187           0 :                                                 net->ssthresh = net->mtu;
     188             :                                         }
     189             :                                 } else {
     190           0 :                                         net->ssthresh = net->cwnd / 2;
     191           0 :                                         if (net->ssthresh < (net->mtu * 2)) {
     192           0 :                                                 net->ssthresh = 2 * net->mtu;
     193             :                                         }
     194             :                                 }
     195           0 :                                 net->cwnd = net->ssthresh;
     196           0 :                                 sctp_enforce_cwnd_limit(asoc, net);
     197             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     198             :                                 SDT_PROBE(sctp, cwnd, net, fr,
     199             :                                           stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
     200             :                                           old_cwnd, net->cwnd);
     201             : #endif
     202           0 :                                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
     203           0 :                                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
     204             :                                                 SCTP_CWND_LOG_FROM_FR);
     205             :                                 }
     206           0 :                                 lchk = TAILQ_FIRST(&asoc->send_queue);
     207             : 
     208           0 :                                 net->partial_bytes_acked = 0;
     209             :                                 /* Turn on fast recovery window */
     210           0 :                                 asoc->fast_retran_loss_recovery = 1;
     211           0 :                                 if (lchk == NULL) {
     212             :                                         /* Mark end of the window */
     213           0 :                                         asoc->fast_recovery_tsn = asoc->sending_seq - 1;
     214             :                                 } else {
     215           0 :                                         asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
     216             :                                 }
     217             : 
     218             :                                 /*
     219             :                                  * CMT fast recovery -- per destination
     220             :                                  * recovery variable.
     221             :                                  */
     222           0 :                                 net->fast_retran_loss_recovery = 1;
     223             : 
     224           0 :                                 if (lchk == NULL) {
     225             :                                         /* Mark end of the window */
     226           0 :                                         net->fast_recovery_tsn = asoc->sending_seq - 1;
     227             :                                 } else {
     228           0 :                                         net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
     229             :                                 }
     230             : 
     231           0 :                                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
     232             :                                                 stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA+SCTP_LOC_32 );
     233           0 :                                 sctp_timer_start(SCTP_TIMER_TYPE_SEND,
     234             :                                                  stcb->sctp_ep, stcb, net);
     235             :                         }
     236           0 :                 } else if (net->net_ack > 0) {
     237             :                         /*
     238             :                          * Mark a peg that we WOULD have done a cwnd
     239             :                          * reduction but RFC2582 prevented this action.
     240             :                          */
     241           0 :                         SCTP_STAT_INCR(sctps_fastretransinrtt);
     242             :                 }
     243             :         }
     244           0 : }
     245             : 
     246             : /* Defines for instantaneous bw decisions */
     247             : #define SCTP_INST_LOOSING 1 /* Loosing to other flows */
     248             : #define SCTP_INST_NEUTRAL 2 /* Neutral, no indication */
     249             : #define SCTP_INST_GAINING 3 /* Gaining, step down possible */
     250             : 
     251             : 
     252             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     253             : static int
     254             : cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
     255             :            uint64_t rtt_offset, uint64_t vtag, uint8_t inst_ind)
     256             : #else
     257             : static int
     258           0 : cc_bw_same(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw,
     259             :            uint64_t rtt_offset, uint8_t inst_ind)
     260             : #endif
     261             : {
     262             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     263             :         uint64_t oth, probepoint;
     264             : #endif
     265             : 
     266             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     267             :         probepoint = (((uint64_t)net->cwnd) << 32);
     268             : #endif
     269           0 :         if (net->rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) {
     270             :                 /*
     271             :                  * rtt increased
     272             :                  * we don't update bw.. so we don't
     273             :                  * update the rtt either.
     274             :                  */
     275             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     276             :                 /* Probe point 5 */
     277             :                 probepoint |=  ((5 << 16) | 1);
     278             :                 SDT_PROBE(sctp, cwnd, net, rttvar,
     279             :                           vtag,
     280             :                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
     281             :                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     282             :                           net->flight_size,
     283             :                           probepoint);
     284             : #endif
     285           0 :                 if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
     286           0 :                         if (net->cc_mod.rtcc.last_step_state == 5)
     287           0 :                                 net->cc_mod.rtcc.step_cnt++;
     288             :                         else
     289           0 :                                 net->cc_mod.rtcc.step_cnt = 1;
     290           0 :                         net->cc_mod.rtcc.last_step_state = 5;
     291           0 :                         if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
     292           0 :                             ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
     293           0 :                              ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
     294             :                                 /* Try a step down */
     295             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     296             :                                 oth = net->cc_mod.rtcc.vol_reduce;
     297             :                                 oth <<= 16;
     298             :                                 oth |= net->cc_mod.rtcc.step_cnt;
     299             :                                 oth <<= 16;
     300             :                                 oth |= net->cc_mod.rtcc.last_step_state;
     301             :                                 SDT_PROBE(sctp, cwnd, net, rttstep,
     302             :                                           vtag,
     303             :                                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
     304             :                                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     305             :                                           oth,
     306             :                                           probepoint);
     307             : #endif
     308           0 :                                 if (net->cwnd > (4 * net->mtu)) {
     309           0 :                                         net->cwnd -= net->mtu;
     310           0 :                                         net->cc_mod.rtcc.vol_reduce++;
     311             :                                 } else {
     312           0 :                                         net->cc_mod.rtcc.step_cnt = 0;
     313             :                                 }
     314             :                         }
     315             :                 }
     316           0 :                 return (1);
     317             :         }
     318           0 :         if (net->rtt < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
     319             :                 /*
     320             :                  * rtt decreased, there could be more room.
     321             :                  * we update both the bw and the rtt here to
     322             :                  * lock this in as a good step down.
     323             :                  */
     324             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     325             :                 /* Probe point 6 */
     326             :                 probepoint |=  ((6 << 16) | 0);
     327             :                 SDT_PROBE(sctp, cwnd, net, rttvar,
     328             :                           vtag,
     329             :                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
     330             :                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     331             :                           net->flight_size,
     332             :                           probepoint);
     333             : #endif
     334           0 :                 if (net->cc_mod.rtcc.steady_step) {
     335             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     336             :                         oth = net->cc_mod.rtcc.vol_reduce;
     337             :                         oth <<= 16;
     338             :                         oth |= net->cc_mod.rtcc.step_cnt;
     339             :                         oth <<= 16;
     340             :                         oth |= net->cc_mod.rtcc.last_step_state;
     341             :                         SDT_PROBE(sctp, cwnd, net, rttstep,
     342             :                                   vtag,
     343             :                                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
     344             :                                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     345             :                                   oth,
     346             :                                   probepoint);
     347             : #endif
     348           0 :                         if ((net->cc_mod.rtcc.last_step_state == 5) &&
     349           0 :                             (net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step)) {
     350             :                                 /* Step down worked */
     351           0 :                                 net->cc_mod.rtcc.step_cnt = 0;
     352           0 :                                 return (1);
     353             :                         } else {
     354           0 :                                 net->cc_mod.rtcc.last_step_state = 6;
     355           0 :                                 net->cc_mod.rtcc.step_cnt = 0;
     356             :                         }
     357             :                 }
     358           0 :                 net->cc_mod.rtcc.lbw = nbw;
     359           0 :                 net->cc_mod.rtcc.lbw_rtt = net->rtt;
     360           0 :                 net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
     361           0 :                 if (inst_ind == SCTP_INST_GAINING)
     362           0 :                         return (1);
     363           0 :                 else if (inst_ind == SCTP_INST_NEUTRAL)
     364           0 :                         return (1);
     365             :                 else
     366           0 :                         return (0);
     367             :         }
     368             :         /* Ok bw and rtt remained the same .. no update to any
     369             :          */
     370             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     371             :         /* Probe point 7 */
     372             :         probepoint |=  ((7 << 16) | net->cc_mod.rtcc.ret_from_eq);
     373             :         SDT_PROBE(sctp, cwnd, net, rttvar,
     374             :                   vtag,
     375             :                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
     376             :                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     377             :                   net->flight_size,
     378             :                   probepoint);
     379             : #endif
     380           0 :         if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
     381           0 :                 if (net->cc_mod.rtcc.last_step_state == 5)
     382           0 :                         net->cc_mod.rtcc.step_cnt++;
     383             :                 else
     384           0 :                         net->cc_mod.rtcc.step_cnt = 1;
     385           0 :                 net->cc_mod.rtcc.last_step_state = 5;
     386           0 :                 if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
     387           0 :                     ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
     388           0 :                      ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
     389             :                         /* Try a step down */
     390           0 :                         if (net->cwnd > (4 * net->mtu)) {
     391           0 :                                 net->cwnd -= net->mtu;
     392           0 :                                 net->cc_mod.rtcc.vol_reduce++;
     393           0 :                                 return (1);
     394             :                         } else {
     395           0 :                                 net->cc_mod.rtcc.step_cnt = 0;
     396             :                         }
     397             :                 }
     398             :         }
     399           0 :         if (inst_ind == SCTP_INST_GAINING)
     400           0 :                 return (1);
     401           0 :         else if (inst_ind == SCTP_INST_NEUTRAL)
     402           0 :                 return (1);
     403             :         else
     404           0 :                 return ((int)net->cc_mod.rtcc.ret_from_eq);
     405             : }
     406             : 
     407             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     408             : static int
     409             : cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset,
     410             :                uint64_t vtag, uint8_t inst_ind)
     411             : #else
     412             : static int
     413           0 : cc_bw_decrease(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset,
     414             :                uint8_t inst_ind)
     415             : #endif
     416             : {
     417             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     418             :         uint64_t oth, probepoint;
     419             : #endif
     420             : 
     421             :         /* Bandwidth decreased.*/
     422             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     423             :         probepoint = (((uint64_t)net->cwnd) << 32);
     424             : #endif
     425           0 :         if (net->rtt  > net->cc_mod.rtcc.lbw_rtt+rtt_offset) {
     426             :                 /* rtt increased */
     427             :                 /* Did we add more */
     428           0 :                 if ((net->cwnd > net->cc_mod.rtcc.cwnd_at_bw_set) &&
     429             :                     (inst_ind != SCTP_INST_LOOSING)) {
     430             :                         /* We caused it maybe.. back off? */
     431             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     432             :                         /* PROBE POINT 1 */
     433             :                         probepoint |=  ((1 << 16) | 1);
     434             :                         SDT_PROBE(sctp, cwnd, net, rttvar,
     435             :                                   vtag,
     436             :                                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
     437             :                                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     438             :                                   net->flight_size,
     439             :                                   probepoint);
     440             : #endif
     441           0 :                         if (net->cc_mod.rtcc.ret_from_eq) {
     442             :                                 /* Switch over to CA if we are less aggressive */
     443           0 :                                 net->ssthresh = net->cwnd-1;
     444           0 :                                 net->partial_bytes_acked = 0;
     445             :                         }
     446           0 :                         return (1);
     447             :                 }
     448             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     449             :                 /* Probe point 2 */
     450             :                 probepoint |=  ((2 << 16) | 0);
     451             :                 SDT_PROBE(sctp, cwnd, net, rttvar,
     452             :                           vtag,
     453             :                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
     454             :                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     455             :                           net->flight_size,
     456             :                           probepoint);
     457             : #endif
     458             :                 /* Someone else - fight for more? */
     459           0 :                 if (net->cc_mod.rtcc.steady_step) {
     460             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     461             :                         oth = net->cc_mod.rtcc.vol_reduce;
     462             :                         oth <<= 16;
     463             :                         oth |= net->cc_mod.rtcc.step_cnt;
     464             :                         oth <<= 16;
     465             :                         oth |= net->cc_mod.rtcc.last_step_state;
     466             :                         SDT_PROBE(sctp, cwnd, net, rttstep,
     467             :                                   vtag,
     468             :                                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
     469             :                                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     470             :                                   oth,
     471             :                                   probepoint);
     472             : #endif
     473             :                         /* Did we voluntarily give up some? if so take
     474             :                          * one back please
     475             :                          */
     476           0 :                         if ((net->cc_mod.rtcc.vol_reduce) &&
     477             :                             (inst_ind != SCTP_INST_GAINING)) {
     478           0 :                                 net->cwnd += net->mtu;
     479           0 :                                 sctp_enforce_cwnd_limit(&stcb->asoc, net);
     480           0 :                                 net->cc_mod.rtcc.vol_reduce--;
     481             :                         }
     482           0 :                         net->cc_mod.rtcc.last_step_state = 2;
     483           0 :                         net->cc_mod.rtcc.step_cnt = 0;
     484             :                 }
     485           0 :                 goto out_decision;
     486           0 :         } else  if (net->rtt  < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
     487             :                 /* bw & rtt decreased */
     488             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     489             :                 /* Probe point 3 */
     490             :                 probepoint |=  ((3 << 16) | 0);
     491             :                 SDT_PROBE(sctp, cwnd, net, rttvar,
     492             :                           vtag,
     493             :                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
     494             :                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     495             :                           net->flight_size,
     496             :                           probepoint);
     497             : #endif
     498           0 :                 if (net->cc_mod.rtcc.steady_step) {
     499             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     500             :                         oth = net->cc_mod.rtcc.vol_reduce;
     501             :                         oth <<= 16;
     502             :                         oth |= net->cc_mod.rtcc.step_cnt;
     503             :                         oth <<= 16;
     504             :                         oth |= net->cc_mod.rtcc.last_step_state;
     505             :                         SDT_PROBE(sctp, cwnd, net, rttstep,
     506             :                                   vtag,
     507             :                                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
     508             :                                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     509             :                                   oth,
     510             :                                   probepoint);
     511             : #endif
     512           0 :                         if ((net->cc_mod.rtcc.vol_reduce) &&
     513             :                             (inst_ind != SCTP_INST_GAINING)) {
     514           0 :                                 net->cwnd += net->mtu;
     515           0 :                                 sctp_enforce_cwnd_limit(&stcb->asoc, net);
     516           0 :                                 net->cc_mod.rtcc.vol_reduce--;
     517             :                         }
     518           0 :                         net->cc_mod.rtcc.last_step_state = 3;
     519           0 :                         net->cc_mod.rtcc.step_cnt = 0;
     520             :                 }
     521           0 :                 goto out_decision;
     522             :         }
     523             :         /* The bw decreased but rtt stayed the same */
     524             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     525             :         /* Probe point 4 */
     526             :         probepoint |=  ((4 << 16) | 0);
     527             :         SDT_PROBE(sctp, cwnd, net, rttvar,
     528             :                   vtag,
     529             :                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
     530             :                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     531             :                   net->flight_size,
     532             :                   probepoint);
     533             : #endif
     534           0 :         if (net->cc_mod.rtcc.steady_step) {
     535             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     536             :                 oth = net->cc_mod.rtcc.vol_reduce;
     537             :                 oth <<= 16;
     538             :                 oth |= net->cc_mod.rtcc.step_cnt;
     539             :                 oth <<= 16;
     540             :                 oth |= net->cc_mod.rtcc.last_step_state;
     541             :                 SDT_PROBE(sctp, cwnd, net, rttstep,
     542             :                           vtag,
     543             :                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
     544             :                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     545             :                           oth,
     546             :                           probepoint);
     547             : #endif
     548           0 :                 if ((net->cc_mod.rtcc.vol_reduce) &&
     549             :                     (inst_ind != SCTP_INST_GAINING)) {
     550           0 :                         net->cwnd += net->mtu;
     551           0 :                         sctp_enforce_cwnd_limit(&stcb->asoc, net);
     552           0 :                         net->cc_mod.rtcc.vol_reduce--;
     553             :                 }
     554           0 :                 net->cc_mod.rtcc.last_step_state = 4;
     555           0 :                 net->cc_mod.rtcc.step_cnt = 0;
     556             :         }
     557             : out_decision:
     558           0 :         net->cc_mod.rtcc.lbw = nbw;
     559           0 :         net->cc_mod.rtcc.lbw_rtt = net->rtt;
     560           0 :         net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
     561           0 :         if (inst_ind == SCTP_INST_GAINING) {
     562           0 :                 return (1);
     563             :         } else {
     564           0 :                 return (0);
     565             :         }
     566             : }
     567             : 
     568             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     569             : static int
     570             : cc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t vtag)
     571             : #else
     572             : static int
     573           0 : cc_bw_increase(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw)
     574             : #endif
     575             : {
     576             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     577             :         uint64_t oth, probepoint;
     578             : 
     579             : #endif
     580             :         /* BW increased, so update and
     581             :          * return 0, since all actions in
     582             :          * our table say to do the normal CC
     583             :          * update. Note that we pay no attention to
     584             :          * the inst_ind since our overall sum is increasing.
     585             :          */
     586             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     587             :         /* PROBE POINT 0 */
     588             :         probepoint = (((uint64_t)net->cwnd) << 32);
     589             :         SDT_PROBE(sctp, cwnd, net, rttvar,
     590             :                   vtag,
     591             :                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
     592             :                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     593             :                   net->flight_size,
     594             :                   probepoint);
     595             : #endif
     596           0 :         if (net->cc_mod.rtcc.steady_step) {
     597             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     598             :                 oth = net->cc_mod.rtcc.vol_reduce;
     599             :                 oth <<= 16;
     600             :                 oth |= net->cc_mod.rtcc.step_cnt;
     601             :                 oth <<= 16;
     602             :                 oth |= net->cc_mod.rtcc.last_step_state;
     603             :                 SDT_PROBE(sctp, cwnd, net, rttstep,
     604             :                           vtag,
     605             :                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
     606             :                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     607             :                           oth,
     608             :                           probepoint);
     609             : #endif
     610           0 :                 net->cc_mod.rtcc.last_step_state = 0;
     611           0 :                 net->cc_mod.rtcc.step_cnt = 0;
     612           0 :                 net->cc_mod.rtcc.vol_reduce = 0;
     613             :         }
     614           0 :         net->cc_mod.rtcc.lbw = nbw;
     615           0 :         net->cc_mod.rtcc.lbw_rtt = net->rtt;
     616           0 :         net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
     617           0 :         return (0);
     618             : }
     619             : 
     620             : /* RTCC Algoritm to limit growth of cwnd, return
     621             :  * true if you want to NOT allow cwnd growth
     622             :  */
     623             : static int
     624           0 : cc_bw_limit(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw)
     625             : {
     626             :         uint64_t bw_offset, rtt_offset;
     627             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     628             :         uint64_t probepoint, rtt, vtag;
     629             : #endif
     630             :         uint64_t bytes_for_this_rtt, inst_bw;
     631             :         uint64_t div, inst_off;
     632             :         int bw_shift;
     633             :         uint8_t inst_ind;
     634             :         int ret;
     635             :         /*-
     636             :          * Here we need to see if we want
     637             :          * to limit cwnd growth due to increase
     638             :          * in overall rtt but no increase in bw.
     639             :          * We use the following table to figure
     640             :          * out what we should do. When we return
     641             :          * 0, cc update goes on as planned. If we
     642             :          * return 1, then no cc update happens and cwnd
     643             :          * stays where it is at.
     644             :          * ----------------------------------
     645             :          *   BW    |    RTT   | Action
     646             :          * *********************************
     647             :          *   INC   |    INC   | return 0
     648             :          * ----------------------------------
     649             :          *   INC   |    SAME  | return 0
     650             :          * ----------------------------------
     651             :          *   INC   |    DECR  | return 0
     652             :          * ----------------------------------
     653             :          *   SAME  |    INC   | return 1
     654             :          * ----------------------------------
     655             :          *   SAME  |    SAME  | return 1
     656             :          * ----------------------------------
     657             :          *   SAME  |    DECR  | return 0
     658             :          * ----------------------------------
     659             :          *   DECR  |    INC   | return 0 or 1 based on if we caused.
     660             :          * ----------------------------------
     661             :          *   DECR  |    SAME  | return 0
     662             :          * ----------------------------------
     663             :          *   DECR  |    DECR  | return 0
     664             :          * ----------------------------------
     665             :          *
     666             :          * We are a bit fuzz on what an increase or
     667             :          * decrease is. For BW it is the same if
     668             :          * it did not change within 1/64th. For
     669             :          * RTT it stayed the same if it did not
     670             :          * change within 1/32nd
     671             :          */
     672           0 :         bw_shift = SCTP_BASE_SYSCTL(sctp_rttvar_bw);
     673             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     674             :         rtt = stcb->asoc.my_vtag;
     675             :         vtag = (rtt << 32) | (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) | (stcb->rport);
     676             :         probepoint = (((uint64_t)net->cwnd) << 32);
     677             :         rtt = net->rtt;
     678             : #endif
     679           0 :         if (net->cc_mod.rtcc.rtt_set_this_sack) {
     680           0 :                 net->cc_mod.rtcc.rtt_set_this_sack = 0;
     681           0 :                 bytes_for_this_rtt = net->cc_mod.rtcc.bw_bytes - net->cc_mod.rtcc.bw_bytes_at_last_rttc;
     682           0 :                 net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
     683           0 :                 if (net->rtt) {
     684           0 :                         div = net->rtt / 1000;
     685           0 :                         if (div) {
     686           0 :                                 inst_bw = bytes_for_this_rtt / div;
     687           0 :                                 inst_off = inst_bw >> bw_shift;
     688           0 :                                 if (inst_bw > nbw)
     689           0 :                                         inst_ind = SCTP_INST_GAINING;
     690           0 :                                 else if ((inst_bw+inst_off) < nbw)
     691           0 :                                         inst_ind = SCTP_INST_LOOSING;
     692             :                                 else
     693           0 :                                         inst_ind = SCTP_INST_NEUTRAL;
     694             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     695             :                                 probepoint |=  ((0xb << 16) | inst_ind);
     696             : #endif
     697             :                         } else {
     698           0 :                                 inst_ind = net->cc_mod.rtcc.last_inst_ind;
     699             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     700             :                                 inst_bw = bytes_for_this_rtt / (uint64_t)(net->rtt);
     701             :                                 /* Can't determine do not change */
     702             :                                 probepoint |=  ((0xc << 16) | inst_ind);
     703             : #endif
     704             :                         }
     705             :                 } else {
     706           0 :                         inst_ind = net->cc_mod.rtcc.last_inst_ind;
     707             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     708             :                         inst_bw = bytes_for_this_rtt;
     709             :                         /* Can't determine do not change */
     710             :                         probepoint |=  ((0xd << 16) | inst_ind);
     711             : #endif
     712             :                 }
     713             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     714             :                 SDT_PROBE(sctp, cwnd, net, rttvar,
     715             :                           vtag,
     716             :                           ((nbw << 32) | inst_bw),
     717             :                           ((net->cc_mod.rtcc.lbw_rtt << 32) | rtt),
     718             :                           net->flight_size,
     719             :                           probepoint);
     720             : #endif
     721             :         } else {
     722             :                 /* No rtt measurement, use last one */
     723           0 :                 inst_ind = net->cc_mod.rtcc.last_inst_ind;
     724             :         }
     725           0 :         bw_offset = net->cc_mod.rtcc.lbw >> bw_shift;
     726           0 :         if (nbw > net->cc_mod.rtcc.lbw + bw_offset) {
     727             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     728             :                 ret = cc_bw_increase(stcb, net, nbw, vtag);
     729             : #else
     730           0 :                 ret = cc_bw_increase(stcb, net, nbw);
     731             : #endif
     732           0 :                 goto out;
     733             :         }
     734           0 :         rtt_offset = net->cc_mod.rtcc.lbw_rtt >> SCTP_BASE_SYSCTL(sctp_rttvar_rtt);
     735           0 :         if (nbw < net->cc_mod.rtcc.lbw - bw_offset) {
     736             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     737             :                 ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, vtag, inst_ind);
     738             : #else
     739           0 :                 ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, inst_ind);
     740             : #endif
     741           0 :                 goto out;
     742             :         }
     743             :         /* If we reach here then
     744             :          * we are in a situation where
     745             :          * the bw stayed the same.
     746             :          */
     747             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     748             :         ret = cc_bw_same(stcb, net, nbw, rtt_offset, vtag, inst_ind);
     749             : #else
     750           0 :         ret = cc_bw_same(stcb, net, nbw, rtt_offset, inst_ind);
     751             : #endif
     752             : out:
     753           0 :         net->cc_mod.rtcc.last_inst_ind = inst_ind;
     754           0 :         return (ret);
     755             : }
     756             : 
     757             : static void
     758           0 : sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
     759             :                                    struct sctp_association *asoc,
     760             :                                    int accum_moved, int reneged_all SCTP_UNUSED, int will_exit, int use_rtcc)
     761             : {
     762             :         struct sctp_nets *net;
     763             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     764             :         int old_cwnd;
     765             : #endif
     766             :         uint32_t t_ssthresh, t_cwnd, incr;
     767             :         uint64_t t_ucwnd_sbw;
     768             :         uint64_t t_path_mptcp;
     769             :         uint64_t mptcp_like_alpha;
     770             :         uint32_t srtt;
     771             :         uint64_t max_path;
     772             : 
     773             :         /* MT FIXME: Don't compute this over and over again */
     774           0 :         t_ssthresh = 0;
     775           0 :         t_cwnd = 0;
     776           0 :         t_ucwnd_sbw = 0;
     777           0 :         t_path_mptcp = 0;
     778           0 :         mptcp_like_alpha = 1;
     779           0 :         if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
     780           0 :             (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2) ||
     781           0 :             (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_MPTCP)) {
     782           0 :                 max_path = 0;
     783           0 :                 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
     784           0 :                         t_ssthresh += net->ssthresh;
     785           0 :                         t_cwnd += net->cwnd;
     786             :                         /* lastsa>>3;  we don't need to devide ...*/
     787           0 :                         srtt = net->lastsa;
     788           0 :                         if (srtt > 0) {
     789             :                                 uint64_t tmp;
     790             : 
     791           0 :                                 t_ucwnd_sbw += (uint64_t)net->cwnd / (uint64_t)srtt;
     792           0 :                                 t_path_mptcp += (((uint64_t)net->cwnd) << SHIFT_MPTCP_MULTI_Z) /
     793           0 :                                                 (((uint64_t)net->mtu) * (uint64_t)srtt);
     794           0 :                                 tmp = (((uint64_t)net->cwnd) << SHIFT_MPTCP_MULTI_N) /
     795           0 :                                       ((uint64_t)net->mtu * (uint64_t)(srtt * srtt));
     796           0 :                                 if (tmp > max_path) {
     797           0 :                                         max_path = tmp;
     798             :                                 }
     799             :                         }
     800             :                 }
     801           0 :                 if (t_path_mptcp > 0) {
     802           0 :                         mptcp_like_alpha = max_path / (t_path_mptcp * t_path_mptcp);
     803             :                 } else {
     804           0 :                         mptcp_like_alpha = 1;
     805             :                 }
     806             :         }
     807           0 :         if (t_ssthresh == 0) {
     808           0 :                 t_ssthresh = 1;
     809             :         }
     810           0 :         if (t_ucwnd_sbw == 0) {
     811           0 :                 t_ucwnd_sbw = 1;
     812             :         }
     813             :         /******************************/
     814             :         /* update cwnd and Early FR   */
     815             :         /******************************/
     816           0 :         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
     817             : 
     818             : #ifdef JANA_CMT_FAST_RECOVERY
     819             :                 /*
     820             :                  * CMT fast recovery code. Need to debug.
     821             :                  */
     822             :                 if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
     823             :                         if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
     824             :                             SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
     825             :                                 net->will_exit_fast_recovery = 1;
     826             :                         }
     827             :                 }
     828             : #endif
     829             :                 /* if nothing was acked on this destination skip it */
     830           0 :                 if (net->net_ack == 0) {
     831           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
     832           0 :                                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
     833             :                         }
     834           0 :                         continue;
     835             :                 }
     836             : #ifdef JANA_CMT_FAST_RECOVERY
     837             :                 /* CMT fast recovery code
     838             :                  */
     839             :                 /*
     840             :                   if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
     841             :                   @@@ Do something
     842             :                   }
     843             :                   else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
     844             :                 */
     845             : #endif
     846             : 
     847           0 :                 if (asoc->fast_retran_loss_recovery &&
     848           0 :                     (will_exit == 0) &&
     849           0 :                     (asoc->sctp_cmt_on_off == 0)) {
     850             :                         /*
     851             :                          * If we are in loss recovery we skip any cwnd
     852             :                          * update
     853             :                          */
     854           0 :                         return;
     855             :                 }
     856             :                 /*
     857             :                  * Did any measurements go on for this network?
     858             :                  */
     859           0 :                 if (use_rtcc && (net->cc_mod.rtcc.tls_needs_set > 0)) {
     860             :                         uint64_t nbw;
     861             :                         /*
     862             :                          * At this point our bw_bytes has been updated
     863             :                          * by incoming sack information.
     864             :                          *
     865             :                          * But our bw may not yet be set.
     866             :                          *
     867             :                          */
     868           0 :                         if ((net->cc_mod.rtcc.new_tot_time/1000) > 0) {
     869           0 :                                 nbw = net->cc_mod.rtcc.bw_bytes/(net->cc_mod.rtcc.new_tot_time/1000);
     870             :                         } else {
     871           0 :                                 nbw = net->cc_mod.rtcc.bw_bytes;
     872             :                         }
     873           0 :                         if (net->cc_mod.rtcc.lbw) {
     874           0 :                                 if (cc_bw_limit(stcb, net, nbw)) {
     875             :                                         /* Hold here, no update */
     876           0 :                                         continue;
     877             :                                 }
     878             :                         } else {
     879             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     880             :                                 uint64_t vtag, probepoint;
     881             : 
     882             :                                 probepoint = (((uint64_t)net->cwnd) << 32);
     883             :                                 probepoint |=  ((0xa << 16) | 0);
     884             :                                 vtag = (net->rtt << 32) |
     885             :                                         (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
     886             :                                         (stcb->rport);
     887             : 
     888             :                                 SDT_PROBE(sctp, cwnd, net, rttvar,
     889             :                                           vtag,
     890             :                                           nbw,
     891             :                                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
     892             :                                           net->flight_size,
     893             :                                           probepoint);
     894             : #endif
     895           0 :                                 net->cc_mod.rtcc.lbw = nbw;
     896           0 :                                 net->cc_mod.rtcc.lbw_rtt = net->rtt;
     897           0 :                                 if (net->cc_mod.rtcc.rtt_set_this_sack) {
     898           0 :                                         net->cc_mod.rtcc.rtt_set_this_sack = 0;
     899           0 :                                         net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
     900             :                                 }
     901             :                         }
     902             :                 }
     903             :                 /*
     904             :                  * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
     905             :                  * moved.
     906             :                  */
     907           0 :                 if (accum_moved ||
     908           0 :                     ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
     909             :                         /* If the cumulative ack moved we can proceed */
     910           0 :                         if (net->cwnd <= net->ssthresh) {
     911             :                                 /* We are in slow start */
     912           0 :                                 if (net->flight_size + net->net_ack >= net->cwnd) {
     913             :                                         uint32_t limit;
     914             : 
     915             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     916             :                                         old_cwnd = net->cwnd;
     917             : #endif
     918           0 :                                         switch (asoc->sctp_cmt_on_off) {
     919             :                                         case SCTP_CMT_RPV1:
     920           0 :                                                 limit = (uint32_t)(((uint64_t)net->mtu *
     921           0 :                                                                     (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
     922           0 :                                                                     (uint64_t)net->ssthresh) /
     923           0 :                                                                    (uint64_t)t_ssthresh);
     924           0 :                                                 incr = (uint32_t)(((uint64_t)net->net_ack *
     925           0 :                                                                    (uint64_t)net->ssthresh) /
     926           0 :                                                                   (uint64_t)t_ssthresh);
     927           0 :                                                 if (incr > limit) {
     928           0 :                                                         incr = limit;
     929             :                                                 }
     930           0 :                                                 if (incr == 0) {
     931           0 :                                                         incr = 1;
     932             :                                                 }
     933           0 :                                                 break;
     934             :                                         case SCTP_CMT_RPV2:
     935             :                                                 /* lastsa>>3;  we don't need to divide ...*/
     936           0 :                                                 srtt = net->lastsa;
     937           0 :                                                 if (srtt == 0) {
     938           0 :                                                         srtt = 1;
     939             :                                                 }
     940           0 :                                                 limit = (uint32_t)(((uint64_t)net->mtu *
     941           0 :                                                                     (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
     942           0 :                                                                     (uint64_t)net->cwnd) /
     943           0 :                                                                    ((uint64_t)srtt * t_ucwnd_sbw));
     944             :                                                                    /* INCREASE FACTOR */
     945           0 :                                                 incr = (uint32_t)(((uint64_t)net->net_ack *
     946           0 :                                                                    (uint64_t)net->cwnd) /
     947           0 :                                                                   ((uint64_t)srtt * t_ucwnd_sbw));
     948             :                                                                   /* INCREASE FACTOR */
     949           0 :                                                 if (incr > limit) {
     950           0 :                                                         incr = limit;
     951             :                                                 }
     952           0 :                                                 if (incr == 0) {
     953           0 :                                                         incr = 1;
     954             :                                                 }
     955           0 :                                                 break;
     956             :                                         case SCTP_CMT_MPTCP:
     957           0 :                                                 limit = (uint32_t)(((uint64_t)net->mtu *
     958           0 :                                                                     mptcp_like_alpha *
     959           0 :                                                                     (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) >>
     960             :                                                                    SHIFT_MPTCP_MULTI);
     961           0 :                                                 incr  = (uint32_t)(((uint64_t)net->net_ack *
     962           0 :                                                                     mptcp_like_alpha) >>
     963             :                                                                    SHIFT_MPTCP_MULTI);
     964           0 :                                                 if (incr > limit) {
     965           0 :                                                         incr = limit;
     966             :                                                 }
     967           0 :                                                 if (incr > net->net_ack) {
     968           0 :                                                         incr = net->net_ack;
     969             :                                                 }
     970           0 :                                                 if (incr > net->mtu) {
     971           0 :                                                         incr = net->mtu;
     972             :                                                 }
     973           0 :                                                 break;
     974             :                                         default:
     975           0 :                                                 incr = net->net_ack;
     976           0 :                                                 if (incr > net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) {
     977           0 :                                                         incr = net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable);
     978             :                                                 }
     979           0 :                                                 break;
     980             :                                         }
     981           0 :                                         net->cwnd += incr;
     982           0 :                                         sctp_enforce_cwnd_limit(asoc, net);
     983           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
     984           0 :                                                 sctp_log_cwnd(stcb, net, incr,
     985             :                                                               SCTP_CWND_LOG_FROM_SS);
     986             :                                         }
     987             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
     988             :                                         SDT_PROBE(sctp, cwnd, net, ack,
     989             :                                                   stcb->asoc.my_vtag,
     990             :                                                   ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
     991             :                                                   net,
     992             :                                                   old_cwnd, net->cwnd);
     993             : #endif
     994             :                                 } else {
     995           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
     996           0 :                                                 sctp_log_cwnd(stcb, net, net->net_ack,
     997             :                                                               SCTP_CWND_LOG_NOADV_SS);
     998             :                                         }
     999             :                                 }
    1000             :                         } else {
    1001             :                                 /* We are in congestion avoidance */
    1002             :                                 /*
    1003             :                                  * Add to pba
    1004             :                                  */
    1005           0 :                                 net->partial_bytes_acked += net->net_ack;
    1006             : 
    1007           0 :                                 if ((net->flight_size + net->net_ack >= net->cwnd) &&
    1008           0 :                                     (net->partial_bytes_acked >= net->cwnd)) {
    1009           0 :                                         net->partial_bytes_acked -= net->cwnd;
    1010             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1011             :                                         old_cwnd = net->cwnd;
    1012             : #endif
    1013           0 :                                         switch (asoc->sctp_cmt_on_off) {
    1014             :                                         case SCTP_CMT_RPV1:
    1015           0 :                                                 incr = (uint32_t)(((uint64_t)net->mtu *
    1016           0 :                                                                    (uint64_t)net->ssthresh) /
    1017           0 :                                                                   (uint64_t)t_ssthresh);
    1018           0 :                                                 if (incr == 0) {
    1019           0 :                                                         incr = 1;
    1020             :                                                 }
    1021           0 :                                                 break;
    1022             :                                         case SCTP_CMT_RPV2:
    1023             :                                                 /* lastsa>>3;  we don't need to divide ... */
    1024           0 :                                                 srtt = net->lastsa;
    1025           0 :                                                 if (srtt == 0) {
    1026           0 :                                                         srtt = 1;
    1027             :                                                 }
    1028           0 :                                                 incr = (uint32_t)((uint64_t)net->mtu *
    1029           0 :                                                                   (uint64_t)net->cwnd /
    1030           0 :                                                                   ((uint64_t)srtt *
    1031             :                                                                    t_ucwnd_sbw));
    1032             :                                                                   /* INCREASE FACTOR */
    1033           0 :                                                 if (incr == 0) {
    1034           0 :                                                         incr = 1;
    1035             :                                                 }
    1036           0 :                                                 break;
    1037             :                                         case SCTP_CMT_MPTCP:
    1038           0 :                                                 incr = (uint32_t)((mptcp_like_alpha *
    1039           0 :                                                                    (uint64_t) net->cwnd) >>
    1040             :                                                                   SHIFT_MPTCP_MULTI);
    1041           0 :                                                 if (incr > net->mtu) {
    1042           0 :                                                         incr = net->mtu;
    1043             :                                                 }
    1044           0 :                                                 break;
    1045             :                                         default:
    1046           0 :                                                 incr = net->mtu;
    1047           0 :                                                 break;
    1048             :                                         }
    1049           0 :                                         net->cwnd += incr;
    1050           0 :                                         sctp_enforce_cwnd_limit(asoc, net);
    1051             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1052             :                                         SDT_PROBE(sctp, cwnd, net, ack,
    1053             :                                                   stcb->asoc.my_vtag,
    1054             :                                                   ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
    1055             :                                                   net,
    1056             :                                                   old_cwnd, net->cwnd);
    1057             : #endif
    1058           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    1059           0 :                                                 sctp_log_cwnd(stcb, net, net->mtu,
    1060             :                                                               SCTP_CWND_LOG_FROM_CA);
    1061             :                                         }
    1062             :                                 } else {
    1063           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
    1064           0 :                                                 sctp_log_cwnd(stcb, net, net->net_ack,
    1065             :                                                               SCTP_CWND_LOG_NOADV_CA);
    1066             :                                         }
    1067             :                                 }
    1068             :                         }
    1069             :                 } else {
    1070           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
    1071           0 :                                 sctp_log_cwnd(stcb, net, net->mtu,
    1072             :                                               SCTP_CWND_LOG_NO_CUMACK);
    1073             :                         }
    1074             :                 }
    1075             :         }
    1076             : }
    1077             : 
    1078             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1079             : static void
    1080             : sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb, struct sctp_nets *net)
    1081             : #else
    1082             : static void
    1083           0 : sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net)
    1084             : #endif
    1085             : {
    1086             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1087             :         int old_cwnd;
    1088             : 
    1089             :         old_cwnd = net->cwnd;
    1090             : #endif
    1091           0 :         net->cwnd = net->mtu;
    1092             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1093             :         SDT_PROBE(sctp, cwnd, net, ack,
    1094             :                   stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
    1095             :                   old_cwnd, net->cwnd);
    1096             : #endif
    1097           0 :         SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
    1098             :                 (void *)net, net->cwnd);
    1099           0 : }
    1100             : 
    1101             : 
    1102             : static void
    1103           0 : sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
    1104             : {
    1105           0 :         int old_cwnd = net->cwnd;
    1106             :         uint32_t t_ssthresh, t_cwnd;
    1107             :         uint64_t t_ucwnd_sbw;
    1108             : 
    1109             :         /* MT FIXME: Don't compute this over and over again */
    1110           0 :         t_ssthresh = 0;
    1111           0 :         t_cwnd = 0;
    1112           0 :         if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
    1113           0 :             (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
    1114             :                 struct sctp_nets *lnet;
    1115             :                 uint32_t srtt;
    1116             : 
    1117           0 :                 t_ucwnd_sbw = 0;
    1118           0 :                 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
    1119           0 :                         t_ssthresh += lnet->ssthresh;
    1120           0 :                         t_cwnd += lnet->cwnd;
    1121           0 :                         srtt = lnet->lastsa;
    1122             :                         /* lastsa>>3;  we don't need to divide ... */
    1123           0 :                         if (srtt > 0) {
    1124           0 :                                 t_ucwnd_sbw += (uint64_t)lnet->cwnd / (uint64_t)srtt;
    1125             :                         }
    1126             :                 }
    1127           0 :                 if (t_ssthresh < 1) {
    1128           0 :                         t_ssthresh = 1;
    1129             :                 }
    1130           0 :                 if (t_ucwnd_sbw < 1) {
    1131           0 :                         t_ucwnd_sbw = 1;
    1132             :                 }
    1133           0 :                 if (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) {
    1134           0 :                         net->ssthresh = (uint32_t)(((uint64_t)4 *
    1135           0 :                                                     (uint64_t)net->mtu *
    1136           0 :                                                     (uint64_t)net->ssthresh) /
    1137           0 :                                                    (uint64_t)t_ssthresh);
    1138             :                 } else {
    1139             :                         uint64_t cc_delta;
    1140             : 
    1141           0 :                         srtt = net->lastsa;
    1142             :                         /* lastsa>>3;  we don't need to divide ... */
    1143           0 :                         if (srtt == 0) {
    1144           0 :                                 srtt = 1;
    1145             :                         }
    1146           0 :                         cc_delta = t_ucwnd_sbw * (uint64_t)srtt / 2;
    1147           0 :                         if (cc_delta < t_cwnd) {
    1148           0 :                                 net->ssthresh = (uint32_t)((uint64_t)t_cwnd - cc_delta);
    1149             :                         } else {
    1150           0 :                                 net->ssthresh  = net->mtu;
    1151             :                         }
    1152             :                 }
    1153           0 :                 if ((net->cwnd > t_cwnd / 2) &&
    1154           0 :                     (net->ssthresh < net->cwnd - t_cwnd / 2)) {
    1155           0 :                         net->ssthresh = net->cwnd - t_cwnd / 2;
    1156             :                 }
    1157           0 :                 if (net->ssthresh < net->mtu) {
    1158           0 :                         net->ssthresh = net->mtu;
    1159             :                 }
    1160             :         } else {
    1161           0 :                 net->ssthresh = max(net->cwnd / 2, 4 * net->mtu);
    1162             :         }
    1163           0 :         net->cwnd = net->mtu;
    1164           0 :         net->partial_bytes_acked = 0;
    1165             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1166             :         SDT_PROBE(sctp, cwnd, net, to,
    1167             :                   stcb->asoc.my_vtag,
    1168             :                   ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
    1169             :                   net,
    1170             :                   old_cwnd, net->cwnd);
    1171             : #endif
    1172           0 :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    1173           0 :                 sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
    1174             :         }
    1175           0 : }
    1176             : 
    1177             : static void
    1178           0 : sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets *net,
    1179             :                                             int in_window, int num_pkt_lost, int use_rtcc)
    1180             : {
    1181           0 :         int old_cwnd = net->cwnd;
    1182           0 :         if ((use_rtcc) && (net->lan_type == SCTP_LAN_LOCAL) && (net->cc_mod.rtcc.use_dccc_ecn)) {
    1183             :                 /* Data center Congestion Control */
    1184           0 :                 if (in_window == 0) {
    1185             :                         /* Go to CA with the cwnd at the point we sent
    1186             :                          * the TSN that was marked with a CE.
    1187             :                          */
    1188           0 :                         if (net->ecn_prev_cwnd < net->cwnd) {
    1189             :                                 /* Restore to prev cwnd */
    1190           0 :                                 net->cwnd = net->ecn_prev_cwnd - (net->mtu * num_pkt_lost);
    1191             :                         } else {
    1192             :                                 /* Just cut in 1/2 */
    1193           0 :                                 net->cwnd /= 2;
    1194             :                         }
    1195             :                         /* Drop to CA */
    1196           0 :                         net->ssthresh = net->cwnd - (num_pkt_lost * net->mtu);
    1197           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    1198           0 :                                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
    1199             :                         }
    1200             :                 } else {
    1201             :                         /* Further tuning down required over the drastic orginal cut */
    1202           0 :                         net->ssthresh -= (net->mtu * num_pkt_lost);
    1203           0 :                         net->cwnd -= (net->mtu * num_pkt_lost);
    1204           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    1205           0 :                                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
    1206             :                         }
    1207             : 
    1208             :                 }
    1209           0 :                 SCTP_STAT_INCR(sctps_ecnereducedcwnd);
    1210             :         }  else {
    1211           0 :                 if (in_window == 0) {
    1212           0 :                         SCTP_STAT_INCR(sctps_ecnereducedcwnd);
    1213           0 :                         net->ssthresh = net->cwnd / 2;
    1214           0 :                         if (net->ssthresh < net->mtu) {
    1215           0 :                                 net->ssthresh = net->mtu;
    1216             :                                 /* here back off the timer as well, to slow us down */
    1217           0 :                                 net->RTO <<= 1;
    1218             :                         }
    1219           0 :                         net->cwnd = net->ssthresh;
    1220             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1221             :                         SDT_PROBE(sctp, cwnd, net, ecn,
    1222             :                                   stcb->asoc.my_vtag,
    1223             :                                   ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
    1224             :                                   net,
    1225             :                                   old_cwnd, net->cwnd);
    1226             : #endif
    1227           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    1228           0 :                                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
    1229             :                         }
    1230             :                 }
    1231             :         }
    1232             : 
    1233           0 : }
    1234             : 
    1235             : static void
    1236           0 : sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
    1237             :         struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
    1238             :         uint32_t *bottle_bw, uint32_t *on_queue)
    1239             : {
    1240             :         uint32_t bw_avail;
    1241             :         unsigned int incr;
    1242           0 :         int old_cwnd = net->cwnd;
    1243             : 
    1244             :         /* get bottle neck bw */
    1245           0 :         *bottle_bw = ntohl(cp->bottle_bw);
    1246             :         /* and whats on queue */
    1247           0 :         *on_queue = ntohl(cp->current_onq);
    1248             :         /*
    1249             :          * adjust the on-queue if our flight is more it could be
    1250             :          * that the router has not yet gotten data "in-flight" to it
    1251             :          */
    1252           0 :         if (*on_queue < net->flight_size) {
    1253           0 :                 *on_queue = net->flight_size;
    1254             :         }
    1255             :         /* rtt is measured in micro seconds, bottle_bw in bytes per second */
    1256           0 :         bw_avail = (uint32_t)(((uint64_t)(*bottle_bw) * net->rtt) / (uint64_t)1000000);
    1257           0 :         if (bw_avail > *bottle_bw) {
    1258             :                 /*
    1259             :                  * Cap the growth to no more than the bottle neck.
    1260             :                  * This can happen as RTT slides up due to queues.
    1261             :                  * It also means if you have more than a 1 second
    1262             :                  * RTT with a empty queue you will be limited to the
    1263             :                  * bottle_bw per second no matter if other points
    1264             :                  * have 1/2 the RTT and you could get more out...
    1265             :                  */
    1266           0 :                 bw_avail = *bottle_bw;
    1267             :         }
    1268           0 :         if (*on_queue > bw_avail) {
    1269             :                 /*
    1270             :                  * No room for anything else don't allow anything
    1271             :                  * else to be "added to the fire".
    1272             :                  */
    1273             :                 int seg_inflight, seg_onqueue, my_portion;
    1274             : 
    1275           0 :                 net->partial_bytes_acked = 0;
    1276             :                 /* how much are we over queue size? */
    1277           0 :                 incr = *on_queue - bw_avail;
    1278           0 :                 if (stcb->asoc.seen_a_sack_this_pkt) {
    1279             :                         /*
    1280             :                          * undo any cwnd adjustment that the sack
    1281             :                          * might have made
    1282             :                          */
    1283           0 :                         net->cwnd = net->prev_cwnd;
    1284             :                 }
    1285             :                 /* Now how much of that is mine? */
    1286           0 :                 seg_inflight = net->flight_size / net->mtu;
    1287           0 :                 seg_onqueue = *on_queue / net->mtu;
    1288           0 :                 my_portion = (incr * seg_inflight) / seg_onqueue;
    1289             : 
    1290             :                 /* Have I made an adjustment already */
    1291           0 :                 if (net->cwnd > net->flight_size) {
    1292             :                         /*
    1293             :                          * for this flight I made an adjustment we
    1294             :                          * need to decrease the portion by a share
    1295             :                          * our previous adjustment.
    1296             :                          */
    1297             :                         int diff_adj;
    1298             : 
    1299           0 :                         diff_adj = net->cwnd - net->flight_size;
    1300           0 :                         if (diff_adj > my_portion)
    1301           0 :                                 my_portion = 0;
    1302             :                         else
    1303           0 :                                 my_portion -= diff_adj;
    1304             :                 }
    1305             :                 /*
    1306             :                  * back down to the previous cwnd (assume we have
    1307             :                  * had a sack before this packet). minus what ever
    1308             :                  * portion of the overage is my fault.
    1309             :                  */
    1310           0 :                 net->cwnd -= my_portion;
    1311             : 
    1312             :                 /* we will NOT back down more than 1 MTU */
    1313           0 :                 if (net->cwnd <= net->mtu) {
    1314           0 :                         net->cwnd = net->mtu;
    1315             :                 }
    1316             :                 /* force into CA */
    1317           0 :                 net->ssthresh = net->cwnd - 1;
    1318             :         } else {
    1319             :                 /*
    1320             :                  * Take 1/4 of the space left or max burst up ..
    1321             :                  * whichever is less.
    1322             :                  */
    1323           0 :                 incr = (bw_avail - *on_queue) >> 2;
    1324           0 :                 if ((stcb->asoc.max_burst > 0) &&
    1325           0 :                     (stcb->asoc.max_burst * net->mtu < incr)) {
    1326           0 :                         incr = stcb->asoc.max_burst * net->mtu;
    1327             :                 }
    1328           0 :                 net->cwnd += incr;
    1329             :         }
    1330           0 :         if (net->cwnd > bw_avail) {
    1331             :                 /* We can't exceed the pipe size */
    1332           0 :                 net->cwnd = bw_avail;
    1333             :         }
    1334           0 :         if (net->cwnd < net->mtu) {
    1335             :                 /* We always have 1 MTU */
    1336           0 :                 net->cwnd = net->mtu;
    1337             :         }
    1338           0 :         sctp_enforce_cwnd_limit(&stcb->asoc, net);
    1339           0 :         if (net->cwnd - old_cwnd != 0) {
    1340             :                 /* log only changes */
    1341             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1342             :                 SDT_PROBE(sctp, cwnd, net, pd,
    1343             :                           stcb->asoc.my_vtag,
    1344             :                           ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
    1345             :                           net,
    1346             :                           old_cwnd, net->cwnd);
    1347             : #endif
    1348           0 :                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    1349           0 :                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
    1350             :                                 SCTP_CWND_LOG_FROM_SAT);
    1351             :                 }
    1352             :         }
    1353           0 : }
    1354             : 
    1355             : static void
    1356           0 : sctp_cwnd_update_after_output(struct sctp_tcb *stcb,
    1357             :                               struct sctp_nets *net, int burst_limit)
    1358             : {
    1359           0 :         int old_cwnd = net->cwnd;
    1360             : 
    1361           0 :         if (net->ssthresh < net->cwnd)
    1362           0 :                 net->ssthresh = net->cwnd;
    1363           0 :         if (burst_limit) {
    1364           0 :                 net->cwnd = (net->flight_size + (burst_limit * net->mtu));
    1365           0 :                 sctp_enforce_cwnd_limit(&stcb->asoc, net);
    1366             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1367             :                 SDT_PROBE(sctp, cwnd, net, bl,
    1368             :                           stcb->asoc.my_vtag,
    1369             :                           ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
    1370             :                           net,
    1371             :                           old_cwnd, net->cwnd);
    1372             : #endif
    1373           0 :                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    1374           0 :                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST);
    1375             :                 }
    1376             :         }
    1377           0 : }
    1378             : 
    1379             : static void
    1380           0 : sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
    1381             :                             struct sctp_association *asoc,
    1382             :                             int accum_moved, int reneged_all, int will_exit)
    1383             : {
    1384             :         /* Passing a zero argument in last disables the rtcc algoritm */
    1385           0 :         sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 0);
    1386           0 : }
    1387             : 
    1388             : static void
    1389           0 : sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
    1390             :         int in_window, int num_pkt_lost)
    1391             : {
    1392             :         /* Passing a zero argument in last disables the rtcc algoritm */
    1393           0 :         sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 0);
    1394           0 : }
    1395             : 
    1396             : /* Here starts the RTCCVAR type CC invented by RRS which
    1397             :  * is a slight mod to RFC2581. We reuse a common routine or
    1398             :  * two since these algoritms are so close and need to
    1399             :  * remain the same.
    1400             :  */
    1401             : static void
    1402           0 : sctp_cwnd_update_rtcc_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
    1403             :                                      int in_window, int num_pkt_lost)
    1404             : {
    1405           0 :         sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 1);
    1406           0 : }
    1407             : 
    1408             : 
    1409             : static
    1410           0 : void sctp_cwnd_update_rtcc_tsn_acknowledged(struct sctp_nets *net,
    1411             :                                             struct sctp_tmit_chunk *tp1)
    1412             : {
    1413           0 :         net->cc_mod.rtcc.bw_bytes += tp1->send_size;
    1414           0 : }
    1415             : 
    1416             : static void
    1417           0 : sctp_cwnd_prepare_rtcc_net_for_sack(struct sctp_tcb *stcb SCTP_UNUSED,
    1418             :                                     struct sctp_nets *net)
    1419             : {
    1420           0 :         if (net->cc_mod.rtcc.tls_needs_set > 0) {
    1421             :                 /* We had a bw measurment going on */
    1422             :                 struct timeval ltls;
    1423           0 :                 SCTP_GETPTIME_TIMEVAL(&ltls);
    1424           0 :                 timevalsub(&ltls, &net->cc_mod.rtcc.tls);
    1425           0 :                 net->cc_mod.rtcc.new_tot_time = (ltls.tv_sec * 1000000) + ltls.tv_usec;
    1426             :         }
    1427           0 : }
    1428             : 
    1429             : static void
    1430           0 : sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb,
    1431             :                                        struct sctp_nets *net)
    1432             : {
    1433             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1434             :         uint64_t vtag, probepoint;
    1435             : 
    1436             : #endif
    1437           0 :         if (net->cc_mod.rtcc.lbw) {
    1438             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1439             :                 /* Clear the old bw.. we went to 0 in-flight */
    1440             :                 vtag = (net->rtt << 32) | (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
    1441             :                         (stcb->rport);
    1442             :                 probepoint = (((uint64_t)net->cwnd) << 32);
    1443             :                 /* Probe point 8 */
    1444             :                 probepoint |=  ((8 << 16) | 0);
    1445             :                 SDT_PROBE(sctp, cwnd, net, rttvar,
    1446             :                           vtag,
    1447             :                           ((net->cc_mod.rtcc.lbw << 32) | 0),
    1448             :                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
    1449             :                           net->flight_size,
    1450             :                           probepoint);
    1451             : #endif
    1452           0 :                 net->cc_mod.rtcc.lbw_rtt = 0;
    1453           0 :                 net->cc_mod.rtcc.cwnd_at_bw_set = 0;
    1454           0 :                 net->cc_mod.rtcc.lbw = 0;
    1455           0 :                 net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
    1456           0 :                 net->cc_mod.rtcc.vol_reduce = 0;
    1457           0 :                 net->cc_mod.rtcc.bw_tot_time = 0;
    1458           0 :                 net->cc_mod.rtcc.bw_bytes = 0;
    1459           0 :                 net->cc_mod.rtcc.tls_needs_set = 0;
    1460           0 :                 if (net->cc_mod.rtcc.steady_step) {
    1461           0 :                         net->cc_mod.rtcc.vol_reduce = 0;
    1462           0 :                         net->cc_mod.rtcc.step_cnt = 0;
    1463           0 :                         net->cc_mod.rtcc.last_step_state = 0;
    1464             :                 }
    1465           0 :                 if (net->cc_mod.rtcc.ret_from_eq) {
    1466             :                         /* less aggressive one - reset cwnd too */
    1467             :                         uint32_t cwnd_in_mtu, cwnd;
    1468             : 
    1469           0 :                         cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
    1470           0 :                         if (cwnd_in_mtu == 0) {
    1471             :                                 /* Using 0 means that the value of RFC 4960 is used. */
    1472           0 :                                 cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
    1473             :                         } else {
    1474             :                                 /*
    1475             :                                  * We take the minimum of the burst limit and the
    1476             :                                  * initial congestion window.
    1477             :                                  */
    1478           0 :                                 if ((stcb->asoc.max_burst > 0) && (cwnd_in_mtu > stcb->asoc.max_burst))
    1479           0 :                                         cwnd_in_mtu = stcb->asoc.max_burst;
    1480           0 :                                 cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
    1481             :                         }
    1482           0 :                         if (net->cwnd > cwnd) {
    1483             :                                 /* Only set if we are not a timeout (i.e. down to 1 mtu) */
    1484           0 :                                 net->cwnd = cwnd;
    1485             :                         }
    1486             :                 }
    1487             :         }
    1488           0 : }
    1489             : 
    1490             : static void
    1491           0 : sctp_set_rtcc_initial_cc_param(struct sctp_tcb *stcb,
    1492             :                                struct sctp_nets *net)
    1493             : {
    1494             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1495             :         uint64_t vtag, probepoint;
    1496             : 
    1497             : #endif
    1498           0 :         sctp_set_initial_cc_param(stcb, net);
    1499           0 :         stcb->asoc.use_precise_time = 1;
    1500             : #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
    1501             :         probepoint = (((uint64_t)net->cwnd) << 32);
    1502             :         probepoint |=  ((9 << 16) | 0);
    1503             :         vtag = (net->rtt << 32) |
    1504             :                 (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
    1505             :                 (stcb->rport);
    1506             :         SDT_PROBE(sctp, cwnd, net, rttvar,
    1507             :                   vtag,
    1508             :                   0,
    1509             :                   0,
    1510             :                   0,
    1511             :                   probepoint);
    1512             : #endif
    1513           0 :         net->cc_mod.rtcc.lbw_rtt = 0;
    1514           0 :         net->cc_mod.rtcc.cwnd_at_bw_set = 0;
    1515           0 :         net->cc_mod.rtcc.vol_reduce = 0;
    1516           0 :         net->cc_mod.rtcc.lbw = 0;
    1517           0 :         net->cc_mod.rtcc.vol_reduce = 0;
    1518           0 :         net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
    1519           0 :         net->cc_mod.rtcc.bw_tot_time = 0;
    1520           0 :         net->cc_mod.rtcc.bw_bytes = 0;
    1521           0 :         net->cc_mod.rtcc.tls_needs_set = 0;
    1522           0 :         net->cc_mod.rtcc.ret_from_eq = SCTP_BASE_SYSCTL(sctp_rttvar_eqret);
    1523           0 :         net->cc_mod.rtcc.steady_step = SCTP_BASE_SYSCTL(sctp_steady_step);
    1524           0 :         net->cc_mod.rtcc.use_dccc_ecn = SCTP_BASE_SYSCTL(sctp_use_dccc_ecn);
    1525           0 :         net->cc_mod.rtcc.step_cnt = 0;
    1526           0 :         net->cc_mod.rtcc.last_step_state = 0;
    1527             : 
    1528             : 
    1529           0 : }
    1530             : 
    1531             : static int
    1532           0 : sctp_cwnd_rtcc_socket_option(struct sctp_tcb *stcb, int setorget,
    1533             :                              struct sctp_cc_option *cc_opt)
    1534             : {
    1535             :         struct sctp_nets *net;
    1536           0 :         if (setorget == 1) {
    1537             :                 /* a set */
    1538           0 :                 if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
    1539           0 :                         if ((cc_opt->aid_value.assoc_value != 0) &&
    1540           0 :                             (cc_opt->aid_value.assoc_value != 1)) {
    1541           0 :                                 return (EINVAL);
    1542             :                         }
    1543           0 :                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
    1544           0 :                                 net->cc_mod.rtcc.ret_from_eq = cc_opt->aid_value.assoc_value;
    1545             :                         }
    1546           0 :                 } else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
    1547           0 :                         if ((cc_opt->aid_value.assoc_value != 0) &&
    1548           0 :                             (cc_opt->aid_value.assoc_value != 1)) {
    1549           0 :                                 return (EINVAL);
    1550             :                         }
    1551           0 :                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
    1552           0 :                                 net->cc_mod.rtcc.use_dccc_ecn = cc_opt->aid_value.assoc_value;
    1553             :                         }
    1554           0 :                 } else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
    1555           0 :                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
    1556           0 :                                 net->cc_mod.rtcc.steady_step = cc_opt->aid_value.assoc_value;
    1557             :                         }
    1558             :                 } else {
    1559           0 :                         return (EINVAL);
    1560             :                 }
    1561             :         } else {
    1562             :                 /* a get */
    1563           0 :                 if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
    1564           0 :                         net = TAILQ_FIRST(&stcb->asoc.nets);
    1565           0 :                         if (net == NULL) {
    1566           0 :                                 return (EFAULT);
    1567             :                         }
    1568           0 :                         cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.ret_from_eq;
    1569           0 :                 } else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
    1570           0 :                         net = TAILQ_FIRST(&stcb->asoc.nets);
    1571           0 :                         if (net == NULL) {
    1572           0 :                                 return (EFAULT);
    1573             :                         }
    1574           0 :                         cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.use_dccc_ecn;
    1575           0 :                 } else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
    1576           0 :                         net = TAILQ_FIRST(&stcb->asoc.nets);
    1577           0 :                         if (net == NULL) {
    1578           0 :                                 return (EFAULT);
    1579             :                         }
    1580           0 :                         cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.steady_step;
    1581             :                 } else {
    1582           0 :                         return (EINVAL);
    1583             :                 }
    1584             :         }
    1585           0 :         return (0);
    1586             : }
    1587             : 
    1588             : static void
    1589           0 : sctp_cwnd_update_rtcc_packet_transmitted(struct sctp_tcb *stcb SCTP_UNUSED,
    1590             :                                          struct sctp_nets *net)
    1591             : {
    1592           0 :         if (net->cc_mod.rtcc.tls_needs_set == 0) {
    1593           0 :                 SCTP_GETPTIME_TIMEVAL(&net->cc_mod.rtcc.tls);
    1594           0 :                 net->cc_mod.rtcc.tls_needs_set = 2;
    1595             :         }
    1596           0 : }
    1597             : 
    1598             : static void
    1599           0 : sctp_cwnd_update_rtcc_after_sack(struct sctp_tcb *stcb,
    1600             :                                  struct sctp_association *asoc,
    1601             :                                  int accum_moved, int reneged_all, int will_exit)
    1602             : {
    1603             :         /* Passing a one argument at the last enables the rtcc algoritm */
    1604           0 :         sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 1);
    1605           0 : }
    1606             : 
    1607             : static void
    1608           0 : sctp_rtt_rtcc_calculated(struct sctp_tcb *stcb SCTP_UNUSED,
    1609             :                          struct sctp_nets *net,
    1610             :                          struct timeval *now SCTP_UNUSED)
    1611             : {
    1612           0 :         net->cc_mod.rtcc.rtt_set_this_sack = 1;
    1613           0 : }
    1614             : 
    1615             : /* Here starts Sally Floyds HS-TCP */
    1616             : 
    1617             : struct sctp_hs_raise_drop {
    1618             :         int32_t cwnd;
    1619             :         int32_t increase;
    1620             :         int32_t drop_percent;
    1621             : };
    1622             : 
    1623             : #define SCTP_HS_TABLE_SIZE 73
    1624             : 
    1625             : struct sctp_hs_raise_drop sctp_cwnd_adjust[SCTP_HS_TABLE_SIZE] = {
    1626             :         {38, 1, 50},            /* 0   */
    1627             :         {118, 2, 44},           /* 1   */
    1628             :         {221, 3, 41},           /* 2   */
    1629             :         {347, 4, 38},           /* 3   */
    1630             :         {495, 5, 37},           /* 4   */
    1631             :         {663, 6, 35},           /* 5   */
    1632             :         {851, 7, 34},           /* 6   */
    1633             :         {1058, 8, 33},          /* 7   */
    1634             :         {1284, 9, 32},          /* 8   */
    1635             :         {1529, 10, 31},         /* 9   */
    1636             :         {1793, 11, 30},         /* 10  */
    1637             :         {2076, 12, 29},         /* 11  */
    1638             :         {2378, 13, 28},         /* 12  */
    1639             :         {2699, 14, 28},         /* 13  */
    1640             :         {3039, 15, 27},         /* 14  */
    1641             :         {3399, 16, 27},         /* 15  */
    1642             :         {3778, 17, 26},         /* 16  */
    1643             :         {4177, 18, 26},         /* 17  */
    1644             :         {4596, 19, 25},         /* 18  */
    1645             :         {5036, 20, 25},         /* 19  */
    1646             :         {5497, 21, 24},         /* 20  */
    1647             :         {5979, 22, 24},         /* 21  */
    1648             :         {6483, 23, 23},         /* 22  */
    1649             :         {7009, 24, 23},         /* 23  */
    1650             :         {7558, 25, 22},         /* 24  */
    1651             :         {8130, 26, 22},         /* 25  */
    1652             :         {8726, 27, 22},         /* 26  */
    1653             :         {9346, 28, 21},         /* 27  */
    1654             :         {9991, 29, 21},         /* 28  */
    1655             :         {10661, 30, 21},        /* 29  */
    1656             :         {11358, 31, 20},        /* 30  */
    1657             :         {12082, 32, 20},        /* 31  */
    1658             :         {12834, 33, 20},        /* 32  */
    1659             :         {13614, 34, 19},        /* 33  */
    1660             :         {14424, 35, 19},        /* 34  */
    1661             :         {15265, 36, 19},        /* 35  */
    1662             :         {16137, 37, 19},        /* 36  */
    1663             :         {17042, 38, 18},        /* 37  */
    1664             :         {17981, 39, 18},        /* 38  */
    1665             :         {18955, 40, 18},        /* 39  */
    1666             :         {19965, 41, 17},        /* 40  */
    1667             :         {21013, 42, 17},        /* 41  */
    1668             :         {22101, 43, 17},        /* 42  */
    1669             :         {23230, 44, 17},        /* 43  */
    1670             :         {24402, 45, 16},        /* 44  */
    1671             :         {25618, 46, 16},        /* 45  */
    1672             :         {26881, 47, 16},        /* 46  */
    1673             :         {28193, 48, 16},        /* 47  */
    1674             :         {29557, 49, 15},        /* 48  */
    1675             :         {30975, 50, 15},        /* 49  */
    1676             :         {32450, 51, 15},        /* 50  */
    1677             :         {33986, 52, 15},        /* 51  */
    1678             :         {35586, 53, 14},        /* 52  */
    1679             :         {37253, 54, 14},        /* 53  */
    1680             :         {38992, 55, 14},        /* 54  */
    1681             :         {40808, 56, 14},        /* 55  */
    1682             :         {42707, 57, 13},        /* 56  */
    1683             :         {44694, 58, 13},        /* 57  */
    1684             :         {46776, 59, 13},        /* 58  */
    1685             :         {48961, 60, 13},        /* 59  */
    1686             :         {51258, 61, 13},        /* 60  */
    1687             :         {53677, 62, 12},        /* 61  */
    1688             :         {56230, 63, 12},        /* 62  */
    1689             :         {58932, 64, 12},        /* 63  */
    1690             :         {61799, 65, 12},        /* 64  */
    1691             :         {64851, 66, 11},        /* 65  */
    1692             :         {68113, 67, 11},        /* 66  */
    1693             :         {71617, 68, 11},        /* 67  */
    1694             :         {75401, 69, 10},        /* 68  */
    1695             :         {79517, 70, 10},        /* 69  */
    1696             :         {84035, 71, 10},        /* 70  */
    1697             :         {89053, 72, 10},        /* 71  */
    1698             :         {94717, 73, 9}          /* 72  */
    1699             : };
    1700             : 
    1701             : static void
    1702           0 : sctp_hs_cwnd_increase(struct sctp_tcb *stcb, struct sctp_nets *net)
    1703             : {
    1704             :         int cur_val, i, indx, incr;
    1705           0 :         int old_cwnd = net->cwnd;
    1706             : 
    1707           0 :         cur_val = net->cwnd >> 10;
    1708           0 :         indx = SCTP_HS_TABLE_SIZE - 1;
    1709             : 
    1710           0 :         if (cur_val < sctp_cwnd_adjust[0].cwnd) {
    1711             :                 /* normal mode */
    1712           0 :                 if (net->net_ack > net->mtu) {
    1713           0 :                         net->cwnd += net->mtu;
    1714             :                 } else {
    1715           0 :                         net->cwnd += net->net_ack;
    1716             :                 }
    1717             :         } else {
    1718           0 :                 for (i = net->last_hs_used; i < SCTP_HS_TABLE_SIZE; i++) {
    1719           0 :                         if (cur_val < sctp_cwnd_adjust[i].cwnd) {
    1720           0 :                                 indx = i;
    1721           0 :                                 break;
    1722             :                         }
    1723             :                 }
    1724           0 :                 net->last_hs_used = indx;
    1725           0 :                 incr = ((sctp_cwnd_adjust[indx].increase) << 10);
    1726           0 :                 net->cwnd += incr;
    1727             :         }
    1728           0 :         sctp_enforce_cwnd_limit(&stcb->asoc, net);
    1729           0 :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    1730           0 :                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SS);
    1731             :         }
    1732           0 : }
    1733             : 
    1734             : static void
    1735           0 : sctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net)
    1736             : {
    1737             :         int cur_val, i, indx;
    1738           0 :         int old_cwnd = net->cwnd;
    1739             : 
    1740           0 :         cur_val = net->cwnd >> 10;
    1741           0 :         if (cur_val < sctp_cwnd_adjust[0].cwnd) {
    1742             :                 /* normal mode */
    1743           0 :                 net->ssthresh = net->cwnd / 2;
    1744           0 :                 if (net->ssthresh < (net->mtu * 2)) {
    1745           0 :                         net->ssthresh = 2 * net->mtu;
    1746             :                 }
    1747           0 :                 net->cwnd = net->ssthresh;
    1748             :         } else {
    1749             :                 /* drop by the proper amount */
    1750           0 :                 net->ssthresh = net->cwnd - (int)((net->cwnd / 100) *
    1751           0 :                     sctp_cwnd_adjust[net->last_hs_used].drop_percent);
    1752           0 :                 net->cwnd = net->ssthresh;
    1753             :                 /* now where are we */
    1754           0 :                 indx = net->last_hs_used;
    1755           0 :                 cur_val = net->cwnd >> 10;
    1756             :                 /* reset where we are in the table */
    1757           0 :                 if (cur_val < sctp_cwnd_adjust[0].cwnd) {
    1758             :                         /* feel out of hs */
    1759           0 :                         net->last_hs_used = 0;
    1760             :                 } else {
    1761           0 :                         for (i = indx; i >= 1; i--) {
    1762           0 :                                 if (cur_val > sctp_cwnd_adjust[i - 1].cwnd) {
    1763           0 :                                         break;
    1764             :                                 }
    1765             :                         }
    1766           0 :                         net->last_hs_used = indx;
    1767             :                 }
    1768             :         }
    1769           0 :         sctp_enforce_cwnd_limit(&stcb->asoc, net);
    1770           0 :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    1771           0 :                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_FR);
    1772             :         }
    1773           0 : }
    1774             : 
    1775             : static void
    1776           0 : sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
    1777             :                              struct sctp_association *asoc)
    1778             : {
    1779             :         struct sctp_nets *net;
    1780             :                 /*
    1781             :          * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
    1782             :          * (net->fast_retran_loss_recovery == 0)))
    1783             :          */
    1784           0 :         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
    1785           0 :                 if ((asoc->fast_retran_loss_recovery == 0) ||
    1786           0 :                     (asoc->sctp_cmt_on_off > 0)) {
    1787             :                         /* out of a RFC2582 Fast recovery window? */
    1788           0 :                         if (net->net_ack > 0) {
    1789             :                                 /*
    1790             :                                  * per section 7.2.3, are there any
    1791             :                                  * destinations that had a fast retransmit
    1792             :                                  * to them. If so what we need to do is
    1793             :                                  * adjust ssthresh and cwnd.
    1794             :                                  */
    1795             :                                 struct sctp_tmit_chunk *lchk;
    1796             : 
    1797           0 :                                 sctp_hs_cwnd_decrease(stcb, net);
    1798             : 
    1799           0 :                                 lchk = TAILQ_FIRST(&asoc->send_queue);
    1800             : 
    1801           0 :                                 net->partial_bytes_acked = 0;
    1802             :                                 /* Turn on fast recovery window */
    1803           0 :                                 asoc->fast_retran_loss_recovery = 1;
    1804           0 :                                 if (lchk == NULL) {
    1805             :                                         /* Mark end of the window */
    1806           0 :                                         asoc->fast_recovery_tsn = asoc->sending_seq - 1;
    1807             :                                 } else {
    1808           0 :                                         asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
    1809             :                                 }
    1810             : 
    1811             :                                 /*
    1812             :                                  * CMT fast recovery -- per destination
    1813             :                                  * recovery variable.
    1814             :                                  */
    1815           0 :                                 net->fast_retran_loss_recovery = 1;
    1816             : 
    1817           0 :                                 if (lchk == NULL) {
    1818             :                                         /* Mark end of the window */
    1819           0 :                                         net->fast_recovery_tsn = asoc->sending_seq - 1;
    1820             :                                 } else {
    1821           0 :                                         net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
    1822             :                                 }
    1823             : 
    1824           0 :                                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
    1825             :                                                 stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA+SCTP_LOC_32);
    1826           0 :                                 sctp_timer_start(SCTP_TIMER_TYPE_SEND,
    1827             :                                                  stcb->sctp_ep, stcb, net);
    1828             :                         }
    1829           0 :                 } else if (net->net_ack > 0) {
    1830             :                         /*
    1831             :                          * Mark a peg that we WOULD have done a cwnd
    1832             :                          * reduction but RFC2582 prevented this action.
    1833             :                          */
    1834           0 :                         SCTP_STAT_INCR(sctps_fastretransinrtt);
    1835             :                 }
    1836             :         }
    1837           0 : }
    1838             : 
    1839             : static void
    1840           0 : sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
    1841             :                  struct sctp_association *asoc,
    1842             :                  int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
    1843             : {
    1844             :         struct sctp_nets *net;
    1845             :         /******************************/
    1846             :         /* update cwnd and Early FR   */
    1847             :         /******************************/
    1848           0 :         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
    1849             : 
    1850             : #ifdef JANA_CMT_FAST_RECOVERY
    1851             :                 /*
    1852             :                  * CMT fast recovery code. Need to debug.
    1853             :                  */
    1854             :                 if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
    1855             :                         if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
    1856             :                             SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
    1857             :                                 net->will_exit_fast_recovery = 1;
    1858             :                         }
    1859             :                 }
    1860             : #endif
    1861             :                 /* if nothing was acked on this destination skip it */
    1862           0 :                 if (net->net_ack == 0) {
    1863           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
    1864           0 :                                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
    1865             :                         }
    1866           0 :                         continue;
    1867             :                 }
    1868             : #ifdef JANA_CMT_FAST_RECOVERY
    1869             :                 /* CMT fast recovery code
    1870             :                  */
    1871             :                 /*
    1872             :                 if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
    1873             :                     @@@ Do something
    1874             :                  }
    1875             :                  else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
    1876             :                 */
    1877             : #endif
    1878             : 
    1879           0 :                  if (asoc->fast_retran_loss_recovery &&
    1880           0 :                      (will_exit == 0) &&
    1881           0 :                      (asoc->sctp_cmt_on_off == 0)) {
    1882             :                         /*
    1883             :                          * If we are in loss recovery we skip any cwnd
    1884             :                          * update
    1885             :                          */
    1886           0 :                         return;
    1887             :                 }
    1888             :                 /*
    1889             :                  * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
    1890             :                  * moved.
    1891             :                  */
    1892           0 :                 if (accum_moved ||
    1893           0 :                     ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
    1894             :                         /* If the cumulative ack moved we can proceed */
    1895           0 :                         if (net->cwnd <= net->ssthresh) {
    1896             :                                 /* We are in slow start */
    1897           0 :                                 if (net->flight_size + net->net_ack >= net->cwnd) {
    1898           0 :                                         sctp_hs_cwnd_increase(stcb, net);
    1899             :                                 } else {
    1900           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
    1901           0 :                                                 sctp_log_cwnd(stcb, net, net->net_ack,
    1902             :                                                         SCTP_CWND_LOG_NOADV_SS);
    1903             :                                         }
    1904             :                                 }
    1905             :                         } else {
    1906             :                                 /* We are in congestion avoidance */
    1907           0 :                                 net->partial_bytes_acked += net->net_ack;
    1908           0 :                                 if ((net->flight_size + net->net_ack >= net->cwnd) &&
    1909           0 :                                     (net->partial_bytes_acked >= net->cwnd)) {
    1910           0 :                                         net->partial_bytes_acked -= net->cwnd;
    1911           0 :                                         net->cwnd += net->mtu;
    1912           0 :                                         sctp_enforce_cwnd_limit(asoc, net);
    1913           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    1914           0 :                                                 sctp_log_cwnd(stcb, net, net->mtu,
    1915             :                                                         SCTP_CWND_LOG_FROM_CA);
    1916             :                                         }
    1917             :                                 } else {
    1918           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
    1919           0 :                                                 sctp_log_cwnd(stcb, net, net->net_ack,
    1920             :                                                         SCTP_CWND_LOG_NOADV_CA);
    1921             :                                         }
    1922             :                                 }
    1923             :                         }
    1924             :                 } else {
    1925           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
    1926           0 :                                 sctp_log_cwnd(stcb, net, net->mtu,
    1927             :                                         SCTP_CWND_LOG_NO_CUMACK);
    1928             :                         }
    1929             :                 }
    1930             :         }
    1931             : }
    1932             : 
    1933             : 
    1934             : /*
    1935             :  * H-TCP congestion control. The algorithm is detailed in:
    1936             :  * R.N.Shorten, D.J.Leith:
    1937             :  *   "H-TCP: TCP for high-speed and long-distance networks"
    1938             :  *   Proc. PFLDnet, Argonne, 2004.
    1939             :  * http://www.hamilton.ie/net/htcp3.pdf
    1940             :  */
    1941             : 
    1942             : 
    1943             : static int use_rtt_scaling = 1;
    1944             : static int use_bandwidth_switch = 1;
    1945             : 
    1946             : static inline int
    1947           0 : between(uint32_t seq1, uint32_t seq2, uint32_t seq3)
    1948             : {
    1949           0 :         return (seq3 - seq2 >= seq1 - seq2);
    1950             : }
    1951             : 
    1952             : static inline uint32_t
    1953           0 : htcp_cong_time(struct htcp *ca)
    1954             : {
    1955           0 :         return (sctp_get_tick_count() - ca->last_cong);
    1956             : }
    1957             : 
    1958             : static inline uint32_t
    1959           0 : htcp_ccount(struct htcp *ca)
    1960             : {
    1961           0 :         return (htcp_cong_time(ca)/ca->minRTT);
    1962             : }
    1963             : 
    1964             : static inline void
    1965           0 : htcp_reset(struct htcp *ca)
    1966             : {
    1967           0 :         ca->undo_last_cong = ca->last_cong;
    1968           0 :         ca->undo_maxRTT = ca->maxRTT;
    1969           0 :         ca->undo_old_maxB = ca->old_maxB;
    1970           0 :         ca->last_cong = sctp_get_tick_count();
    1971           0 : }
    1972             : 
    1973             : #ifdef SCTP_NOT_USED
    1974             : 
    1975             : static uint32_t
    1976             : htcp_cwnd_undo(struct sctp_tcb *stcb, struct sctp_nets *net)
    1977             : {
    1978             :         net->cc_mod.htcp_ca.last_cong = net->cc_mod.htcp_ca.undo_last_cong;
    1979             :         net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.undo_maxRTT;
    1980             :         net->cc_mod.htcp_ca.old_maxB = net->cc_mod.htcp_ca.undo_old_maxB;
    1981             :         return (max(net->cwnd, ((net->ssthresh/net->mtu<<7)/net->cc_mod.htcp_ca.beta)*net->mtu));
    1982             : }
    1983             : 
    1984             : #endif
    1985             : 
    1986             : static inline void
    1987           0 : measure_rtt(struct sctp_nets *net)
    1988             : {
    1989           0 :         uint32_t srtt = net->lastsa>>SCTP_RTT_SHIFT;
    1990             : 
    1991             :         /* keep track of minimum RTT seen so far, minRTT is zero at first */
    1992           0 :         if (net->cc_mod.htcp_ca.minRTT > srtt || !net->cc_mod.htcp_ca.minRTT)
    1993           0 :                 net->cc_mod.htcp_ca.minRTT = srtt;
    1994             : 
    1995             :         /* max RTT */
    1996           0 :         if (net->fast_retran_ip == 0 && net->ssthresh < 0xFFFF && htcp_ccount(&net->cc_mod.htcp_ca) > 3) {
    1997           0 :                 if (net->cc_mod.htcp_ca.maxRTT < net->cc_mod.htcp_ca.minRTT)
    1998           0 :                         net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.minRTT;
    1999           0 :                 if (net->cc_mod.htcp_ca.maxRTT < srtt && srtt <= net->cc_mod.htcp_ca.maxRTT+MSEC_TO_TICKS(20))
    2000           0 :                         net->cc_mod.htcp_ca.maxRTT = srtt;
    2001             :         }
    2002           0 : }
    2003             : 
    2004             : static void
    2005           0 : measure_achieved_throughput(struct sctp_nets *net)
    2006             : {
    2007           0 :         uint32_t now = sctp_get_tick_count();
    2008             : 
    2009           0 :         if (net->fast_retran_ip == 0)
    2010           0 :                 net->cc_mod.htcp_ca.bytes_acked = net->net_ack;
    2011             : 
    2012           0 :         if (!use_bandwidth_switch)
    2013           0 :                 return;
    2014             : 
    2015             :         /* achieved throughput calculations */
    2016             :         /* JRS - not 100% sure of this statement */
    2017           0 :         if (net->fast_retran_ip == 1) {
    2018           0 :                 net->cc_mod.htcp_ca.bytecount = 0;
    2019           0 :                 net->cc_mod.htcp_ca.lasttime = now;
    2020           0 :                 return;
    2021             :         }
    2022             : 
    2023           0 :         net->cc_mod.htcp_ca.bytecount += net->net_ack;
    2024           0 :         if ((net->cc_mod.htcp_ca.bytecount >= net->cwnd - (((net->cc_mod.htcp_ca.alpha >> 7) ? (net->cc_mod.htcp_ca.alpha >> 7) : 1) * net->mtu)) &&
    2025           0 :             (now - net->cc_mod.htcp_ca.lasttime >= net->cc_mod.htcp_ca.minRTT) &&
    2026           0 :             (net->cc_mod.htcp_ca.minRTT > 0)) {
    2027           0 :                 uint32_t cur_Bi = net->cc_mod.htcp_ca.bytecount/net->mtu*hz/(now - net->cc_mod.htcp_ca.lasttime);
    2028             : 
    2029           0 :                 if (htcp_ccount(&net->cc_mod.htcp_ca) <= 3) {
    2030             :                         /* just after backoff */
    2031           0 :                         net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi = cur_Bi;
    2032             :                 } else {
    2033           0 :                         net->cc_mod.htcp_ca.Bi = (3*net->cc_mod.htcp_ca.Bi + cur_Bi)/4;
    2034           0 :                         if (net->cc_mod.htcp_ca.Bi > net->cc_mod.htcp_ca.maxB)
    2035           0 :                                 net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi;
    2036           0 :                         if (net->cc_mod.htcp_ca.minB > net->cc_mod.htcp_ca.maxB)
    2037           0 :                                 net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB;
    2038             :                 }
    2039           0 :                 net->cc_mod.htcp_ca.bytecount = 0;
    2040           0 :                 net->cc_mod.htcp_ca.lasttime = now;
    2041             :         }
    2042             : }
    2043             : 
    2044             : static inline void
    2045           0 : htcp_beta_update(struct htcp *ca, uint32_t minRTT, uint32_t maxRTT)
    2046             : {
    2047           0 :         if (use_bandwidth_switch) {
    2048           0 :                 uint32_t maxB = ca->maxB;
    2049           0 :                 uint32_t old_maxB = ca->old_maxB;
    2050           0 :                 ca->old_maxB = ca->maxB;
    2051             : 
    2052           0 :                 if (!between(5*maxB, 4*old_maxB, 6*old_maxB)) {
    2053           0 :                         ca->beta = BETA_MIN;
    2054           0 :                         ca->modeswitch = 0;
    2055           0 :                         return;
    2056             :                 }
    2057             :         }
    2058             : 
    2059           0 :         if (ca->modeswitch && minRTT > (uint32_t)MSEC_TO_TICKS(10) && maxRTT) {
    2060           0 :                 ca->beta = (minRTT<<7)/maxRTT;
    2061           0 :                 if (ca->beta < BETA_MIN)
    2062           0 :                         ca->beta = BETA_MIN;
    2063           0 :                 else if (ca->beta > BETA_MAX)
    2064           0 :                         ca->beta = BETA_MAX;
    2065             :         } else {
    2066           0 :                 ca->beta = BETA_MIN;
    2067           0 :                 ca->modeswitch = 1;
    2068             :         }
    2069             : }
    2070             : 
    2071             : static inline void
    2072           0 : htcp_alpha_update(struct htcp *ca)
    2073             : {
    2074           0 :         uint32_t minRTT = ca->minRTT;
    2075           0 :         uint32_t factor = 1;
    2076           0 :         uint32_t diff = htcp_cong_time(ca);
    2077             : 
    2078           0 :         if (diff > (uint32_t)hz) {
    2079           0 :                 diff -= hz;
    2080           0 :                 factor = 1+ ( 10*diff + ((diff/2)*(diff/2)/hz))/hz;
    2081             :         }
    2082             : 
    2083           0 :         if (use_rtt_scaling && minRTT) {
    2084           0 :                 uint32_t scale = (hz<<3)/(10*minRTT);
    2085           0 :                 scale = min(max(scale, 1U<<2), 10U<<3); /* clamping ratio to interval [0.5,10]<<3 */
    2086           0 :                 factor = (factor<<3)/scale;
    2087           0 :                 if (!factor)
    2088           0 :                         factor = 1;
    2089             :         }
    2090             : 
    2091           0 :         ca->alpha = 2*factor*((1<<7)-ca->beta);
    2092           0 :         if (!ca->alpha)
    2093           0 :                 ca->alpha = ALPHA_BASE;
    2094           0 : }
    2095             : 
    2096             : /* After we have the rtt data to calculate beta, we'd still prefer to wait one
    2097             :  * rtt before we adjust our beta to ensure we are working from a consistent
    2098             :  * data.
    2099             :  *
    2100             :  * This function should be called when we hit a congestion event since only at
    2101             :  * that point do we really have a real sense of maxRTT (the queues en route
    2102             :  * were getting just too full now).
    2103             :  */
    2104             : static void
    2105           0 : htcp_param_update(struct sctp_nets *net)
    2106             : {
    2107           0 :         uint32_t minRTT = net->cc_mod.htcp_ca.minRTT;
    2108           0 :         uint32_t maxRTT = net->cc_mod.htcp_ca.maxRTT;
    2109             : 
    2110           0 :         htcp_beta_update(&net->cc_mod.htcp_ca, minRTT, maxRTT);
    2111           0 :         htcp_alpha_update(&net->cc_mod.htcp_ca);
    2112             : 
    2113             :         /* add slowly fading memory for maxRTT to accommodate routing changes etc */
    2114           0 :         if (minRTT > 0 && maxRTT > minRTT)
    2115           0 :                 net->cc_mod.htcp_ca.maxRTT = minRTT + ((maxRTT-minRTT)*95)/100;
    2116           0 : }
    2117             : 
    2118             : static uint32_t
    2119           0 : htcp_recalc_ssthresh(struct sctp_nets *net)
    2120             : {
    2121           0 :         htcp_param_update(net);
    2122           0 :         return (max(((net->cwnd/net->mtu * net->cc_mod.htcp_ca.beta) >> 7)*net->mtu, 2U*net->mtu));
    2123             : }
    2124             : 
    2125             : static void
    2126           0 : htcp_cong_avoid(struct sctp_tcb *stcb, struct sctp_nets *net)
    2127             : {
    2128             :         /*-
    2129             :          * How to handle these functions?
    2130             :          *      if (!tcp_is_cwnd_limited(sk, in_flight)) RRS - good question.
    2131             :          *              return;
    2132             :          */
    2133           0 :         if (net->cwnd <= net->ssthresh) {
    2134             :                 /* We are in slow start */
    2135           0 :                 if (net->flight_size + net->net_ack >= net->cwnd) {
    2136           0 :                         if (net->net_ack > (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable))) {
    2137           0 :                                 net->cwnd += (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable));
    2138           0 :                                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    2139           0 :                                         sctp_log_cwnd(stcb, net, net->mtu,
    2140             :                                                 SCTP_CWND_LOG_FROM_SS);
    2141             :                                 }
    2142             : 
    2143             :                         } else {
    2144           0 :                                 net->cwnd += net->net_ack;
    2145           0 :                                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    2146           0 :                                         sctp_log_cwnd(stcb, net, net->net_ack,
    2147             :                                                 SCTP_CWND_LOG_FROM_SS);
    2148             :                                 }
    2149             : 
    2150             :                         }
    2151           0 :                         sctp_enforce_cwnd_limit(&stcb->asoc, net);
    2152             :                 } else {
    2153           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
    2154           0 :                                 sctp_log_cwnd(stcb, net, net->net_ack,
    2155             :                                         SCTP_CWND_LOG_NOADV_SS);
    2156             :                         }
    2157             :                 }
    2158             :         } else {
    2159           0 :                 measure_rtt(net);
    2160             : 
    2161             :                 /* In dangerous area, increase slowly.
    2162             :                  * In theory this is net->cwnd += alpha / net->cwnd
    2163             :                  */
    2164             :                 /* What is snd_cwnd_cnt?? */
    2165           0 :                 if (((net->partial_bytes_acked/net->mtu * net->cc_mod.htcp_ca.alpha) >> 7)*net->mtu >= net->cwnd) {
    2166             :                         /*-
    2167             :                          * Does SCTP have a cwnd clamp?
    2168             :                          * if (net->snd_cwnd < net->snd_cwnd_clamp) - Nope (RRS).
    2169             :                          */
    2170           0 :                         net->cwnd += net->mtu;
    2171           0 :                         net->partial_bytes_acked = 0;
    2172           0 :                         sctp_enforce_cwnd_limit(&stcb->asoc, net);
    2173           0 :                         htcp_alpha_update(&net->cc_mod.htcp_ca);
    2174           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    2175           0 :                                 sctp_log_cwnd(stcb, net, net->mtu,
    2176             :                                         SCTP_CWND_LOG_FROM_CA);
    2177             :                         }
    2178             :                 } else {
    2179           0 :                         net->partial_bytes_acked += net->net_ack;
    2180           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
    2181           0 :                                 sctp_log_cwnd(stcb, net, net->net_ack,
    2182             :                                         SCTP_CWND_LOG_NOADV_CA);
    2183             :                         }
    2184             :                 }
    2185             : 
    2186           0 :                 net->cc_mod.htcp_ca.bytes_acked = net->mtu;
    2187             :         }
    2188           0 : }
    2189             : 
    2190             : #ifdef SCTP_NOT_USED
    2191             : /* Lower bound on congestion window. */
    2192             : static uint32_t
    2193             : htcp_min_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net)
    2194             : {
    2195             :         return (net->ssthresh);
    2196             : }
    2197             : #endif
    2198             : 
    2199             : static void
    2200           0 : htcp_init(struct sctp_nets *net)
    2201             : {
    2202           0 :         memset(&net->cc_mod.htcp_ca, 0, sizeof(struct htcp));
    2203           0 :         net->cc_mod.htcp_ca.alpha = ALPHA_BASE;
    2204           0 :         net->cc_mod.htcp_ca.beta = BETA_MIN;
    2205           0 :         net->cc_mod.htcp_ca.bytes_acked = net->mtu;
    2206           0 :         net->cc_mod.htcp_ca.last_cong = sctp_get_tick_count();
    2207           0 : }
    2208             : 
    2209             : static void
    2210           0 : sctp_htcp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
    2211             : {
    2212             :         /*
    2213             :          * We take the max of the burst limit times a MTU or the
    2214             :          * INITIAL_CWND. We then limit this to 4 MTU's of sending.
    2215             :          */
    2216           0 :         net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
    2217           0 :         net->ssthresh = stcb->asoc.peers_rwnd;
    2218           0 :         sctp_enforce_cwnd_limit(&stcb->asoc, net);
    2219           0 :         htcp_init(net);
    2220             : 
    2221           0 :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) {
    2222           0 :                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
    2223             :         }
    2224           0 : }
    2225             : 
    2226             : static void
    2227           0 : sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
    2228             :                  struct sctp_association *asoc,
    2229             :                  int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
    2230             : {
    2231             :         struct sctp_nets *net;
    2232             : 
    2233             :         /******************************/
    2234             :         /* update cwnd and Early FR   */
    2235             :         /******************************/
    2236           0 :         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
    2237             : 
    2238             : #ifdef JANA_CMT_FAST_RECOVERY
    2239             :                 /*
    2240             :                  * CMT fast recovery code. Need to debug.
    2241             :                  */
    2242             :                 if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
    2243             :                         if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
    2244             :                             SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
    2245             :                                 net->will_exit_fast_recovery = 1;
    2246             :                         }
    2247             :                 }
    2248             : #endif
    2249             :                 /* if nothing was acked on this destination skip it */
    2250           0 :                 if (net->net_ack == 0) {
    2251           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
    2252           0 :                                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
    2253             :                         }
    2254           0 :                         continue;
    2255             :                 }
    2256             : #ifdef JANA_CMT_FAST_RECOVERY
    2257             :                 /* CMT fast recovery code
    2258             :                  */
    2259             :                 /*
    2260             :                 if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
    2261             :                     @@@ Do something
    2262             :                  }
    2263             :                  else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
    2264             :                 */
    2265             : #endif
    2266             : 
    2267           0 :                 if (asoc->fast_retran_loss_recovery &&
    2268           0 :                     will_exit == 0 &&
    2269           0 :                     (asoc->sctp_cmt_on_off == 0)) {
    2270             :                         /*
    2271             :                          * If we are in loss recovery we skip any cwnd
    2272             :                          * update
    2273             :                          */
    2274           0 :                         return;
    2275             :                 }
    2276             :                 /*
    2277             :                  * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
    2278             :                  * moved.
    2279             :                  */
    2280           0 :                 if (accum_moved ||
    2281           0 :                     ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
    2282           0 :                         htcp_cong_avoid(stcb, net);
    2283           0 :                         measure_achieved_throughput(net);
    2284             :                 } else {
    2285           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
    2286           0 :                                 sctp_log_cwnd(stcb, net, net->mtu,
    2287             :                                         SCTP_CWND_LOG_NO_CUMACK);
    2288             :                         }
    2289             :                 }
    2290             :         }
    2291             : }
    2292             : 
    2293             : static void
    2294           0 : sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
    2295             :                 struct sctp_association *asoc)
    2296             : {
    2297             :         struct sctp_nets *net;
    2298             :         /*
    2299             :          * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
    2300             :          * (net->fast_retran_loss_recovery == 0)))
    2301             :          */
    2302           0 :         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
    2303           0 :                 if ((asoc->fast_retran_loss_recovery == 0) ||
    2304           0 :                     (asoc->sctp_cmt_on_off > 0)) {
    2305             :                         /* out of a RFC2582 Fast recovery window? */
    2306           0 :                         if (net->net_ack > 0) {
    2307             :                                 /*
    2308             :                                  * per section 7.2.3, are there any
    2309             :                                  * destinations that had a fast retransmit
    2310             :                                  * to them. If so what we need to do is
    2311             :                                  * adjust ssthresh and cwnd.
    2312             :                                  */
    2313             :                                 struct sctp_tmit_chunk *lchk;
    2314           0 :                                 int old_cwnd = net->cwnd;
    2315             : 
    2316             :                                 /* JRS - reset as if state were changed */
    2317           0 :                                 htcp_reset(&net->cc_mod.htcp_ca);
    2318           0 :                                 net->ssthresh = htcp_recalc_ssthresh(net);
    2319           0 :                                 net->cwnd = net->ssthresh;
    2320           0 :                                 sctp_enforce_cwnd_limit(asoc, net);
    2321           0 :                                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    2322           0 :                                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
    2323             :                                                 SCTP_CWND_LOG_FROM_FR);
    2324             :                                 }
    2325           0 :                                 lchk = TAILQ_FIRST(&asoc->send_queue);
    2326             : 
    2327           0 :                                 net->partial_bytes_acked = 0;
    2328             :                                 /* Turn on fast recovery window */
    2329           0 :                                 asoc->fast_retran_loss_recovery = 1;
    2330           0 :                                 if (lchk == NULL) {
    2331             :                                         /* Mark end of the window */
    2332           0 :                                         asoc->fast_recovery_tsn = asoc->sending_seq - 1;
    2333             :                                 } else {
    2334           0 :                                         asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
    2335             :                                 }
    2336             : 
    2337             :                                 /*
    2338             :                                  * CMT fast recovery -- per destination
    2339             :                                  * recovery variable.
    2340             :                                  */
    2341           0 :                                 net->fast_retran_loss_recovery = 1;
    2342             : 
    2343           0 :                                 if (lchk == NULL) {
    2344             :                                         /* Mark end of the window */
    2345           0 :                                         net->fast_recovery_tsn = asoc->sending_seq - 1;
    2346             :                                 } else {
    2347           0 :                                         net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
    2348             :                                 }
    2349             : 
    2350           0 :                                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
    2351             :                                                 stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA+SCTP_LOC_32);
    2352           0 :                                 sctp_timer_start(SCTP_TIMER_TYPE_SEND,
    2353             :                                                  stcb->sctp_ep, stcb, net);
    2354             :                         }
    2355           0 :                 } else if (net->net_ack > 0) {
    2356             :                         /*
    2357             :                          * Mark a peg that we WOULD have done a cwnd
    2358             :                          * reduction but RFC2582 prevented this action.
    2359             :                          */
    2360           0 :                         SCTP_STAT_INCR(sctps_fastretransinrtt);
    2361             :                 }
    2362             :         }
    2363           0 : }
    2364             : 
    2365             : static void
    2366           0 : sctp_htcp_cwnd_update_after_timeout(struct sctp_tcb *stcb,
    2367             :         struct sctp_nets *net)
    2368             : {
    2369           0 :                 int old_cwnd = net->cwnd;
    2370             : 
    2371             :                 /* JRS - reset as if the state were being changed to timeout */
    2372           0 :                 htcp_reset(&net->cc_mod.htcp_ca);
    2373           0 :                 net->ssthresh = htcp_recalc_ssthresh(net);
    2374           0 :                 net->cwnd = net->mtu;
    2375           0 :                 net->partial_bytes_acked = 0;
    2376           0 :                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    2377           0 :                         sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
    2378             :                 }
    2379           0 : }
    2380             : 
    2381             : static void
    2382           0 : sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
    2383             :                 struct sctp_nets *net, int in_window, int num_pkt_lost SCTP_UNUSED)
    2384             : {
    2385             :         int old_cwnd;
    2386           0 :         old_cwnd = net->cwnd;
    2387             : 
    2388             :         /* JRS - reset hctp as if state changed */
    2389           0 :         if (in_window == 0) {
    2390           0 :                 htcp_reset(&net->cc_mod.htcp_ca);
    2391           0 :                 SCTP_STAT_INCR(sctps_ecnereducedcwnd);
    2392           0 :                 net->ssthresh = htcp_recalc_ssthresh(net);
    2393           0 :                 if (net->ssthresh < net->mtu) {
    2394           0 :                         net->ssthresh = net->mtu;
    2395             :                         /* here back off the timer as well, to slow us down */
    2396           0 :                         net->RTO <<= 1;
    2397             :                 }
    2398           0 :                 net->cwnd = net->ssthresh;
    2399           0 :                 sctp_enforce_cwnd_limit(&stcb->asoc, net);
    2400           0 :                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
    2401           0 :                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
    2402             :                 }
    2403             :         }
    2404           0 : }
    2405             : 
    2406             : struct sctp_cc_functions sctp_cc_functions[] = {
    2407             : {
    2408             : #if defined(__Windows__) || defined(__Userspace_os_Windows)
    2409             :         sctp_set_initial_cc_param,
    2410             :         sctp_cwnd_update_after_sack,
    2411             :         sctp_cwnd_update_exit_pf_common,
    2412             :         sctp_cwnd_update_after_fr,
    2413             :         sctp_cwnd_update_after_timeout,
    2414             :         sctp_cwnd_update_after_ecn_echo,
    2415             :         sctp_cwnd_update_after_packet_dropped,
    2416             :         sctp_cwnd_update_after_output,
    2417             : #else
    2418             :         .sctp_set_initial_cc_param = sctp_set_initial_cc_param,
    2419             :         .sctp_cwnd_update_after_sack = sctp_cwnd_update_after_sack,
    2420             :         .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
    2421             :         .sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
    2422             :         .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
    2423             :         .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
    2424             :         .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
    2425             :         .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
    2426             : #endif
    2427             : },
    2428             : {
    2429             : #if defined(__Windows__) || defined(__Userspace_os_Windows)
    2430             :         sctp_set_initial_cc_param,
    2431             :         sctp_hs_cwnd_update_after_sack,
    2432             :         sctp_cwnd_update_exit_pf_common,
    2433             :         sctp_hs_cwnd_update_after_fr,
    2434             :         sctp_cwnd_update_after_timeout,
    2435             :         sctp_cwnd_update_after_ecn_echo,
    2436             :         sctp_cwnd_update_after_packet_dropped,
    2437             :         sctp_cwnd_update_after_output,
    2438             : #else
    2439             :         .sctp_set_initial_cc_param = sctp_set_initial_cc_param,
    2440             :         .sctp_cwnd_update_after_sack = sctp_hs_cwnd_update_after_sack,
    2441             :         .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
    2442             :         .sctp_cwnd_update_after_fr = sctp_hs_cwnd_update_after_fr,
    2443             :         .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
    2444             :         .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
    2445             :         .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
    2446             :         .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
    2447             : #endif
    2448             : },
    2449             : {
    2450             : #if defined(__Windows__) || defined(__Userspace_os_Windows)
    2451             :         sctp_htcp_set_initial_cc_param,
    2452             :         sctp_htcp_cwnd_update_after_sack,
    2453             :         sctp_cwnd_update_exit_pf_common,
    2454             :         sctp_htcp_cwnd_update_after_fr,
    2455             :         sctp_htcp_cwnd_update_after_timeout,
    2456             :         sctp_htcp_cwnd_update_after_ecn_echo,
    2457             :         sctp_cwnd_update_after_packet_dropped,
    2458             :         sctp_cwnd_update_after_output,
    2459             : #else
    2460             :         .sctp_set_initial_cc_param = sctp_htcp_set_initial_cc_param,
    2461             :         .sctp_cwnd_update_after_sack = sctp_htcp_cwnd_update_after_sack,
    2462             :         .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
    2463             :         .sctp_cwnd_update_after_fr = sctp_htcp_cwnd_update_after_fr,
    2464             :         .sctp_cwnd_update_after_timeout = sctp_htcp_cwnd_update_after_timeout,
    2465             :         .sctp_cwnd_update_after_ecn_echo = sctp_htcp_cwnd_update_after_ecn_echo,
    2466             :         .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
    2467             :         .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
    2468             : #endif
    2469             : },
    2470             : {
    2471             : #if defined(__Windows__) || defined(__Userspace_os_Windows)
    2472             :         sctp_set_rtcc_initial_cc_param,
    2473             :         sctp_cwnd_update_rtcc_after_sack,
    2474             :         sctp_cwnd_update_exit_pf_common,
    2475             :         sctp_cwnd_update_after_fr,
    2476             :         sctp_cwnd_update_after_timeout,
    2477             :         sctp_cwnd_update_rtcc_after_ecn_echo,
    2478             :         sctp_cwnd_update_after_packet_dropped,
    2479             :         sctp_cwnd_update_after_output,
    2480             :         sctp_cwnd_update_rtcc_packet_transmitted,
    2481             :         sctp_cwnd_update_rtcc_tsn_acknowledged,
    2482             :         sctp_cwnd_new_rtcc_transmission_begins,
    2483             :         sctp_cwnd_prepare_rtcc_net_for_sack,
    2484             :         sctp_cwnd_rtcc_socket_option,
    2485             :         sctp_rtt_rtcc_calculated
    2486             : #else
    2487             :         .sctp_set_initial_cc_param = sctp_set_rtcc_initial_cc_param,
    2488             :         .sctp_cwnd_update_after_sack = sctp_cwnd_update_rtcc_after_sack,
    2489             :         .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
    2490             :         .sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
    2491             :         .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
    2492             :         .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_rtcc_after_ecn_echo,
    2493             :         .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
    2494             :         .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
    2495             :         .sctp_cwnd_update_packet_transmitted = sctp_cwnd_update_rtcc_packet_transmitted,
    2496             :         .sctp_cwnd_update_tsn_acknowledged = sctp_cwnd_update_rtcc_tsn_acknowledged,
    2497             :         .sctp_cwnd_new_transmission_begins = sctp_cwnd_new_rtcc_transmission_begins,
    2498             :         .sctp_cwnd_prepare_net_for_sack = sctp_cwnd_prepare_rtcc_net_for_sack,
    2499             :         .sctp_cwnd_socket_option = sctp_cwnd_rtcc_socket_option,
    2500             :         .sctp_rtt_calculated = sctp_rtt_rtcc_calculated
    2501             : #endif
    2502             : }
    2503             : };

Generated by: LCOV version 1.13