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