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