xref: /freebsd/sys/netinet/sctp_cc_functions.c (revision c3179e6660e1365111b89cb6c05c3a4c47375e73)
1b54d3a6cSRandall Stewart /*-
251369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni  *
4b54d3a6cSRandall Stewart  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
5807aad63SMichael Tuexen  * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
6807aad63SMichael Tuexen  * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
7b54d3a6cSRandall Stewart  *
8b54d3a6cSRandall Stewart  * Redistribution and use in source and binary forms, with or without
9b54d3a6cSRandall Stewart  * modification, are permitted provided that the following conditions are met:
10b54d3a6cSRandall Stewart  *
11b54d3a6cSRandall Stewart  * a) Redistributions of source code must retain the above copyright notice,
12b54d3a6cSRandall Stewart  *    this list of conditions and the following disclaimer.
13b54d3a6cSRandall Stewart  *
14b54d3a6cSRandall Stewart  * b) Redistributions in binary form must reproduce the above copyright
15b54d3a6cSRandall Stewart  *    notice, this list of conditions and the following disclaimer in
16b54d3a6cSRandall Stewart  *    the documentation and/or other materials provided with the distribution.
17b54d3a6cSRandall Stewart  *
18b54d3a6cSRandall Stewart  * c) Neither the name of Cisco Systems, Inc. nor the names of its
19b54d3a6cSRandall Stewart  *    contributors may be used to endorse or promote products derived
20b54d3a6cSRandall Stewart  *    from this software without specific prior written permission.
21b54d3a6cSRandall Stewart  *
22b54d3a6cSRandall Stewart  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23b54d3a6cSRandall Stewart  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24b54d3a6cSRandall Stewart  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25b54d3a6cSRandall Stewart  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26b54d3a6cSRandall Stewart  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27b54d3a6cSRandall Stewart  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28b54d3a6cSRandall Stewart  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29b54d3a6cSRandall Stewart  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30b54d3a6cSRandall Stewart  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31b54d3a6cSRandall Stewart  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32b54d3a6cSRandall Stewart  * THE POSSIBILITY OF SUCH DAMAGE.
33b54d3a6cSRandall Stewart  */
34b54d3a6cSRandall Stewart 
35b54d3a6cSRandall Stewart #include <netinet/sctp_os.h>
36b54d3a6cSRandall Stewart #include <netinet/sctp_var.h>
37b54d3a6cSRandall Stewart #include <netinet/sctp_sysctl.h>
38b54d3a6cSRandall Stewart #include <netinet/sctp_pcb.h>
39b54d3a6cSRandall Stewart #include <netinet/sctp_header.h>
40b54d3a6cSRandall Stewart #include <netinet/sctputil.h>
41b54d3a6cSRandall Stewart #include <netinet/sctp_output.h>
42b54d3a6cSRandall Stewart #include <netinet/sctp_input.h>
43b54d3a6cSRandall Stewart #include <netinet/sctp_indata.h>
44b54d3a6cSRandall Stewart #include <netinet/sctp_uio.h>
45b54d3a6cSRandall Stewart #include <netinet/sctp_timer.h>
46b54d3a6cSRandall Stewart #include <netinet/sctp_auth.h>
47b54d3a6cSRandall Stewart #include <netinet/sctp_asconf.h>
48fcfd8ad5SMichael Tuexen #include <netinet/sctp_kdtrace.h>
49dcfc0625SMichael Tuexen 
50c3d72c80SMichael Tuexen #define SHIFT_MPTCP_MULTI_N 40
51c3d72c80SMichael Tuexen #define SHIFT_MPTCP_MULTI_Z 16
52c3d72c80SMichael Tuexen #define SHIFT_MPTCP_MULTI 8
53c3d72c80SMichael Tuexen 
54*fb259f62SMichael Tuexen #ifdef KDTRACE_HOOKS
55db2ce691SMateusz Guzik #define __dtrace
56db2ce691SMateusz Guzik #else
57db2ce691SMateusz Guzik #define __dtrace __unused
58db2ce691SMateusz Guzik #endif
59db2ce691SMateusz Guzik 
600e9a9c10SMichael Tuexen static void
sctp_enforce_cwnd_limit(struct sctp_association * assoc,struct sctp_nets * net)6159b6d5beSMichael Tuexen sctp_enforce_cwnd_limit(struct sctp_association *assoc, struct sctp_nets *net)
6259b6d5beSMichael Tuexen {
6359b6d5beSMichael Tuexen 	if ((assoc->max_cwnd > 0) &&
6459b6d5beSMichael Tuexen 	    (net->cwnd > assoc->max_cwnd) &&
6559b6d5beSMichael Tuexen 	    (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
6659b6d5beSMichael Tuexen 		net->cwnd = assoc->max_cwnd;
6759b6d5beSMichael Tuexen 		if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
6859b6d5beSMichael Tuexen 			net->cwnd = net->mtu - sizeof(struct sctphdr);
6959b6d5beSMichael Tuexen 		}
7059b6d5beSMichael Tuexen 	}
7159b6d5beSMichael Tuexen }
7259b6d5beSMichael Tuexen 
7359b6d5beSMichael Tuexen static void
sctp_set_initial_cc_param(struct sctp_tcb * stcb,struct sctp_nets * net)74b54d3a6cSRandall Stewart sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
75b54d3a6cSRandall Stewart {
76dcfc0625SMichael Tuexen 	struct sctp_association *assoc;
77dcfc0625SMichael Tuexen 	uint32_t cwnd_in_mtu;
78b54d3a6cSRandall Stewart 
79dcfc0625SMichael Tuexen 	assoc = &stcb->asoc;
80dcfc0625SMichael Tuexen 	cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
81060bd882SMichael Tuexen 	if (cwnd_in_mtu == 0) {
82060bd882SMichael Tuexen 		/* Using 0 means that the value of RFC 4960 is used. */
83060bd882SMichael Tuexen 		net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
84060bd882SMichael Tuexen 	} else {
85060bd882SMichael Tuexen 		/*
86060bd882SMichael Tuexen 		 * We take the minimum of the burst limit and the initial
87060bd882SMichael Tuexen 		 * congestion window.
88060bd882SMichael Tuexen 		 */
89dcfc0625SMichael Tuexen 		if ((assoc->max_burst > 0) && (cwnd_in_mtu > assoc->max_burst))
90dcfc0625SMichael Tuexen 			cwnd_in_mtu = assoc->max_burst;
91dcfc0625SMichael Tuexen 		net->cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
92060bd882SMichael Tuexen 	}
93c3d72c80SMichael Tuexen 	if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
94c3d72c80SMichael Tuexen 	    (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
95ea8345d6SMichael Tuexen 		/* In case of resource pooling initialize appropriately */
96ea8345d6SMichael Tuexen 		net->cwnd /= assoc->numnets;
97ea8345d6SMichael Tuexen 		if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
98ea8345d6SMichael Tuexen 			net->cwnd = net->mtu - sizeof(struct sctphdr);
99ea8345d6SMichael Tuexen 		}
100ea8345d6SMichael Tuexen 	}
10159b6d5beSMichael Tuexen 	sctp_enforce_cwnd_limit(assoc, net);
102dcfc0625SMichael Tuexen 	net->ssthresh = assoc->peers_rwnd;
10336160958SMark Johnston 	SDT_PROBE5(sctp, cwnd, net, init,
1046324ca61SRandall Stewart 	    stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
1056324ca61SRandall Stewart 	    0, net->cwnd);
106dcfc0625SMichael Tuexen 	if (SCTP_BASE_SYSCTL(sctp_logging_level) &
107dcfc0625SMichael Tuexen 	    (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
108b54d3a6cSRandall Stewart 		sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
109b54d3a6cSRandall Stewart 	}
110b54d3a6cSRandall Stewart }
111b54d3a6cSRandall Stewart 
1120e9a9c10SMichael Tuexen static void
sctp_cwnd_update_after_fr(struct sctp_tcb * stcb,struct sctp_association * asoc)113b54d3a6cSRandall Stewart sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
114b54d3a6cSRandall Stewart     struct sctp_association *asoc)
115b54d3a6cSRandall Stewart {
116b54d3a6cSRandall Stewart 	struct sctp_nets *net;
117ea8345d6SMichael Tuexen 	uint32_t t_ssthresh, t_cwnd;
118c3d72c80SMichael Tuexen 	uint64_t t_ucwnd_sbw;
119b54d3a6cSRandall Stewart 
120ea8345d6SMichael Tuexen 	/* MT FIXME: Don't compute this over and over again */
121ea8345d6SMichael Tuexen 	t_ssthresh = 0;
122ea8345d6SMichael Tuexen 	t_cwnd = 0;
123c3d72c80SMichael Tuexen 	t_ucwnd_sbw = 0;
124c3d72c80SMichael Tuexen 	if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
125c3d72c80SMichael Tuexen 	    (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
126ea8345d6SMichael Tuexen 		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
127ea8345d6SMichael Tuexen 			t_ssthresh += net->ssthresh;
128ea8345d6SMichael Tuexen 			t_cwnd += net->cwnd;
129c3d72c80SMichael Tuexen 			if (net->lastsa > 0) {
130c3d72c80SMichael Tuexen 				t_ucwnd_sbw += (uint64_t)net->cwnd / (uint64_t)net->lastsa;
131c3d72c80SMichael Tuexen 			}
132c3d72c80SMichael Tuexen 		}
133c3d72c80SMichael Tuexen 		if (t_ucwnd_sbw == 0) {
134c3d72c80SMichael Tuexen 			t_ucwnd_sbw = 1;
135ea8345d6SMichael Tuexen 		}
136ea8345d6SMichael Tuexen 	}
1370053ed28SMichael Tuexen 
138b54d3a6cSRandall Stewart 	/*-
1397c99d56fSMichael Tuexen 	 * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
140b54d3a6cSRandall Stewart 	 * (net->fast_retran_loss_recovery == 0)))
141b54d3a6cSRandall Stewart 	 */
142b54d3a6cSRandall Stewart 	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
14320083c2eSMichael Tuexen 		if ((asoc->fast_retran_loss_recovery == 0) ||
1447c99d56fSMichael Tuexen 		    (asoc->sctp_cmt_on_off > 0)) {
145b54d3a6cSRandall Stewart 			/* out of a RFC2582 Fast recovery window? */
146b54d3a6cSRandall Stewart 			if (net->net_ack > 0) {
147b54d3a6cSRandall Stewart 				/*
148b54d3a6cSRandall Stewart 				 * per section 7.2.3, are there any
149b54d3a6cSRandall Stewart 				 * destinations that had a fast retransmit
150b54d3a6cSRandall Stewart 				 * to them. If so what we need to do is
151b54d3a6cSRandall Stewart 				 * adjust ssthresh and cwnd.
152b54d3a6cSRandall Stewart 				 */
153b54d3a6cSRandall Stewart 				struct sctp_tmit_chunk *lchk;
154b54d3a6cSRandall Stewart 				int old_cwnd = net->cwnd;
155b54d3a6cSRandall Stewart 
156c3d72c80SMichael Tuexen 				if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
157c3d72c80SMichael Tuexen 				    (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
158c3d72c80SMichael Tuexen 					if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) {
159ea8345d6SMichael Tuexen 						net->ssthresh = (uint32_t)(((uint64_t)4 *
160ea8345d6SMichael Tuexen 						    (uint64_t)net->mtu *
161ea8345d6SMichael Tuexen 						    (uint64_t)net->ssthresh) /
162ea8345d6SMichael Tuexen 						    (uint64_t)t_ssthresh);
163c3d72c80SMichael Tuexen 					}
164c3d72c80SMichael Tuexen 					if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2) {
165c3d72c80SMichael Tuexen 						uint32_t srtt;
166c3d72c80SMichael Tuexen 
167c3d72c80SMichael Tuexen 						srtt = net->lastsa;
168b7b84c0eSMichael Tuexen 						/*
169b7b84c0eSMichael Tuexen 						 * lastsa>>3;  we don't need
170b7b84c0eSMichael Tuexen 						 * to devide ...
171b7b84c0eSMichael Tuexen 						 */
172c3d72c80SMichael Tuexen 						if (srtt == 0) {
173c3d72c80SMichael Tuexen 							srtt = 1;
174c3d72c80SMichael Tuexen 						}
175b7b84c0eSMichael Tuexen 						/*
176b7b84c0eSMichael Tuexen 						 * Short Version => Equal to
177b7b84c0eSMichael Tuexen 						 * Contel Version MBe
178b7b84c0eSMichael Tuexen 						 */
179c3d72c80SMichael Tuexen 						net->ssthresh = (uint32_t)(((uint64_t)4 *
180c3d72c80SMichael Tuexen 						    (uint64_t)net->mtu *
181c3d72c80SMichael Tuexen 						    (uint64_t)net->cwnd) /
182c3d72c80SMichael Tuexen 						    ((uint64_t)srtt *
183c3d72c80SMichael Tuexen 						    t_ucwnd_sbw));
184c3d72c80SMichael Tuexen 						 /* INCREASE FACTOR */ ;
185c3d72c80SMichael Tuexen 					}
186ea8345d6SMichael Tuexen 					if ((net->cwnd > t_cwnd / 2) &&
187ea8345d6SMichael Tuexen 					    (net->ssthresh < net->cwnd - t_cwnd / 2)) {
188ea8345d6SMichael Tuexen 						net->ssthresh = net->cwnd - t_cwnd / 2;
189ea8345d6SMichael Tuexen 					}
190ea8345d6SMichael Tuexen 					if (net->ssthresh < net->mtu) {
191ea8345d6SMichael Tuexen 						net->ssthresh = net->mtu;
192ea8345d6SMichael Tuexen 					}
193ea8345d6SMichael Tuexen 				} else {
194b54d3a6cSRandall Stewart 					net->ssthresh = net->cwnd / 2;
195b54d3a6cSRandall Stewart 					if (net->ssthresh < (net->mtu * 2)) {
196b54d3a6cSRandall Stewart 						net->ssthresh = 2 * net->mtu;
197b54d3a6cSRandall Stewart 					}
198ea8345d6SMichael Tuexen 				}
199b54d3a6cSRandall Stewart 				net->cwnd = net->ssthresh;
20059b6d5beSMichael Tuexen 				sctp_enforce_cwnd_limit(asoc, net);
20136160958SMark Johnston 				SDT_PROBE5(sctp, cwnd, net, fr,
2026324ca61SRandall Stewart 				    stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
2036324ca61SRandall Stewart 				    old_cwnd, net->cwnd);
204b3f1ea41SRandall Stewart 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
205b54d3a6cSRandall Stewart 					sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
206b54d3a6cSRandall Stewart 					    SCTP_CWND_LOG_FROM_FR);
207b54d3a6cSRandall Stewart 				}
208b54d3a6cSRandall Stewart 				lchk = TAILQ_FIRST(&asoc->send_queue);
209b54d3a6cSRandall Stewart 
210b54d3a6cSRandall Stewart 				net->partial_bytes_acked = 0;
211b54d3a6cSRandall Stewart 				/* Turn on fast recovery window */
212b54d3a6cSRandall Stewart 				asoc->fast_retran_loss_recovery = 1;
213b54d3a6cSRandall Stewart 				if (lchk == NULL) {
214b54d3a6cSRandall Stewart 					/* Mark end of the window */
215b54d3a6cSRandall Stewart 					asoc->fast_recovery_tsn = asoc->sending_seq - 1;
216b54d3a6cSRandall Stewart 				} else {
21749656eefSMichael Tuexen 					asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1;
218b54d3a6cSRandall Stewart 				}
219b54d3a6cSRandall Stewart 
220b54d3a6cSRandall Stewart 				/*
221b54d3a6cSRandall Stewart 				 * CMT fast recovery -- per destination
222b54d3a6cSRandall Stewart 				 * recovery variable.
223b54d3a6cSRandall Stewart 				 */
224b54d3a6cSRandall Stewart 				net->fast_retran_loss_recovery = 1;
225b54d3a6cSRandall Stewart 
226b54d3a6cSRandall Stewart 				if (lchk == NULL) {
227b54d3a6cSRandall Stewart 					/* Mark end of the window */
228b54d3a6cSRandall Stewart 					net->fast_recovery_tsn = asoc->sending_seq - 1;
229b54d3a6cSRandall Stewart 				} else {
23049656eefSMichael Tuexen 					net->fast_recovery_tsn = lchk->rec.data.tsn - 1;
231b54d3a6cSRandall Stewart 				}
232b54d3a6cSRandall Stewart 
233b54d3a6cSRandall Stewart 				sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
234b7d130beSMichael Tuexen 				    stcb->sctp_ep, stcb, net,
235b7d130beSMichael Tuexen 				    SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_1);
236b54d3a6cSRandall Stewart 				sctp_timer_start(SCTP_TIMER_TYPE_SEND,
237b54d3a6cSRandall Stewart 				    stcb->sctp_ep, stcb, net);
238b54d3a6cSRandall Stewart 			}
239b54d3a6cSRandall Stewart 		} else if (net->net_ack > 0) {
240b54d3a6cSRandall Stewart 			/*
241b54d3a6cSRandall Stewart 			 * Mark a peg that we WOULD have done a cwnd
242b54d3a6cSRandall Stewart 			 * reduction but RFC2582 prevented this action.
243b54d3a6cSRandall Stewart 			 */
244b54d3a6cSRandall Stewart 			SCTP_STAT_INCR(sctps_fastretransinrtt);
245b54d3a6cSRandall Stewart 		}
246b54d3a6cSRandall Stewart 	}
247b54d3a6cSRandall Stewart }
248b54d3a6cSRandall Stewart 
249f79aab18SRandall Stewart /* Defines for instantaneous bw decisions */
250cd0a4ff6SPedro F. Giffuni #define SCTP_INST_LOOSING 1	/* Losing to other flows */
251f79aab18SRandall Stewart #define SCTP_INST_NEUTRAL 2	/* Neutral, no indication */
252f79aab18SRandall Stewart #define SCTP_INST_GAINING 3	/* Gaining, step down possible */
253f79aab18SRandall Stewart 
254f79aab18SRandall Stewart static int
cc_bw_same(struct sctp_tcb * stcb,struct sctp_nets * net,uint64_t nbw,uint64_t rtt_offset,uint64_t vtag,uint8_t inst_ind)255f79aab18SRandall Stewart cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
256f79aab18SRandall Stewart     uint64_t rtt_offset, uint64_t vtag, uint8_t inst_ind)
257f79aab18SRandall Stewart {
258db2ce691SMateusz Guzik 	uint64_t oth __dtrace, probepoint __dtrace;
259f79aab18SRandall Stewart 
260f79aab18SRandall Stewart 	probepoint = (((uint64_t)net->cwnd) << 32);
261f79aab18SRandall Stewart 	if (net->rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) {
262f79aab18SRandall Stewart 		/*
263f79aab18SRandall Stewart 		 * rtt increased we don't update bw.. so we don't update the
264f79aab18SRandall Stewart 		 * rtt either.
265f79aab18SRandall Stewart 		 */
266f79aab18SRandall Stewart 		/* Probe point 5 */
267f79aab18SRandall Stewart 		probepoint |= ((5 << 16) | 1);
26836160958SMark Johnston 		SDT_PROBE5(sctp, cwnd, net, rttvar,
269f79aab18SRandall Stewart 		    vtag,
270f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw << 32) | nbw),
271f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
272f79aab18SRandall Stewart 		    net->flight_size,
273f79aab18SRandall Stewart 		    probepoint);
274f79aab18SRandall Stewart 		if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
275f79aab18SRandall Stewart 			if (net->cc_mod.rtcc.last_step_state == 5)
276f79aab18SRandall Stewart 				net->cc_mod.rtcc.step_cnt++;
277f79aab18SRandall Stewart 			else
278f79aab18SRandall Stewart 				net->cc_mod.rtcc.step_cnt = 1;
279f79aab18SRandall Stewart 			net->cc_mod.rtcc.last_step_state = 5;
280f79aab18SRandall Stewart 			if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
281f79aab18SRandall Stewart 			    ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
282f79aab18SRandall Stewart 			    ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
283f79aab18SRandall Stewart 				/* Try a step down */
284f79aab18SRandall Stewart 				oth = net->cc_mod.rtcc.vol_reduce;
285f79aab18SRandall Stewart 				oth <<= 16;
286f79aab18SRandall Stewart 				oth |= net->cc_mod.rtcc.step_cnt;
287f79aab18SRandall Stewart 				oth <<= 16;
288f79aab18SRandall Stewart 				oth |= net->cc_mod.rtcc.last_step_state;
28936160958SMark Johnston 				SDT_PROBE5(sctp, cwnd, net, rttstep,
290f79aab18SRandall Stewart 				    vtag,
291f79aab18SRandall Stewart 				    ((net->cc_mod.rtcc.lbw << 32) | nbw),
292f79aab18SRandall Stewart 				    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
293f79aab18SRandall Stewart 				    oth,
294f79aab18SRandall Stewart 				    probepoint);
295f79aab18SRandall Stewart 				if (net->cwnd > (4 * net->mtu)) {
296f79aab18SRandall Stewart 					net->cwnd -= net->mtu;
297f79aab18SRandall Stewart 					net->cc_mod.rtcc.vol_reduce++;
298f79aab18SRandall Stewart 				} else {
299f79aab18SRandall Stewart 					net->cc_mod.rtcc.step_cnt = 0;
300f79aab18SRandall Stewart 				}
301f79aab18SRandall Stewart 			}
302f79aab18SRandall Stewart 		}
303f79aab18SRandall Stewart 		return (1);
304f79aab18SRandall Stewart 	}
305f79aab18SRandall Stewart 	if (net->rtt < net->cc_mod.rtcc.lbw_rtt - rtt_offset) {
306f79aab18SRandall Stewart 		/*
307f79aab18SRandall Stewart 		 * rtt decreased, there could be more room. we update both
308f79aab18SRandall Stewart 		 * the bw and the rtt here to lock this in as a good step
309f79aab18SRandall Stewart 		 * down.
310f79aab18SRandall Stewart 		 */
311f79aab18SRandall Stewart 		/* Probe point 6 */
312f79aab18SRandall Stewart 		probepoint |= ((6 << 16) | 0);
31336160958SMark Johnston 		SDT_PROBE5(sctp, cwnd, net, rttvar,
314f79aab18SRandall Stewart 		    vtag,
315f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw << 32) | nbw),
316f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
317f79aab18SRandall Stewart 		    net->flight_size,
318f79aab18SRandall Stewart 		    probepoint);
319f79aab18SRandall Stewart 		if (net->cc_mod.rtcc.steady_step) {
320f79aab18SRandall Stewart 			oth = net->cc_mod.rtcc.vol_reduce;
321f79aab18SRandall Stewart 			oth <<= 16;
322f79aab18SRandall Stewart 			oth |= net->cc_mod.rtcc.step_cnt;
323f79aab18SRandall Stewart 			oth <<= 16;
324f79aab18SRandall Stewart 			oth |= net->cc_mod.rtcc.last_step_state;
32536160958SMark Johnston 			SDT_PROBE5(sctp, cwnd, net, rttstep,
326f79aab18SRandall Stewart 			    vtag,
327f79aab18SRandall Stewart 			    ((net->cc_mod.rtcc.lbw << 32) | nbw),
328f79aab18SRandall Stewart 			    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
329f79aab18SRandall Stewart 			    oth,
330f79aab18SRandall Stewart 			    probepoint);
331f79aab18SRandall Stewart 			if ((net->cc_mod.rtcc.last_step_state == 5) &&
332f79aab18SRandall Stewart 			    (net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step)) {
333f79aab18SRandall Stewart 				/* Step down worked */
334f79aab18SRandall Stewart 				net->cc_mod.rtcc.step_cnt = 0;
335f79aab18SRandall Stewart 				return (1);
336f79aab18SRandall Stewart 			} else {
337f79aab18SRandall Stewart 				net->cc_mod.rtcc.last_step_state = 6;
338f79aab18SRandall Stewart 				net->cc_mod.rtcc.step_cnt = 0;
339f79aab18SRandall Stewart 			}
340f79aab18SRandall Stewart 		}
341f79aab18SRandall Stewart 		net->cc_mod.rtcc.lbw = nbw;
342f79aab18SRandall Stewart 		net->cc_mod.rtcc.lbw_rtt = net->rtt;
343f79aab18SRandall Stewart 		net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
344f79aab18SRandall Stewart 		if (inst_ind == SCTP_INST_GAINING)
345f79aab18SRandall Stewart 			return (1);
346f79aab18SRandall Stewart 		else if (inst_ind == SCTP_INST_NEUTRAL)
347f79aab18SRandall Stewart 			return (1);
348f79aab18SRandall Stewart 		else
349f79aab18SRandall Stewart 			return (0);
350f79aab18SRandall Stewart 	}
351f79aab18SRandall Stewart 	/*
352f79aab18SRandall Stewart 	 * Ok bw and rtt remained the same .. no update to any
353f79aab18SRandall Stewart 	 */
354f79aab18SRandall Stewart 	/* Probe point 7 */
355f79aab18SRandall Stewart 	probepoint |= ((7 << 16) | net->cc_mod.rtcc.ret_from_eq);
35636160958SMark Johnston 	SDT_PROBE5(sctp, cwnd, net, rttvar,
357f79aab18SRandall Stewart 	    vtag,
358f79aab18SRandall Stewart 	    ((net->cc_mod.rtcc.lbw << 32) | nbw),
359f79aab18SRandall Stewart 	    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
360f79aab18SRandall Stewart 	    net->flight_size,
361f79aab18SRandall Stewart 	    probepoint);
362f79aab18SRandall Stewart 	if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
363f79aab18SRandall Stewart 		if (net->cc_mod.rtcc.last_step_state == 5)
364f79aab18SRandall Stewart 			net->cc_mod.rtcc.step_cnt++;
365f79aab18SRandall Stewart 		else
366f79aab18SRandall Stewart 			net->cc_mod.rtcc.step_cnt = 1;
367f79aab18SRandall Stewart 		net->cc_mod.rtcc.last_step_state = 5;
368f79aab18SRandall Stewart 		if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
369f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
370f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
371f79aab18SRandall Stewart 			/* Try a step down */
372f79aab18SRandall Stewart 			if (net->cwnd > (4 * net->mtu)) {
373f79aab18SRandall Stewart 				net->cwnd -= net->mtu;
374f79aab18SRandall Stewart 				net->cc_mod.rtcc.vol_reduce++;
375f79aab18SRandall Stewart 				return (1);
376f79aab18SRandall Stewart 			} else {
377f79aab18SRandall Stewart 				net->cc_mod.rtcc.step_cnt = 0;
378f79aab18SRandall Stewart 			}
379f79aab18SRandall Stewart 		}
380f79aab18SRandall Stewart 	}
381f79aab18SRandall Stewart 	if (inst_ind == SCTP_INST_GAINING)
382f79aab18SRandall Stewart 		return (1);
383f79aab18SRandall Stewart 	else if (inst_ind == SCTP_INST_NEUTRAL)
384f79aab18SRandall Stewart 		return (1);
385f79aab18SRandall Stewart 	else
386f79aab18SRandall Stewart 		return ((int)net->cc_mod.rtcc.ret_from_eq);
387f79aab18SRandall Stewart }
388f79aab18SRandall Stewart 
389f79aab18SRandall Stewart static int
cc_bw_decrease(struct sctp_tcb * stcb,struct sctp_nets * net,uint64_t nbw,uint64_t rtt_offset,uint64_t vtag,uint8_t inst_ind)390f79aab18SRandall Stewart cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset,
391f79aab18SRandall Stewart     uint64_t vtag, uint8_t inst_ind)
392f79aab18SRandall Stewart {
393db2ce691SMateusz Guzik 	uint64_t oth __dtrace, probepoint __dtrace;
394f79aab18SRandall Stewart 
395f79aab18SRandall Stewart 	/* Bandwidth decreased. */
396f79aab18SRandall Stewart 	probepoint = (((uint64_t)net->cwnd) << 32);
397f79aab18SRandall Stewart 	if (net->rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) {
398f79aab18SRandall Stewart 		/* rtt increased */
399f79aab18SRandall Stewart 		/* Did we add more */
400f79aab18SRandall Stewart 		if ((net->cwnd > net->cc_mod.rtcc.cwnd_at_bw_set) &&
401f79aab18SRandall Stewart 		    (inst_ind != SCTP_INST_LOOSING)) {
402f79aab18SRandall Stewart 			/* We caused it maybe.. back off? */
403f79aab18SRandall Stewart 			/* PROBE POINT 1 */
404f79aab18SRandall Stewart 			probepoint |= ((1 << 16) | 1);
40536160958SMark Johnston 			SDT_PROBE5(sctp, cwnd, net, rttvar,
406f79aab18SRandall Stewart 			    vtag,
407f79aab18SRandall Stewart 			    ((net->cc_mod.rtcc.lbw << 32) | nbw),
408f79aab18SRandall Stewart 			    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
409f79aab18SRandall Stewart 			    net->flight_size,
410f79aab18SRandall Stewart 			    probepoint);
411f79aab18SRandall Stewart 			if (net->cc_mod.rtcc.ret_from_eq) {
412b7b84c0eSMichael Tuexen 				/*
413b7b84c0eSMichael Tuexen 				 * Switch over to CA if we are less
414b7b84c0eSMichael Tuexen 				 * aggressive
415b7b84c0eSMichael Tuexen 				 */
416f79aab18SRandall Stewart 				net->ssthresh = net->cwnd - 1;
417f79aab18SRandall Stewart 				net->partial_bytes_acked = 0;
418f79aab18SRandall Stewart 			}
419f79aab18SRandall Stewart 			return (1);
420f79aab18SRandall Stewart 		}
421f79aab18SRandall Stewart 		/* Probe point 2 */
422f79aab18SRandall Stewart 		probepoint |= ((2 << 16) | 0);
42336160958SMark Johnston 		SDT_PROBE5(sctp, cwnd, net, rttvar,
424f79aab18SRandall Stewart 		    vtag,
425f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw << 32) | nbw),
426f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
427f79aab18SRandall Stewart 		    net->flight_size,
428f79aab18SRandall Stewart 		    probepoint);
429f79aab18SRandall Stewart 		/* Someone else - fight for more? */
430f79aab18SRandall Stewart 		if (net->cc_mod.rtcc.steady_step) {
431f79aab18SRandall Stewart 			oth = net->cc_mod.rtcc.vol_reduce;
432f79aab18SRandall Stewart 			oth <<= 16;
433f79aab18SRandall Stewart 			oth |= net->cc_mod.rtcc.step_cnt;
434f79aab18SRandall Stewart 			oth <<= 16;
435f79aab18SRandall Stewart 			oth |= net->cc_mod.rtcc.last_step_state;
43636160958SMark Johnston 			SDT_PROBE5(sctp, cwnd, net, rttstep,
437f79aab18SRandall Stewart 			    vtag,
438f79aab18SRandall Stewart 			    ((net->cc_mod.rtcc.lbw << 32) | nbw),
439f79aab18SRandall Stewart 			    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
440f79aab18SRandall Stewart 			    oth,
441f79aab18SRandall Stewart 			    probepoint);
442f79aab18SRandall Stewart 			/*
443f79aab18SRandall Stewart 			 * Did we voluntarily give up some? if so take one
444f79aab18SRandall Stewart 			 * back please
445f79aab18SRandall Stewart 			 */
446f79aab18SRandall Stewart 			if ((net->cc_mod.rtcc.vol_reduce) &&
447f79aab18SRandall Stewart 			    (inst_ind != SCTP_INST_GAINING)) {
448f79aab18SRandall Stewart 				net->cwnd += net->mtu;
44959b6d5beSMichael Tuexen 				sctp_enforce_cwnd_limit(&stcb->asoc, net);
450f79aab18SRandall Stewart 				net->cc_mod.rtcc.vol_reduce--;
451f79aab18SRandall Stewart 			}
452f79aab18SRandall Stewart 			net->cc_mod.rtcc.last_step_state = 2;
453f79aab18SRandall Stewart 			net->cc_mod.rtcc.step_cnt = 0;
454f79aab18SRandall Stewart 		}
455f79aab18SRandall Stewart 		goto out_decision;
456f79aab18SRandall Stewart 	} else if (net->rtt < net->cc_mod.rtcc.lbw_rtt - rtt_offset) {
457f79aab18SRandall Stewart 		/* bw & rtt decreased */
458f79aab18SRandall Stewart 		/* Probe point 3 */
459f79aab18SRandall Stewart 		probepoint |= ((3 << 16) | 0);
46036160958SMark Johnston 		SDT_PROBE5(sctp, cwnd, net, rttvar,
461f79aab18SRandall Stewart 		    vtag,
462f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw << 32) | nbw),
463f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
464f79aab18SRandall Stewart 		    net->flight_size,
465f79aab18SRandall Stewart 		    probepoint);
466f79aab18SRandall Stewart 		if (net->cc_mod.rtcc.steady_step) {
467f79aab18SRandall Stewart 			oth = net->cc_mod.rtcc.vol_reduce;
468f79aab18SRandall Stewart 			oth <<= 16;
469f79aab18SRandall Stewart 			oth |= net->cc_mod.rtcc.step_cnt;
470f79aab18SRandall Stewart 			oth <<= 16;
471f79aab18SRandall Stewart 			oth |= net->cc_mod.rtcc.last_step_state;
47236160958SMark Johnston 			SDT_PROBE5(sctp, cwnd, net, rttstep,
473f79aab18SRandall Stewart 			    vtag,
474f79aab18SRandall Stewart 			    ((net->cc_mod.rtcc.lbw << 32) | nbw),
475f79aab18SRandall Stewart 			    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
476f79aab18SRandall Stewart 			    oth,
477f79aab18SRandall Stewart 			    probepoint);
478f79aab18SRandall Stewart 			if ((net->cc_mod.rtcc.vol_reduce) &&
479f79aab18SRandall Stewart 			    (inst_ind != SCTP_INST_GAINING)) {
480f79aab18SRandall Stewart 				net->cwnd += net->mtu;
48159b6d5beSMichael Tuexen 				sctp_enforce_cwnd_limit(&stcb->asoc, net);
482f79aab18SRandall Stewart 				net->cc_mod.rtcc.vol_reduce--;
483f79aab18SRandall Stewart 			}
484f79aab18SRandall Stewart 			net->cc_mod.rtcc.last_step_state = 3;
485f79aab18SRandall Stewart 			net->cc_mod.rtcc.step_cnt = 0;
486f79aab18SRandall Stewart 		}
487f79aab18SRandall Stewart 		goto out_decision;
488f79aab18SRandall Stewart 	}
489f79aab18SRandall Stewart 	/* The bw decreased but rtt stayed the same */
490f79aab18SRandall Stewart 	/* Probe point 4 */
491f79aab18SRandall Stewart 	probepoint |= ((4 << 16) | 0);
49236160958SMark Johnston 	SDT_PROBE5(sctp, cwnd, net, rttvar,
493f79aab18SRandall Stewart 	    vtag,
494f79aab18SRandall Stewart 	    ((net->cc_mod.rtcc.lbw << 32) | nbw),
495f79aab18SRandall Stewart 	    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
496f79aab18SRandall Stewart 	    net->flight_size,
497f79aab18SRandall Stewart 	    probepoint);
498f79aab18SRandall Stewart 	if (net->cc_mod.rtcc.steady_step) {
499f79aab18SRandall Stewart 		oth = net->cc_mod.rtcc.vol_reduce;
500f79aab18SRandall Stewart 		oth <<= 16;
501f79aab18SRandall Stewart 		oth |= net->cc_mod.rtcc.step_cnt;
502f79aab18SRandall Stewart 		oth <<= 16;
503f79aab18SRandall Stewart 		oth |= net->cc_mod.rtcc.last_step_state;
50436160958SMark Johnston 		SDT_PROBE5(sctp, cwnd, net, rttstep,
505f79aab18SRandall Stewart 		    vtag,
506f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw << 32) | nbw),
507f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
508f79aab18SRandall Stewart 		    oth,
509f79aab18SRandall Stewart 		    probepoint);
510f79aab18SRandall Stewart 		if ((net->cc_mod.rtcc.vol_reduce) &&
511f79aab18SRandall Stewart 		    (inst_ind != SCTP_INST_GAINING)) {
512f79aab18SRandall Stewart 			net->cwnd += net->mtu;
51359b6d5beSMichael Tuexen 			sctp_enforce_cwnd_limit(&stcb->asoc, net);
514f79aab18SRandall Stewart 			net->cc_mod.rtcc.vol_reduce--;
515f79aab18SRandall Stewart 		}
516f79aab18SRandall Stewart 		net->cc_mod.rtcc.last_step_state = 4;
517f79aab18SRandall Stewart 		net->cc_mod.rtcc.step_cnt = 0;
518f79aab18SRandall Stewart 	}
519f79aab18SRandall Stewart out_decision:
520f79aab18SRandall Stewart 	net->cc_mod.rtcc.lbw = nbw;
521f79aab18SRandall Stewart 	net->cc_mod.rtcc.lbw_rtt = net->rtt;
522f79aab18SRandall Stewart 	net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
523f79aab18SRandall Stewart 	if (inst_ind == SCTP_INST_GAINING) {
524f79aab18SRandall Stewart 		return (1);
525f79aab18SRandall Stewart 	} else {
526f79aab18SRandall Stewart 		return (0);
527f79aab18SRandall Stewart 	}
528f79aab18SRandall Stewart }
529f79aab18SRandall Stewart 
530f79aab18SRandall Stewart static int
cc_bw_increase(struct sctp_tcb * stcb,struct sctp_nets * net,uint64_t nbw,uint64_t vtag)5317215cc1bSMichael Tuexen cc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t vtag)
532f79aab18SRandall Stewart {
533db2ce691SMateusz Guzik 	uint64_t oth __dtrace, probepoint __dtrace;
534f79aab18SRandall Stewart 
535f79aab18SRandall Stewart 	/*
536f79aab18SRandall Stewart 	 * BW increased, so update and return 0, since all actions in our
537f79aab18SRandall Stewart 	 * table say to do the normal CC update. Note that we pay no
538f79aab18SRandall Stewart 	 * attention to the inst_ind since our overall sum is increasing.
539f79aab18SRandall Stewart 	 */
540f79aab18SRandall Stewart 	/* PROBE POINT 0 */
541f79aab18SRandall Stewart 	probepoint = (((uint64_t)net->cwnd) << 32);
54236160958SMark Johnston 	SDT_PROBE5(sctp, cwnd, net, rttvar,
543f79aab18SRandall Stewart 	    vtag,
544f79aab18SRandall Stewart 	    ((net->cc_mod.rtcc.lbw << 32) | nbw),
545f79aab18SRandall Stewart 	    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
546f79aab18SRandall Stewart 	    net->flight_size,
547f79aab18SRandall Stewart 	    probepoint);
548f79aab18SRandall Stewart 	if (net->cc_mod.rtcc.steady_step) {
549f79aab18SRandall Stewart 		oth = net->cc_mod.rtcc.vol_reduce;
550f79aab18SRandall Stewart 		oth <<= 16;
551f79aab18SRandall Stewart 		oth |= net->cc_mod.rtcc.step_cnt;
552f79aab18SRandall Stewart 		oth <<= 16;
553f79aab18SRandall Stewart 		oth |= net->cc_mod.rtcc.last_step_state;
55436160958SMark Johnston 		SDT_PROBE5(sctp, cwnd, net, rttstep,
555f79aab18SRandall Stewart 		    vtag,
556f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw << 32) | nbw),
557f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
558f79aab18SRandall Stewart 		    oth,
559f79aab18SRandall Stewart 		    probepoint);
560f79aab18SRandall Stewart 		net->cc_mod.rtcc.last_step_state = 0;
561f79aab18SRandall Stewart 		net->cc_mod.rtcc.step_cnt = 0;
562f79aab18SRandall Stewart 		net->cc_mod.rtcc.vol_reduce = 0;
563f79aab18SRandall Stewart 	}
564f79aab18SRandall Stewart 	net->cc_mod.rtcc.lbw = nbw;
565f79aab18SRandall Stewart 	net->cc_mod.rtcc.lbw_rtt = net->rtt;
566f79aab18SRandall Stewart 	net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
567f79aab18SRandall Stewart 	return (0);
568f79aab18SRandall Stewart }
56948b6c649SRandall Stewart 
570cd0a4ff6SPedro F. Giffuni /* RTCC Algorithm to limit growth of cwnd, return
57148b6c649SRandall Stewart  * true if you want to NOT allow cwnd growth
57248b6c649SRandall Stewart  */
57348b6c649SRandall Stewart static int
cc_bw_limit(struct sctp_tcb * stcb,struct sctp_nets * net,uint64_t nbw)57448b6c649SRandall Stewart cc_bw_limit(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw)
57548b6c649SRandall Stewart {
57660990c0cSMichael Tuexen 	uint64_t bw_offset, rtt_offset;
577db2ce691SMateusz Guzik 	uint64_t probepoint __dtrace, rtt, vtag;
578f79aab18SRandall Stewart 	uint64_t bytes_for_this_rtt, inst_bw;
579f79aab18SRandall Stewart 	uint64_t div, inst_off;
580f79aab18SRandall Stewart 	int bw_shift;
581f79aab18SRandall Stewart 	uint8_t inst_ind;
582f79aab18SRandall Stewart 	int ret;
58348b6c649SRandall Stewart 
58448b6c649SRandall Stewart 	/*-
58548b6c649SRandall Stewart 	 * Here we need to see if we want
58648b6c649SRandall Stewart 	 * to limit cwnd growth due to increase
58748b6c649SRandall Stewart 	 * in overall rtt but no increase in bw.
58848b6c649SRandall Stewart 	 * We use the following table to figure
58948b6c649SRandall Stewart 	 * out what we should do. When we return
59048b6c649SRandall Stewart 	 * 0, cc update goes on as planned. If we
59148b6c649SRandall Stewart 	 * return 1, then no cc update happens and cwnd
59248b6c649SRandall Stewart 	 * stays where it is at.
59348b6c649SRandall Stewart 	 * ----------------------------------
59448b6c649SRandall Stewart 	 *   BW    |    RTT   | Action
59548b6c649SRandall Stewart 	 * *********************************
59648b6c649SRandall Stewart 	 *   INC   |    INC   | return 0
59748b6c649SRandall Stewart 	 * ----------------------------------
59848b6c649SRandall Stewart 	 *   INC   |    SAME  | return 0
59948b6c649SRandall Stewart 	 * ----------------------------------
60048b6c649SRandall Stewart 	 *   INC   |    DECR  | return 0
60148b6c649SRandall Stewart 	 * ----------------------------------
60248b6c649SRandall Stewart 	 *   SAME  |    INC   | return 1
60348b6c649SRandall Stewart 	 * ----------------------------------
60448b6c649SRandall Stewart 	 *   SAME  |    SAME  | return 1
60548b6c649SRandall Stewart 	 * ----------------------------------
60648b6c649SRandall Stewart 	 *   SAME  |    DECR  | return 0
60748b6c649SRandall Stewart 	 * ----------------------------------
60848b6c649SRandall Stewart 	 *   DECR  |    INC   | return 0 or 1 based on if we caused.
60948b6c649SRandall Stewart 	 * ----------------------------------
61048b6c649SRandall Stewart 	 *   DECR  |    SAME  | return 0
61148b6c649SRandall Stewart 	 * ----------------------------------
61248b6c649SRandall Stewart 	 *   DECR  |    DECR  | return 0
61348b6c649SRandall Stewart 	 * ----------------------------------
61448b6c649SRandall Stewart 	 *
61548b6c649SRandall Stewart 	 * We are a bit fuzz on what an increase or
61648b6c649SRandall Stewart 	 * decrease is. For BW it is the same if
61748b6c649SRandall Stewart 	 * it did not change within 1/64th. For
61848b6c649SRandall Stewart 	 * RTT it stayed the same if it did not
61948b6c649SRandall Stewart 	 * change within 1/32nd
62048b6c649SRandall Stewart 	 */
621f79aab18SRandall Stewart 	bw_shift = SCTP_BASE_SYSCTL(sctp_rttvar_bw);
62248b6c649SRandall Stewart 	rtt = stcb->asoc.my_vtag;
62348b6c649SRandall Stewart 	vtag = (rtt << 32) | (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) | (stcb->rport);
62448b6c649SRandall Stewart 	probepoint = (((uint64_t)net->cwnd) << 32);
62548b6c649SRandall Stewart 	rtt = net->rtt;
626f79aab18SRandall Stewart 	if (net->cc_mod.rtcc.rtt_set_this_sack) {
627f79aab18SRandall Stewart 		net->cc_mod.rtcc.rtt_set_this_sack = 0;
628f79aab18SRandall Stewart 		bytes_for_this_rtt = net->cc_mod.rtcc.bw_bytes - net->cc_mod.rtcc.bw_bytes_at_last_rttc;
629f79aab18SRandall Stewart 		net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
630f79aab18SRandall Stewart 		if (net->rtt) {
631f79aab18SRandall Stewart 			div = net->rtt / 1000;
632f79aab18SRandall Stewart 			if (div) {
633f79aab18SRandall Stewart 				inst_bw = bytes_for_this_rtt / div;
634f79aab18SRandall Stewart 				inst_off = inst_bw >> bw_shift;
635f79aab18SRandall Stewart 				if (inst_bw > nbw)
636f79aab18SRandall Stewart 					inst_ind = SCTP_INST_GAINING;
637f79aab18SRandall Stewart 				else if ((inst_bw + inst_off) < nbw)
638f79aab18SRandall Stewart 					inst_ind = SCTP_INST_LOOSING;
639f79aab18SRandall Stewart 				else
640f79aab18SRandall Stewart 					inst_ind = SCTP_INST_NEUTRAL;
641f79aab18SRandall Stewart 				probepoint |= ((0xb << 16) | inst_ind);
642f79aab18SRandall Stewart 			} else {
64360990c0cSMichael Tuexen 				inst_ind = net->cc_mod.rtcc.last_inst_ind;
644f79aab18SRandall Stewart 				inst_bw = bytes_for_this_rtt / (uint64_t)(net->rtt);
645f79aab18SRandall Stewart 				/* Can't determine do not change */
646f79aab18SRandall Stewart 				probepoint |= ((0xc << 16) | inst_ind);
647f79aab18SRandall Stewart 			}
648f79aab18SRandall Stewart 		} else {
64960990c0cSMichael Tuexen 			inst_ind = net->cc_mod.rtcc.last_inst_ind;
650f79aab18SRandall Stewart 			inst_bw = bytes_for_this_rtt;
651f79aab18SRandall Stewart 			/* Can't determine do not change */
652f79aab18SRandall Stewart 			probepoint |= ((0xd << 16) | inst_ind);
653f79aab18SRandall Stewart 		}
65436160958SMark Johnston 		SDT_PROBE5(sctp, cwnd, net, rttvar,
65548b6c649SRandall Stewart 		    vtag,
656f79aab18SRandall Stewart 		    ((nbw << 32) | inst_bw),
657f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw_rtt << 32) | rtt),
658f79aab18SRandall Stewart 		    net->flight_size,
65948b6c649SRandall Stewart 		    probepoint);
660f79aab18SRandall Stewart 	} else {
661f79aab18SRandall Stewart 		/* No rtt measurement, use last one */
662f79aab18SRandall Stewart 		inst_ind = net->cc_mod.rtcc.last_inst_ind;
663f79aab18SRandall Stewart 	}
664f79aab18SRandall Stewart 	bw_offset = net->cc_mod.rtcc.lbw >> bw_shift;
665f79aab18SRandall Stewart 	if (nbw > net->cc_mod.rtcc.lbw + bw_offset) {
6667215cc1bSMichael Tuexen 		ret = cc_bw_increase(stcb, net, nbw, vtag);
667f79aab18SRandall Stewart 		goto out;
66848b6c649SRandall Stewart 	}
66948b6c649SRandall Stewart 	rtt_offset = net->cc_mod.rtcc.lbw_rtt >> SCTP_BASE_SYSCTL(sctp_rttvar_rtt);
67048b6c649SRandall Stewart 	if (nbw < net->cc_mod.rtcc.lbw - bw_offset) {
671f79aab18SRandall Stewart 		ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, vtag, inst_ind);
672f79aab18SRandall Stewart 		goto out;
67348b6c649SRandall Stewart 	}
67448b6c649SRandall Stewart 	/*
67548b6c649SRandall Stewart 	 * If we reach here then we are in a situation where the bw stayed
67648b6c649SRandall Stewart 	 * the same.
67748b6c649SRandall Stewart 	 */
678f79aab18SRandall Stewart 	ret = cc_bw_same(stcb, net, nbw, rtt_offset, vtag, inst_ind);
679f79aab18SRandall Stewart out:
680f79aab18SRandall Stewart 	net->cc_mod.rtcc.last_inst_ind = inst_ind;
681f79aab18SRandall Stewart 	return (ret);
68248b6c649SRandall Stewart }
68348b6c649SRandall Stewart 
6840e9a9c10SMichael Tuexen static void
sctp_cwnd_update_after_sack_common(struct sctp_tcb * stcb,struct sctp_association * asoc,int accum_moved,int reneged_all SCTP_UNUSED,int will_exit,int use_rtcc)68548b6c649SRandall Stewart sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
686b54d3a6cSRandall Stewart     struct sctp_association *asoc,
6877215cc1bSMichael Tuexen     int accum_moved, int reneged_all SCTP_UNUSED, int will_exit, int use_rtcc)
688b54d3a6cSRandall Stewart {
689b54d3a6cSRandall Stewart 	struct sctp_nets *net;
690db2ce691SMateusz Guzik 	int old_cwnd __dtrace;
6913808ab73SMichael Tuexen 	uint32_t t_ssthresh, incr;
692c3d72c80SMichael Tuexen 	uint64_t t_ucwnd_sbw;
693c3d72c80SMichael Tuexen 	uint64_t t_path_mptcp;
694c3d72c80SMichael Tuexen 	uint64_t mptcp_like_alpha;
695c3d72c80SMichael Tuexen 	uint32_t srtt;
696c3d72c80SMichael Tuexen 	uint64_t max_path;
697b54d3a6cSRandall Stewart 
698ea8345d6SMichael Tuexen 	/* MT FIXME: Don't compute this over and over again */
699ea8345d6SMichael Tuexen 	t_ssthresh = 0;
700c3d72c80SMichael Tuexen 	t_ucwnd_sbw = 0;
701c3d72c80SMichael Tuexen 	t_path_mptcp = 0;
702c3d72c80SMichael Tuexen 	mptcp_like_alpha = 1;
703c3d72c80SMichael Tuexen 	if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
704c3d72c80SMichael Tuexen 	    (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2) ||
705c3d72c80SMichael Tuexen 	    (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_MPTCP)) {
706c3d72c80SMichael Tuexen 		max_path = 0;
707ea8345d6SMichael Tuexen 		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
708ea8345d6SMichael Tuexen 			t_ssthresh += net->ssthresh;
709c3d72c80SMichael Tuexen 			/* lastsa>>3;  we don't need to devide ... */
710c3d72c80SMichael Tuexen 			srtt = net->lastsa;
711c3d72c80SMichael Tuexen 			if (srtt > 0) {
712c3d72c80SMichael Tuexen 				uint64_t tmp;
713c3d72c80SMichael Tuexen 
714c3d72c80SMichael Tuexen 				t_ucwnd_sbw += (uint64_t)net->cwnd / (uint64_t)srtt;
715c3d72c80SMichael Tuexen 				t_path_mptcp += (((uint64_t)net->cwnd) << SHIFT_MPTCP_MULTI_Z) /
716c3d72c80SMichael Tuexen 				    (((uint64_t)net->mtu) * (uint64_t)srtt);
717c3d72c80SMichael Tuexen 				tmp = (((uint64_t)net->cwnd) << SHIFT_MPTCP_MULTI_N) /
718c3d72c80SMichael Tuexen 				    ((uint64_t)net->mtu * (uint64_t)(srtt * srtt));
719c3d72c80SMichael Tuexen 				if (tmp > max_path) {
720c3d72c80SMichael Tuexen 					max_path = tmp;
721c3d72c80SMichael Tuexen 				}
722c3d72c80SMichael Tuexen 			}
723c3d72c80SMichael Tuexen 		}
724c3d72c80SMichael Tuexen 		if (t_path_mptcp > 0) {
725c3d72c80SMichael Tuexen 			mptcp_like_alpha = max_path / (t_path_mptcp * t_path_mptcp);
726c3d72c80SMichael Tuexen 		} else {
727c3d72c80SMichael Tuexen 			mptcp_like_alpha = 1;
728ea8345d6SMichael Tuexen 		}
729ea8345d6SMichael Tuexen 	}
73060990c0cSMichael Tuexen 	if (t_ssthresh == 0) {
73160990c0cSMichael Tuexen 		t_ssthresh = 1;
73260990c0cSMichael Tuexen 	}
73360990c0cSMichael Tuexen 	if (t_ucwnd_sbw == 0) {
73460990c0cSMichael Tuexen 		t_ucwnd_sbw = 1;
73560990c0cSMichael Tuexen 	}
736b54d3a6cSRandall Stewart 	/******************************/
737b54d3a6cSRandall Stewart 	/* update cwnd and Early FR   */
738b54d3a6cSRandall Stewart 	/******************************/
739b54d3a6cSRandall Stewart 	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
740b54d3a6cSRandall Stewart #ifdef JANA_CMT_FAST_RECOVERY
741b54d3a6cSRandall Stewart 		/*
742b54d3a6cSRandall Stewart 		 * CMT fast recovery code. Need to debug.
743b54d3a6cSRandall Stewart 		 */
744b54d3a6cSRandall Stewart 		if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
745ea8345d6SMichael Tuexen 			if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
746ea8345d6SMichael Tuexen 			    SCTP_TSN_GE(net->pseudo_cumack, net->fast_recovery_tsn)) {
747b54d3a6cSRandall Stewart 				net->will_exit_fast_recovery = 1;
748b54d3a6cSRandall Stewart 			}
749b54d3a6cSRandall Stewart 		}
750b54d3a6cSRandall Stewart #endif
751b54d3a6cSRandall Stewart 		/* if nothing was acked on this destination skip it */
752b54d3a6cSRandall Stewart 		if (net->net_ack == 0) {
753b3f1ea41SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
754b54d3a6cSRandall Stewart 				sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
755b54d3a6cSRandall Stewart 			}
756b54d3a6cSRandall Stewart 			continue;
757b54d3a6cSRandall Stewart 		}
758b54d3a6cSRandall Stewart #ifdef JANA_CMT_FAST_RECOVERY
759b54d3a6cSRandall Stewart 		/*
760b54d3a6cSRandall Stewart 		 * CMT fast recovery code
761b54d3a6cSRandall Stewart 		 */
762b54d3a6cSRandall Stewart 		/*
7637c99d56fSMichael Tuexen 		 * if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery
7647c99d56fSMichael Tuexen 		 * && net->will_exit_fast_recovery == 0) { @@@ Do something
7657c99d56fSMichael Tuexen 		 * } else if (sctp_cmt_on_off == 0 &&
766b54d3a6cSRandall Stewart 		 * asoc->fast_retran_loss_recovery && will_exit == 0) {
767b54d3a6cSRandall Stewart 		 */
768b54d3a6cSRandall Stewart #endif
769b54d3a6cSRandall Stewart 
77020083c2eSMichael Tuexen 		if (asoc->fast_retran_loss_recovery &&
77120083c2eSMichael Tuexen 		    (will_exit == 0) &&
77220083c2eSMichael Tuexen 		    (asoc->sctp_cmt_on_off == 0)) {
773b54d3a6cSRandall Stewart 			/*
774b54d3a6cSRandall Stewart 			 * If we are in loss recovery we skip any cwnd
775b54d3a6cSRandall Stewart 			 * update
776b54d3a6cSRandall Stewart 			 */
777ca85e948SMichael Tuexen 			return;
778b54d3a6cSRandall Stewart 		}
779b54d3a6cSRandall Stewart 		/*
78048b6c649SRandall Stewart 		 * Did any measurements go on for this network?
78148b6c649SRandall Stewart 		 */
78248b6c649SRandall Stewart 		if (use_rtcc && (net->cc_mod.rtcc.tls_needs_set > 0)) {
78348b6c649SRandall Stewart 			uint64_t nbw;
78448b6c649SRandall Stewart 
78548b6c649SRandall Stewart 			/*
78648b6c649SRandall Stewart 			 * At this point our bw_bytes has been updated by
78748b6c649SRandall Stewart 			 * incoming sack information.
78848b6c649SRandall Stewart 			 *
78948b6c649SRandall Stewart 			 * But our bw may not yet be set.
79048b6c649SRandall Stewart 			 *
79148b6c649SRandall Stewart 			 */
79248b6c649SRandall Stewart 			if ((net->cc_mod.rtcc.new_tot_time / 1000) > 0) {
79348b6c649SRandall Stewart 				nbw = net->cc_mod.rtcc.bw_bytes / (net->cc_mod.rtcc.new_tot_time / 1000);
79448b6c649SRandall Stewart 			} else {
79548b6c649SRandall Stewart 				nbw = net->cc_mod.rtcc.bw_bytes;
79648b6c649SRandall Stewart 			}
79748b6c649SRandall Stewart 			if (net->cc_mod.rtcc.lbw) {
79848b6c649SRandall Stewart 				if (cc_bw_limit(stcb, net, nbw)) {
79948b6c649SRandall Stewart 					/* Hold here, no update */
800ca85e948SMichael Tuexen 					continue;
80148b6c649SRandall Stewart 				}
80248b6c649SRandall Stewart 			} else {
803db2ce691SMateusz Guzik 				uint64_t vtag __dtrace, probepoint __dtrace;
80448b6c649SRandall Stewart 
80548b6c649SRandall Stewart 				probepoint = (((uint64_t)net->cwnd) << 32);
80648b6c649SRandall Stewart 				probepoint |= ((0xa << 16) | 0);
80748b6c649SRandall Stewart 				vtag = (net->rtt << 32) |
80848b6c649SRandall Stewart 				    (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
80948b6c649SRandall Stewart 				    (stcb->rport);
81048b6c649SRandall Stewart 
81136160958SMark Johnston 				SDT_PROBE5(sctp, cwnd, net, rttvar,
81248b6c649SRandall Stewart 				    vtag,
81348b6c649SRandall Stewart 				    nbw,
814f79aab18SRandall Stewart 				    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
815f79aab18SRandall Stewart 				    net->flight_size,
81648b6c649SRandall Stewart 				    probepoint);
81748b6c649SRandall Stewart 				net->cc_mod.rtcc.lbw = nbw;
81848b6c649SRandall Stewart 				net->cc_mod.rtcc.lbw_rtt = net->rtt;
819f79aab18SRandall Stewart 				if (net->cc_mod.rtcc.rtt_set_this_sack) {
820f79aab18SRandall Stewart 					net->cc_mod.rtcc.rtt_set_this_sack = 0;
821f79aab18SRandall Stewart 					net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
822f79aab18SRandall Stewart 				}
82348b6c649SRandall Stewart 			}
82448b6c649SRandall Stewart 		}
82548b6c649SRandall Stewart 		/*
826b54d3a6cSRandall Stewart 		 * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
827b54d3a6cSRandall Stewart 		 * moved.
828b54d3a6cSRandall Stewart 		 */
82920083c2eSMichael Tuexen 		if (accum_moved ||
8307c99d56fSMichael Tuexen 		    ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
831b54d3a6cSRandall Stewart 			/* If the cumulative ack moved we can proceed */
832b54d3a6cSRandall Stewart 			if (net->cwnd <= net->ssthresh) {
833b54d3a6cSRandall Stewart 				/* We are in slow start */
834c54a18d2SRandall Stewart 				if (net->flight_size + net->net_ack >= net->cwnd) {
835ea8345d6SMichael Tuexen 					uint32_t limit;
836ea8345d6SMichael Tuexen 
837c3d72c80SMichael Tuexen 					old_cwnd = net->cwnd;
838c3d72c80SMichael Tuexen 					switch (asoc->sctp_cmt_on_off) {
839c3d72c80SMichael Tuexen 					case SCTP_CMT_RPV1:
840ea8345d6SMichael Tuexen 						limit = (uint32_t)(((uint64_t)net->mtu *
841ea8345d6SMichael Tuexen 						    (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
842ea8345d6SMichael Tuexen 						    (uint64_t)net->ssthresh) /
843ea8345d6SMichael Tuexen 						    (uint64_t)t_ssthresh);
844ea8345d6SMichael Tuexen 						incr = (uint32_t)(((uint64_t)net->net_ack *
845ea8345d6SMichael Tuexen 						    (uint64_t)net->ssthresh) /
846ea8345d6SMichael Tuexen 						    (uint64_t)t_ssthresh);
847ea8345d6SMichael Tuexen 						if (incr > limit) {
848ea8345d6SMichael Tuexen 							incr = limit;
849ea8345d6SMichael Tuexen 						}
850ea8345d6SMichael Tuexen 						if (incr == 0) {
851ea8345d6SMichael Tuexen 							incr = 1;
852b54d3a6cSRandall Stewart 						}
853c3d72c80SMichael Tuexen 						break;
854c3d72c80SMichael Tuexen 					case SCTP_CMT_RPV2:
855b7b84c0eSMichael Tuexen 						/*
856b7b84c0eSMichael Tuexen 						 * lastsa>>3;  we don't need
857b7b84c0eSMichael Tuexen 						 * to divide ...
858b7b84c0eSMichael Tuexen 						 */
859c3d72c80SMichael Tuexen 						srtt = net->lastsa;
860c3d72c80SMichael Tuexen 						if (srtt == 0) {
861c3d72c80SMichael Tuexen 							srtt = 1;
862c3d72c80SMichael Tuexen 						}
863c3d72c80SMichael Tuexen 						limit = (uint32_t)(((uint64_t)net->mtu *
864c3d72c80SMichael Tuexen 						    (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
865c3d72c80SMichael Tuexen 						    (uint64_t)net->cwnd) /
866c3d72c80SMichael Tuexen 						    ((uint64_t)srtt * t_ucwnd_sbw));
867c3d72c80SMichael Tuexen 						/* INCREASE FACTOR */
868c3d72c80SMichael Tuexen 						incr = (uint32_t)(((uint64_t)net->net_ack *
869c3d72c80SMichael Tuexen 						    (uint64_t)net->cwnd) /
870c3d72c80SMichael Tuexen 						    ((uint64_t)srtt * t_ucwnd_sbw));
871c3d72c80SMichael Tuexen 						/* INCREASE FACTOR */
872c3d72c80SMichael Tuexen 						if (incr > limit) {
873c3d72c80SMichael Tuexen 							incr = limit;
874c3d72c80SMichael Tuexen 						}
875c3d72c80SMichael Tuexen 						if (incr == 0) {
876c3d72c80SMichael Tuexen 							incr = 1;
877c3d72c80SMichael Tuexen 						}
878c3d72c80SMichael Tuexen 						break;
879c3d72c80SMichael Tuexen 					case SCTP_CMT_MPTCP:
880c3d72c80SMichael Tuexen 						limit = (uint32_t)(((uint64_t)net->mtu *
881c3d72c80SMichael Tuexen 						    mptcp_like_alpha *
882c3d72c80SMichael Tuexen 						    (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) >>
883c3d72c80SMichael Tuexen 						    SHIFT_MPTCP_MULTI);
884c3d72c80SMichael Tuexen 						incr = (uint32_t)(((uint64_t)net->net_ack *
885c3d72c80SMichael Tuexen 						    mptcp_like_alpha) >>
886c3d72c80SMichael Tuexen 						    SHIFT_MPTCP_MULTI);
887c3d72c80SMichael Tuexen 						if (incr > limit) {
888c3d72c80SMichael Tuexen 							incr = limit;
889c3d72c80SMichael Tuexen 						}
890c3d72c80SMichael Tuexen 						if (incr > net->net_ack) {
891c3d72c80SMichael Tuexen 							incr = net->net_ack;
892c3d72c80SMichael Tuexen 						}
893c3d72c80SMichael Tuexen 						if (incr > net->mtu) {
894c3d72c80SMichael Tuexen 							incr = net->mtu;
895c3d72c80SMichael Tuexen 						}
896c3d72c80SMichael Tuexen 						break;
897c3d72c80SMichael Tuexen 					default:
898ea8345d6SMichael Tuexen 						incr = net->net_ack;
899ea8345d6SMichael Tuexen 						if (incr > net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) {
900ea8345d6SMichael Tuexen 							incr = net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable);
901ea8345d6SMichael Tuexen 						}
902c3d72c80SMichael Tuexen 						break;
903ea8345d6SMichael Tuexen 					}
904ea8345d6SMichael Tuexen 					net->cwnd += incr;
90559b6d5beSMichael Tuexen 					sctp_enforce_cwnd_limit(asoc, net);
906ea8345d6SMichael Tuexen 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
907ea8345d6SMichael Tuexen 						sctp_log_cwnd(stcb, net, incr,
908ea8345d6SMichael Tuexen 						    SCTP_CWND_LOG_FROM_SS);
909ea8345d6SMichael Tuexen 					}
91036160958SMark Johnston 					SDT_PROBE5(sctp, cwnd, net, ack,
9116324ca61SRandall Stewart 					    stcb->asoc.my_vtag,
9126324ca61SRandall Stewart 					    ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
9136324ca61SRandall Stewart 					    net,
9146324ca61SRandall Stewart 					    old_cwnd, net->cwnd);
915b54d3a6cSRandall Stewart 				} else {
916b3f1ea41SRandall Stewart 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
917b54d3a6cSRandall Stewart 						sctp_log_cwnd(stcb, net, net->net_ack,
918b54d3a6cSRandall Stewart 						    SCTP_CWND_LOG_NOADV_SS);
919b54d3a6cSRandall Stewart 					}
920b54d3a6cSRandall Stewart 				}
921b54d3a6cSRandall Stewart 			} else {
922b54d3a6cSRandall Stewart 				/* We are in congestion avoidance */
923b54d3a6cSRandall Stewart 				/*
924bfefd190SRandall Stewart 				 * Add to pba
925b54d3a6cSRandall Stewart 				 */
926c54a18d2SRandall Stewart 				net->partial_bytes_acked += net->net_ack;
927b54d3a6cSRandall Stewart 
928bfefd190SRandall Stewart 				if ((net->flight_size + net->net_ack >= net->cwnd) &&
929bfefd190SRandall Stewart 				    (net->partial_bytes_acked >= net->cwnd)) {
930bfefd190SRandall Stewart 					net->partial_bytes_acked -= net->cwnd;
9316324ca61SRandall Stewart 					old_cwnd = net->cwnd;
932c3d72c80SMichael Tuexen 					switch (asoc->sctp_cmt_on_off) {
933c3d72c80SMichael Tuexen 					case SCTP_CMT_RPV1:
934ea8345d6SMichael Tuexen 						incr = (uint32_t)(((uint64_t)net->mtu *
935ea8345d6SMichael Tuexen 						    (uint64_t)net->ssthresh) /
936ea8345d6SMichael Tuexen 						    (uint64_t)t_ssthresh);
937ea8345d6SMichael Tuexen 						if (incr == 0) {
938ea8345d6SMichael Tuexen 							incr = 1;
939ea8345d6SMichael Tuexen 						}
940c3d72c80SMichael Tuexen 						break;
941c3d72c80SMichael Tuexen 					case SCTP_CMT_RPV2:
942b7b84c0eSMichael Tuexen 						/*
943b7b84c0eSMichael Tuexen 						 * lastsa>>3;  we don't need
944b7b84c0eSMichael Tuexen 						 * to divide ...
945b7b84c0eSMichael Tuexen 						 */
946c3d72c80SMichael Tuexen 						srtt = net->lastsa;
947c3d72c80SMichael Tuexen 						if (srtt == 0) {
948c3d72c80SMichael Tuexen 							srtt = 1;
949c3d72c80SMichael Tuexen 						}
950c3d72c80SMichael Tuexen 						incr = (uint32_t)((uint64_t)net->mtu *
951c3d72c80SMichael Tuexen 						    (uint64_t)net->cwnd /
952c3d72c80SMichael Tuexen 						    ((uint64_t)srtt *
953c3d72c80SMichael Tuexen 						    t_ucwnd_sbw));
954c3d72c80SMichael Tuexen 						/* INCREASE FACTOR */
955c3d72c80SMichael Tuexen 						if (incr == 0) {
956c3d72c80SMichael Tuexen 							incr = 1;
957c3d72c80SMichael Tuexen 						}
958c3d72c80SMichael Tuexen 						break;
959c3d72c80SMichael Tuexen 					case SCTP_CMT_MPTCP:
960c3d72c80SMichael Tuexen 						incr = (uint32_t)((mptcp_like_alpha *
961c3d72c80SMichael Tuexen 						    (uint64_t)net->cwnd) >>
962c3d72c80SMichael Tuexen 						    SHIFT_MPTCP_MULTI);
963c3d72c80SMichael Tuexen 						if (incr > net->mtu) {
964ea8345d6SMichael Tuexen 							incr = net->mtu;
965ea8345d6SMichael Tuexen 						}
966c3d72c80SMichael Tuexen 						break;
967c3d72c80SMichael Tuexen 					default:
968c3d72c80SMichael Tuexen 						incr = net->mtu;
969c3d72c80SMichael Tuexen 						break;
970c3d72c80SMichael Tuexen 					}
971ea8345d6SMichael Tuexen 					net->cwnd += incr;
97259b6d5beSMichael Tuexen 					sctp_enforce_cwnd_limit(asoc, net);
97336160958SMark Johnston 					SDT_PROBE5(sctp, cwnd, net, ack,
9746324ca61SRandall Stewart 					    stcb->asoc.my_vtag,
9756324ca61SRandall Stewart 					    ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
9766324ca61SRandall Stewart 					    net,
9776324ca61SRandall Stewart 					    old_cwnd, net->cwnd);
978b3f1ea41SRandall Stewart 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
979b54d3a6cSRandall Stewart 						sctp_log_cwnd(stcb, net, net->mtu,
980b54d3a6cSRandall Stewart 						    SCTP_CWND_LOG_FROM_CA);
981b54d3a6cSRandall Stewart 					}
982b54d3a6cSRandall Stewart 				} else {
983b3f1ea41SRandall Stewart 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
984b54d3a6cSRandall Stewart 						sctp_log_cwnd(stcb, net, net->net_ack,
985b54d3a6cSRandall Stewart 						    SCTP_CWND_LOG_NOADV_CA);
986b54d3a6cSRandall Stewart 					}
987b54d3a6cSRandall Stewart 				}
988b54d3a6cSRandall Stewart 			}
989b54d3a6cSRandall Stewart 		} else {
990b3f1ea41SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
991b54d3a6cSRandall Stewart 				sctp_log_cwnd(stcb, net, net->mtu,
992b54d3a6cSRandall Stewart 				    SCTP_CWND_LOG_NO_CUMACK);
993b54d3a6cSRandall Stewart 			}
994b54d3a6cSRandall Stewart 		}
995b54d3a6cSRandall Stewart 	}
996b54d3a6cSRandall Stewart }
997ca85e948SMichael Tuexen 
998ca85e948SMichael Tuexen static void
sctp_cwnd_update_exit_pf_common(struct sctp_tcb * stcb,struct sctp_nets * net)999ca85e948SMichael Tuexen sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb, struct sctp_nets *net)
1000ca85e948SMichael Tuexen {
1001db2ce691SMateusz Guzik 	int old_cwnd __dtrace;
1002ca85e948SMichael Tuexen 
1003ca85e948SMichael Tuexen 	old_cwnd = net->cwnd;
1004ca85e948SMichael Tuexen 	net->cwnd = net->mtu;
100536160958SMark Johnston 	SDT_PROBE5(sctp, cwnd, net, ack,
1006ca85e948SMichael Tuexen 	    stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
1007ca85e948SMichael Tuexen 	    old_cwnd, net->cwnd);
1008ca85e948SMichael Tuexen 	SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
1009dd294dceSMichael Tuexen 	    (void *)net, net->cwnd);
1010b54d3a6cSRandall Stewart }
1011ca85e948SMichael Tuexen 
10120e9a9c10SMichael Tuexen static void
sctp_cwnd_update_after_timeout(struct sctp_tcb * stcb,struct sctp_nets * net)1013c54a18d2SRandall Stewart sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
1014b54d3a6cSRandall Stewart {
1015b54d3a6cSRandall Stewart 	int old_cwnd = net->cwnd;
1016ea8345d6SMichael Tuexen 	uint32_t t_ssthresh, t_cwnd;
1017c3d72c80SMichael Tuexen 	uint64_t t_ucwnd_sbw;
1018b54d3a6cSRandall Stewart 
1019ea8345d6SMichael Tuexen 	/* MT FIXME: Don't compute this over and over again */
1020ea8345d6SMichael Tuexen 	t_ssthresh = 0;
1021ea8345d6SMichael Tuexen 	t_cwnd = 0;
1022c3d72c80SMichael Tuexen 	if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
1023c3d72c80SMichael Tuexen 	    (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
1024ea8345d6SMichael Tuexen 		struct sctp_nets *lnet;
1025c3d72c80SMichael Tuexen 		uint32_t srtt;
1026ea8345d6SMichael Tuexen 
1027c3d72c80SMichael Tuexen 		t_ucwnd_sbw = 0;
1028ea8345d6SMichael Tuexen 		TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
1029ea8345d6SMichael Tuexen 			t_ssthresh += lnet->ssthresh;
1030ea8345d6SMichael Tuexen 			t_cwnd += lnet->cwnd;
1031c3d72c80SMichael Tuexen 			srtt = lnet->lastsa;
1032c3d72c80SMichael Tuexen 			/* lastsa>>3;  we don't need to divide ... */
1033c3d72c80SMichael Tuexen 			if (srtt > 0) {
1034c3d72c80SMichael Tuexen 				t_ucwnd_sbw += (uint64_t)lnet->cwnd / (uint64_t)srtt;
1035ea8345d6SMichael Tuexen 			}
1036c3d72c80SMichael Tuexen 		}
103760990c0cSMichael Tuexen 		if (t_ssthresh < 1) {
103860990c0cSMichael Tuexen 			t_ssthresh = 1;
103960990c0cSMichael Tuexen 		}
1040c3d72c80SMichael Tuexen 		if (t_ucwnd_sbw < 1) {
1041c3d72c80SMichael Tuexen 			t_ucwnd_sbw = 1;
1042c3d72c80SMichael Tuexen 		}
1043c3d72c80SMichael Tuexen 		if (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) {
1044ea8345d6SMichael Tuexen 			net->ssthresh = (uint32_t)(((uint64_t)4 *
1045ea8345d6SMichael Tuexen 			    (uint64_t)net->mtu *
1046ea8345d6SMichael Tuexen 			    (uint64_t)net->ssthresh) /
1047ea8345d6SMichael Tuexen 			    (uint64_t)t_ssthresh);
1048c3d72c80SMichael Tuexen 		} else {
1049c3d72c80SMichael Tuexen 			uint64_t cc_delta;
1050c3d72c80SMichael Tuexen 
1051c3d72c80SMichael Tuexen 			srtt = net->lastsa;
1052c3d72c80SMichael Tuexen 			/* lastsa>>3;  we don't need to divide ... */
1053c3d72c80SMichael Tuexen 			if (srtt == 0) {
1054c3d72c80SMichael Tuexen 				srtt = 1;
1055c3d72c80SMichael Tuexen 			}
1056c3d72c80SMichael Tuexen 			cc_delta = t_ucwnd_sbw * (uint64_t)srtt / 2;
1057c3d72c80SMichael Tuexen 			if (cc_delta < t_cwnd) {
1058c3d72c80SMichael Tuexen 				net->ssthresh = (uint32_t)((uint64_t)t_cwnd - cc_delta);
1059c3d72c80SMichael Tuexen 			} else {
1060c3d72c80SMichael Tuexen 				net->ssthresh = net->mtu;
1061c3d72c80SMichael Tuexen 			}
1062c3d72c80SMichael Tuexen 		}
1063ea8345d6SMichael Tuexen 		if ((net->cwnd > t_cwnd / 2) &&
1064ea8345d6SMichael Tuexen 		    (net->ssthresh < net->cwnd - t_cwnd / 2)) {
1065ea8345d6SMichael Tuexen 			net->ssthresh = net->cwnd - t_cwnd / 2;
1066ea8345d6SMichael Tuexen 		}
1067ea8345d6SMichael Tuexen 		if (net->ssthresh < net->mtu) {
1068ea8345d6SMichael Tuexen 			net->ssthresh = net->mtu;
1069ea8345d6SMichael Tuexen 		}
1070ea8345d6SMichael Tuexen 	} else {
1071d18f7e0aSMichael Tuexen 		net->ssthresh = max(net->cwnd / 2, 4 * net->mtu);
1072ea8345d6SMichael Tuexen 	}
1073b54d3a6cSRandall Stewart 	net->cwnd = net->mtu;
1074c54a18d2SRandall Stewart 	net->partial_bytes_acked = 0;
107536160958SMark Johnston 	SDT_PROBE5(sctp, cwnd, net, to,
10766324ca61SRandall Stewart 	    stcb->asoc.my_vtag,
10776324ca61SRandall Stewart 	    ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
10786324ca61SRandall Stewart 	    net,
10796324ca61SRandall Stewart 	    old_cwnd, net->cwnd);
1080b3f1ea41SRandall Stewart 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1081b54d3a6cSRandall Stewart 		sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
1082b54d3a6cSRandall Stewart 	}
1083c54a18d2SRandall Stewart }
1084c54a18d2SRandall Stewart 
10850e9a9c10SMichael Tuexen static void
sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb * stcb,struct sctp_nets * net,int in_window,int num_pkt_lost,int use_rtcc)108648b6c649SRandall Stewart sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets *net,
108748b6c649SRandall Stewart     int in_window, int num_pkt_lost, int use_rtcc)
1088c54a18d2SRandall Stewart {
1089c54a18d2SRandall Stewart 	int old_cwnd = net->cwnd;
1090c54a18d2SRandall Stewart 
109148b6c649SRandall Stewart 	if ((use_rtcc) && (net->lan_type == SCTP_LAN_LOCAL) && (net->cc_mod.rtcc.use_dccc_ecn)) {
109248b6c649SRandall Stewart 		/* Data center Congestion Control */
109348b6c649SRandall Stewart 		if (in_window == 0) {
109448b6c649SRandall Stewart 			/*
109548b6c649SRandall Stewart 			 * Go to CA with the cwnd at the point we sent the
109648b6c649SRandall Stewart 			 * TSN that was marked with a CE.
109748b6c649SRandall Stewart 			 */
109848b6c649SRandall Stewart 			if (net->ecn_prev_cwnd < net->cwnd) {
109948b6c649SRandall Stewart 				/* Restore to prev cwnd */
110048b6c649SRandall Stewart 				net->cwnd = net->ecn_prev_cwnd - (net->mtu * num_pkt_lost);
110148b6c649SRandall Stewart 			} else {
110248b6c649SRandall Stewart 				/* Just cut in 1/2 */
110348b6c649SRandall Stewart 				net->cwnd /= 2;
110448b6c649SRandall Stewart 			}
110548b6c649SRandall Stewart 			/* Drop to CA */
110648b6c649SRandall Stewart 			net->ssthresh = net->cwnd - (num_pkt_lost * net->mtu);
110748b6c649SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
110848b6c649SRandall Stewart 				sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
110948b6c649SRandall Stewart 			}
111048b6c649SRandall Stewart 		} else {
1111b7b84c0eSMichael Tuexen 			/*
1112b7b84c0eSMichael Tuexen 			 * Further tuning down required over the drastic
1113b7b84c0eSMichael Tuexen 			 * original cut
1114b7b84c0eSMichael Tuexen 			 */
111548b6c649SRandall Stewart 			net->ssthresh -= (net->mtu * num_pkt_lost);
111648b6c649SRandall Stewart 			net->cwnd -= (net->mtu * num_pkt_lost);
111748b6c649SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
111848b6c649SRandall Stewart 				sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
111948b6c649SRandall Stewart 			}
112048b6c649SRandall Stewart 		}
112148b6c649SRandall Stewart 		SCTP_STAT_INCR(sctps_ecnereducedcwnd);
112248b6c649SRandall Stewart 	} else {
1123493d8e5aSRandall Stewart 		if (in_window == 0) {
1124c54a18d2SRandall Stewart 			SCTP_STAT_INCR(sctps_ecnereducedcwnd);
1125c54a18d2SRandall Stewart 			net->ssthresh = net->cwnd / 2;
1126c54a18d2SRandall Stewart 			if (net->ssthresh < net->mtu) {
1127c54a18d2SRandall Stewart 				net->ssthresh = net->mtu;
1128b7b84c0eSMichael Tuexen 				/*
1129b7b84c0eSMichael Tuexen 				 * here back off the timer as well, to slow
1130b7b84c0eSMichael Tuexen 				 * us down
1131b7b84c0eSMichael Tuexen 				 */
1132c54a18d2SRandall Stewart 				net->RTO <<= 1;
1133c54a18d2SRandall Stewart 			}
1134c54a18d2SRandall Stewart 			net->cwnd = net->ssthresh;
113536160958SMark Johnston 			SDT_PROBE5(sctp, cwnd, net, ecn,
11366324ca61SRandall Stewart 			    stcb->asoc.my_vtag,
11376324ca61SRandall Stewart 			    ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
11386324ca61SRandall Stewart 			    net,
11396324ca61SRandall Stewart 			    old_cwnd, net->cwnd);
1140b3f1ea41SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1141c54a18d2SRandall Stewart 				sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
1142c54a18d2SRandall Stewart 			}
1143c54a18d2SRandall Stewart 		}
1144493d8e5aSRandall Stewart 	}
1145c54a18d2SRandall Stewart 
114648b6c649SRandall Stewart }
114748b6c649SRandall Stewart 
11480e9a9c10SMichael Tuexen static void
sctp_cwnd_update_after_packet_dropped(struct sctp_tcb * stcb,struct sctp_nets * net,struct sctp_pktdrop_chunk * cp,uint32_t * bottle_bw,uint32_t * on_queue)1149c54a18d2SRandall Stewart sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
1150c54a18d2SRandall Stewart     struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
1151c54a18d2SRandall Stewart     uint32_t *bottle_bw, uint32_t *on_queue)
1152c54a18d2SRandall Stewart {
1153c54a18d2SRandall Stewart 	uint32_t bw_avail;
1154dec0177dSRandall Stewart 	unsigned int incr;
1155c54a18d2SRandall Stewart 	int old_cwnd = net->cwnd;
1156c54a18d2SRandall Stewart 
1157c54a18d2SRandall Stewart 	/* get bottle neck bw */
1158c54a18d2SRandall Stewart 	*bottle_bw = ntohl(cp->bottle_bw);
1159c54a18d2SRandall Stewart 	/* and whats on queue */
1160c54a18d2SRandall Stewart 	*on_queue = ntohl(cp->current_onq);
1161c54a18d2SRandall Stewart 	/*
1162c54a18d2SRandall Stewart 	 * adjust the on-queue if our flight is more it could be that the
1163c54a18d2SRandall Stewart 	 * router has not yet gotten data "in-flight" to it
1164c54a18d2SRandall Stewart 	 */
1165667eb487SMichael Tuexen 	if (*on_queue < net->flight_size) {
1166c54a18d2SRandall Stewart 		*on_queue = net->flight_size;
1167667eb487SMichael Tuexen 	}
1168667eb487SMichael Tuexen 	/* rtt is measured in micro seconds, bottle_bw in bytes per second */
1169667eb487SMichael Tuexen 	bw_avail = (uint32_t)(((uint64_t)(*bottle_bw) * net->rtt) / (uint64_t)1000000);
1170c54a18d2SRandall Stewart 	if (bw_avail > *bottle_bw) {
1171c54a18d2SRandall Stewart 		/*
1172c54a18d2SRandall Stewart 		 * Cap the growth to no more than the bottle neck. This can
1173c54a18d2SRandall Stewart 		 * happen as RTT slides up due to queues. It also means if
1174c54a18d2SRandall Stewart 		 * you have more than a 1 second RTT with a empty queue you
1175c54a18d2SRandall Stewart 		 * will be limited to the bottle_bw per second no matter if
1176c54a18d2SRandall Stewart 		 * other points have 1/2 the RTT and you could get more
1177c54a18d2SRandall Stewart 		 * out...
1178c54a18d2SRandall Stewart 		 */
1179c54a18d2SRandall Stewart 		bw_avail = *bottle_bw;
1180c54a18d2SRandall Stewart 	}
1181c54a18d2SRandall Stewart 	if (*on_queue > bw_avail) {
1182c54a18d2SRandall Stewart 		/*
1183c54a18d2SRandall Stewart 		 * No room for anything else don't allow anything else to be
1184c54a18d2SRandall Stewart 		 * "added to the fire".
1185c54a18d2SRandall Stewart 		 */
1186c54a18d2SRandall Stewart 		int seg_inflight, seg_onqueue, my_portion;
1187c54a18d2SRandall Stewart 
1188b54d3a6cSRandall Stewart 		net->partial_bytes_acked = 0;
1189c54a18d2SRandall Stewart 		/* how much are we over queue size? */
1190c54a18d2SRandall Stewart 		incr = *on_queue - bw_avail;
1191c54a18d2SRandall Stewart 		if (stcb->asoc.seen_a_sack_this_pkt) {
1192c54a18d2SRandall Stewart 			/*
1193c54a18d2SRandall Stewart 			 * undo any cwnd adjustment that the sack might have
1194c54a18d2SRandall Stewart 			 * made
1195c54a18d2SRandall Stewart 			 */
1196c54a18d2SRandall Stewart 			net->cwnd = net->prev_cwnd;
1197c54a18d2SRandall Stewart 		}
1198c54a18d2SRandall Stewart 		/* Now how much of that is mine? */
1199c54a18d2SRandall Stewart 		seg_inflight = net->flight_size / net->mtu;
1200c54a18d2SRandall Stewart 		seg_onqueue = *on_queue / net->mtu;
1201c54a18d2SRandall Stewart 		my_portion = (incr * seg_inflight) / seg_onqueue;
1202c54a18d2SRandall Stewart 
1203c54a18d2SRandall Stewart 		/* Have I made an adjustment already */
1204c54a18d2SRandall Stewart 		if (net->cwnd > net->flight_size) {
1205c54a18d2SRandall Stewart 			/*
1206c54a18d2SRandall Stewart 			 * for this flight I made an adjustment we need to
1207c54a18d2SRandall Stewart 			 * decrease the portion by a share our previous
1208c54a18d2SRandall Stewart 			 * adjustment.
1209c54a18d2SRandall Stewart 			 */
1210c54a18d2SRandall Stewart 			int diff_adj;
1211c54a18d2SRandall Stewart 
1212c54a18d2SRandall Stewart 			diff_adj = net->cwnd - net->flight_size;
1213c54a18d2SRandall Stewart 			if (diff_adj > my_portion)
1214c54a18d2SRandall Stewart 				my_portion = 0;
1215c54a18d2SRandall Stewart 			else
1216c54a18d2SRandall Stewart 				my_portion -= diff_adj;
1217c54a18d2SRandall Stewart 		}
1218c54a18d2SRandall Stewart 		/*
1219c54a18d2SRandall Stewart 		 * back down to the previous cwnd (assume we have had a sack
1220c54a18d2SRandall Stewart 		 * before this packet). minus what ever portion of the
1221c54a18d2SRandall Stewart 		 * overage is my fault.
1222c54a18d2SRandall Stewart 		 */
1223c54a18d2SRandall Stewart 		net->cwnd -= my_portion;
1224c54a18d2SRandall Stewart 
1225c54a18d2SRandall Stewart 		/* we will NOT back down more than 1 MTU */
1226c54a18d2SRandall Stewart 		if (net->cwnd <= net->mtu) {
1227c54a18d2SRandall Stewart 			net->cwnd = net->mtu;
1228c54a18d2SRandall Stewart 		}
1229c54a18d2SRandall Stewart 		/* force into CA */
1230c54a18d2SRandall Stewart 		net->ssthresh = net->cwnd - 1;
1231c54a18d2SRandall Stewart 	} else {
1232c54a18d2SRandall Stewart 		/*
1233c54a18d2SRandall Stewart 		 * Take 1/4 of the space left or max burst up .. whichever
1234c54a18d2SRandall Stewart 		 * is less.
1235c54a18d2SRandall Stewart 		 */
123690fed1d8SMichael Tuexen 		incr = (bw_avail - *on_queue) >> 2;
123790fed1d8SMichael Tuexen 		if ((stcb->asoc.max_burst > 0) &&
123890fed1d8SMichael Tuexen 		    (stcb->asoc.max_burst * net->mtu < incr)) {
123990fed1d8SMichael Tuexen 			incr = stcb->asoc.max_burst * net->mtu;
124090fed1d8SMichael Tuexen 		}
1241c54a18d2SRandall Stewart 		net->cwnd += incr;
1242c54a18d2SRandall Stewart 	}
1243c54a18d2SRandall Stewart 	if (net->cwnd > bw_avail) {
1244c54a18d2SRandall Stewart 		/* We can't exceed the pipe size */
1245c54a18d2SRandall Stewart 		net->cwnd = bw_avail;
1246c54a18d2SRandall Stewart 	}
1247c54a18d2SRandall Stewart 	if (net->cwnd < net->mtu) {
1248c54a18d2SRandall Stewart 		/* We always have 1 MTU */
1249c54a18d2SRandall Stewart 		net->cwnd = net->mtu;
1250c54a18d2SRandall Stewart 	}
125159b6d5beSMichael Tuexen 	sctp_enforce_cwnd_limit(&stcb->asoc, net);
1252c54a18d2SRandall Stewart 	if (net->cwnd - old_cwnd != 0) {
1253c54a18d2SRandall Stewart 		/* log only changes */
125436160958SMark Johnston 		SDT_PROBE5(sctp, cwnd, net, pd,
12556324ca61SRandall Stewart 		    stcb->asoc.my_vtag,
12566324ca61SRandall Stewart 		    ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
12576324ca61SRandall Stewart 		    net,
12586324ca61SRandall Stewart 		    old_cwnd, net->cwnd);
1259b3f1ea41SRandall Stewart 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1260c54a18d2SRandall Stewart 			sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
1261c54a18d2SRandall Stewart 			    SCTP_CWND_LOG_FROM_SAT);
1262c54a18d2SRandall Stewart 		}
1263c54a18d2SRandall Stewart 	}
1264c54a18d2SRandall Stewart }
1265c54a18d2SRandall Stewart 
12660e9a9c10SMichael Tuexen static void
sctp_cwnd_update_after_output(struct sctp_tcb * stcb,struct sctp_nets * net,int burst_limit)1267c54a18d2SRandall Stewart sctp_cwnd_update_after_output(struct sctp_tcb *stcb,
1268c54a18d2SRandall Stewart     struct sctp_nets *net, int burst_limit)
1269c54a18d2SRandall Stewart {
1270c54a18d2SRandall Stewart 	int old_cwnd = net->cwnd;
1271c54a18d2SRandall Stewart 
1272c54a18d2SRandall Stewart 	if (net->ssthresh < net->cwnd)
1273c54a18d2SRandall Stewart 		net->ssthresh = net->cwnd;
127448b6c649SRandall Stewart 	if (burst_limit) {
1275c54a18d2SRandall Stewart 		net->cwnd = (net->flight_size + (burst_limit * net->mtu));
127659b6d5beSMichael Tuexen 		sctp_enforce_cwnd_limit(&stcb->asoc, net);
127736160958SMark Johnston 		SDT_PROBE5(sctp, cwnd, net, bl,
12786324ca61SRandall Stewart 		    stcb->asoc.my_vtag,
12796324ca61SRandall Stewart 		    ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
12806324ca61SRandall Stewart 		    net,
12816324ca61SRandall Stewart 		    old_cwnd, net->cwnd);
1282b3f1ea41SRandall Stewart 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1283c54a18d2SRandall Stewart 			sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST);
1284c54a18d2SRandall Stewart 		}
1285c54a18d2SRandall Stewart 	}
128648b6c649SRandall Stewart }
1287c54a18d2SRandall Stewart 
12880e9a9c10SMichael Tuexen static void
sctp_cwnd_update_after_sack(struct sctp_tcb * stcb,struct sctp_association * asoc,int accum_moved,int reneged_all,int will_exit)128948b6c649SRandall Stewart sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
129048b6c649SRandall Stewart     struct sctp_association *asoc,
129148b6c649SRandall Stewart     int accum_moved, int reneged_all, int will_exit)
129248b6c649SRandall Stewart {
1293cd0a4ff6SPedro F. Giffuni 	/* Passing a zero argument in last disables the rtcc algorithm */
129448b6c649SRandall Stewart 	sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 0);
129548b6c649SRandall Stewart }
129648b6c649SRandall Stewart 
129748b6c649SRandall Stewart static void
sctp_cwnd_update_after_ecn_echo(struct sctp_tcb * stcb,struct sctp_nets * net,int in_window,int num_pkt_lost)129848b6c649SRandall Stewart sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
129948b6c649SRandall Stewart     int in_window, int num_pkt_lost)
130048b6c649SRandall Stewart {
1301cd0a4ff6SPedro F. Giffuni 	/* Passing a zero argument in last disables the rtcc algorithm */
130248b6c649SRandall Stewart 	sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 0);
130348b6c649SRandall Stewart }
130448b6c649SRandall Stewart 
130548b6c649SRandall Stewart /* Here starts the RTCCVAR type CC invented by RRS which
130648b6c649SRandall Stewart  * is a slight mod to RFC2581. We reuse a common routine or
1307cd0a4ff6SPedro F. Giffuni  * two since these algorithms are so close and need to
130848b6c649SRandall Stewart  * remain the same.
130948b6c649SRandall Stewart  */
131048b6c649SRandall Stewart static void
sctp_cwnd_update_rtcc_after_ecn_echo(struct sctp_tcb * stcb,struct sctp_nets * net,int in_window,int num_pkt_lost)131148b6c649SRandall Stewart sctp_cwnd_update_rtcc_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
131248b6c649SRandall Stewart     int in_window, int num_pkt_lost)
131348b6c649SRandall Stewart {
131448b6c649SRandall Stewart 	sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 1);
131548b6c649SRandall Stewart }
131648b6c649SRandall Stewart 
1317b6db274dSMichael Tuexen static void
sctp_cwnd_update_rtcc_tsn_acknowledged(struct sctp_nets * net,struct sctp_tmit_chunk * tp1)131848b6c649SRandall Stewart sctp_cwnd_update_rtcc_tsn_acknowledged(struct sctp_nets *net,
131948b6c649SRandall Stewart     struct sctp_tmit_chunk *tp1)
132048b6c649SRandall Stewart {
132148b6c649SRandall Stewart 	net->cc_mod.rtcc.bw_bytes += tp1->send_size;
132248b6c649SRandall Stewart }
132348b6c649SRandall Stewart 
132448b6c649SRandall Stewart static void
sctp_cwnd_prepare_rtcc_net_for_sack(struct sctp_tcb * stcb SCTP_UNUSED,struct sctp_nets * net)13257215cc1bSMichael Tuexen sctp_cwnd_prepare_rtcc_net_for_sack(struct sctp_tcb *stcb SCTP_UNUSED,
132648b6c649SRandall Stewart     struct sctp_nets *net)
132748b6c649SRandall Stewart {
132848b6c649SRandall Stewart 	if (net->cc_mod.rtcc.tls_needs_set > 0) {
1329e7e65008SMichael Tuexen 		/* We had a bw measurement going on */
133048b6c649SRandall Stewart 		struct timeval ltls;
133148b6c649SRandall Stewart 
133248b6c649SRandall Stewart 		SCTP_GETPTIME_TIMEVAL(&ltls);
133348b6c649SRandall Stewart 		timevalsub(&ltls, &net->cc_mod.rtcc.tls);
133448b6c649SRandall Stewart 		net->cc_mod.rtcc.new_tot_time = (ltls.tv_sec * 1000000) + ltls.tv_usec;
133548b6c649SRandall Stewart 	}
133648b6c649SRandall Stewart }
133748b6c649SRandall Stewart 
133848b6c649SRandall Stewart static void
sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb * stcb,struct sctp_nets * net)133948b6c649SRandall Stewart sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb,
134048b6c649SRandall Stewart     struct sctp_nets *net)
134148b6c649SRandall Stewart {
1342db2ce691SMateusz Guzik 	uint64_t vtag __dtrace, probepoint __dtrace;
134348b6c649SRandall Stewart 
134448b6c649SRandall Stewart 	if (net->cc_mod.rtcc.lbw) {
134548b6c649SRandall Stewart 		/* Clear the old bw.. we went to 0 in-flight */
134648b6c649SRandall Stewart 		vtag = (net->rtt << 32) | (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
134748b6c649SRandall Stewart 		    (stcb->rport);
134848b6c649SRandall Stewart 		probepoint = (((uint64_t)net->cwnd) << 32);
134948b6c649SRandall Stewart 		/* Probe point 8 */
135048b6c649SRandall Stewart 		probepoint |= ((8 << 16) | 0);
135136160958SMark Johnston 		SDT_PROBE5(sctp, cwnd, net, rttvar,
135248b6c649SRandall Stewart 		    vtag,
135348b6c649SRandall Stewart 		    ((net->cc_mod.rtcc.lbw << 32) | 0),
1354f79aab18SRandall Stewart 		    ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
1355f79aab18SRandall Stewart 		    net->flight_size,
135648b6c649SRandall Stewart 		    probepoint);
135748b6c649SRandall Stewart 		net->cc_mod.rtcc.lbw_rtt = 0;
135848b6c649SRandall Stewart 		net->cc_mod.rtcc.cwnd_at_bw_set = 0;
135948b6c649SRandall Stewart 		net->cc_mod.rtcc.lbw = 0;
1360f79aab18SRandall Stewart 		net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
1361f79aab18SRandall Stewart 		net->cc_mod.rtcc.vol_reduce = 0;
136248b6c649SRandall Stewart 		net->cc_mod.rtcc.bw_tot_time = 0;
136348b6c649SRandall Stewart 		net->cc_mod.rtcc.bw_bytes = 0;
136448b6c649SRandall Stewart 		net->cc_mod.rtcc.tls_needs_set = 0;
1365f79aab18SRandall Stewart 		if (net->cc_mod.rtcc.steady_step) {
1366f79aab18SRandall Stewart 			net->cc_mod.rtcc.vol_reduce = 0;
1367f79aab18SRandall Stewart 			net->cc_mod.rtcc.step_cnt = 0;
1368f79aab18SRandall Stewart 			net->cc_mod.rtcc.last_step_state = 0;
1369f79aab18SRandall Stewart 		}
137048b6c649SRandall Stewart 		if (net->cc_mod.rtcc.ret_from_eq) {
137148b6c649SRandall Stewart 			/* less aggressive one - reset cwnd too */
137248b6c649SRandall Stewart 			uint32_t cwnd_in_mtu, cwnd;
137348b6c649SRandall Stewart 
137448b6c649SRandall Stewart 			cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
137548b6c649SRandall Stewart 			if (cwnd_in_mtu == 0) {
1376b7b84c0eSMichael Tuexen 				/*
1377b7b84c0eSMichael Tuexen 				 * Using 0 means that the value of RFC 4960
1378b7b84c0eSMichael Tuexen 				 * is used.
1379b7b84c0eSMichael Tuexen 				 */
138048b6c649SRandall Stewart 				cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
138148b6c649SRandall Stewart 			} else {
138248b6c649SRandall Stewart 				/*
138348b6c649SRandall Stewart 				 * We take the minimum of the burst limit
138448b6c649SRandall Stewart 				 * and the initial congestion window.
138548b6c649SRandall Stewart 				 */
138648b6c649SRandall Stewart 				if ((stcb->asoc.max_burst > 0) && (cwnd_in_mtu > stcb->asoc.max_burst))
138748b6c649SRandall Stewart 					cwnd_in_mtu = stcb->asoc.max_burst;
138848b6c649SRandall Stewart 				cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
138948b6c649SRandall Stewart 			}
139048b6c649SRandall Stewart 			if (net->cwnd > cwnd) {
1391b7b84c0eSMichael Tuexen 				/*
1392b7b84c0eSMichael Tuexen 				 * Only set if we are not a timeout (i.e.
1393b7b84c0eSMichael Tuexen 				 * down to 1 mtu)
1394b7b84c0eSMichael Tuexen 				 */
139548b6c649SRandall Stewart 				net->cwnd = cwnd;
139648b6c649SRandall Stewart 			}
139748b6c649SRandall Stewart 		}
139848b6c649SRandall Stewart 	}
139948b6c649SRandall Stewart }
140048b6c649SRandall Stewart 
140148b6c649SRandall Stewart static void
sctp_set_rtcc_initial_cc_param(struct sctp_tcb * stcb,struct sctp_nets * net)140248b6c649SRandall Stewart sctp_set_rtcc_initial_cc_param(struct sctp_tcb *stcb,
140348b6c649SRandall Stewart     struct sctp_nets *net)
140448b6c649SRandall Stewart {
1405*fb259f62SMichael Tuexen 	uint64_t vtag __dtrace, probepoint __dtrace;
140648b6c649SRandall Stewart 
140748b6c649SRandall Stewart 	sctp_set_initial_cc_param(stcb, net);
140848b6c649SRandall Stewart 	stcb->asoc.use_precise_time = 1;
140948b6c649SRandall Stewart 	probepoint = (((uint64_t)net->cwnd) << 32);
141048b6c649SRandall Stewart 	probepoint |= ((9 << 16) | 0);
141148b6c649SRandall Stewart 	vtag = (net->rtt << 32) |
141248b6c649SRandall Stewart 	    (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
141348b6c649SRandall Stewart 	    (stcb->rport);
141436160958SMark Johnston 	SDT_PROBE5(sctp, cwnd, net, rttvar,
141548b6c649SRandall Stewart 	    vtag,
141648b6c649SRandall Stewart 	    0,
141748b6c649SRandall Stewart 	    0,
141848b6c649SRandall Stewart 	    0,
141948b6c649SRandall Stewart 	    probepoint);
142048b6c649SRandall Stewart 	net->cc_mod.rtcc.lbw_rtt = 0;
142148b6c649SRandall Stewart 	net->cc_mod.rtcc.cwnd_at_bw_set = 0;
1422f79aab18SRandall Stewart 	net->cc_mod.rtcc.vol_reduce = 0;
142348b6c649SRandall Stewart 	net->cc_mod.rtcc.lbw = 0;
1424f79aab18SRandall Stewart 	net->cc_mod.rtcc.vol_reduce = 0;
1425f79aab18SRandall Stewart 	net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
142648b6c649SRandall Stewart 	net->cc_mod.rtcc.bw_tot_time = 0;
142748b6c649SRandall Stewart 	net->cc_mod.rtcc.bw_bytes = 0;
142848b6c649SRandall Stewart 	net->cc_mod.rtcc.tls_needs_set = 0;
142948b6c649SRandall Stewart 	net->cc_mod.rtcc.ret_from_eq = SCTP_BASE_SYSCTL(sctp_rttvar_eqret);
1430f79aab18SRandall Stewart 	net->cc_mod.rtcc.steady_step = SCTP_BASE_SYSCTL(sctp_steady_step);
1431f79aab18SRandall Stewart 	net->cc_mod.rtcc.use_dccc_ecn = SCTP_BASE_SYSCTL(sctp_use_dccc_ecn);
1432f79aab18SRandall Stewart 	net->cc_mod.rtcc.step_cnt = 0;
1433f79aab18SRandall Stewart 	net->cc_mod.rtcc.last_step_state = 0;
143448b6c649SRandall Stewart }
143548b6c649SRandall Stewart 
143648b6c649SRandall Stewart static int
sctp_cwnd_rtcc_socket_option(struct sctp_tcb * stcb,int setorget,struct sctp_cc_option * cc_opt)143748b6c649SRandall Stewart sctp_cwnd_rtcc_socket_option(struct sctp_tcb *stcb, int setorget,
143848b6c649SRandall Stewart     struct sctp_cc_option *cc_opt)
143948b6c649SRandall Stewart {
144048b6c649SRandall Stewart 	struct sctp_nets *net;
144148b6c649SRandall Stewart 
144248b6c649SRandall Stewart 	if (setorget == 1) {
144348b6c649SRandall Stewart 		/* a set */
144448b6c649SRandall Stewart 		if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
144548b6c649SRandall Stewart 			if ((cc_opt->aid_value.assoc_value != 0) &&
144648b6c649SRandall Stewart 			    (cc_opt->aid_value.assoc_value != 1)) {
144748b6c649SRandall Stewart 				return (EINVAL);
144848b6c649SRandall Stewart 			}
144948b6c649SRandall Stewart 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
145048b6c649SRandall Stewart 				net->cc_mod.rtcc.ret_from_eq = cc_opt->aid_value.assoc_value;
145148b6c649SRandall Stewart 			}
145248b6c649SRandall Stewart 		} else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
145348b6c649SRandall Stewart 			if ((cc_opt->aid_value.assoc_value != 0) &&
145448b6c649SRandall Stewart 			    (cc_opt->aid_value.assoc_value != 1)) {
145548b6c649SRandall Stewart 				return (EINVAL);
145648b6c649SRandall Stewart 			}
145748b6c649SRandall Stewart 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
145848b6c649SRandall Stewart 				net->cc_mod.rtcc.use_dccc_ecn = cc_opt->aid_value.assoc_value;
145948b6c649SRandall Stewart 			}
1460f79aab18SRandall Stewart 		} else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
1461f79aab18SRandall Stewart 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1462f79aab18SRandall Stewart 				net->cc_mod.rtcc.steady_step = cc_opt->aid_value.assoc_value;
1463f79aab18SRandall Stewart 			}
146448b6c649SRandall Stewart 		} else {
146548b6c649SRandall Stewart 			return (EINVAL);
146648b6c649SRandall Stewart 		}
146748b6c649SRandall Stewart 	} else {
146848b6c649SRandall Stewart 		/* a get */
146948b6c649SRandall Stewart 		if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
147048b6c649SRandall Stewart 			net = TAILQ_FIRST(&stcb->asoc.nets);
147148b6c649SRandall Stewart 			if (net == NULL) {
147248b6c649SRandall Stewart 				return (EFAULT);
147348b6c649SRandall Stewart 			}
147448b6c649SRandall Stewart 			cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.ret_from_eq;
147548b6c649SRandall Stewart 		} else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
147648b6c649SRandall Stewart 			net = TAILQ_FIRST(&stcb->asoc.nets);
147748b6c649SRandall Stewart 			if (net == NULL) {
147848b6c649SRandall Stewart 				return (EFAULT);
147948b6c649SRandall Stewart 			}
148048b6c649SRandall Stewart 			cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.use_dccc_ecn;
1481f79aab18SRandall Stewart 		} else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
1482f79aab18SRandall Stewart 			net = TAILQ_FIRST(&stcb->asoc.nets);
1483f79aab18SRandall Stewart 			if (net == NULL) {
1484f79aab18SRandall Stewart 				return (EFAULT);
1485f79aab18SRandall Stewart 			}
1486f79aab18SRandall Stewart 			cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.steady_step;
148748b6c649SRandall Stewart 		} else {
148848b6c649SRandall Stewart 			return (EINVAL);
148948b6c649SRandall Stewart 		}
149048b6c649SRandall Stewart 	}
149148b6c649SRandall Stewart 	return (0);
149248b6c649SRandall Stewart }
149348b6c649SRandall Stewart 
149448b6c649SRandall Stewart static void
sctp_cwnd_update_rtcc_packet_transmitted(struct sctp_tcb * stcb SCTP_UNUSED,struct sctp_nets * net)14957215cc1bSMichael Tuexen sctp_cwnd_update_rtcc_packet_transmitted(struct sctp_tcb *stcb SCTP_UNUSED,
149648b6c649SRandall Stewart     struct sctp_nets *net)
149748b6c649SRandall Stewart {
149848b6c649SRandall Stewart 	if (net->cc_mod.rtcc.tls_needs_set == 0) {
149948b6c649SRandall Stewart 		SCTP_GETPTIME_TIMEVAL(&net->cc_mod.rtcc.tls);
150048b6c649SRandall Stewart 		net->cc_mod.rtcc.tls_needs_set = 2;
150148b6c649SRandall Stewart 	}
150248b6c649SRandall Stewart }
150348b6c649SRandall Stewart 
150448b6c649SRandall Stewart static void
sctp_cwnd_update_rtcc_after_sack(struct sctp_tcb * stcb,struct sctp_association * asoc,int accum_moved,int reneged_all,int will_exit)150548b6c649SRandall Stewart sctp_cwnd_update_rtcc_after_sack(struct sctp_tcb *stcb,
150648b6c649SRandall Stewart     struct sctp_association *asoc,
150748b6c649SRandall Stewart     int accum_moved, int reneged_all, int will_exit)
150848b6c649SRandall Stewart {
1509cd0a4ff6SPedro F. Giffuni 	/* Passing a one argument at the last enables the rtcc algorithm */
151048b6c649SRandall Stewart 	sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 1);
151148b6c649SRandall Stewart }
151248b6c649SRandall Stewart 
1513f79aab18SRandall Stewart static void
sctp_rtt_rtcc_calculated(struct sctp_tcb * stcb SCTP_UNUSED,struct sctp_nets * net,struct timeval * now SCTP_UNUSED)15147215cc1bSMichael Tuexen sctp_rtt_rtcc_calculated(struct sctp_tcb *stcb SCTP_UNUSED,
15157215cc1bSMichael Tuexen     struct sctp_nets *net,
15167215cc1bSMichael Tuexen     struct timeval *now SCTP_UNUSED)
1517f79aab18SRandall Stewart {
1518f79aab18SRandall Stewart 	net->cc_mod.rtcc.rtt_set_this_sack = 1;
1519f79aab18SRandall Stewart }
152048b6c649SRandall Stewart 
152148b6c649SRandall Stewart /* Here starts Sally Floyds HS-TCP */
152248b6c649SRandall Stewart 
1523b54d3a6cSRandall Stewart struct sctp_hs_raise_drop {
1524b54d3a6cSRandall Stewart 	int32_t cwnd;
1525ed654363SMichael Tuexen 	int8_t increase;
1526ed654363SMichael Tuexen 	int8_t drop_percent;
1527b54d3a6cSRandall Stewart };
1528b54d3a6cSRandall Stewart 
1529b54d3a6cSRandall Stewart #define SCTP_HS_TABLE_SIZE 73
1530b54d3a6cSRandall Stewart 
1531ed654363SMichael Tuexen static const struct sctp_hs_raise_drop sctp_cwnd_adjust[SCTP_HS_TABLE_SIZE] = {
1532b54d3a6cSRandall Stewart 	{38, 1, 50},		/* 0   */
1533b54d3a6cSRandall Stewart 	{118, 2, 44},		/* 1   */
1534b54d3a6cSRandall Stewart 	{221, 3, 41},		/* 2   */
1535b54d3a6cSRandall Stewart 	{347, 4, 38},		/* 3   */
1536b54d3a6cSRandall Stewart 	{495, 5, 37},		/* 4   */
1537b54d3a6cSRandall Stewart 	{663, 6, 35},		/* 5   */
1538b54d3a6cSRandall Stewart 	{851, 7, 34},		/* 6   */
1539b54d3a6cSRandall Stewart 	{1058, 8, 33},		/* 7   */
1540b54d3a6cSRandall Stewart 	{1284, 9, 32},		/* 8   */
1541b54d3a6cSRandall Stewart 	{1529, 10, 31},		/* 9   */
1542b54d3a6cSRandall Stewart 	{1793, 11, 30},		/* 10  */
1543b54d3a6cSRandall Stewart 	{2076, 12, 29},		/* 11  */
1544b54d3a6cSRandall Stewart 	{2378, 13, 28},		/* 12  */
1545b54d3a6cSRandall Stewart 	{2699, 14, 28},		/* 13  */
1546b54d3a6cSRandall Stewart 	{3039, 15, 27},		/* 14  */
1547b54d3a6cSRandall Stewart 	{3399, 16, 27},		/* 15  */
1548b54d3a6cSRandall Stewart 	{3778, 17, 26},		/* 16  */
1549b54d3a6cSRandall Stewart 	{4177, 18, 26},		/* 17  */
1550b54d3a6cSRandall Stewart 	{4596, 19, 25},		/* 18  */
1551b54d3a6cSRandall Stewart 	{5036, 20, 25},		/* 19  */
1552b54d3a6cSRandall Stewart 	{5497, 21, 24},		/* 20  */
1553b54d3a6cSRandall Stewart 	{5979, 22, 24},		/* 21  */
1554b54d3a6cSRandall Stewart 	{6483, 23, 23},		/* 22  */
1555b54d3a6cSRandall Stewart 	{7009, 24, 23},		/* 23  */
1556b54d3a6cSRandall Stewart 	{7558, 25, 22},		/* 24  */
1557b54d3a6cSRandall Stewart 	{8130, 26, 22},		/* 25  */
1558b54d3a6cSRandall Stewart 	{8726, 27, 22},		/* 26  */
1559b54d3a6cSRandall Stewart 	{9346, 28, 21},		/* 27  */
1560b54d3a6cSRandall Stewart 	{9991, 29, 21},		/* 28  */
1561b54d3a6cSRandall Stewart 	{10661, 30, 21},	/* 29  */
1562b54d3a6cSRandall Stewart 	{11358, 31, 20},	/* 30  */
1563b54d3a6cSRandall Stewart 	{12082, 32, 20},	/* 31  */
1564b54d3a6cSRandall Stewart 	{12834, 33, 20},	/* 32  */
1565b54d3a6cSRandall Stewart 	{13614, 34, 19},	/* 33  */
1566b54d3a6cSRandall Stewart 	{14424, 35, 19},	/* 34  */
1567b54d3a6cSRandall Stewart 	{15265, 36, 19},	/* 35  */
1568b54d3a6cSRandall Stewart 	{16137, 37, 19},	/* 36  */
1569b54d3a6cSRandall Stewart 	{17042, 38, 18},	/* 37  */
1570b54d3a6cSRandall Stewart 	{17981, 39, 18},	/* 38  */
1571b54d3a6cSRandall Stewart 	{18955, 40, 18},	/* 39  */
1572b54d3a6cSRandall Stewart 	{19965, 41, 17},	/* 40  */
1573b54d3a6cSRandall Stewart 	{21013, 42, 17},	/* 41  */
1574b54d3a6cSRandall Stewart 	{22101, 43, 17},	/* 42  */
1575b54d3a6cSRandall Stewart 	{23230, 44, 17},	/* 43  */
1576b54d3a6cSRandall Stewart 	{24402, 45, 16},	/* 44  */
1577b54d3a6cSRandall Stewart 	{25618, 46, 16},	/* 45  */
1578b54d3a6cSRandall Stewart 	{26881, 47, 16},	/* 46  */
1579b54d3a6cSRandall Stewart 	{28193, 48, 16},	/* 47  */
1580b54d3a6cSRandall Stewart 	{29557, 49, 15},	/* 48  */
1581b54d3a6cSRandall Stewart 	{30975, 50, 15},	/* 49  */
1582b54d3a6cSRandall Stewart 	{32450, 51, 15},	/* 50  */
1583b54d3a6cSRandall Stewart 	{33986, 52, 15},	/* 51  */
1584b54d3a6cSRandall Stewart 	{35586, 53, 14},	/* 52  */
1585b54d3a6cSRandall Stewart 	{37253, 54, 14},	/* 53  */
1586b54d3a6cSRandall Stewart 	{38992, 55, 14},	/* 54  */
1587b54d3a6cSRandall Stewart 	{40808, 56, 14},	/* 55  */
1588b54d3a6cSRandall Stewart 	{42707, 57, 13},	/* 56  */
1589b54d3a6cSRandall Stewart 	{44694, 58, 13},	/* 57  */
1590b54d3a6cSRandall Stewart 	{46776, 59, 13},	/* 58  */
1591b54d3a6cSRandall Stewart 	{48961, 60, 13},	/* 59  */
1592b54d3a6cSRandall Stewart 	{51258, 61, 13},	/* 60  */
1593b54d3a6cSRandall Stewart 	{53677, 62, 12},	/* 61  */
1594b54d3a6cSRandall Stewart 	{56230, 63, 12},	/* 62  */
1595b54d3a6cSRandall Stewart 	{58932, 64, 12},	/* 63  */
1596b54d3a6cSRandall Stewart 	{61799, 65, 12},	/* 64  */
1597b54d3a6cSRandall Stewart 	{64851, 66, 11},	/* 65  */
1598b54d3a6cSRandall Stewart 	{68113, 67, 11},	/* 66  */
1599b54d3a6cSRandall Stewart 	{71617, 68, 11},	/* 67  */
1600b54d3a6cSRandall Stewart 	{75401, 69, 10},	/* 68  */
1601b54d3a6cSRandall Stewart 	{79517, 70, 10},	/* 69  */
1602b54d3a6cSRandall Stewart 	{84035, 71, 10},	/* 70  */
1603b54d3a6cSRandall Stewart 	{89053, 72, 10},	/* 71  */
1604b54d3a6cSRandall Stewart 	{94717, 73, 9}		/* 72  */
1605b54d3a6cSRandall Stewart };
1606b54d3a6cSRandall Stewart 
1607b54d3a6cSRandall Stewart static void
sctp_hs_cwnd_increase(struct sctp_tcb * stcb,struct sctp_nets * net)1608b54d3a6cSRandall Stewart sctp_hs_cwnd_increase(struct sctp_tcb *stcb, struct sctp_nets *net)
1609b54d3a6cSRandall Stewart {
1610b54d3a6cSRandall Stewart 	int cur_val, i, indx, incr;
161159b6d5beSMichael Tuexen 	int old_cwnd = net->cwnd;
1612b54d3a6cSRandall Stewart 
1613b54d3a6cSRandall Stewart 	cur_val = net->cwnd >> 10;
1614b54d3a6cSRandall Stewart 	indx = SCTP_HS_TABLE_SIZE - 1;
1615cd3fd531SMichael Tuexen 
1616b54d3a6cSRandall Stewart 	if (cur_val < sctp_cwnd_adjust[0].cwnd) {
1617b54d3a6cSRandall Stewart 		/* normal mode */
1618b54d3a6cSRandall Stewart 		if (net->net_ack > net->mtu) {
1619b54d3a6cSRandall Stewart 			net->cwnd += net->mtu;
1620b54d3a6cSRandall Stewart 		} else {
1621b54d3a6cSRandall Stewart 			net->cwnd += net->net_ack;
1622b54d3a6cSRandall Stewart 		}
1623b54d3a6cSRandall Stewart 	} else {
1624b54d3a6cSRandall Stewart 		for (i = net->last_hs_used; i < SCTP_HS_TABLE_SIZE; i++) {
1625b54d3a6cSRandall Stewart 			if (cur_val < sctp_cwnd_adjust[i].cwnd) {
1626b54d3a6cSRandall Stewart 				indx = i;
1627b54d3a6cSRandall Stewart 				break;
1628b54d3a6cSRandall Stewart 			}
1629b54d3a6cSRandall Stewart 		}
1630b54d3a6cSRandall Stewart 		net->last_hs_used = indx;
1631ed654363SMichael Tuexen 		incr = (((int32_t)sctp_cwnd_adjust[indx].increase) << 10);
1632b54d3a6cSRandall Stewart 		net->cwnd += incr;
1633b54d3a6cSRandall Stewart 	}
163459b6d5beSMichael Tuexen 	sctp_enforce_cwnd_limit(&stcb->asoc, net);
163559b6d5beSMichael Tuexen 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
163659b6d5beSMichael Tuexen 		sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SS);
1637b54d3a6cSRandall Stewart 	}
1638b54d3a6cSRandall Stewart }
1639b54d3a6cSRandall Stewart 
1640b54d3a6cSRandall Stewart static void
sctp_hs_cwnd_decrease(struct sctp_tcb * stcb,struct sctp_nets * net)1641b54d3a6cSRandall Stewart sctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net)
1642b54d3a6cSRandall Stewart {
1643b54d3a6cSRandall Stewart 	int cur_val, i, indx;
1644b54d3a6cSRandall Stewart 	int old_cwnd = net->cwnd;
1645b54d3a6cSRandall Stewart 
1646b54d3a6cSRandall Stewart 	cur_val = net->cwnd >> 10;
1647b54d3a6cSRandall Stewart 	if (cur_val < sctp_cwnd_adjust[0].cwnd) {
1648b54d3a6cSRandall Stewart 		/* normal mode */
1649b54d3a6cSRandall Stewart 		net->ssthresh = net->cwnd / 2;
1650b54d3a6cSRandall Stewart 		if (net->ssthresh < (net->mtu * 2)) {
1651b54d3a6cSRandall Stewart 			net->ssthresh = 2 * net->mtu;
1652b54d3a6cSRandall Stewart 		}
1653b54d3a6cSRandall Stewart 		net->cwnd = net->ssthresh;
1654b54d3a6cSRandall Stewart 	} else {
1655b54d3a6cSRandall Stewart 		/* drop by the proper amount */
1656b54d3a6cSRandall Stewart 		net->ssthresh = net->cwnd - (int)((net->cwnd / 100) *
1657ed654363SMichael Tuexen 		    (int32_t)sctp_cwnd_adjust[net->last_hs_used].drop_percent);
1658b54d3a6cSRandall Stewart 		net->cwnd = net->ssthresh;
1659b54d3a6cSRandall Stewart 		/* now where are we */
1660b54d3a6cSRandall Stewart 		indx = net->last_hs_used;
1661b54d3a6cSRandall Stewart 		cur_val = net->cwnd >> 10;
1662b54d3a6cSRandall Stewart 		/* reset where we are in the table */
1663b54d3a6cSRandall Stewart 		if (cur_val < sctp_cwnd_adjust[0].cwnd) {
1664b54d3a6cSRandall Stewart 			/* feel out of hs */
1665b54d3a6cSRandall Stewart 			net->last_hs_used = 0;
1666b54d3a6cSRandall Stewart 		} else {
1667b54d3a6cSRandall Stewart 			for (i = indx; i >= 1; i--) {
1668b54d3a6cSRandall Stewart 				if (cur_val > sctp_cwnd_adjust[i - 1].cwnd) {
1669b54d3a6cSRandall Stewart 					break;
1670b54d3a6cSRandall Stewart 				}
1671b54d3a6cSRandall Stewart 			}
1672b54d3a6cSRandall Stewart 			net->last_hs_used = indx;
1673b54d3a6cSRandall Stewart 		}
1674b54d3a6cSRandall Stewart 	}
167559b6d5beSMichael Tuexen 	sctp_enforce_cwnd_limit(&stcb->asoc, net);
1676b3f1ea41SRandall Stewart 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1677b54d3a6cSRandall Stewart 		sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_FR);
1678b54d3a6cSRandall Stewart 	}
1679b54d3a6cSRandall Stewart }
1680b54d3a6cSRandall Stewart 
16810e9a9c10SMichael Tuexen static void
sctp_hs_cwnd_update_after_fr(struct sctp_tcb * stcb,struct sctp_association * asoc)1682b54d3a6cSRandall Stewart sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
1683b54d3a6cSRandall Stewart     struct sctp_association *asoc)
1684b54d3a6cSRandall Stewart {
1685b54d3a6cSRandall Stewart 	struct sctp_nets *net;
1686b54d3a6cSRandall Stewart 
1687b54d3a6cSRandall Stewart 	/*
16887c99d56fSMichael Tuexen 	 * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
1689b54d3a6cSRandall Stewart 	 * (net->fast_retran_loss_recovery == 0)))
1690b54d3a6cSRandall Stewart 	 */
1691b54d3a6cSRandall Stewart 	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
169220083c2eSMichael Tuexen 		if ((asoc->fast_retran_loss_recovery == 0) ||
16937c99d56fSMichael Tuexen 		    (asoc->sctp_cmt_on_off > 0)) {
1694b54d3a6cSRandall Stewart 			/* out of a RFC2582 Fast recovery window? */
1695b54d3a6cSRandall Stewart 			if (net->net_ack > 0) {
1696b54d3a6cSRandall Stewart 				/*
1697b54d3a6cSRandall Stewart 				 * per section 7.2.3, are there any
1698b54d3a6cSRandall Stewart 				 * destinations that had a fast retransmit
1699b54d3a6cSRandall Stewart 				 * to them. If so what we need to do is
1700b54d3a6cSRandall Stewart 				 * adjust ssthresh and cwnd.
1701b54d3a6cSRandall Stewart 				 */
1702b54d3a6cSRandall Stewart 				struct sctp_tmit_chunk *lchk;
1703b54d3a6cSRandall Stewart 
1704b54d3a6cSRandall Stewart 				sctp_hs_cwnd_decrease(stcb, net);
1705b54d3a6cSRandall Stewart 
1706b54d3a6cSRandall Stewart 				lchk = TAILQ_FIRST(&asoc->send_queue);
1707b54d3a6cSRandall Stewart 
1708b54d3a6cSRandall Stewart 				net->partial_bytes_acked = 0;
1709b54d3a6cSRandall Stewart 				/* Turn on fast recovery window */
1710b54d3a6cSRandall Stewart 				asoc->fast_retran_loss_recovery = 1;
1711b54d3a6cSRandall Stewart 				if (lchk == NULL) {
1712b54d3a6cSRandall Stewart 					/* Mark end of the window */
1713b54d3a6cSRandall Stewart 					asoc->fast_recovery_tsn = asoc->sending_seq - 1;
1714b54d3a6cSRandall Stewart 				} else {
171549656eefSMichael Tuexen 					asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1;
1716b54d3a6cSRandall Stewart 				}
1717b54d3a6cSRandall Stewart 
1718b54d3a6cSRandall Stewart 				/*
1719b54d3a6cSRandall Stewart 				 * CMT fast recovery -- per destination
1720b54d3a6cSRandall Stewart 				 * recovery variable.
1721b54d3a6cSRandall Stewart 				 */
1722b54d3a6cSRandall Stewart 				net->fast_retran_loss_recovery = 1;
1723b54d3a6cSRandall Stewart 
1724b54d3a6cSRandall Stewart 				if (lchk == NULL) {
1725b54d3a6cSRandall Stewart 					/* Mark end of the window */
1726b54d3a6cSRandall Stewart 					net->fast_recovery_tsn = asoc->sending_seq - 1;
1727b54d3a6cSRandall Stewart 				} else {
172849656eefSMichael Tuexen 					net->fast_recovery_tsn = lchk->rec.data.tsn - 1;
1729b54d3a6cSRandall Stewart 				}
1730b54d3a6cSRandall Stewart 
1731b54d3a6cSRandall Stewart 				sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
1732b7d130beSMichael Tuexen 				    stcb->sctp_ep, stcb, net,
1733b7d130beSMichael Tuexen 				    SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_2);
1734b54d3a6cSRandall Stewart 				sctp_timer_start(SCTP_TIMER_TYPE_SEND,
1735b54d3a6cSRandall Stewart 				    stcb->sctp_ep, stcb, net);
1736b54d3a6cSRandall Stewart 			}
1737b54d3a6cSRandall Stewart 		} else if (net->net_ack > 0) {
1738b54d3a6cSRandall Stewart 			/*
1739b54d3a6cSRandall Stewart 			 * Mark a peg that we WOULD have done a cwnd
1740b54d3a6cSRandall Stewart 			 * reduction but RFC2582 prevented this action.
1741b54d3a6cSRandall Stewart 			 */
1742b54d3a6cSRandall Stewart 			SCTP_STAT_INCR(sctps_fastretransinrtt);
1743b54d3a6cSRandall Stewart 		}
1744b54d3a6cSRandall Stewart 	}
1745b54d3a6cSRandall Stewart }
1746b54d3a6cSRandall Stewart 
17470e9a9c10SMichael Tuexen static void
sctp_hs_cwnd_update_after_sack(struct sctp_tcb * stcb,struct sctp_association * asoc,int accum_moved,int reneged_all SCTP_UNUSED,int will_exit)1748b54d3a6cSRandall Stewart sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
1749b54d3a6cSRandall Stewart     struct sctp_association *asoc,
17507215cc1bSMichael Tuexen     int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
1751b54d3a6cSRandall Stewart {
1752b54d3a6cSRandall Stewart 	struct sctp_nets *net;
1753b54d3a6cSRandall Stewart 
1754b54d3a6cSRandall Stewart 	/******************************/
1755b54d3a6cSRandall Stewart 	/* update cwnd and Early FR   */
1756b54d3a6cSRandall Stewart 	/******************************/
1757b54d3a6cSRandall Stewart 	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
1758b54d3a6cSRandall Stewart #ifdef JANA_CMT_FAST_RECOVERY
1759b54d3a6cSRandall Stewart 		/*
1760b54d3a6cSRandall Stewart 		 * CMT fast recovery code. Need to debug.
1761b54d3a6cSRandall Stewart 		 */
1762b54d3a6cSRandall Stewart 		if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
1763ea8345d6SMichael Tuexen 			if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
1764ea8345d6SMichael Tuexen 			    SCTP_TSN_GE(net->pseudo_cumack, net->fast_recovery_tsn)) {
1765b54d3a6cSRandall Stewart 				net->will_exit_fast_recovery = 1;
1766b54d3a6cSRandall Stewart 			}
1767b54d3a6cSRandall Stewart 		}
1768b54d3a6cSRandall Stewart #endif
1769b54d3a6cSRandall Stewart 		/* if nothing was acked on this destination skip it */
1770b54d3a6cSRandall Stewart 		if (net->net_ack == 0) {
1771b3f1ea41SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
1772b54d3a6cSRandall Stewart 				sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
1773b54d3a6cSRandall Stewart 			}
1774b54d3a6cSRandall Stewart 			continue;
1775b54d3a6cSRandall Stewart 		}
1776b54d3a6cSRandall Stewart #ifdef JANA_CMT_FAST_RECOVERY
1777b54d3a6cSRandall Stewart 		/*
1778b54d3a6cSRandall Stewart 		 * CMT fast recovery code
1779b54d3a6cSRandall Stewart 		 */
1780b54d3a6cSRandall Stewart 		/*
17817c99d56fSMichael Tuexen 		 * if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery
17827c99d56fSMichael Tuexen 		 * && net->will_exit_fast_recovery == 0) { @@@ Do something
17837c99d56fSMichael Tuexen 		 * } else if (sctp_cmt_on_off == 0 &&
1784b54d3a6cSRandall Stewart 		 * asoc->fast_retran_loss_recovery && will_exit == 0) {
1785b54d3a6cSRandall Stewart 		 */
1786b54d3a6cSRandall Stewart #endif
1787b54d3a6cSRandall Stewart 
178820083c2eSMichael Tuexen 		if (asoc->fast_retran_loss_recovery &&
178920083c2eSMichael Tuexen 		    (will_exit == 0) &&
179020083c2eSMichael Tuexen 		    (asoc->sctp_cmt_on_off == 0)) {
1791b54d3a6cSRandall Stewart 			/*
1792b54d3a6cSRandall Stewart 			 * If we are in loss recovery we skip any cwnd
1793b54d3a6cSRandall Stewart 			 * update
1794b54d3a6cSRandall Stewart 			 */
1795ca85e948SMichael Tuexen 			return;
1796b54d3a6cSRandall Stewart 		}
1797b54d3a6cSRandall Stewart 		/*
1798b54d3a6cSRandall Stewart 		 * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
1799b54d3a6cSRandall Stewart 		 * moved.
1800b54d3a6cSRandall Stewart 		 */
180120083c2eSMichael Tuexen 		if (accum_moved ||
18027c99d56fSMichael Tuexen 		    ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
1803b54d3a6cSRandall Stewart 			/* If the cumulative ack moved we can proceed */
1804b54d3a6cSRandall Stewart 			if (net->cwnd <= net->ssthresh) {
1805b54d3a6cSRandall Stewart 				/* We are in slow start */
1806c54a18d2SRandall Stewart 				if (net->flight_size + net->net_ack >= net->cwnd) {
1807b54d3a6cSRandall Stewart 					sctp_hs_cwnd_increase(stcb, net);
1808b54d3a6cSRandall Stewart 				} else {
1809b3f1ea41SRandall Stewart 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
1810b54d3a6cSRandall Stewart 						sctp_log_cwnd(stcb, net, net->net_ack,
1811b54d3a6cSRandall Stewart 						    SCTP_CWND_LOG_NOADV_SS);
1812b54d3a6cSRandall Stewart 					}
1813b54d3a6cSRandall Stewart 				}
1814b54d3a6cSRandall Stewart 			} else {
1815b54d3a6cSRandall Stewart 				/* We are in congestion avoidance */
1816c54a18d2SRandall Stewart 				net->partial_bytes_acked += net->net_ack;
1817c54a18d2SRandall Stewart 				if ((net->flight_size + net->net_ack >= net->cwnd) &&
1818c54a18d2SRandall Stewart 				    (net->partial_bytes_acked >= net->cwnd)) {
1819c54a18d2SRandall Stewart 					net->partial_bytes_acked -= net->cwnd;
1820b54d3a6cSRandall Stewart 					net->cwnd += net->mtu;
182159b6d5beSMichael Tuexen 					sctp_enforce_cwnd_limit(asoc, net);
1822b3f1ea41SRandall Stewart 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1823b54d3a6cSRandall Stewart 						sctp_log_cwnd(stcb, net, net->mtu,
1824b54d3a6cSRandall Stewart 						    SCTP_CWND_LOG_FROM_CA);
1825b54d3a6cSRandall Stewart 					}
1826b54d3a6cSRandall Stewart 				} else {
1827b3f1ea41SRandall Stewart 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
1828b54d3a6cSRandall Stewart 						sctp_log_cwnd(stcb, net, net->net_ack,
1829b54d3a6cSRandall Stewart 						    SCTP_CWND_LOG_NOADV_CA);
1830b54d3a6cSRandall Stewart 					}
1831b54d3a6cSRandall Stewart 				}
1832b54d3a6cSRandall Stewart 			}
1833b54d3a6cSRandall Stewart 		} else {
1834b3f1ea41SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
1835b54d3a6cSRandall Stewart 				sctp_log_cwnd(stcb, net, net->mtu,
1836b54d3a6cSRandall Stewart 				    SCTP_CWND_LOG_NO_CUMACK);
1837b54d3a6cSRandall Stewart 			}
1838b54d3a6cSRandall Stewart 		}
1839b54d3a6cSRandall Stewart 	}
1840b54d3a6cSRandall Stewart }
1841b54d3a6cSRandall Stewart 
1842b54d3a6cSRandall Stewart /*
1843b54d3a6cSRandall Stewart  * H-TCP congestion control. The algorithm is detailed in:
1844b54d3a6cSRandall Stewart  * R.N.Shorten, D.J.Leith:
1845b54d3a6cSRandall Stewart  *   "H-TCP: TCP for high-speed and long-distance networks"
1846b54d3a6cSRandall Stewart  *   Proc. PFLDnet, Argonne, 2004.
1847b54d3a6cSRandall Stewart  * http://www.hamilton.ie/net/htcp3.pdf
1848b54d3a6cSRandall Stewart  */
1849b54d3a6cSRandall Stewart 
1850b54d3a6cSRandall Stewart static int use_rtt_scaling = 1;
1851b54d3a6cSRandall Stewart static int use_bandwidth_switch = 1;
1852b54d3a6cSRandall Stewart 
1853b54d3a6cSRandall Stewart static inline int
between(uint32_t seq1,uint32_t seq2,uint32_t seq3)1854b54d3a6cSRandall Stewart between(uint32_t seq1, uint32_t seq2, uint32_t seq3)
1855b54d3a6cSRandall Stewart {
185660990c0cSMichael Tuexen 	return (seq3 - seq2 >= seq1 - seq2);
1857b54d3a6cSRandall Stewart }
1858b54d3a6cSRandall Stewart 
1859b54d3a6cSRandall Stewart static inline uint32_t
htcp_cong_time(struct htcp * ca)1860b0471b4bSMichael Tuexen htcp_cong_time(struct htcp *ca)
1861b0471b4bSMichael Tuexen {
186260990c0cSMichael Tuexen 	return (sctp_get_tick_count() - ca->last_cong);
1863b54d3a6cSRandall Stewart }
1864b54d3a6cSRandall Stewart 
1865b54d3a6cSRandall Stewart static inline uint32_t
htcp_ccount(struct htcp * ca)1866b0471b4bSMichael Tuexen htcp_ccount(struct htcp *ca)
1867b0471b4bSMichael Tuexen {
1868fc0eb763SMichael Tuexen 	return (ca->minRTT == 0 ? htcp_cong_time(ca) : htcp_cong_time(ca) / ca->minRTT);
1869b54d3a6cSRandall Stewart }
1870b54d3a6cSRandall Stewart 
1871b54d3a6cSRandall Stewart static inline void
htcp_reset(struct htcp * ca)1872b54d3a6cSRandall Stewart htcp_reset(struct htcp *ca)
1873b54d3a6cSRandall Stewart {
1874b54d3a6cSRandall Stewart 	ca->undo_last_cong = ca->last_cong;
1875b54d3a6cSRandall Stewart 	ca->undo_maxRTT = ca->maxRTT;
1876b54d3a6cSRandall Stewart 	ca->undo_old_maxB = ca->old_maxB;
187718e198d3SRandall Stewart 	ca->last_cong = sctp_get_tick_count();
1878b54d3a6cSRandall Stewart }
1879b54d3a6cSRandall Stewart 
1880b54d3a6cSRandall Stewart #ifdef SCTP_NOT_USED
1881b54d3a6cSRandall Stewart 
1882b54d3a6cSRandall Stewart static uint32_t
htcp_cwnd_undo(struct sctp_tcb * stcb,struct sctp_nets * net)1883b0471b4bSMichael Tuexen htcp_cwnd_undo(struct sctp_tcb *stcb, struct sctp_nets *net)
1884b0471b4bSMichael Tuexen {
1885299108c5SRandall Stewart 	net->cc_mod.htcp_ca.last_cong = net->cc_mod.htcp_ca.undo_last_cong;
1886299108c5SRandall Stewart 	net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.undo_maxRTT;
1887299108c5SRandall Stewart 	net->cc_mod.htcp_ca.old_maxB = net->cc_mod.htcp_ca.undo_old_maxB;
188860990c0cSMichael Tuexen 	return (max(net->cwnd, ((net->ssthresh / net->mtu << 7) / net->cc_mod.htcp_ca.beta) * net->mtu));
1889b54d3a6cSRandall Stewart }
1890b54d3a6cSRandall Stewart 
1891b54d3a6cSRandall Stewart #endif
1892b54d3a6cSRandall Stewart 
1893b54d3a6cSRandall Stewart static inline void
measure_rtt(struct sctp_nets * net)18947215cc1bSMichael Tuexen measure_rtt(struct sctp_nets *net)
1895b54d3a6cSRandall Stewart {
18960191fb6dSMichael Tuexen 	uint32_t srtt = net->lastsa >> SCTP_RTT_SHIFT;
1897b54d3a6cSRandall Stewart 
1898b54d3a6cSRandall Stewart 	/* keep track of minimum RTT seen so far, minRTT is zero at first */
1899299108c5SRandall Stewart 	if (net->cc_mod.htcp_ca.minRTT > srtt || !net->cc_mod.htcp_ca.minRTT)
1900299108c5SRandall Stewart 		net->cc_mod.htcp_ca.minRTT = srtt;
1901b54d3a6cSRandall Stewart 
1902b54d3a6cSRandall Stewart 	/* max RTT */
1903299108c5SRandall Stewart 	if (net->fast_retran_ip == 0 && net->ssthresh < 0xFFFF && htcp_ccount(&net->cc_mod.htcp_ca) > 3) {
1904299108c5SRandall Stewart 		if (net->cc_mod.htcp_ca.maxRTT < net->cc_mod.htcp_ca.minRTT)
1905299108c5SRandall Stewart 			net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.minRTT;
190625ec3553SMichael Tuexen 		if (net->cc_mod.htcp_ca.maxRTT < srtt && srtt <= net->cc_mod.htcp_ca.maxRTT + sctp_msecs_to_ticks(20))
1907299108c5SRandall Stewart 			net->cc_mod.htcp_ca.maxRTT = srtt;
1908b54d3a6cSRandall Stewart 	}
1909b54d3a6cSRandall Stewart }
1910b54d3a6cSRandall Stewart 
1911b54d3a6cSRandall Stewart static void
measure_achieved_throughput(struct sctp_nets * net)19127215cc1bSMichael Tuexen measure_achieved_throughput(struct sctp_nets *net)
1913b54d3a6cSRandall Stewart {
191418e198d3SRandall Stewart 	uint32_t now = sctp_get_tick_count();
1915b54d3a6cSRandall Stewart 
1916b54d3a6cSRandall Stewart 	if (net->fast_retran_ip == 0)
1917299108c5SRandall Stewart 		net->cc_mod.htcp_ca.bytes_acked = net->net_ack;
1918b54d3a6cSRandall Stewart 
1919b54d3a6cSRandall Stewart 	if (!use_bandwidth_switch)
1920b54d3a6cSRandall Stewart 		return;
1921b54d3a6cSRandall Stewart 
1922b54d3a6cSRandall Stewart 	/* achieved throughput calculations */
1923b54d3a6cSRandall Stewart 	/* JRS - not 100% sure of this statement */
1924b54d3a6cSRandall Stewart 	if (net->fast_retran_ip == 1) {
1925299108c5SRandall Stewart 		net->cc_mod.htcp_ca.bytecount = 0;
1926299108c5SRandall Stewart 		net->cc_mod.htcp_ca.lasttime = now;
1927b54d3a6cSRandall Stewart 		return;
1928b54d3a6cSRandall Stewart 	}
19290053ed28SMichael Tuexen 
1930299108c5SRandall Stewart 	net->cc_mod.htcp_ca.bytecount += net->net_ack;
193112780a59SMichael Tuexen 	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)) &&
193212780a59SMichael Tuexen 	    (now - net->cc_mod.htcp_ca.lasttime >= net->cc_mod.htcp_ca.minRTT) &&
193312780a59SMichael Tuexen 	    (net->cc_mod.htcp_ca.minRTT > 0)) {
1934299108c5SRandall Stewart 		uint32_t cur_Bi = net->cc_mod.htcp_ca.bytecount / net->mtu * hz / (now - net->cc_mod.htcp_ca.lasttime);
1935b54d3a6cSRandall Stewart 
1936299108c5SRandall Stewart 		if (htcp_ccount(&net->cc_mod.htcp_ca) <= 3) {
1937b54d3a6cSRandall Stewart 			/* just after backoff */
1938299108c5SRandall Stewart 			net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi = cur_Bi;
1939b54d3a6cSRandall Stewart 		} else {
1940299108c5SRandall Stewart 			net->cc_mod.htcp_ca.Bi = (3 * net->cc_mod.htcp_ca.Bi + cur_Bi) / 4;
1941299108c5SRandall Stewart 			if (net->cc_mod.htcp_ca.Bi > net->cc_mod.htcp_ca.maxB)
1942299108c5SRandall Stewart 				net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi;
1943299108c5SRandall Stewart 			if (net->cc_mod.htcp_ca.minB > net->cc_mod.htcp_ca.maxB)
1944299108c5SRandall Stewart 				net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB;
1945b54d3a6cSRandall Stewart 		}
1946299108c5SRandall Stewart 		net->cc_mod.htcp_ca.bytecount = 0;
1947299108c5SRandall Stewart 		net->cc_mod.htcp_ca.lasttime = now;
1948b54d3a6cSRandall Stewart 	}
1949b54d3a6cSRandall Stewart }
1950b54d3a6cSRandall Stewart 
1951b54d3a6cSRandall Stewart static inline void
htcp_beta_update(struct htcp * ca,uint32_t minRTT,uint32_t maxRTT)1952b54d3a6cSRandall Stewart htcp_beta_update(struct htcp *ca, uint32_t minRTT, uint32_t maxRTT)
1953b54d3a6cSRandall Stewart {
1954b54d3a6cSRandall Stewart 	if (use_bandwidth_switch) {
1955b54d3a6cSRandall Stewart 		uint32_t maxB = ca->maxB;
1956b54d3a6cSRandall Stewart 		uint32_t old_maxB = ca->old_maxB;
1957b54d3a6cSRandall Stewart 
1958b54d3a6cSRandall Stewart 		ca->old_maxB = ca->maxB;
1959b54d3a6cSRandall Stewart 
1960b54d3a6cSRandall Stewart 		if (!between(5 * maxB, 4 * old_maxB, 6 * old_maxB)) {
1961b54d3a6cSRandall Stewart 			ca->beta = BETA_MIN;
1962b54d3a6cSRandall Stewart 			ca->modeswitch = 0;
1963b54d3a6cSRandall Stewart 			return;
1964b54d3a6cSRandall Stewart 		}
1965b54d3a6cSRandall Stewart 	}
19660053ed28SMichael Tuexen 
196725ec3553SMichael Tuexen 	if (ca->modeswitch && minRTT > sctp_msecs_to_ticks(10) && maxRTT) {
1968b54d3a6cSRandall Stewart 		ca->beta = (minRTT << 7) / maxRTT;
1969b54d3a6cSRandall Stewart 		if (ca->beta < BETA_MIN)
1970b54d3a6cSRandall Stewart 			ca->beta = BETA_MIN;
1971b54d3a6cSRandall Stewart 		else if (ca->beta > BETA_MAX)
1972b54d3a6cSRandall Stewart 			ca->beta = BETA_MAX;
1973b54d3a6cSRandall Stewart 	} else {
1974b54d3a6cSRandall Stewart 		ca->beta = BETA_MIN;
1975b54d3a6cSRandall Stewart 		ca->modeswitch = 1;
1976b54d3a6cSRandall Stewart 	}
1977b54d3a6cSRandall Stewart }
1978b54d3a6cSRandall Stewart 
1979b54d3a6cSRandall Stewart static inline void
htcp_alpha_update(struct htcp * ca)1980b54d3a6cSRandall Stewart htcp_alpha_update(struct htcp *ca)
1981b54d3a6cSRandall Stewart {
1982b54d3a6cSRandall Stewart 	uint32_t minRTT = ca->minRTT;
1983b54d3a6cSRandall Stewart 	uint32_t factor = 1;
1984b54d3a6cSRandall Stewart 	uint32_t diff = htcp_cong_time(ca);
1985b54d3a6cSRandall Stewart 
1986b54d3a6cSRandall Stewart 	if (diff > (uint32_t)hz) {
1987b54d3a6cSRandall Stewart 		diff -= hz;
1988b54d3a6cSRandall Stewart 		factor = 1 + (10 * diff + ((diff / 2) * (diff / 2) / hz)) / hz;
1989b54d3a6cSRandall Stewart 	}
19900053ed28SMichael Tuexen 
1991b54d3a6cSRandall Stewart 	if (use_rtt_scaling && minRTT) {
1992b54d3a6cSRandall Stewart 		uint32_t scale = (hz << 3) / (10 * minRTT);
1993b54d3a6cSRandall Stewart 
1994b54d3a6cSRandall Stewart 		scale = min(max(scale, 1U << 2), 10U << 3);	/* clamping ratio to
1995b54d3a6cSRandall Stewart 								 * interval [0.5,10]<<3 */
1996b54d3a6cSRandall Stewart 		factor = (factor << 3) / scale;
1997e7a39b85SMichael Tuexen 		if (factor != 0)
1998b54d3a6cSRandall Stewart 			factor = 1;
1999b54d3a6cSRandall Stewart 	}
20000053ed28SMichael Tuexen 
2001b54d3a6cSRandall Stewart 	ca->alpha = 2 * factor * ((1 << 7) - ca->beta);
2002e7a39b85SMichael Tuexen 	if (ca->alpha != 0)
2003b54d3a6cSRandall Stewart 		ca->alpha = ALPHA_BASE;
2004b54d3a6cSRandall Stewart }
2005b54d3a6cSRandall Stewart 
2006b54d3a6cSRandall Stewart /* After we have the rtt data to calculate beta, we'd still prefer to wait one
2007b54d3a6cSRandall Stewart  * rtt before we adjust our beta to ensure we are working from a consistent
2008b54d3a6cSRandall Stewart  * data.
2009b54d3a6cSRandall Stewart  *
2010b54d3a6cSRandall Stewart  * This function should be called when we hit a congestion event since only at
2011b54d3a6cSRandall Stewart  * that point do we really have a real sense of maxRTT (the queues en route
2012b54d3a6cSRandall Stewart  * were getting just too full now).
2013b54d3a6cSRandall Stewart  */
2014b54d3a6cSRandall Stewart static void
htcp_param_update(struct sctp_nets * net)20157215cc1bSMichael Tuexen htcp_param_update(struct sctp_nets *net)
2016b54d3a6cSRandall Stewart {
2017299108c5SRandall Stewart 	uint32_t minRTT = net->cc_mod.htcp_ca.minRTT;
2018299108c5SRandall Stewart 	uint32_t maxRTT = net->cc_mod.htcp_ca.maxRTT;
2019b54d3a6cSRandall Stewart 
2020299108c5SRandall Stewart 	htcp_beta_update(&net->cc_mod.htcp_ca, minRTT, maxRTT);
2021299108c5SRandall Stewart 	htcp_alpha_update(&net->cc_mod.htcp_ca);
2022b54d3a6cSRandall Stewart 
2023b7b84c0eSMichael Tuexen 	/*
2024b7b84c0eSMichael Tuexen 	 * add slowly fading memory for maxRTT to accommodate routing
2025b7b84c0eSMichael Tuexen 	 * changes etc
2026b7b84c0eSMichael Tuexen 	 */
2027b54d3a6cSRandall Stewart 	if (minRTT > 0 && maxRTT > minRTT)
2028299108c5SRandall Stewart 		net->cc_mod.htcp_ca.maxRTT = minRTT + ((maxRTT - minRTT) * 95) / 100;
2029b54d3a6cSRandall Stewart }
2030b54d3a6cSRandall Stewart 
2031b54d3a6cSRandall Stewart static uint32_t
htcp_recalc_ssthresh(struct sctp_nets * net)2032b0471b4bSMichael Tuexen htcp_recalc_ssthresh(struct sctp_nets *net)
2033b0471b4bSMichael Tuexen {
20347215cc1bSMichael Tuexen 	htcp_param_update(net);
203560990c0cSMichael Tuexen 	return (max(((net->cwnd / net->mtu * net->cc_mod.htcp_ca.beta) >> 7) * net->mtu, 2U * net->mtu));
2036b54d3a6cSRandall Stewart }
2037b54d3a6cSRandall Stewart 
2038b54d3a6cSRandall Stewart static void
htcp_cong_avoid(struct sctp_tcb * stcb,struct sctp_nets * net)2039b54d3a6cSRandall Stewart htcp_cong_avoid(struct sctp_tcb *stcb, struct sctp_nets *net)
2040b54d3a6cSRandall Stewart {
2041b54d3a6cSRandall Stewart 	/*-
2042b54d3a6cSRandall Stewart 	 * How to handle these functions?
2043b54d3a6cSRandall Stewart 	 *	if (!tcp_is_cwnd_limited(sk, in_flight)) RRS - good question.
2044b54d3a6cSRandall Stewart 	 *		return;
2045b54d3a6cSRandall Stewart 	 */
2046b54d3a6cSRandall Stewart 	if (net->cwnd <= net->ssthresh) {
2047b54d3a6cSRandall Stewart 		/* We are in slow start */
2048b54d3a6cSRandall Stewart 		if (net->flight_size + net->net_ack >= net->cwnd) {
2049b3f1ea41SRandall Stewart 			if (net->net_ack > (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable))) {
2050b3f1ea41SRandall Stewart 				net->cwnd += (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable));
2051b3f1ea41SRandall Stewart 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2052b54d3a6cSRandall Stewart 					sctp_log_cwnd(stcb, net, net->mtu,
2053b54d3a6cSRandall Stewart 					    SCTP_CWND_LOG_FROM_SS);
2054b54d3a6cSRandall Stewart 				}
20550053ed28SMichael Tuexen 
2056b54d3a6cSRandall Stewart 			} else {
2057b54d3a6cSRandall Stewart 				net->cwnd += net->net_ack;
2058b3f1ea41SRandall Stewart 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2059b54d3a6cSRandall Stewart 					sctp_log_cwnd(stcb, net, net->net_ack,
2060b54d3a6cSRandall Stewart 					    SCTP_CWND_LOG_FROM_SS);
2061b54d3a6cSRandall Stewart 				}
2062b54d3a6cSRandall Stewart 			}
206359b6d5beSMichael Tuexen 			sctp_enforce_cwnd_limit(&stcb->asoc, net);
2064b54d3a6cSRandall Stewart 		} else {
2065b3f1ea41SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
2066b54d3a6cSRandall Stewart 				sctp_log_cwnd(stcb, net, net->net_ack,
2067b54d3a6cSRandall Stewart 				    SCTP_CWND_LOG_NOADV_SS);
2068b54d3a6cSRandall Stewart 			}
2069b54d3a6cSRandall Stewart 		}
2070b54d3a6cSRandall Stewart 	} else {
20717215cc1bSMichael Tuexen 		measure_rtt(net);
2072b54d3a6cSRandall Stewart 
2073b54d3a6cSRandall Stewart 		/*
2074b54d3a6cSRandall Stewart 		 * In dangerous area, increase slowly. In theory this is
2075b54d3a6cSRandall Stewart 		 * net->cwnd += alpha / net->cwnd
2076b54d3a6cSRandall Stewart 		 */
2077b54d3a6cSRandall Stewart 		/* What is snd_cwnd_cnt?? */
2078299108c5SRandall Stewart 		if (((net->partial_bytes_acked / net->mtu * net->cc_mod.htcp_ca.alpha) >> 7) * net->mtu >= net->cwnd) {
2079b54d3a6cSRandall Stewart 			/*-
2080b54d3a6cSRandall Stewart 			 * Does SCTP have a cwnd clamp?
2081b54d3a6cSRandall Stewart 			 * if (net->snd_cwnd < net->snd_cwnd_clamp) - Nope (RRS).
2082b54d3a6cSRandall Stewart 			 */
2083b54d3a6cSRandall Stewart 			net->cwnd += net->mtu;
2084b54d3a6cSRandall Stewart 			net->partial_bytes_acked = 0;
208559b6d5beSMichael Tuexen 			sctp_enforce_cwnd_limit(&stcb->asoc, net);
2086299108c5SRandall Stewart 			htcp_alpha_update(&net->cc_mod.htcp_ca);
2087b3f1ea41SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2088b54d3a6cSRandall Stewart 				sctp_log_cwnd(stcb, net, net->mtu,
2089b54d3a6cSRandall Stewart 				    SCTP_CWND_LOG_FROM_CA);
2090b54d3a6cSRandall Stewart 			}
2091b54d3a6cSRandall Stewart 		} else {
2092b54d3a6cSRandall Stewart 			net->partial_bytes_acked += net->net_ack;
2093b3f1ea41SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
2094b54d3a6cSRandall Stewart 				sctp_log_cwnd(stcb, net, net->net_ack,
2095b54d3a6cSRandall Stewart 				    SCTP_CWND_LOG_NOADV_CA);
2096b54d3a6cSRandall Stewart 			}
2097b54d3a6cSRandall Stewart 		}
2098b54d3a6cSRandall Stewart 
2099299108c5SRandall Stewart 		net->cc_mod.htcp_ca.bytes_acked = net->mtu;
2100b54d3a6cSRandall Stewart 	}
2101b54d3a6cSRandall Stewart }
2102b54d3a6cSRandall Stewart 
2103b54d3a6cSRandall Stewart #ifdef SCTP_NOT_USED
2104b54d3a6cSRandall Stewart /* Lower bound on congestion window. */
2105b54d3a6cSRandall Stewart static uint32_t
htcp_min_cwnd(struct sctp_tcb * stcb,struct sctp_nets * net)2106b0471b4bSMichael Tuexen htcp_min_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net)
2107b0471b4bSMichael Tuexen {
210860990c0cSMichael Tuexen 	return (net->ssthresh);
2109b54d3a6cSRandall Stewart }
2110b54d3a6cSRandall Stewart #endif
2111b54d3a6cSRandall Stewart 
2112b54d3a6cSRandall Stewart static void
htcp_init(struct sctp_nets * net)21137215cc1bSMichael Tuexen htcp_init(struct sctp_nets *net)
2114b54d3a6cSRandall Stewart {
2115299108c5SRandall Stewart 	memset(&net->cc_mod.htcp_ca, 0, sizeof(struct htcp));
2116299108c5SRandall Stewart 	net->cc_mod.htcp_ca.alpha = ALPHA_BASE;
2117299108c5SRandall Stewart 	net->cc_mod.htcp_ca.beta = BETA_MIN;
2118299108c5SRandall Stewart 	net->cc_mod.htcp_ca.bytes_acked = net->mtu;
2119299108c5SRandall Stewart 	net->cc_mod.htcp_ca.last_cong = sctp_get_tick_count();
2120b54d3a6cSRandall Stewart }
2121b54d3a6cSRandall Stewart 
21220e9a9c10SMichael Tuexen static void
sctp_htcp_set_initial_cc_param(struct sctp_tcb * stcb,struct sctp_nets * net)2123b54d3a6cSRandall Stewart sctp_htcp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
2124b54d3a6cSRandall Stewart {
2125b54d3a6cSRandall Stewart 	/*
2126b54d3a6cSRandall Stewart 	 * We take the max of the burst limit times a MTU or the
2127b54d3a6cSRandall Stewart 	 * INITIAL_CWND. We then limit this to 4 MTU's of sending.
2128b54d3a6cSRandall Stewart 	 */
2129b54d3a6cSRandall Stewart 	net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
2130b54d3a6cSRandall Stewart 	net->ssthresh = stcb->asoc.peers_rwnd;
213159b6d5beSMichael Tuexen 	sctp_enforce_cwnd_limit(&stcb->asoc, net);
21327215cc1bSMichael Tuexen 	htcp_init(net);
2133b54d3a6cSRandall Stewart 
2134b3f1ea41SRandall Stewart 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
2135b54d3a6cSRandall Stewart 		sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
2136b54d3a6cSRandall Stewart 	}
2137b54d3a6cSRandall Stewart }
2138b54d3a6cSRandall Stewart 
21390e9a9c10SMichael Tuexen static void
sctp_htcp_cwnd_update_after_sack(struct sctp_tcb * stcb,struct sctp_association * asoc,int accum_moved,int reneged_all SCTP_UNUSED,int will_exit)2140b54d3a6cSRandall Stewart sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
2141b54d3a6cSRandall Stewart     struct sctp_association *asoc,
21427215cc1bSMichael Tuexen     int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
2143b54d3a6cSRandall Stewart {
2144b54d3a6cSRandall Stewart 	struct sctp_nets *net;
2145b54d3a6cSRandall Stewart 
2146b54d3a6cSRandall Stewart 	/******************************/
2147b54d3a6cSRandall Stewart 	/* update cwnd and Early FR   */
2148b54d3a6cSRandall Stewart 	/******************************/
2149b54d3a6cSRandall Stewart 	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
2150b54d3a6cSRandall Stewart #ifdef JANA_CMT_FAST_RECOVERY
2151b54d3a6cSRandall Stewart 		/*
2152b54d3a6cSRandall Stewart 		 * CMT fast recovery code. Need to debug.
2153b54d3a6cSRandall Stewart 		 */
2154b54d3a6cSRandall Stewart 		if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
2155ea8345d6SMichael Tuexen 			if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
2156ea8345d6SMichael Tuexen 			    SCTP_TSN_GE(net->pseudo_cumack, net->fast_recovery_tsn)) {
2157b54d3a6cSRandall Stewart 				net->will_exit_fast_recovery = 1;
2158b54d3a6cSRandall Stewart 			}
2159b54d3a6cSRandall Stewart 		}
2160b54d3a6cSRandall Stewart #endif
2161b54d3a6cSRandall Stewart 		/* if nothing was acked on this destination skip it */
2162b54d3a6cSRandall Stewart 		if (net->net_ack == 0) {
2163b3f1ea41SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
2164b54d3a6cSRandall Stewart 				sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
2165b54d3a6cSRandall Stewart 			}
2166b54d3a6cSRandall Stewart 			continue;
2167b54d3a6cSRandall Stewart 		}
2168b54d3a6cSRandall Stewart #ifdef JANA_CMT_FAST_RECOVERY
2169b54d3a6cSRandall Stewart 		/*
2170b54d3a6cSRandall Stewart 		 * CMT fast recovery code
2171b54d3a6cSRandall Stewart 		 */
2172b54d3a6cSRandall Stewart 		/*
21737c99d56fSMichael Tuexen 		 * if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery
21747c99d56fSMichael Tuexen 		 * && net->will_exit_fast_recovery == 0) { @@@ Do something
21757c99d56fSMichael Tuexen 		 * } else if (sctp_cmt_on_off == 0 &&
2176b54d3a6cSRandall Stewart 		 * asoc->fast_retran_loss_recovery && will_exit == 0) {
2177b54d3a6cSRandall Stewart 		 */
2178b54d3a6cSRandall Stewart #endif
2179b54d3a6cSRandall Stewart 
218020083c2eSMichael Tuexen 		if (asoc->fast_retran_loss_recovery &&
218120083c2eSMichael Tuexen 		    will_exit == 0 &&
218220083c2eSMichael Tuexen 		    (asoc->sctp_cmt_on_off == 0)) {
2183b54d3a6cSRandall Stewart 			/*
2184b54d3a6cSRandall Stewart 			 * If we are in loss recovery we skip any cwnd
2185b54d3a6cSRandall Stewart 			 * update
2186b54d3a6cSRandall Stewart 			 */
2187ca85e948SMichael Tuexen 			return;
2188b54d3a6cSRandall Stewart 		}
2189b54d3a6cSRandall Stewart 		/*
2190b54d3a6cSRandall Stewart 		 * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
2191b54d3a6cSRandall Stewart 		 * moved.
2192b54d3a6cSRandall Stewart 		 */
219320083c2eSMichael Tuexen 		if (accum_moved ||
21947c99d56fSMichael Tuexen 		    ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
2195b54d3a6cSRandall Stewart 			htcp_cong_avoid(stcb, net);
21967215cc1bSMichael Tuexen 			measure_achieved_throughput(net);
2197b54d3a6cSRandall Stewart 		} else {
2198b3f1ea41SRandall Stewart 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
2199b54d3a6cSRandall Stewart 				sctp_log_cwnd(stcb, net, net->mtu,
2200b54d3a6cSRandall Stewart 				    SCTP_CWND_LOG_NO_CUMACK);
2201b54d3a6cSRandall Stewart 			}
2202b54d3a6cSRandall Stewart 		}
2203b54d3a6cSRandall Stewart 	}
2204b54d3a6cSRandall Stewart }
2205b54d3a6cSRandall Stewart 
22060e9a9c10SMichael Tuexen static void
sctp_htcp_cwnd_update_after_fr(struct sctp_tcb * stcb,struct sctp_association * asoc)2207b54d3a6cSRandall Stewart sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
2208b54d3a6cSRandall Stewart     struct sctp_association *asoc)
2209b54d3a6cSRandall Stewart {
2210b54d3a6cSRandall Stewart 	struct sctp_nets *net;
2211b54d3a6cSRandall Stewart 
2212b54d3a6cSRandall Stewart 	/*
22137c99d56fSMichael Tuexen 	 * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
2214b54d3a6cSRandall Stewart 	 * (net->fast_retran_loss_recovery == 0)))
2215b54d3a6cSRandall Stewart 	 */
2216b54d3a6cSRandall Stewart 	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
221720083c2eSMichael Tuexen 		if ((asoc->fast_retran_loss_recovery == 0) ||
22187c99d56fSMichael Tuexen 		    (asoc->sctp_cmt_on_off > 0)) {
2219b54d3a6cSRandall Stewart 			/* out of a RFC2582 Fast recovery window? */
2220b54d3a6cSRandall Stewart 			if (net->net_ack > 0) {
2221b54d3a6cSRandall Stewart 				/*
2222b54d3a6cSRandall Stewart 				 * per section 7.2.3, are there any
2223b54d3a6cSRandall Stewart 				 * destinations that had a fast retransmit
2224b54d3a6cSRandall Stewart 				 * to them. If so what we need to do is
2225b54d3a6cSRandall Stewart 				 * adjust ssthresh and cwnd.
2226b54d3a6cSRandall Stewart 				 */
2227b54d3a6cSRandall Stewart 				struct sctp_tmit_chunk *lchk;
2228b54d3a6cSRandall Stewart 				int old_cwnd = net->cwnd;
2229b54d3a6cSRandall Stewart 
2230b54d3a6cSRandall Stewart 				/* JRS - reset as if state were changed */
2231299108c5SRandall Stewart 				htcp_reset(&net->cc_mod.htcp_ca);
22327215cc1bSMichael Tuexen 				net->ssthresh = htcp_recalc_ssthresh(net);
2233b54d3a6cSRandall Stewart 				net->cwnd = net->ssthresh;
223459b6d5beSMichael Tuexen 				sctp_enforce_cwnd_limit(asoc, net);
2235b3f1ea41SRandall Stewart 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2236b54d3a6cSRandall Stewart 					sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
2237b54d3a6cSRandall Stewart 					    SCTP_CWND_LOG_FROM_FR);
2238b54d3a6cSRandall Stewart 				}
2239b54d3a6cSRandall Stewart 				lchk = TAILQ_FIRST(&asoc->send_queue);
2240b54d3a6cSRandall Stewart 
2241b54d3a6cSRandall Stewart 				net->partial_bytes_acked = 0;
2242b54d3a6cSRandall Stewart 				/* Turn on fast recovery window */
2243b54d3a6cSRandall Stewart 				asoc->fast_retran_loss_recovery = 1;
2244b54d3a6cSRandall Stewart 				if (lchk == NULL) {
2245b54d3a6cSRandall Stewart 					/* Mark end of the window */
2246b54d3a6cSRandall Stewart 					asoc->fast_recovery_tsn = asoc->sending_seq - 1;
2247b54d3a6cSRandall Stewart 				} else {
224849656eefSMichael Tuexen 					asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1;
2249b54d3a6cSRandall Stewart 				}
2250b54d3a6cSRandall Stewart 
2251b54d3a6cSRandall Stewart 				/*
2252b54d3a6cSRandall Stewart 				 * CMT fast recovery -- per destination
2253b54d3a6cSRandall Stewart 				 * recovery variable.
2254b54d3a6cSRandall Stewart 				 */
2255b54d3a6cSRandall Stewart 				net->fast_retran_loss_recovery = 1;
2256b54d3a6cSRandall Stewart 
2257b54d3a6cSRandall Stewart 				if (lchk == NULL) {
2258b54d3a6cSRandall Stewart 					/* Mark end of the window */
2259b54d3a6cSRandall Stewart 					net->fast_recovery_tsn = asoc->sending_seq - 1;
2260b54d3a6cSRandall Stewart 				} else {
226149656eefSMichael Tuexen 					net->fast_recovery_tsn = lchk->rec.data.tsn - 1;
2262b54d3a6cSRandall Stewart 				}
2263b54d3a6cSRandall Stewart 
2264b54d3a6cSRandall Stewart 				sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
2265b7d130beSMichael Tuexen 				    stcb->sctp_ep, stcb, net,
2266b7d130beSMichael Tuexen 				    SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_3);
2267b54d3a6cSRandall Stewart 				sctp_timer_start(SCTP_TIMER_TYPE_SEND,
2268b54d3a6cSRandall Stewart 				    stcb->sctp_ep, stcb, net);
2269b54d3a6cSRandall Stewart 			}
2270b54d3a6cSRandall Stewart 		} else if (net->net_ack > 0) {
2271b54d3a6cSRandall Stewart 			/*
2272b54d3a6cSRandall Stewart 			 * Mark a peg that we WOULD have done a cwnd
2273b54d3a6cSRandall Stewart 			 * reduction but RFC2582 prevented this action.
2274b54d3a6cSRandall Stewart 			 */
2275b54d3a6cSRandall Stewart 			SCTP_STAT_INCR(sctps_fastretransinrtt);
2276b54d3a6cSRandall Stewart 		}
2277b54d3a6cSRandall Stewart 	}
2278b54d3a6cSRandall Stewart }
2279b54d3a6cSRandall Stewart 
22800e9a9c10SMichael Tuexen static void
sctp_htcp_cwnd_update_after_timeout(struct sctp_tcb * stcb,struct sctp_nets * net)2281b54d3a6cSRandall Stewart sctp_htcp_cwnd_update_after_timeout(struct sctp_tcb *stcb,
2282b54d3a6cSRandall Stewart     struct sctp_nets *net)
2283b54d3a6cSRandall Stewart {
2284b54d3a6cSRandall Stewart 	int old_cwnd = net->cwnd;
2285b54d3a6cSRandall Stewart 
2286b54d3a6cSRandall Stewart 	/* JRS - reset as if the state were being changed to timeout */
2287299108c5SRandall Stewart 	htcp_reset(&net->cc_mod.htcp_ca);
22887215cc1bSMichael Tuexen 	net->ssthresh = htcp_recalc_ssthresh(net);
2289b54d3a6cSRandall Stewart 	net->cwnd = net->mtu;
2290c54a18d2SRandall Stewart 	net->partial_bytes_acked = 0;
2291b3f1ea41SRandall Stewart 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2292b54d3a6cSRandall Stewart 		sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
2293b54d3a6cSRandall Stewart 	}
2294b54d3a6cSRandall Stewart }
2295b54d3a6cSRandall Stewart 
22960e9a9c10SMichael Tuexen static void
sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb * stcb,struct sctp_nets * net,int in_window,int num_pkt_lost SCTP_UNUSED)2297b54d3a6cSRandall Stewart sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
22987215cc1bSMichael Tuexen     struct sctp_nets *net, int in_window, int num_pkt_lost SCTP_UNUSED)
2299b54d3a6cSRandall Stewart {
2300b54d3a6cSRandall Stewart 	int old_cwnd;
2301b54d3a6cSRandall Stewart 
2302b54d3a6cSRandall Stewart 	old_cwnd = net->cwnd;
2303b54d3a6cSRandall Stewart 
2304b54d3a6cSRandall Stewart 	/* JRS - reset hctp as if state changed */
2305493d8e5aSRandall Stewart 	if (in_window == 0) {
2306299108c5SRandall Stewart 		htcp_reset(&net->cc_mod.htcp_ca);
2307b54d3a6cSRandall Stewart 		SCTP_STAT_INCR(sctps_ecnereducedcwnd);
23087215cc1bSMichael Tuexen 		net->ssthresh = htcp_recalc_ssthresh(net);
2309b54d3a6cSRandall Stewart 		if (net->ssthresh < net->mtu) {
2310b54d3a6cSRandall Stewart 			net->ssthresh = net->mtu;
2311b54d3a6cSRandall Stewart 			/* here back off the timer as well, to slow us down */
2312b54d3a6cSRandall Stewart 			net->RTO <<= 1;
2313b54d3a6cSRandall Stewart 		}
2314b54d3a6cSRandall Stewart 		net->cwnd = net->ssthresh;
231559b6d5beSMichael Tuexen 		sctp_enforce_cwnd_limit(&stcb->asoc, net);
2316b3f1ea41SRandall Stewart 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2317b54d3a6cSRandall Stewart 			sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
2318b54d3a6cSRandall Stewart 		}
2319b54d3a6cSRandall Stewart 	}
2320493d8e5aSRandall Stewart }
23210e9a9c10SMichael Tuexen 
2322ed654363SMichael Tuexen const struct sctp_cc_functions sctp_cc_functions[] = {
23230e9a9c10SMichael Tuexen 	{
23240e9a9c10SMichael Tuexen 		.sctp_set_initial_cc_param = sctp_set_initial_cc_param,
23250e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_sack = sctp_cwnd_update_after_sack,
2326ca85e948SMichael Tuexen 		.sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
23270e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
23280e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
23290e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
23300e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
23310e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
23320e9a9c10SMichael Tuexen 	},
23330e9a9c10SMichael Tuexen 	{
23340e9a9c10SMichael Tuexen 		.sctp_set_initial_cc_param = sctp_set_initial_cc_param,
23350e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_sack = sctp_hs_cwnd_update_after_sack,
2336ca85e948SMichael Tuexen 		.sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
23370e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_fr = sctp_hs_cwnd_update_after_fr,
23380e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
23390e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
23400e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
23410e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
23420e9a9c10SMichael Tuexen 	},
23430e9a9c10SMichael Tuexen 	{
23440e9a9c10SMichael Tuexen 		.sctp_set_initial_cc_param = sctp_htcp_set_initial_cc_param,
23450e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_sack = sctp_htcp_cwnd_update_after_sack,
2346ca85e948SMichael Tuexen 		.sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
23470e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_fr = sctp_htcp_cwnd_update_after_fr,
23480e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_timeout = sctp_htcp_cwnd_update_after_timeout,
23490e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_ecn_echo = sctp_htcp_cwnd_update_after_ecn_echo,
23500e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
23510e9a9c10SMichael Tuexen 		.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
235248b6c649SRandall Stewart 	},
235348b6c649SRandall Stewart 	{
235448b6c649SRandall Stewart 		.sctp_set_initial_cc_param = sctp_set_rtcc_initial_cc_param,
235548b6c649SRandall Stewart 		.sctp_cwnd_update_after_sack = sctp_cwnd_update_rtcc_after_sack,
2356ca85e948SMichael Tuexen 		.sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
235748b6c649SRandall Stewart 		.sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
235848b6c649SRandall Stewart 		.sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
235948b6c649SRandall Stewart 		.sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_rtcc_after_ecn_echo,
236048b6c649SRandall Stewart 		.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
236148b6c649SRandall Stewart 		.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
236248b6c649SRandall Stewart 		.sctp_cwnd_update_packet_transmitted = sctp_cwnd_update_rtcc_packet_transmitted,
236348b6c649SRandall Stewart 		.sctp_cwnd_update_tsn_acknowledged = sctp_cwnd_update_rtcc_tsn_acknowledged,
236448b6c649SRandall Stewart 		.sctp_cwnd_new_transmission_begins = sctp_cwnd_new_rtcc_transmission_begins,
236548b6c649SRandall Stewart 		.sctp_cwnd_prepare_net_for_sack = sctp_cwnd_prepare_rtcc_net_for_sack,
2366f79aab18SRandall Stewart 		.sctp_cwnd_socket_option = sctp_cwnd_rtcc_socket_option,
2367f79aab18SRandall Stewart 		.sctp_rtt_calculated = sctp_rtt_rtcc_calculated
23680e9a9c10SMichael Tuexen 	}
23690e9a9c10SMichael Tuexen };
2370