18c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
28c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
3ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
58c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
68c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Redistribution and use in source and binary forms, with or without
78c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * modification, are permitted provided that the following conditions are met:
88c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
98c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) Redistributions of source code must retain the above copyright notice,
100ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    this list of conditions and the following disclaimer.
118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * b) Redistributions in binary form must reproduce the above copyright
138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    notice, this list of conditions and the following disclaimer in
140ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    the documentation and/or other materials provided with the distribution.
158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * c) Neither the name of Cisco Systems, Inc. nor the names of its
178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    contributors may be used to endorse or promote products derived
188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    from this software without specific prior written permission.
198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE POSSIBILITY OF SUCH DAMAGE.
318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen#ifdef __FreeBSD__
34ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen#include <sys/cdefs.h>
35a7e2a63200c3155382d862ceb5cf07a1176ee531t__FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 240158 2012-09-06 07:03:56Z tuexen $");
36ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen#endif
37ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen
388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h>
398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h>
408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h>
418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h>
428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_header.h>
438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h>
448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_output.h>
458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_input.h>
468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_indata.h>
478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_uio.h>
488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_timer.h>
498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_auth.h>
508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_asconf.h>
51f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_dtrace_declare.h>
53b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SHIFT_MPTCP_MULTI_N 40
568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SHIFT_MPTCP_MULTI_Z 16
578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SHIFT_MPTCP_MULTI 8
588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *assoc;
638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t cwnd_in_mtu;
648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	assoc = &stcb->asoc;
668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (cwnd_in_mtu == 0) {
688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Using 0 means that the value of RFC 4960 is used. */
698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * We take the minimum of the burst limit and the
738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * initial congestion window.
748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((assoc->max_burst > 0) && (cwnd_in_mtu > assoc->max_burst))
768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cwnd_in_mtu = assoc->max_burst;
778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* In case of resource pooling initialize appropriately */
828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd /= assoc->numnets;
838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwnd = net->mtu - sizeof(struct sctphdr);
858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->ssthresh = assoc->peers_rwnd;
88f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SDT_PROBE(sctp, cwnd, net, init,
90b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	          stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	          0, net->cwnd);
92b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) &
948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) {
958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
1008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
1018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                          struct sctp_association *asoc)
1028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
1048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t t_ssthresh, t_cwnd;
1058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t t_ucwnd_sbw;
1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* MT FIXME: Don't compute this over and over again */
1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	t_ssthresh = 0;
1098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	t_cwnd = 0;
1108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	t_ucwnd_sbw = 0;
1118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
1128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
1138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
1148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			t_ssthresh += net->ssthresh;
1158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			t_cwnd += net->cwnd;
1168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->lastsa > 0) {
1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				t_ucwnd_sbw += (uint64_t)net->cwnd / (uint64_t)net->lastsa;
1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
1208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (t_ucwnd_sbw == 0) {
1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			t_ucwnd_sbw = 1;
1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
1278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * (net->fast_retran_loss_recovery == 0)))
1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
1298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((asoc->fast_retran_loss_recovery == 0) ||
1318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (asoc->sctp_cmt_on_off > 0)) {
1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* out of a RFC2582 Fast recovery window? */
1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->net_ack > 0) {
1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
1358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * per section 7.2.3, are there any
1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * destinations that had a fast retransmit
1378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * to them. If so what we need to do is
1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * adjust ssthresh and cwnd.
1398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
1408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_tmit_chunk *lchk;
1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				int old_cwnd = net->cwnd;
1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
1448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) {
1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->ssthresh = (uint32_t)(((uint64_t)4 *
1478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                                    (uint64_t)net->mtu *
1488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                                    (uint64_t)net->ssthresh) /
1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                           (uint64_t)t_ssthresh);
1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
1528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2) {
1538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						uint32_t srtt;
1548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						srtt = net->lastsa;
1568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* lastsa>>3;  we don't need to devide ...*/
1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (srtt == 0) {
1588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							srtt = 1;
1598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
1608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* Short Version => Equal to Contel Version MBe */
1618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->ssthresh = (uint32_t) (((uint64_t)4 *
1628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                             (uint64_t)net->mtu *
1638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                             (uint64_t)net->cwnd) /
1648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                            ((uint64_t)srtt *
1658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                             t_ucwnd_sbw));
1668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									     /* INCREASE FACTOR */;
1678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
1688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((net->cwnd > t_cwnd / 2) &&
1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (net->ssthresh < net->cwnd - t_cwnd / 2)) {
1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->ssthresh = net->cwnd - t_cwnd / 2;
1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->ssthresh < net->mtu) {
1738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->ssthresh = net->mtu;
1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
1768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->ssthresh = net->cwnd / 2;
1778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->ssthresh < (net->mtu * 2)) {
1788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->ssthresh = 2 * net->mtu;
1798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
1808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cwnd = net->ssthresh;
182f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
183000a5bac556b28e74e4e98c540f66b1743e9312dtuexen				SDT_PROBE(sctp, cwnd, net, fr,
184000a5bac556b28e74e4e98c540f66b1743e9312dtuexen					  stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  old_cwnd, net->cwnd);
186b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
1898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_CWND_LOG_FROM_FR);
1908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
1918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				lchk = TAILQ_FIRST(&asoc->send_queue);
1928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->partial_bytes_acked = 0;
1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Turn on fast recovery window */
1958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->fast_retran_loss_recovery = 1;
1968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (lchk == NULL) {
1978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Mark end of the window */
1988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->fast_recovery_tsn = asoc->sending_seq - 1;
1998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
2008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
2018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
2028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
2048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * CMT fast recovery -- per destination
2058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * recovery variable.
2068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
2078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->fast_retran_loss_recovery = 1;
2088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (lchk == NULL) {
2108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Mark end of the window */
2118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->fast_recovery_tsn = asoc->sending_seq - 1;
2128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
2138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
2148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
2158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
2178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA+SCTP_LOC_32 );
2188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SEND,
2198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 stcb->sctp_ep, stcb, net);
2208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
2218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (net->net_ack > 0) {
2228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
2238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Mark a peg that we WOULD have done a cwnd
2248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * reduction but RFC2582 prevented this action.
2258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
2268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_INCR(sctps_fastretransinrtt);
2278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* Defines for instantaneous bw decisions */
2328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SCTP_INST_LOOSING 1 /* Loosing to other flows */
2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SCTP_INST_NEUTRAL 2 /* Neutral, no indication */
2348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SCTP_INST_GAINING 3 /* Gaining, step down possible */
2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
237f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
2388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
239000a5bac556b28e74e4e98c540f66b1743e9312dtuexencc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
2408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	   uint64_t rtt_offset, uint64_t vtag, uint8_t inst_ind)
2410ac02f34d6041cd0018437596a5a9a94685e6919tuexen#else
2420ac02f34d6041cd0018437596a5a9a94685e6919tuexenstatic int
243000a5bac556b28e74e4e98c540f66b1743e9312dtuexencc_bw_same(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw,
244b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	   uint64_t rtt_offset, uint8_t inst_ind)
2450ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif
2468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
247f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t oth, probepoint;
249b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
250000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
251f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
2528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	probepoint = (((uint64_t)net->cwnd) << 32);
253b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
2540ac02f34d6041cd0018437596a5a9a94685e6919tuexen	if (net->rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) {
2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
256000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		 * rtt increased
2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * we don't update bw.. so we don't
2588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * update the rtt either.
2598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
260f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
2618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Probe point 5 */
2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		probepoint |=  ((5 << 16) | 1);
2638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SDT_PROBE(sctp, cwnd, net, rttvar,
2648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  vtag,
2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw << 32) | nbw),
2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  net->flight_size,
2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  probepoint);
269b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->cc_mod.rtcc.last_step_state == 5)
2728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.step_cnt++;
273000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			else
2748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.step_cnt = 1;
2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.last_step_state = 5;
2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
2778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			     ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Try a step down */
280f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
2818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				oth = net->cc_mod.rtcc.vol_reduce;
2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				oth <<= 16;
2838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				oth |= net->cc_mod.rtcc.step_cnt;
2848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				oth <<= 16;
2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				oth |= net->cc_mod.rtcc.last_step_state;
2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SDT_PROBE(sctp, cwnd, net, rttstep,
2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  vtag,
2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  ((net->cc_mod.rtcc.lbw << 32) | nbw),
2898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  oth,
2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  probepoint);
292b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
2938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->cwnd > (4 * net->mtu)) {
2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->cwnd -= net->mtu;
2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->cc_mod.rtcc.vol_reduce++;
2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->cc_mod.rtcc.step_cnt = 0;
2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
2998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (1);
3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->rtt  < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
3058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * rtt decreased, there could be more room.
3068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * we update both the bw and the rtt here to
3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * lock this in as a good step down.
3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
309f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
3108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Probe point 6 */
3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		probepoint |=  ((6 << 16) | 0);
3128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SDT_PROBE(sctp, cwnd, net, rttvar,
3138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  vtag,
3148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw << 32) | nbw),
3158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  net->flight_size,
3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  probepoint);
318b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cc_mod.rtcc.steady_step) {
320f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth = net->cc_mod.rtcc.vol_reduce;
3228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth <<= 16;
3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth |= net->cc_mod.rtcc.step_cnt;
3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth <<= 16;
3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth |= net->cc_mod.rtcc.last_step_state;
3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SDT_PROBE(sctp, cwnd, net, rttstep,
3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  vtag,
3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  ((net->cc_mod.rtcc.lbw << 32) | nbw),
3298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  oth,
3318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  probepoint);
332b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
3338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((net->cc_mod.rtcc.last_step_state == 5) &&
3348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step)) {
3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Step down worked */
3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.step_cnt = 0;
3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (1);
3388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.last_step_state = 6;
3408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.step_cnt = 0;
3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.lbw = nbw;
3448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.lbw_rtt = net->rtt;
3458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
3468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inst_ind == SCTP_INST_GAINING)
3478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
348000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		else if (inst_ind == SCTP_INST_NEUTRAL)
3498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
3518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
3528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
353000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	/* Ok bw and rtt remained the same .. no update to any
3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
355f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Probe point 7 */
3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	probepoint |=  ((7 << 16) | net->cc_mod.rtcc.ret_from_eq);
3588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SDT_PROBE(sctp, cwnd, net, rttvar,
3598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  vtag,
3608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  ((net->cc_mod.rtcc.lbw << 32) | nbw),
3618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
3628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  net->flight_size,
3638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  probepoint);
364b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
3658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
3668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cc_mod.rtcc.last_step_state == 5)
3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.step_cnt++;
368000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		else
3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.step_cnt = 1;
3708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.last_step_state = 5;
3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
3728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
3738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Try a step down */
3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->cwnd > (4 * net->mtu)) {
3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cwnd -= net->mtu;
3778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.vol_reduce++;
3788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (1);
3798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.step_cnt = 0;
3818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
3828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inst_ind == SCTP_INST_GAINING)
3858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (1);
386000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	else if (inst_ind == SCTP_INST_NEUTRAL)
3878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (1);
3888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
3898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return ((int)net->cc_mod.rtcc.ret_from_eq);
3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
392f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
394000a5bac556b28e74e4e98c540f66b1743e9312dtuexencc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset,
3958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	       uint64_t vtag, uint8_t inst_ind)
3960ac02f34d6041cd0018437596a5a9a94685e6919tuexen#else
3970ac02f34d6041cd0018437596a5a9a94685e6919tuexenstatic int
398000a5bac556b28e74e4e98c540f66b1743e9312dtuexencc_bw_decrease(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset,
399b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	       uint8_t inst_ind)
4000ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif
4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
402f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t oth, probepoint;
404b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
405b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen
4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Bandwidth decreased.*/
407f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	probepoint = (((uint64_t)net->cwnd) << 32);
409b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->rtt  > net->cc_mod.rtcc.lbw_rtt+rtt_offset) {
4118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* rtt increased */
4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Did we add more */
4138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((net->cwnd > net->cc_mod.rtcc.cwnd_at_bw_set) &&
414b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		    (inst_ind != SCTP_INST_LOOSING)) {
4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We caused it maybe.. back off? */
416f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* PROBE POINT 1 */
4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			probepoint |=  ((1 << 16) | 1);
4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SDT_PROBE(sctp, cwnd, net, rttvar,
4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  vtag,
4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  ((net->cc_mod.rtcc.lbw << 32) | nbw),
4228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  net->flight_size,
4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  probepoint);
425b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->cc_mod.rtcc.ret_from_eq) {
4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Switch over to CA if we are less aggressive */
4288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->ssthresh = net->cwnd-1;
4298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->partial_bytes_acked = 0;
4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
4328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
433f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Probe point 2 */
4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		probepoint |=  ((2 << 16) | 0);
4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SDT_PROBE(sctp, cwnd, net, rttvar,
4378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  vtag,
4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw << 32) | nbw),
4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
4408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  net->flight_size,
4418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  probepoint);
442b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Someone else - fight for more? */
4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cc_mod.rtcc.steady_step) {
445f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
4468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth = net->cc_mod.rtcc.vol_reduce;
4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth <<= 16;
4488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth |= net->cc_mod.rtcc.step_cnt;
4498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth <<= 16;
4508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth |= net->cc_mod.rtcc.last_step_state;
4518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SDT_PROBE(sctp, cwnd, net, rttstep,
4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  vtag,
4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  ((net->cc_mod.rtcc.lbw << 32) | nbw),
4548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  oth,
4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  probepoint);
457b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Did we voluntarily give up some? if so take
459000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			 * one back please
4608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
461000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			if ((net->cc_mod.rtcc.vol_reduce) &&
462b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			    (inst_ind != SCTP_INST_GAINING)) {
4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cwnd += net->mtu;
4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.vol_reduce--;
4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
4668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.last_step_state = 2;
4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.step_cnt = 0;
4688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_decision;
4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else  if (net->rtt  < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* bw & rtt decreased */
472f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Probe point 3 */
4748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		probepoint |=  ((3 << 16) | 0);
4758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SDT_PROBE(sctp, cwnd, net, rttvar,
4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  vtag,
4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw << 32) | nbw),
4788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  net->flight_size,
4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  probepoint);
481b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cc_mod.rtcc.steady_step) {
483f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth = net->cc_mod.rtcc.vol_reduce;
4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth <<= 16;
4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth |= net->cc_mod.rtcc.step_cnt;
4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth <<= 16;
4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			oth |= net->cc_mod.rtcc.last_step_state;
4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SDT_PROBE(sctp, cwnd, net, rttstep,
4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  vtag,
4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  ((net->cc_mod.rtcc.lbw << 32) | nbw),
4928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
4938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  oth,
4948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  probepoint);
495b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
4968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((net->cc_mod.rtcc.vol_reduce) &&
497b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			    (inst_ind != SCTP_INST_GAINING)) {
4988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cwnd += net->mtu;
4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.vol_reduce--;
5008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.last_step_state = 3;
5028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.step_cnt = 0;
5038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_decision;
5058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* The bw decreased but rtt stayed the same */
507f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Probe point 4 */
5098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	probepoint |=  ((4 << 16) | 0);
5108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SDT_PROBE(sctp, cwnd, net, rttvar,
5118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  vtag,
5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  ((net->cc_mod.rtcc.lbw << 32) | nbw),
5138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  net->flight_size,
5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  probepoint);
516b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->cc_mod.rtcc.steady_step) {
518f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		oth = net->cc_mod.rtcc.vol_reduce;
5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		oth <<= 16;
5218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		oth |= net->cc_mod.rtcc.step_cnt;
5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		oth <<= 16;
5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		oth |= net->cc_mod.rtcc.last_step_state;
5248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SDT_PROBE(sctp, cwnd, net, rttstep,
5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  vtag,
5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw << 32) | nbw),
5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  oth,
5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  probepoint);
530b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((net->cc_mod.rtcc.vol_reduce) &&
532b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		    (inst_ind != SCTP_INST_GAINING)) {
5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwnd += net->mtu;
5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.vol_reduce--;
5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.last_step_state = 4;
5378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.step_cnt = 0;
5388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenout_decision:
5408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.lbw = nbw;
5418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.lbw_rtt = net->rtt;
5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inst_ind == SCTP_INST_GAINING) {
544b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (1);
5458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
546b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (0);
5478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
550f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
5518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
5520ac02f34d6041cd0018437596a5a9a94685e6919tuexencc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t vtag)
5530ac02f34d6041cd0018437596a5a9a94685e6919tuexen#else
5540ac02f34d6041cd0018437596a5a9a94685e6919tuexenstatic int
555b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexencc_bw_increase(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw)
5560ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif
5578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
558f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
5598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t oth, probepoint;
5600ac02f34d6041cd0018437596a5a9a94685e6919tuexen
561b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* BW increased, so update and
563000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	 * return 0, since all actions in
5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * our table say to do the normal CC
5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * update. Note that we pay no attention to
5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the inst_ind since our overall sum is increasing.
5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
568f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* PROBE POINT 0 */
5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	probepoint = (((uint64_t)net->cwnd) << 32);
5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SDT_PROBE(sctp, cwnd, net, rttvar,
5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  vtag,
5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  ((net->cc_mod.rtcc.lbw << 32) | nbw),
5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
5758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  net->flight_size,
5768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  probepoint);
577b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
5788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->cc_mod.rtcc.steady_step) {
579f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
5808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		oth = net->cc_mod.rtcc.vol_reduce;
5818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		oth <<= 16;
5828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		oth |= net->cc_mod.rtcc.step_cnt;
5838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		oth <<= 16;
5848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		oth |= net->cc_mod.rtcc.last_step_state;
5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SDT_PROBE(sctp, cwnd, net, rttstep,
5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  vtag,
5878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw << 32) | nbw),
5888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
5898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  oth,
5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  probepoint);
591b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.last_step_state = 0;
5938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.step_cnt = 0;
5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.vol_reduce = 0;
5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.lbw = nbw;
5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.lbw_rtt = net->rtt;
5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
599b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (0);
6008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* RTCC Algoritm to limit growth of cwnd, return
6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * true if you want to NOT allow cwnd growth
6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
6058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexencc_bw_limit(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw)
6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
608b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	uint64_t bw_offset, rtt_offset;
609f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
610b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	uint64_t probepoint, rtt, vtag;
611b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
6128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t bytes_for_this_rtt, inst_bw;
6138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t div, inst_off;
6148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int bw_shift;
6158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t inst_ind;
6168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int ret;
617000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	/*-
6188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Here we need to see if we want
6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * to limit cwnd growth due to increase
6208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * in overall rtt but no increase in bw.
6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * We use the following table to figure
6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * out what we should do. When we return
6238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * 0, cc update goes on as planned. If we
6248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * return 1, then no cc update happens and cwnd
6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * stays where it is at.
6268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ----------------------------------
6278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *   BW    |    RTT   | Action
6288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * *********************************
6298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *   INC   |    INC   | return 0
6308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ----------------------------------
6318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *   INC   |    SAME  | return 0
6328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ----------------------------------
633000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	 *   INC   |    DECR  | return 0
6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ----------------------------------
6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *   SAME  |    INC   | return 1
6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ----------------------------------
6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *   SAME  |    SAME  | return 1
6388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ----------------------------------
6398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *   SAME  |    DECR  | return 0
6408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ----------------------------------
6418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *   DECR  |    INC   | return 0 or 1 based on if we caused.
6428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ----------------------------------
6438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *   DECR  |    SAME  | return 0
6448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ----------------------------------
6458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *   DECR  |    DECR  | return 0
6468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ----------------------------------
6478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
6488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * We are a bit fuzz on what an increase or
6498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * decrease is. For BW it is the same if
6508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * it did not change within 1/64th. For
6518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * RTT it stayed the same if it did not
6528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * change within 1/32nd
6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bw_shift = SCTP_BASE_SYSCTL(sctp_rttvar_bw);
655f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	rtt = stcb->asoc.my_vtag;
6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vtag = (rtt << 32) | (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) | (stcb->rport);
6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	probepoint = (((uint64_t)net->cwnd) << 32);
6598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	rtt = net->rtt;
660b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
6618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->cc_mod.rtcc.rtt_set_this_sack) {
6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.rtt_set_this_sack = 0;
6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bytes_for_this_rtt = net->cc_mod.rtcc.bw_bytes - net->cc_mod.rtcc.bw_bytes_at_last_rttc;
6648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->rtt) {
666b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			div = net->rtt / 1000;
6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (div) {
6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inst_bw = bytes_for_this_rtt / div;
6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inst_off = inst_bw >> bw_shift;
670000a5bac556b28e74e4e98c540f66b1743e9312dtuexen				if (inst_bw > nbw)
671000a5bac556b28e74e4e98c540f66b1743e9312dtuexen					inst_ind = SCTP_INST_GAINING;
6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else if ((inst_bw+inst_off) < nbw)
6738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inst_ind = SCTP_INST_LOOSING;
6748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
6758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inst_ind = SCTP_INST_NEUTRAL;
676f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
6778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				probepoint |=  ((0xb << 16) | inst_ind);
678b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
6798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
680b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				inst_ind = net->cc_mod.rtcc.last_inst_ind;
681f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
6828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inst_bw = bytes_for_this_rtt / (uint64_t)(net->rtt);
6838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Can't determine do not change */
6848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				probepoint |=  ((0xc << 16) | inst_ind);
685b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
6868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
6878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
688b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			inst_ind = net->cc_mod.rtcc.last_inst_ind;
689f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
6908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inst_bw = bytes_for_this_rtt;
6918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't determine do not change */
6928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			probepoint |=  ((0xd << 16) | inst_ind);
693b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
6948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
695f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
6968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SDT_PROBE(sctp, cwnd, net, rttvar,
6978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  vtag,
6988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((nbw << 32) | inst_bw),
6998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw_rtt << 32) | rtt),
7008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  net->flight_size,
7018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  probepoint);
702b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
7038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
7048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* No rtt measurement, use last one */
7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inst_ind = net->cc_mod.rtcc.last_inst_ind;
7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bw_offset = net->cc_mod.rtcc.lbw >> bw_shift;
708b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if (nbw > net->cc_mod.rtcc.lbw + bw_offset) {
709f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
7100ac02f34d6041cd0018437596a5a9a94685e6919tuexen		ret = cc_bw_increase(stcb, net, nbw, vtag);
711b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#else
712b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		ret = cc_bw_increase(stcb, net, nbw);
713b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
7158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	rtt_offset = net->cc_mod.rtcc.lbw_rtt >> SCTP_BASE_SYSCTL(sctp_rttvar_rtt);
717b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if (nbw < net->cc_mod.rtcc.lbw - bw_offset) {
718f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
7198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, vtag, inst_ind);
720b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#else
721b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, inst_ind);
722b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
7238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* If we reach here then
7268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * we are in a situation where
7278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the bw stayed the same.
7288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
729f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ret = cc_bw_same(stcb, net, nbw, rtt_offset, vtag, inst_ind);
731b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#else
732b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	ret = cc_bw_same(stcb, net, nbw, rtt_offset, inst_ind);
733b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
7348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenout:
7358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.last_inst_ind = inst_ind;
736b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (ret);
7378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				   struct sctp_association *asoc,
7420ac02f34d6041cd0018437596a5a9a94685e6919tuexen				   int accum_moved, int reneged_all SCTP_UNUSED, int will_exit, int use_rtcc)
7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
745f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
7468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int old_cwnd;
747b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t t_ssthresh, t_cwnd, incr;
7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t t_ucwnd_sbw;
7508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t t_path_mptcp;
7518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t mptcp_like_alpha;
7528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t srtt;
7538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t max_path;
7548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* MT FIXME: Don't compute this over and over again */
7568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	t_ssthresh = 0;
7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	t_cwnd = 0;
7588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	t_ucwnd_sbw = 0;
7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	t_path_mptcp = 0;
7608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	mptcp_like_alpha = 1;
7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2) ||
7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_MPTCP)) {
7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		max_path = 0;
7658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			t_ssthresh += net->ssthresh;
7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			t_cwnd += net->cwnd;
7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* lastsa>>3;  we don't need to devide ...*/
7698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			srtt = net->lastsa;
7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (srtt > 0) {
7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				uint64_t tmp;
7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				t_ucwnd_sbw += (uint64_t)net->cwnd / (uint64_t)srtt;
7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				t_path_mptcp += (((uint64_t)net->cwnd) << SHIFT_MPTCP_MULTI_Z) /
7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                (((uint64_t)net->mtu) * (uint64_t)srtt);
7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tmp = (((uint64_t)net->cwnd) << SHIFT_MPTCP_MULTI_N) /
7778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				      ((uint64_t)net->mtu * (uint64_t)(srtt * srtt));
7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tmp > max_path) {
7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					max_path = tmp;
7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (t_path_mptcp > 0) {
7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			mptcp_like_alpha = max_path / (t_path_mptcp * t_path_mptcp);
7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
7868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			mptcp_like_alpha = 1;
7878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
789b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if (t_ssthresh == 0) {
790b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		t_ssthresh = 1;
791b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	}
792b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if (t_ucwnd_sbw == 0) {
793b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		t_ucwnd_sbw = 1;
794b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	}
7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/******************************/
7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* update cwnd and Early FR   */
7978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/******************************/
7988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
7998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef JANA_CMT_FAST_RECOVERY
8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
8028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT fast recovery code. Need to debug.
8038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
8058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
8068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
8078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->will_exit_fast_recovery = 1;
8088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
8098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
8118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* if nothing was acked on this destination skip it */
8128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->net_ack == 0) {
8138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
8148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
8158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
8168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
8178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef JANA_CMT_FAST_RECOVERY
8198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                /* CMT fast recovery code
8208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
8218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
8228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
8238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  @@@ Do something
8248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  }
8258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
8268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*/
8278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
8288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->fast_retran_loss_recovery &&
8308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (will_exit == 0) &&
8318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (asoc->sctp_cmt_on_off == 0)) {
8328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
8338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * If we are in loss recovery we skip any cwnd
8348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * update
8358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
8368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
8378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
838000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		/*
8398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Did any measurements go on for this network?
8408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
8418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (use_rtcc && (net->cc_mod.rtcc.tls_needs_set > 0)) {
8428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint64_t nbw;
843000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			/*
844000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			 * At this point our bw_bytes has been updated
8458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * by incoming sack information.
846000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			 *
8478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * But our bw may not yet be set.
848000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			 *
8498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
8508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((net->cc_mod.rtcc.new_tot_time/1000) > 0) {
8518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				nbw = net->cc_mod.rtcc.bw_bytes/(net->cc_mod.rtcc.new_tot_time/1000);
8528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
8538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				nbw = net->cc_mod.rtcc.bw_bytes;
8548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
8558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->cc_mod.rtcc.lbw) {
856b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				if (cc_bw_limit(stcb, net, nbw)) {
8578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Hold here, no update */
8588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
8598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
8608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
861f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
8628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				uint64_t vtag, probepoint;
863b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen
8648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				probepoint = (((uint64_t)net->cwnd) << 32);
8658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				probepoint |=  ((0xa << 16) | 0);
866000a5bac556b28e74e4e98c540f66b1743e9312dtuexen				vtag = (net->rtt << 32) |
8678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
8688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(stcb->rport);
8698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SDT_PROBE(sctp, cwnd, net, rttvar,
8718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  vtag,
8728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  nbw,
8738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
8748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  net->flight_size,
8758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  probepoint);
876b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
8778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.lbw = nbw;
8788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.lbw_rtt = net->rtt;
8798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->cc_mod.rtcc.rtt_set_this_sack) {
8808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->cc_mod.rtcc.rtt_set_this_sack = 0;
8818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
8828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
8838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
8848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
8868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
8878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * moved.
8888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
8898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (accum_moved ||
8908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
8918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* If the cumulative ack moved we can proceed */
8928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->cwnd <= net->ssthresh) {
8938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* We are in slow start */
8948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->flight_size + net->net_ack >= net->cwnd) {
8958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					uint32_t limit;
8968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
897f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
8988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					old_cwnd = net->cwnd;
899b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
9008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					switch (asoc->sctp_cmt_on_off) {
9018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case SCTP_CMT_RPV1:
9028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						limit = (uint32_t)(((uint64_t)net->mtu *
9038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                    (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
9048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                    (uint64_t)net->ssthresh) /
9058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                   (uint64_t)t_ssthresh);
9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						incr = (uint32_t)(((uint64_t)net->net_ack *
9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                   (uint64_t)net->ssthresh) /
9088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                  (uint64_t)t_ssthresh);
9098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr > limit) {
9108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = limit;
9118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
9128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr == 0) {
9138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = 1;
9148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
9158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
9168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case SCTP_CMT_RPV2:
9178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* lastsa>>3;  we don't need to divide ...*/
918000a5bac556b28e74e4e98c540f66b1743e9312dtuexen						srtt = net->lastsa;
9198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (srtt == 0) {
9208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							srtt = 1;
9218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
9228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						limit = (uint32_t)(((uint64_t)net->mtu *
9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                    (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
9248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                    (uint64_t)net->cwnd) /
9258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                   ((uint64_t)srtt * t_ucwnd_sbw));
9268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                   /* INCREASE FACTOR */
9278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						incr = (uint32_t)(((uint64_t)net->net_ack *
928b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen						                   (uint64_t)net->cwnd) /
929b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen						                  ((uint64_t)srtt * t_ucwnd_sbw));
9308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                  /* INCREASE FACTOR */
9318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr > limit) {
9328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = limit;
9338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
9348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr == 0) {
9358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = 1;
9368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
9378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
9388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case SCTP_CMT_MPTCP:
9398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						limit = (uint32_t)(((uint64_t)net->mtu *
9408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                    mptcp_like_alpha *
9418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                    (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) >>
9428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                   SHIFT_MPTCP_MULTI);
9438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						incr  = (uint32_t)(((uint64_t)net->net_ack *
9448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                    mptcp_like_alpha) >>
9458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                   SHIFT_MPTCP_MULTI);
9468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr > limit) {
9478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = limit;
9488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
9498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr > net->net_ack) {
9508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = net->net_ack;
9518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
9528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr > net->mtu) {
9538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = net->mtu;
9548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
9558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
9568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					default:
9578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						incr = net->net_ack;
9588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr > net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) {
9598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable);
9608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
9618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
9628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
9638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->cwnd += incr;
9648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
9658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_cwnd(stcb, net, incr,
9668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						              SCTP_CWND_LOG_FROM_SS);
9678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
968f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
9698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SDT_PROBE(sctp, cwnd, net, ack,
9708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					          stcb->asoc.my_vtag,
971b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen					          ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
9728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					          net,
9738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					          old_cwnd, net->cwnd);
974b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
9758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
9768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
9778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_cwnd(stcb, net, net->net_ack,
9788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							      SCTP_CWND_LOG_NOADV_SS);
9798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
9808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
9818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
9828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* We are in congestion avoidance */
9838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
9848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Add to pba
9858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
9868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			        net->partial_bytes_acked += net->net_ack;
9878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((net->flight_size + net->net_ack >= net->cwnd) &&
9898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                                    (net->partial_bytes_acked >= net->cwnd)) {
9908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->partial_bytes_acked -= net->cwnd;
991f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
9928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					old_cwnd = net->cwnd;
993b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
9948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					switch (asoc->sctp_cmt_on_off) {
9958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case SCTP_CMT_RPV1:
9968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						incr = (uint32_t)(((uint64_t)net->mtu *
9978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                   (uint64_t)net->ssthresh) /
9988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                  (uint64_t)t_ssthresh);
9998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr == 0) {
10008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = 1;
10018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
10028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
10038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case SCTP_CMT_RPV2:
10048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* lastsa>>3;  we don't need to divide ... */
10058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						srtt = net->lastsa;
10068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (srtt == 0) {
10078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							srtt = 1;
10088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
10098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						incr = (uint32_t)((uint64_t)net->mtu *
10108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                  (uint64_t)net->cwnd /
10118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                  ((uint64_t)srtt *
10128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                   t_ucwnd_sbw));
10138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                  /* INCREASE FACTOR */
10148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr == 0) {
10158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = 1;
10168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
10178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
10188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case SCTP_CMT_MPTCP:
10198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						incr = (uint32_t)((mptcp_like_alpha *
10208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                   (uint64_t) net->cwnd) >>
10218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                  SHIFT_MPTCP_MULTI);
10228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (incr > net->mtu) {
10238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							incr = net->mtu;
10248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
10258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
10268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					default:
10278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						incr = net->mtu;
10288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
10298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
10308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->cwnd += incr;
1031f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
10328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SDT_PROBE(sctp, cwnd, net, ack,
10338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  stcb->asoc.my_vtag,
1034b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen						  ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
10358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  net,
10368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  old_cwnd, net->cwnd);
1037b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
10388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
10398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_cwnd(stcb, net, net->mtu,
10408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							      SCTP_CWND_LOG_FROM_CA);
10418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
10428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
10438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
10448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_cwnd(stcb, net, net->net_ack,
10458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							      SCTP_CWND_LOG_NOADV_CA);
10468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
10478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
10488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
10498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
10508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
10518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, net->mtu,
10528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					      SCTP_CWND_LOG_NO_CUMACK);
10538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
10548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
10578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1058f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
10598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
10608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb, struct sctp_nets *net)
10610ac02f34d6041cd0018437596a5a9a94685e6919tuexen#else
10620ac02f34d6041cd0018437596a5a9a94685e6919tuexenstatic void
10630ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net)
10640ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif
10658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1066f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
10678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int old_cwnd;
10688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	old_cwnd = net->cwnd;
1070b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
10718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cwnd = net->mtu;
1072f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
1073000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	SDT_PROBE(sctp, cwnd, net, ack,
1074000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	          stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
10758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	          old_cwnd, net->cwnd);
1076b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
10778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
1078ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t	        (void *)net, net->cwnd);
10798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
10808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
10838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
10848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
10858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int old_cwnd = net->cwnd;
10868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t t_ssthresh, t_cwnd;
10878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t t_ucwnd_sbw;
10888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* MT FIXME: Don't compute this over and over again */
10908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	t_ssthresh = 0;
10918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	t_cwnd = 0;
10928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
10938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
10948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *lnet;
10958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t srtt;
10968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		t_ucwnd_sbw = 0;
10988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
10998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			t_ssthresh += lnet->ssthresh;
11008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			t_cwnd += lnet->cwnd;
11018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			srtt = lnet->lastsa;
11028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* lastsa>>3;  we don't need to divide ... */
11038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (srtt > 0) {
11048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				t_ucwnd_sbw += (uint64_t)lnet->cwnd / (uint64_t)srtt;
11058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
1107b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (t_ssthresh < 1) {
1108b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			t_ssthresh = 1;
1109b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		}
11108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (t_ucwnd_sbw < 1) {
11118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			t_ucwnd_sbw = 1;
11128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) {
11148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ssthresh = (uint32_t)(((uint64_t)4 *
11158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                            (uint64_t)net->mtu *
11168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                            (uint64_t)net->ssthresh) /
11178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                           (uint64_t)t_ssthresh);
11188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
11198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint64_t cc_delta;
11208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			srtt = net->lastsa;
11228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* lastsa>>3;  we don't need to divide ... */
11238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (srtt == 0) {
11248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				srtt = 1;
11258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cc_delta = t_ucwnd_sbw * (uint64_t)srtt / 2;
11278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (cc_delta < t_cwnd) {
11288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->ssthresh = (uint32_t)((uint64_t)t_cwnd - cc_delta);
11298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
11308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->ssthresh  = net->mtu;
11318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((net->cwnd > t_cwnd / 2) &&
11348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (net->ssthresh < net->cwnd - t_cwnd / 2)) {
11358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ssthresh = net->cwnd - t_cwnd / 2;
11368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->ssthresh < net->mtu) {
11388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ssthresh = net->mtu;
11398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
11418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->ssthresh = max(net->cwnd / 2, 4 * net->mtu);
11428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cwnd = net->mtu;
11448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->partial_bytes_acked = 0;
1145f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
11468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SDT_PROBE(sctp, cwnd, net, to,
11478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  stcb->asoc.my_vtag,
1148b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		  ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
11498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  net,
11508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  old_cwnd, net->cwnd);
1151b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
11528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
11538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
11548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
11568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
11588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets *net,
1159b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen					    int in_window, int num_pkt_lost, int use_rtcc)
11608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
11618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int old_cwnd = net->cwnd;
11628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((use_rtcc) && (net->lan_type == SCTP_LAN_LOCAL) && (net->cc_mod.rtcc.use_dccc_ecn)) {
11638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Data center Congestion Control */
11648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (in_window == 0) {
11658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Go to CA with the cwnd at the point we sent
11668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * the TSN that was marked with a CE.
11678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
11688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->ecn_prev_cwnd < net->cwnd) {
11698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Restore to prev cwnd */
11708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cwnd = net->ecn_prev_cwnd - (net->mtu * num_pkt_lost);
11718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
11728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Just cut in 1/2 */
11738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cwnd /= 2;
11748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Drop to CA */
11768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ssthresh = net->cwnd - (num_pkt_lost * net->mtu);
11778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
11788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
11798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
11818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Further tuning down required over the drastic orginal cut */
11828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ssthresh -= (net->mtu * num_pkt_lost);
11838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwnd -= (net->mtu * num_pkt_lost);
11848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
11858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
11868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_ecnereducedcwnd);
11908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}  else {
11918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (in_window == 0) {
11928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_INCR(sctps_ecnereducedcwnd);
11938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ssthresh = net->cwnd / 2;
11948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->ssthresh < net->mtu) {
11958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->ssthresh = net->mtu;
11968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* here back off the timer as well, to slow us down */
11978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->RTO <<= 1;
11988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwnd = net->ssthresh;
1200f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
12018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SDT_PROBE(sctp, cwnd, net, ecn,
12028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  stcb->asoc.my_vtag,
1203b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				  ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
12048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  net,
12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  old_cwnd, net->cwnd);
1206b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
12078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
12088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
12098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
12108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
12168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t *bottle_bw, uint32_t *on_queue)
12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t bw_avail;
12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int rtt;
12228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	unsigned int incr;
12238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int old_cwnd = net->cwnd;
12248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* need real RTT in msd for this calc */
12260ac02f34d6041cd0018437596a5a9a94685e6919tuexen	rtt = net->rtt / 1000;
12278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get bottle neck bw */
12288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*bottle_bw = ntohl(cp->bottle_bw);
12298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* and whats on queue */
12308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*on_queue = ntohl(cp->current_onq);
12318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
12328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * adjust the on-queue if our flight is more it could be
12338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * that the router has not yet gotten data "in-flight" to it
12348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
12358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (*on_queue < net->flight_size)
12368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*on_queue = net->flight_size;
12378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* calculate the available space */
12388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bw_avail = (*bottle_bw * rtt) / 1000;
12398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (bw_avail > *bottle_bw) {
12408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
12418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Cap the growth to no more than the bottle neck.
12428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * This can happen as RTT slides up due to queues.
12438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * It also means if you have more than a 1 second
12448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * RTT with a empty queue you will be limited to the
12458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * bottle_bw per second no matter if other points
12468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * have 1/2 the RTT and you could get more out...
12478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
12488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bw_avail = *bottle_bw;
12498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (*on_queue > bw_avail) {
12518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
12528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * No room for anything else don't allow anything
12538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * else to be "added to the fire".
12548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
12558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int seg_inflight, seg_onqueue, my_portion;
12568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->partial_bytes_acked = 0;
12578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* how much are we over queue size? */
12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		incr = *on_queue - bw_avail;
12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.seen_a_sack_this_pkt) {
12618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * undo any cwnd adjustment that the sack
12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * might have made
12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwnd = net->prev_cwnd;
12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Now how much of that is mine? */
12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		seg_inflight = net->flight_size / net->mtu;
12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		seg_onqueue = *on_queue / net->mtu;
12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		my_portion = (incr * seg_inflight) / seg_onqueue;
12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Have I made an adjustment already */
12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cwnd > net->flight_size) {
12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * for this flight I made an adjustment we
12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * need to decrease the portion by a share
12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * our previous adjustment.
12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
12798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int diff_adj;
12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			diff_adj = net->cwnd - net->flight_size;
12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (diff_adj > my_portion)
12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				my_portion = 0;
12848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
12858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				my_portion -= diff_adj;
12868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * back down to the previous cwnd (assume we have
12898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * had a sack before this packet). minus what ever
12908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * portion of the overage is my fault.
12918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd -= my_portion;
12938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we will NOT back down more than 1 MTU */
12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cwnd <= net->mtu) {
12968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwnd = net->mtu;
12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* force into CA */
12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->ssthresh = net->cwnd - 1;
13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Take 1/4 of the space left or max burst up ..
13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * whichever is less.
13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		incr = (bw_avail - *on_queue) >> 2;
13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb->asoc.max_burst > 0) &&
13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (stcb->asoc.max_burst * net->mtu < incr)) {
13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			incr = stcb->asoc.max_burst * net->mtu;
13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd += incr;
13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->cwnd > bw_avail) {
13138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We can't exceed the pipe size */
13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd = bw_avail;
13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->cwnd < net->mtu) {
13178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We always have 1 MTU */
13188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd = net->mtu;
13198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->cwnd - old_cwnd != 0) {
13228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* log only changes */
1323f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
1324000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		SDT_PROBE(sctp, cwnd, net, pd,
1325000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			  stcb->asoc.my_vtag,
1326000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			  ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
1327000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			  net,
13288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  old_cwnd, net->cwnd);
1329b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
13308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
13318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
13328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_CWND_LOG_FROM_SAT);
13338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_after_output(struct sctp_tcb *stcb,
13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			      struct sctp_nets *net, int burst_limit)
13408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int old_cwnd = net->cwnd;
13428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->ssthresh < net->cwnd)
13448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->ssthresh = net->cwnd;
13458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (burst_limit) {
13468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd = (net->flight_size + (burst_limit * net->mtu));
1347f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
1348000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		SDT_PROBE(sctp, cwnd, net, bl,
1349000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			  stcb->asoc.my_vtag,
1350000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			  ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
1351000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			  net,
13528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  old_cwnd, net->cwnd);
1353b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
13548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
13558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST);
13568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
13628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    struct sctp_association *asoc,
13630ac02f34d6041cd0018437596a5a9a94685e6919tuexen			    int accum_moved, int reneged_all, int will_exit)
13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Passing a zero argument in last disables the rtcc algoritm */
13660ac02f34d6041cd0018437596a5a9a94685e6919tuexen	sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 0);
13678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
13708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
13718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int in_window, int num_pkt_lost)
13728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Passing a zero argument in last disables the rtcc algoritm */
13748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 0);
13758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* Here starts the RTCCVAR type CC invented by RRS which
13788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is a slight mod to RFC2581. We reuse a common routine or
13798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * two since these algoritms are so close and need to
13808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * remain the same.
13818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
13828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
13838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_rtcc_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
13848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     int in_window, int num_pkt_lost)
13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 1);
13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1390000a5bac556b28e74e4e98c540f66b1743e9312dtuexenstatic
1391000a5bac556b28e74e4e98c540f66b1743e9312dtuexenvoid sctp_cwnd_update_rtcc_tsn_acknowledged(struct sctp_nets *net,
13928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    struct sctp_tmit_chunk *tp1)
13938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.bw_bytes += tp1->send_size;
13958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1397000a5bac556b28e74e4e98c540f66b1743e9312dtuexenstatic void
1398000a5bac556b28e74e4e98c540f66b1743e9312dtuexensctp_cwnd_prepare_rtcc_net_for_sack(struct sctp_tcb *stcb SCTP_UNUSED,
13998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    struct sctp_nets *net)
14008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
14018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->cc_mod.rtcc.tls_needs_set > 0) {
14028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We had a bw measurment going on */
14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct timeval ltls;
14048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_GETPTIME_TIMEVAL(&ltls);
14058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		timevalsub(&ltls, &net->cc_mod.rtcc.tls);
14068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.new_tot_time = (ltls.tv_sec * 1000000) + ltls.tv_usec;
14078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
1411000a5bac556b28e74e4e98c540f66b1743e9312dtuexensctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb,
14128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       struct sctp_nets *net)
14138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1414f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t vtag, probepoint;
1416b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen
1417b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
14188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->cc_mod.rtcc.lbw) {
1419f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
14208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Clear the old bw.. we went to 0 in-flight */
1421000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		vtag = (net->rtt << 32) | (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
14228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(stcb->rport);
14238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		probepoint = (((uint64_t)net->cwnd) << 32);
14248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Probe point 8 */
14258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		probepoint |=  ((8 << 16) | 0);
14268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SDT_PROBE(sctp, cwnd, net, rttvar,
14278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  vtag,
14288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw << 32) | 0),
14298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
14308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  net->flight_size,
14318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  probepoint);
1432b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
14338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.lbw_rtt = 0;
14348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.cwnd_at_bw_set = 0;
14358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.lbw = 0;
14368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
14378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.vol_reduce = 0;
14388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.bw_tot_time = 0;
14398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.bw_bytes = 0;
14408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.tls_needs_set = 0;
14418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cc_mod.rtcc.steady_step) {
14428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.vol_reduce = 0;
14438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.step_cnt = 0;
14448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.rtcc.last_step_state = 0;
14458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cc_mod.rtcc.ret_from_eq) {
14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* less aggressive one - reset cwnd too */
14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint32_t cwnd_in_mtu, cwnd;
14498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
14518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (cwnd_in_mtu == 0) {
14528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Using 0 means that the value of RFC 4960 is used. */
14538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
14548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
14558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * We take the minimum of the burst limit and the
14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * initial congestion window.
14588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((stcb->asoc.max_burst > 0) && (cwnd_in_mtu > stcb->asoc.max_burst))
14608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					cwnd_in_mtu = stcb->asoc.max_burst;
14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->cwnd > cwnd) {
14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Only set if we are not a timeout (i.e. down to 1 mtu) */
14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cwnd = cwnd;
14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1471000a5bac556b28e74e4e98c540f66b1743e9312dtuexenstatic void
1472000a5bac556b28e74e4e98c540f66b1743e9312dtuexensctp_set_rtcc_initial_cc_param(struct sctp_tcb *stcb,
14738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       struct sctp_nets *net)
14748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1475f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
14768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint64_t vtag, probepoint;
1477b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen
1478b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
14798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_set_initial_cc_param(stcb, net);
14808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.use_precise_time = 1;
1481f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
14828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	probepoint = (((uint64_t)net->cwnd) << 32);
14838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	probepoint |=  ((9 << 16) | 0);
1484000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	vtag = (net->rtt << 32) |
1485000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		(((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
14868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(stcb->rport);
14878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SDT_PROBE(sctp, cwnd, net, rttvar,
14888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  vtag,
14898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  0,
14908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  0,
14918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  0,
14928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  probepoint);
1493b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif
14948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.lbw_rtt = 0;
14958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.cwnd_at_bw_set = 0;
14968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.vol_reduce = 0;
14978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.lbw = 0;
14988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.vol_reduce = 0;
14998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
15008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.bw_tot_time = 0;
15018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.bw_bytes = 0;
15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.tls_needs_set = 0;
15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.ret_from_eq = SCTP_BASE_SYSCTL(sctp_rttvar_eqret);
15048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.steady_step = SCTP_BASE_SYSCTL(sctp_steady_step);
15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.use_dccc_ecn = SCTP_BASE_SYSCTL(sctp_use_dccc_ecn);
15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.step_cnt = 0;
15078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.last_step_state = 0;
15088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
1513000a5bac556b28e74e4e98c540f66b1743e9312dtuexensctp_cwnd_rtcc_socket_option(struct sctp_tcb *stcb, int setorget,
15148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			     struct sctp_cc_option *cc_opt)
15158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (setorget == 1) {
15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* a set */
15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((cc_opt->aid_value.assoc_value != 0) &&
15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (cc_opt->aid_value.assoc_value != 1)) {
15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EINVAL);
15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.ret_from_eq = cc_opt->aid_value.assoc_value;
15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((cc_opt->aid_value.assoc_value != 0) &&
15298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (cc_opt->aid_value.assoc_value != 1)) {
15308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EINVAL);
15318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
15338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.use_dccc_ecn = cc_opt->aid_value.assoc_value;
15348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
15368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
15378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.rtcc.steady_step = cc_opt->aid_value.assoc_value;
15388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
15408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
15418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
15438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* a get */
15448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
15458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = TAILQ_FIRST(&stcb->asoc.nets);
15468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net == NULL) {
15478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EFAULT);
15488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.ret_from_eq;
15508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
15518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = TAILQ_FIRST(&stcb->asoc.nets);
15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net == NULL) {
15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EFAULT);
15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.use_dccc_ecn;
15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = TAILQ_FIRST(&stcb->asoc.nets);
15588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net == NULL) {
15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EFAULT);
15608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.steady_step;
15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
15648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
1570000a5bac556b28e74e4e98c540f66b1743e9312dtuexensctp_cwnd_update_rtcc_packet_transmitted(struct sctp_tcb *stcb SCTP_UNUSED,
15710ac02f34d6041cd0018437596a5a9a94685e6919tuexen                                         struct sctp_nets *net)
15728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
15738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->cc_mod.rtcc.tls_needs_set == 0) {
15748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_GETPTIME_TIMEVAL(&net->cc_mod.rtcc.tls);
15758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.rtcc.tls_needs_set = 2;
15768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cwnd_update_rtcc_after_sack(struct sctp_tcb *stcb,
15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 struct sctp_association *asoc,
15820ac02f34d6041cd0018437596a5a9a94685e6919tuexen				 int accum_moved, int reneged_all, int will_exit)
15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Passing a one argument at the last enables the rtcc algoritm */
15850ac02f34d6041cd0018437596a5a9a94685e6919tuexen	sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 1);
15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
15890ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_rtt_rtcc_calculated(struct sctp_tcb *stcb SCTP_UNUSED,
15900ac02f34d6041cd0018437596a5a9a94685e6919tuexen                         struct sctp_nets *net,
15910ac02f34d6041cd0018437596a5a9a94685e6919tuexen                         struct timeval *now SCTP_UNUSED)
15928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
15938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.rtcc.rtt_set_this_sack = 1;
15948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* Here starts Sally Floyds HS-TCP */
15978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_hs_raise_drop {
15998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int32_t cwnd;
16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int32_t increase;
16018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int32_t drop_percent;
16028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen};
16038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SCTP_HS_TABLE_SIZE 73
16058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_hs_raise_drop sctp_cwnd_adjust[SCTP_HS_TABLE_SIZE] = {
16078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{38, 1, 50},		/* 0   */
16088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{118, 2, 44},		/* 1   */
16098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{221, 3, 41},		/* 2   */
16108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{347, 4, 38},		/* 3   */
16118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{495, 5, 37},		/* 4   */
16128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{663, 6, 35},		/* 5   */
16138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{851, 7, 34},		/* 6   */
16148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{1058, 8, 33},		/* 7   */
16158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{1284, 9, 32},		/* 8   */
16168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{1529, 10, 31},		/* 9   */
16178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{1793, 11, 30},		/* 10  */
16188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{2076, 12, 29},		/* 11  */
16198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{2378, 13, 28},		/* 12  */
16208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{2699, 14, 28},		/* 13  */
16218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{3039, 15, 27},		/* 14  */
16228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{3399, 16, 27},		/* 15  */
16238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{3778, 17, 26},		/* 16  */
16248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{4177, 18, 26},		/* 17  */
16258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{4596, 19, 25},		/* 18  */
16268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{5036, 20, 25},		/* 19  */
16278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{5497, 21, 24},		/* 20  */
16288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{5979, 22, 24},		/* 21  */
16298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{6483, 23, 23},		/* 22  */
16308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{7009, 24, 23},		/* 23  */
16318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{7558, 25, 22},		/* 24  */
16328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{8130, 26, 22},		/* 25  */
16338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{8726, 27, 22},		/* 26  */
16348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{9346, 28, 21},		/* 27  */
16358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{9991, 29, 21},		/* 28  */
16368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{10661, 30, 21},	/* 29  */
16378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{11358, 31, 20},	/* 30  */
16388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{12082, 32, 20},	/* 31  */
16398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{12834, 33, 20},	/* 32  */
16408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{13614, 34, 19},	/* 33  */
16418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{14424, 35, 19},	/* 34  */
16428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{15265, 36, 19},	/* 35  */
16438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{16137, 37, 19},	/* 36  */
16448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{17042, 38, 18},	/* 37  */
16458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{17981, 39, 18},	/* 38  */
16468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{18955, 40, 18},	/* 39  */
16478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{19965, 41, 17},	/* 40  */
16488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{21013, 42, 17},	/* 41  */
16498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{22101, 43, 17},	/* 42  */
16508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{23230, 44, 17},	/* 43  */
16518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{24402, 45, 16},	/* 44  */
16528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{25618, 46, 16},	/* 45  */
16538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{26881, 47, 16},	/* 46  */
16548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{28193, 48, 16},	/* 47  */
16558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{29557, 49, 15},	/* 48  */
16568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{30975, 50, 15},	/* 49  */
16578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{32450, 51, 15},	/* 50  */
16588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{33986, 52, 15},	/* 51  */
16598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{35586, 53, 14},	/* 52  */
16608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{37253, 54, 14},	/* 53  */
16618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{38992, 55, 14},	/* 54  */
16628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{40808, 56, 14},	/* 55  */
16638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{42707, 57, 13},	/* 56  */
16648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{44694, 58, 13},	/* 57  */
16658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{46776, 59, 13},	/* 58  */
16668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{48961, 60, 13},	/* 59  */
16678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{51258, 61, 13},	/* 60  */
16688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{53677, 62, 12},	/* 61  */
16698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{56230, 63, 12},	/* 62  */
16708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{58932, 64, 12},	/* 63  */
16718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{61799, 65, 12},	/* 64  */
16728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{64851, 66, 11},	/* 65  */
16738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{68113, 67, 11},	/* 66  */
16748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{71617, 68, 11},	/* 67  */
16758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{75401, 69, 10},	/* 68  */
16768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{79517, 70, 10},	/* 69  */
16778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{84035, 71, 10},	/* 70  */
16788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{89053, 72, 10},	/* 71  */
16798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{94717, 73, 9}		/* 72  */
16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen};
16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hs_cwnd_increase(struct sctp_tcb *stcb, struct sctp_nets *net)
16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int cur_val, i, indx, incr;
16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cur_val = net->cwnd >> 10;
16888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	indx = SCTP_HS_TABLE_SIZE - 1;
168947a306d634abf33223ef347472c4b1cd441d139ftuexen
16908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (cur_val < sctp_cwnd_adjust[0].cwnd) {
16918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* normal mode */
16928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->net_ack > net->mtu) {
16938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwnd += net->mtu;
16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
16958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, net->mtu, SCTP_CWND_LOG_FROM_SS);
16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
16978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwnd += net->net_ack;
16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, net->net_ack, SCTP_CWND_LOG_FROM_SS);
17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = net->last_hs_used; i < SCTP_HS_TABLE_SIZE; i++) {
17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (cur_val < sctp_cwnd_adjust[i].cwnd) {
17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				indx = i;
17078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->last_hs_used = indx;
17118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		incr = ((sctp_cwnd_adjust[indx].increase) << 10);
17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd += incr;
17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_cwnd(stcb, net, incr, SCTP_CWND_LOG_FROM_SS);
17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net)
17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int cur_val, i, indx;
17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int old_cwnd = net->cwnd;
17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cur_val = net->cwnd >> 10;
17268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (cur_val < sctp_cwnd_adjust[0].cwnd) {
17278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* normal mode */
17288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->ssthresh = net->cwnd / 2;
17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->ssthresh < (net->mtu * 2)) {
17308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ssthresh = 2 * net->mtu;
17318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd = net->ssthresh;
17338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
17348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* drop by the proper amount */
17358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->ssthresh = net->cwnd - (int)((net->cwnd / 100) *
17368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sctp_cwnd_adjust[net->last_hs_used].drop_percent);
17378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd = net->ssthresh;
17388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* now where are we */
17398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		indx = net->last_hs_used;
17408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cur_val = net->cwnd >> 10;
17418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* reset where we are in the table */
17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (cur_val < sctp_cwnd_adjust[0].cwnd) {
17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* feel out of hs */
17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->last_hs_used = 0;
17458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
17468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			for (i = indx; i >= 1; i--) {
17478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (cur_val > sctp_cwnd_adjust[i - 1].cwnd) {
17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
17498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
17508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
17518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->last_hs_used = indx;
17528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_FR);
17568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
17588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                             struct sctp_association *asoc)
17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
17648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * (net->fast_retran_loss_recovery == 0)))
17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((asoc->fast_retran_loss_recovery == 0) ||
17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (asoc->sctp_cmt_on_off > 0)) {
17718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* out of a RFC2582 Fast recovery window? */
17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->net_ack > 0) {
17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
17748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * per section 7.2.3, are there any
17758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * destinations that had a fast retransmit
17768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * to them. If so what we need to do is
17778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * adjust ssthresh and cwnd.
17788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
17798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_tmit_chunk *lchk;
17808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_hs_cwnd_decrease(stcb, net);
17828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				lchk = TAILQ_FIRST(&asoc->send_queue);
17848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->partial_bytes_acked = 0;
17868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Turn on fast recovery window */
17878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->fast_retran_loss_recovery = 1;
17888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (lchk == NULL) {
17898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Mark end of the window */
17908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->fast_recovery_tsn = asoc->sending_seq - 1;
17918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
17928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
17938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
17948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
17968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * CMT fast recovery -- per destination
17978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * recovery variable.
17988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
17998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->fast_retran_loss_recovery = 1;
18008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (lchk == NULL) {
18028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Mark end of the window */
18038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->fast_recovery_tsn = asoc->sending_seq - 1;
18048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
18058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
18068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
18078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
1809b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen						stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA+SCTP_LOC_32);
18108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SEND,
18118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 stcb->sctp_ep, stcb, net);
18128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (net->net_ack > 0) {
18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
18158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Mark a peg that we WOULD have done a cwnd
18168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * reduction but RFC2582 prevented this action.
18178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
18188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_INCR(sctps_fastretransinrtt);
18198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
18228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
18248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
18258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 struct sctp_association *asoc,
18260ac02f34d6041cd0018437596a5a9a94685e6919tuexen		 int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
18278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
18288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
18298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/******************************/
18308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* update cwnd and Early FR   */
18318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/******************************/
18328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
18338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef JANA_CMT_FAST_RECOVERY
18358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
18368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT fast recovery code. Need to debug.
18378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
18388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
18398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
18408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
18418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->will_exit_fast_recovery = 1;
18428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* if nothing was acked on this destination skip it */
18468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->net_ack == 0) {
18478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
18488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
18498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
18518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef JANA_CMT_FAST_RECOVERY
18538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                /* CMT fast recovery code
18548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
18558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
18568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
18578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    @@@ Do something
18588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 }
18598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
18608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*/
18618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 if (asoc->fast_retran_loss_recovery &&
18648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (will_exit == 0) &&
18658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (asoc->sctp_cmt_on_off == 0)) {
18668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
18678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * If we are in loss recovery we skip any cwnd
18688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * update
18698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
18738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
18748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * moved.
18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (accum_moved ||
18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* If the cumulative ack moved we can proceed */
18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->cwnd <= net->ssthresh) {
18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* We are in slow start */
18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->flight_size + net->net_ack >= net->cwnd) {
18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_hs_cwnd_increase(stcb, net);
18848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
18868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
18878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_cwnd(stcb, net, net->net_ack,
18888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							SCTP_CWND_LOG_NOADV_SS);
18898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
18918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
18928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* We are in congestion avoidance */
18938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->partial_bytes_acked += net->net_ack;
18948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((net->flight_size + net->net_ack >= net->cwnd) &&
18958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (net->partial_bytes_acked >= net->cwnd)) {
18968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->partial_bytes_acked -= net->cwnd;
18978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->cwnd += net->mtu;
18988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
18998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_cwnd(stcb, net, net->mtu,
19008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							SCTP_CWND_LOG_FROM_CA);
19018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
19028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
19038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
19048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_cwnd(stcb, net, net->net_ack,
19058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							SCTP_CWND_LOG_NOADV_CA);
19068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
19078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
19088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
19108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
19118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, net->mtu,
19128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CWND_LOG_NO_CUMACK);
19138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * H-TCP congestion control. The algorithm is detailed in:
19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * R.N.Shorten, D.J.Leith:
19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *   "H-TCP: TCP for high-speed and long-distance networks"
19238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *   Proc. PFLDnet, Argonne, 2004.
19248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * http://www.hamilton.ie/net/htcp3.pdf
19258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
19268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int use_rtt_scaling = 1;
19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int use_bandwidth_switch = 1;
19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic inline int
19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenbetween(uint32_t seq1, uint32_t seq2, uint32_t seq3)
19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1934b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (seq3 - seq2 >= seq1 - seq2);
19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic inline uint32_t
19388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenhtcp_cong_time(struct htcp *ca)
19398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1940b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (sctp_get_tick_count() - ca->last_cong);
19418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic inline uint32_t
19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenhtcp_ccount(struct htcp *ca)
19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1946b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (htcp_cong_time(ca)/ca->minRTT);
19478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic inline void
19508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenhtcp_reset(struct htcp *ca)
19518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ca->undo_last_cong = ca->last_cong;
19538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ca->undo_maxRTT = ca->maxRTT;
19548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ca->undo_old_maxB = ca->old_maxB;
19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ca->last_cong = sctp_get_tick_count();
19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_NOT_USED
19598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t
19618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenhtcp_cwnd_undo(struct sctp_tcb *stcb, struct sctp_nets *net)
19628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.htcp_ca.last_cong = net->cc_mod.htcp_ca.undo_last_cong;
19648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.undo_maxRTT;
19658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.htcp_ca.old_maxB = net->cc_mod.htcp_ca.undo_old_maxB;
1966b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (max(net->cwnd, ((net->ssthresh/net->mtu<<7)/net->cc_mod.htcp_ca.beta)*net->mtu));
19678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic inline void
19720ac02f34d6041cd0018437596a5a9a94685e6919tuexenmeasure_rtt(struct sctp_nets *net)
19738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t srtt = net->lastsa>>SCTP_RTT_SHIFT;
19758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* keep track of minimum RTT seen so far, minRTT is zero at first */
19778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->cc_mod.htcp_ca.minRTT > srtt || !net->cc_mod.htcp_ca.minRTT)
19788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.htcp_ca.minRTT = srtt;
19798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* max RTT */
19818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->fast_retran_ip == 0 && net->ssthresh < 0xFFFF && htcp_ccount(&net->cc_mod.htcp_ca) > 3) {
19828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cc_mod.htcp_ca.maxRTT < net->cc_mod.htcp_ca.minRTT)
19838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.minRTT;
19848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->cc_mod.htcp_ca.maxRTT < srtt && srtt <= net->cc_mod.htcp_ca.maxRTT+MSEC_TO_TICKS(20))
19858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.htcp_ca.maxRTT = srtt;
19868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
19900ac02f34d6041cd0018437596a5a9a94685e6919tuexenmeasure_achieved_throughput(struct sctp_nets *net)
19918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t now = sctp_get_tick_count();
19938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->fast_retran_ip == 0)
19958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.htcp_ca.bytes_acked = net->net_ack;
19968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!use_bandwidth_switch)
19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* achieved throughput calculations */
20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* JRS - not 100% sure of this statement */
20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->fast_retran_ip == 1) {
20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.htcp_ca.bytecount = 0;
20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.htcp_ca.lasttime = now;
20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
20068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.htcp_ca.bytecount += net->net_ack;
2009a7e2a63200c3155382d862ceb5cf07a1176ee531t	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)) &&
2010a7e2a63200c3155382d862ceb5cf07a1176ee531t	    (now - net->cc_mod.htcp_ca.lasttime >= net->cc_mod.htcp_ca.minRTT) &&
2011a7e2a63200c3155382d862ceb5cf07a1176ee531t	    (net->cc_mod.htcp_ca.minRTT > 0)) {
20128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t cur_Bi = net->cc_mod.htcp_ca.bytecount/net->mtu*hz/(now - net->cc_mod.htcp_ca.lasttime);
2013a7e2a63200c3155382d862ceb5cf07a1176ee531t
20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (htcp_ccount(&net->cc_mod.htcp_ca) <= 3) {
20158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* just after backoff */
20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi = cur_Bi;
20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cc_mod.htcp_ca.Bi = (3*net->cc_mod.htcp_ca.Bi + cur_Bi)/4;
20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->cc_mod.htcp_ca.Bi > net->cc_mod.htcp_ca.maxB)
20208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi;
20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->cc_mod.htcp_ca.minB > net->cc_mod.htcp_ca.maxB)
20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB;
20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.htcp_ca.bytecount = 0;
20258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.htcp_ca.lasttime = now;
20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic inline void
20308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenhtcp_beta_update(struct htcp *ca, uint32_t minRTT, uint32_t maxRTT)
20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (use_bandwidth_switch) {
20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t maxB = ca->maxB;
20348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t old_maxB = ca->old_maxB;
20358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ca->old_maxB = ca->maxB;
20368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!between(5*maxB, 4*old_maxB, 6*old_maxB)) {
20388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ca->beta = BETA_MIN;
20398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ca->modeswitch = 0;
20408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ca->modeswitch && minRTT > (uint32_t)MSEC_TO_TICKS(10) && maxRTT) {
20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ca->beta = (minRTT<<7)/maxRTT;
20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ca->beta < BETA_MIN)
20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ca->beta = BETA_MIN;
20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else if (ca->beta > BETA_MAX)
20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ca->beta = BETA_MAX;
20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ca->beta = BETA_MIN;
20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ca->modeswitch = 1;
20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic inline void
20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenhtcp_alpha_update(struct htcp *ca)
20588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t minRTT = ca->minRTT;
20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t factor = 1;
20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t diff = htcp_cong_time(ca);
20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (diff > (uint32_t)hz) {
20648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		diff -= hz;
2065b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		factor = 1+ ( 10*diff + ((diff/2)*(diff/2)/hz))/hz;
20668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (use_rtt_scaling && minRTT) {
20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t scale = (hz<<3)/(10*minRTT);
20708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		scale = min(max(scale, 1U<<2), 10U<<3); /* clamping ratio to interval [0.5,10]<<3 */
20718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		factor = (factor<<3)/scale;
20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!factor)
20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			factor = 1;
20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ca->alpha = 2*factor*((1<<7)-ca->beta);
20778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!ca->alpha)
20788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ca->alpha = ALPHA_BASE;
20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* After we have the rtt data to calculate beta, we'd still prefer to wait one
20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * rtt before we adjust our beta to ensure we are working from a consistent
20838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * data.
20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This function should be called when we hit a congestion event since only at
20868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that point do we really have a real sense of maxRTT (the queues en route
20878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * were getting just too full now).
20888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
20900ac02f34d6041cd0018437596a5a9a94685e6919tuexenhtcp_param_update(struct sctp_nets *net)
20918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
20928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t minRTT = net->cc_mod.htcp_ca.minRTT;
20938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t maxRTT = net->cc_mod.htcp_ca.maxRTT;
20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	htcp_beta_update(&net->cc_mod.htcp_ca, minRTT, maxRTT);
20968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	htcp_alpha_update(&net->cc_mod.htcp_ca);
20978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* add slowly fading memory for maxRTT to accommodate routing changes etc */
20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (minRTT > 0 && maxRTT > minRTT)
21008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.htcp_ca.maxRTT = minRTT + ((maxRTT-minRTT)*95)/100;
21018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
21028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t
21040ac02f34d6041cd0018437596a5a9a94685e6919tuexenhtcp_recalc_ssthresh(struct sctp_nets *net)
21058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
21060ac02f34d6041cd0018437596a5a9a94685e6919tuexen	htcp_param_update(net);
2107b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (max(((net->cwnd/net->mtu * net->cc_mod.htcp_ca.beta) >> 7)*net->mtu, 2U*net->mtu));
21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenhtcp_cong_avoid(struct sctp_tcb *stcb, struct sctp_nets *net)
21128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * How to handle these functions?
21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen         *	if (!tcp_is_cwnd_limited(sk, in_flight)) RRS - good question.
21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *		return;
21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        if (net->cwnd <= net->ssthresh) {
21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We are in slow start */
21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->flight_size + net->net_ack >= net->cwnd) {
21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->net_ack > (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable))) {
21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cwnd += (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable));
21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
21248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_log_cwnd(stcb, net, net->mtu,
21258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_CWND_LOG_FROM_SS);
21268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
21278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
21298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cwnd += net->net_ack;
21308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
21318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_log_cwnd(stcb, net, net->net_ack,
21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_CWND_LOG_FROM_SS);
21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
21348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, net->net_ack,
21398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CWND_LOG_NOADV_SS);
21408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
21430ac02f34d6041cd0018437596a5a9a94685e6919tuexen		measure_rtt(net);
21448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* In dangerous area, increase slowly.
21468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * In theory this is net->cwnd += alpha / net->cwnd
21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* What is snd_cwnd_cnt?? */
21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (((net->partial_bytes_acked/net->mtu * net->cc_mod.htcp_ca.alpha) >> 7)*net->mtu >= net->cwnd) {
21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                        /*-
21518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Does SCTP have a cwnd clamp?
21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * if (net->snd_cwnd < net->snd_cwnd_clamp) - Nope (RRS).
21538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwnd += net->mtu;
21558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->partial_bytes_acked = 0;
21568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			htcp_alpha_update(&net->cc_mod.htcp_ca);
21578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
21588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, net->mtu,
21598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CWND_LOG_FROM_CA);
21608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->partial_bytes_acked += net->net_ack;
21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, net->net_ack,
21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CWND_LOG_NOADV_CA);
21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cc_mod.htcp_ca.bytes_acked = net->mtu;
21708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_NOT_USED
21748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* Lower bound on congestion window. */
21758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t
21768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenhtcp_min_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net)
21778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2178b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (net->ssthresh);
21798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
21808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
21818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
21830ac02f34d6041cd0018437596a5a9a94685e6919tuexenhtcp_init(struct sctp_nets *net)
21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(&net->cc_mod.htcp_ca, 0, sizeof(struct htcp));
21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.htcp_ca.alpha = ALPHA_BASE;
21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.htcp_ca.beta = BETA_MIN;
21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.htcp_ca.bytes_acked = net->mtu;
21898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cc_mod.htcp_ca.last_cong = sctp_get_tick_count();
21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
21918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
21938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_htcp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
21948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
21958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
21968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * We take the max of the burst limit times a MTU or the
21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * INITIAL_CWND. We then limit this to 4 MTU's of sending.
21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->ssthresh = stcb->asoc.peers_rwnd;
22010ac02f34d6041cd0018437596a5a9a94685e6919tuexen	htcp_init(net);
22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) {
22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
22078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 struct sctp_association *asoc,
22110ac02f34d6041cd0018437596a5a9a94685e6919tuexen		 int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
22140ac02f34d6041cd0018437596a5a9a94685e6919tuexen
22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/******************************/
22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* update cwnd and Early FR   */
22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/******************************/
22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef JANA_CMT_FAST_RECOVERY
22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
22228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT fast recovery code. Need to debug.
22238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->will_exit_fast_recovery = 1;
22288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* if nothing was acked on this destination skip it */
22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->net_ack == 0) {
22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
22348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef JANA_CMT_FAST_RECOVERY
22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                /* CMT fast recovery code
22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
22418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
22428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
22438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    @@@ Do something
22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 }
22458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
22468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*/
22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->fast_retran_loss_recovery &&
22508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    will_exit == 0 &&
22518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (asoc->sctp_cmt_on_off == 0)) {
22528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * If we are in loss recovery we skip any cwnd
22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * update
22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * moved.
22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (accum_moved ||
22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			htcp_cong_avoid(stcb, net);
22650ac02f34d6041cd0018437596a5a9a94685e6919tuexen			measure_achieved_throughput(net);
22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_cwnd(stcb, net, net->mtu,
22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CWND_LOG_NO_CUMACK);
22708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
22718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
22748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_association *asoc)
22788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
22808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
22828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * (net->fast_retran_loss_recovery == 0)))
22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
22848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((asoc->fast_retran_loss_recovery == 0) ||
22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (asoc->sctp_cmt_on_off > 0)) {
22878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* out of a RFC2582 Fast recovery window? */
22888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->net_ack > 0) {
22898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
22908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * per section 7.2.3, are there any
22918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * destinations that had a fast retransmit
22928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * to them. If so what we need to do is
22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * adjust ssthresh and cwnd.
22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_tmit_chunk *lchk;
22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				int old_cwnd = net->cwnd;
22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* JRS - reset as if state were changed */
22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				htcp_reset(&net->cc_mod.htcp_ca);
23000ac02f34d6041cd0018437596a5a9a94685e6919tuexen				net->ssthresh = htcp_recalc_ssthresh(net);
23018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->cwnd = net->ssthresh;
23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
23048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_CWND_LOG_FROM_FR);
23058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
23068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				lchk = TAILQ_FIRST(&asoc->send_queue);
23078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->partial_bytes_acked = 0;
23098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Turn on fast recovery window */
23108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->fast_retran_loss_recovery = 1;
23118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (lchk == NULL) {
23128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Mark end of the window */
23138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->fast_recovery_tsn = asoc->sending_seq - 1;
23148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
23158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
23168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
23178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
23198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * CMT fast recovery -- per destination
23208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * recovery variable.
23218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
23228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->fast_retran_loss_recovery = 1;
23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (lchk == NULL) {
23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Mark end of the window */
23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->fast_recovery_tsn = asoc->sending_seq - 1;
23278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
23288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
23298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
23308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
2332b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen						stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA+SCTP_LOC_32);
23338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SEND,
23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 stcb->sctp_ep, stcb, net);
23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
23368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (net->net_ack > 0) {
23378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
23388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Mark a peg that we WOULD have done a cwnd
23398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * reduction but RFC2582 prevented this action.
23408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
23418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_INCR(sctps_fastretransinrtt);
23428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
23458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
23478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_htcp_cwnd_update_after_timeout(struct sctp_tcb *stcb,
23488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net)
23498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
23508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int old_cwnd = net->cwnd;
23518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* JRS - reset as if the state were being changed to timeout */
23538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		htcp_reset(&net->cc_mod.htcp_ca);
23540ac02f34d6041cd0018437596a5a9a94685e6919tuexen		net->ssthresh = htcp_recalc_ssthresh(net);
23558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd = net->mtu;
23568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->partial_bytes_acked = 0;
23578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
23588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
23598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
23618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
23638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
23640ac02f34d6041cd0018437596a5a9a94685e6919tuexen		struct sctp_nets *net, int in_window, int num_pkt_lost SCTP_UNUSED)
23658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
23668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int old_cwnd;
23678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	old_cwnd = net->cwnd;
23688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* JRS - reset hctp as if state changed */
23708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (in_window == 0) {
23718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		htcp_reset(&net->cc_mod.htcp_ca);
23728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_ecnereducedcwnd);
23730ac02f34d6041cd0018437596a5a9a94685e6919tuexen		net->ssthresh = htcp_recalc_ssthresh(net);
23748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->ssthresh < net->mtu) {
23758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ssthresh = net->mtu;
23768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* here back off the timer as well, to slow us down */
23778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->RTO <<= 1;
23788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->cwnd = net->ssthresh;
23808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
23818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
23828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
23858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_cc_functions sctp_cc_functions[] = {
23878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
23880612043f643c9b26245564c05defca64d472060etuexen#if defined(__Windows__) || defined(__Userspace_os_Windows)
23898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_set_initial_cc_param,
23908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_sack,
23918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_exit_pf_common,
23928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_fr,
23938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_timeout,
23948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_ecn_echo,
23958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_packet_dropped,
23968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_output,
23978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
23988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_set_initial_cc_param = sctp_set_initial_cc_param,
23998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_sack = sctp_cwnd_update_after_sack,
24008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
24018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
24028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
24038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
24048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
24058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
24068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
24078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen},
24088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
24090612043f643c9b26245564c05defca64d472060etuexen#if defined(__Windows__) || defined(__Userspace_os_Windows)
24108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_set_initial_cc_param,
24118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hs_cwnd_update_after_sack,
24128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_exit_pf_common,
24138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hs_cwnd_update_after_fr,
24148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_timeout,
24158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_ecn_echo,
24168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_packet_dropped,
24178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_output,
24188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
24198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_set_initial_cc_param = sctp_set_initial_cc_param,
24208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_sack = sctp_hs_cwnd_update_after_sack,
24218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
24228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_fr = sctp_hs_cwnd_update_after_fr,
24238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
24248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
24258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
24268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
24278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
24288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen},
24298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
24300612043f643c9b26245564c05defca64d472060etuexen#if defined(__Windows__) || defined(__Userspace_os_Windows)
24318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_htcp_set_initial_cc_param,
24328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_htcp_cwnd_update_after_sack,
24338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_exit_pf_common,
24348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_htcp_cwnd_update_after_fr,
24358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_htcp_cwnd_update_after_timeout,
24368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_htcp_cwnd_update_after_ecn_echo,
24378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_packet_dropped,
24388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_output,
24398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
24408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_set_initial_cc_param = sctp_htcp_set_initial_cc_param,
24418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_sack = sctp_htcp_cwnd_update_after_sack,
24428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
24438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_fr = sctp_htcp_cwnd_update_after_fr,
24448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_timeout = sctp_htcp_cwnd_update_after_timeout,
24458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_ecn_echo = sctp_htcp_cwnd_update_after_ecn_echo,
24468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
24478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
24488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
24498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen},
24508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
24510612043f643c9b26245564c05defca64d472060etuexen#if defined(__Windows__) || defined(__Userspace_os_Windows)
24528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_set_rtcc_initial_cc_param,
24538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_rtcc_after_sack,
24548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_exit_pf_common,
24558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_fr,
24568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_timeout,
24578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_rtcc_after_ecn_echo,
24588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_packet_dropped,
24598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_after_output,
24608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_rtcc_packet_transmitted,
24618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_update_rtcc_tsn_acknowledged,
24628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_new_rtcc_transmission_begins,
24638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_prepare_rtcc_net_for_sack,
24648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_cwnd_rtcc_socket_option,
24658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_rtt_rtcc_calculated
24668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
24678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_set_initial_cc_param = sctp_set_rtcc_initial_cc_param,
24688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_sack = sctp_cwnd_update_rtcc_after_sack,
24698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
24708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
24718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
24728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_rtcc_after_ecn_echo,
24738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
24748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
24758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_packet_transmitted = sctp_cwnd_update_rtcc_packet_transmitted,
24768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_update_tsn_acknowledged = sctp_cwnd_update_rtcc_tsn_acknowledged,
24778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_new_transmission_begins = sctp_cwnd_new_rtcc_transmission_begins,
24788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_prepare_net_for_sack = sctp_cwnd_prepare_rtcc_net_for_sack,
24798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_cwnd_socket_option = sctp_cwnd_rtcc_socket_option,
24808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.sctp_rtt_calculated = sctp_rtt_rtcc_calculated
24818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
24828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
24838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen};
2484