--- old/usr/src/uts/common/inet/tcp/tcp.c	Thu Mar  1 14:54:15 2018
+++ new/usr/src/uts/common/inet/tcp/tcp.c	Thu Mar  1 14:54:15 2018
@@ -23,7 +23,7 @@
  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2017 Joyent, Inc.
  * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2013,2014 by Delphix. All rights reserved.
+ * Copyright (c) 2013, 2017 by Delphix. All rights reserved.
  * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  */
 /* Copyright (c) 1990 Mentat Inc. */
@@ -74,6 +74,7 @@
 #include <inet/ipsec_impl.h>
 
 #include <inet/common.h>
+#include <inet/cc.h>
 #include <inet/ip.h>
 #include <inet/ip_impl.h>
 #include <inet/ip6.h>
@@ -266,8 +267,6 @@
 /*
  * Functions called directly via squeue having a prototype of edesc_t.
  */
-void		tcp_input_listener(void *arg, mblk_t *mp, void *arg2,
-    ip_recv_attr_t *ira);
 void		tcp_input_data(void *arg, mblk_t *mp, void *arg2,
     ip_recv_attr_t *ira);
 static void	tcp_linger_interrupted(void *arg, mblk_t *mp, void *arg2,
@@ -576,7 +575,37 @@
 	ASSERT(connp->conn_ref == 1);
 }
 
+#pragma inline(tcp_calculate_rto)
+
 /*
+ * RTO = average estimates (sa / 8) + 4 * deviation estimates (sd)
+ *
+ * Add tcp_rexmit_interval extra in case of extreme environment where the
+ * algorithm fails to work.  The default value of tcp_rexmit_interval_extra
+ * should be 0.
+ *
+ * As we use a finer grained clock than BSD and update RTO for every ACKs, add
+ * in another .25 of RTT to the deviation of RTO to accommodate burstiness of
+ * 1/4 of window size.
+ */
+clock_t
+tcp_calculate_rto(tcp_t *tcp, tcp_stack_t *tcps)
+{
+	clock_t rto;
+
+	rto = NSEC2MSEC((tcp->tcp_rtt_sa >> 3) + (tcp->tcp_rtt_sa >> 5) +
+	    tcp->tcp_rtt_sd) + tcps->tcps_rexmit_interval_extra +
+	    tcps->tcps_conn_grace_period;
+
+	if (rto < tcp->tcp_rto_min)
+		rto = tcp->tcp_rto_min;
+	else if (rto > tcp->tcp_rto_max)
+		rto = tcp->tcp_rto_max;
+
+	return (rto);
+}
+
+/*
  * Adapt to the information, such as rtt and rtt_sd, provided from the
  * DCE and IRE maintained by IP.
  *
@@ -640,15 +669,9 @@
 	tcp->tcp_localnet = uinfo.iulp_localnet;
 
 	if (uinfo.iulp_rtt != 0) {
-		clock_t	rto;
-
-		tcp->tcp_rtt_sa = uinfo.iulp_rtt;
-		tcp->tcp_rtt_sd = uinfo.iulp_rtt_sd;
-		rto = (tcp->tcp_rtt_sa >> 3) + tcp->tcp_rtt_sd +
-		    tcps->tcps_rexmit_interval_extra +
-		    (tcp->tcp_rtt_sa >> 5);
-
-		TCP_SET_RTO(tcp, rto);
+		tcp->tcp_rtt_sa = MSEC2NSEC(uinfo.iulp_rtt);
+		tcp->tcp_rtt_sd = MSEC2NSEC(uinfo.iulp_rtt_sd);
+		tcp->tcp_rto = tcp_calculate_rto(tcp, tcps);
 	}
 	if (uinfo.iulp_ssthresh != 0)
 		tcp->tcp_cwnd_ssthresh = uinfo.iulp_ssthresh;
@@ -1238,11 +1261,6 @@
 	if (!TCP_IS_SOCKET(tcp))
 		tcp_acceptor_hash_remove(tcp);
 
-	TCPS_UPDATE_MIB(tcps, tcpHCInSegs, tcp->tcp_ibsegs);
-	tcp->tcp_ibsegs = 0;
-	TCPS_UPDATE_MIB(tcps, tcpHCOutSegs, tcp->tcp_obsegs);
-	tcp->tcp_obsegs = 0;
-
 	/*
 	 * This can be called via tcp_time_wait_processing() if TCP gets a
 	 * SYN with sequence number outside the TIME-WAIT connection's
@@ -1421,6 +1439,10 @@
 	 */
 	tcp_close_mpp(&tcp->tcp_conn.tcp_eager_conn_ind);
 
+	/* Allow the CC algorithm to clean up after itself. */
+	if (tcp->tcp_cc_algo != NULL && tcp->tcp_cc_algo->cb_destroy != NULL)
+		tcp->tcp_cc_algo->cb_destroy(&tcp->tcp_ccv);
+
 	/*
 	 * Destroy any association with SO_REUSEPORT group.
 	 */
@@ -1482,7 +1504,7 @@
  * collector will free up the freelist is the connection ends up sitting
  * there for too long.
  */
-void *
+conn_t *
 tcp_get_conn(void *arg, tcp_stack_t *tcps)
 {
 	tcp_t			*tcp = NULL;
@@ -1521,7 +1543,7 @@
 		connp->conn_recv = tcp_input_data;
 		ASSERT(connp->conn_recvicmp == tcp_icmp_input);
 		ASSERT(connp->conn_verifyicmp == tcp_verifyicmp);
-		return ((void *)connp);
+		return (connp);
 	}
 	mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
 	/*
@@ -1556,7 +1578,7 @@
 	connp->conn_ixa->ixa_notify = tcp_notify;
 	connp->conn_ixa->ixa_notify_cookie = tcp;
 
-	return ((void *)connp);
+	return (connp);
 }
 
 /*
@@ -1926,15 +1948,6 @@
 	/* Cancel outstanding timers */
 	tcp_timers_stop(tcp);
 
-	/*
-	 * Reset everything in the state vector, after updating global
-	 * MIB data from instance counters.
-	 */
-	TCPS_UPDATE_MIB(tcps, tcpHCInSegs, tcp->tcp_ibsegs);
-	tcp->tcp_ibsegs = 0;
-	TCPS_UPDATE_MIB(tcps, tcpHCOutSegs, tcp->tcp_obsegs);
-	tcp->tcp_obsegs = 0;
-
 	tcp_close_mpp(&tcp->tcp_xmit_head);
 	if (tcp->tcp_snd_zcopy_aware)
 		tcp_zcopy_notify(tcp);
@@ -2106,9 +2119,6 @@
 	tcp->tcp_swnd = 0;
 	DONTCARE(tcp->tcp_cwnd);	/* Init in tcp_process_options */
 
-	ASSERT(tcp->tcp_ibsegs == 0);
-	ASSERT(tcp->tcp_obsegs == 0);
-
 	if (connp->conn_ht_iphc != NULL) {
 		kmem_free(connp->conn_ht_iphc, connp->conn_ht_iphc_allocated);
 		connp->conn_ht_iphc = NULL;
@@ -2200,6 +2210,8 @@
 	DONTCARE(tcp->tcp_rtt_sa);		/* Init in tcp_init_values */
 	DONTCARE(tcp->tcp_rtt_sd);		/* Init in tcp_init_values */
 	tcp->tcp_rtt_update = 0;
+	tcp->tcp_rtt_sum = 0;
+	tcp->tcp_rtt_cnt = 0;
 
 	DONTCARE(tcp->tcp_swl1); /* Init in case TCPS_LISTEN/TCPS_SYN_SENT */
 	DONTCARE(tcp->tcp_swl2); /* Init in case TCPS_LISTEN/TCPS_SYN_SENT */
@@ -2335,6 +2347,11 @@
 	ASSERT(tcp->tcp_listen_cnt == NULL);
 	ASSERT(tcp->tcp_reass_tid == 0);
 
+	/* Allow the CC algorithm to clean up after itself. */
+	if (tcp->tcp_cc_algo->cb_destroy != NULL)
+		tcp->tcp_cc_algo->cb_destroy(&tcp->tcp_ccv);
+	tcp->tcp_cc_algo = NULL;
+
 #undef	DONTCARE
 #undef	PRESERVE
 }
@@ -2348,7 +2365,6 @@
 {
 	tcp_stack_t	*tcps = tcp->tcp_tcps;
 	conn_t		*connp = tcp->tcp_connp;
-	clock_t		rto;
 
 	ASSERT((connp->conn_family == AF_INET &&
 	    connp->conn_ipversion == IPV4_VERSION) ||
@@ -2356,7 +2372,12 @@
 	    (connp->conn_ipversion == IPV4_VERSION ||
 	    connp->conn_ipversion == IPV6_VERSION)));
 
+	tcp->tcp_ccv.type = IPPROTO_TCP;
+	tcp->tcp_ccv.ccvc.tcp = tcp;
+
 	if (parent == NULL) {
+		tcp->tcp_cc_algo = tcps->tcps_default_cc_algo;
+
 		tcp->tcp_naglim = tcps->tcps_naglim_def;
 
 		tcp->tcp_rto_initial = tcps->tcps_rexmit_interval_initial;
@@ -2384,6 +2405,8 @@
 		 */
 	} else {
 		/* Inherit various TCP parameters from the parent. */
+		tcp->tcp_cc_algo = parent->tcp_cc_algo;
+
 		tcp->tcp_naglim = parent->tcp_naglim;
 
 		tcp->tcp_rto_initial = parent->tcp_rto_initial;
@@ -2410,6 +2433,9 @@
 		tcp->tcp_init_cwnd = parent->tcp_init_cwnd;
 	}
 
+	if (tcp->tcp_cc_algo->cb_init != NULL)
+		VERIFY(tcp->tcp_cc_algo->cb_init(&tcp->tcp_ccv) == 0);
+
 	/*
 	 * Initialize tcp_rtt_sa and tcp_rtt_sd so that the calculated RTO
 	 * will be close to tcp_rexmit_interval_initial.  By doing this, we
@@ -2417,12 +2443,9 @@
 	 * during first few transmissions of a connection as seen in slow
 	 * links.
 	 */
-	tcp->tcp_rtt_sa = tcp->tcp_rto_initial << 2;
-	tcp->tcp_rtt_sd = tcp->tcp_rto_initial >> 1;
-	rto = (tcp->tcp_rtt_sa >> 3) + tcp->tcp_rtt_sd +
-	    tcps->tcps_rexmit_interval_extra + (tcp->tcp_rtt_sa >> 5) +
-	    tcps->tcps_conn_grace_period;
-	TCP_SET_RTO(tcp, rto);
+	tcp->tcp_rtt_sa = MSEC2NSEC(tcp->tcp_rto_initial) << 2;
+	tcp->tcp_rtt_sd = MSEC2NSEC(tcp->tcp_rto_initial) >> 1;
+	tcp->tcp_rto = tcp_calculate_rto(tcp, tcps);
 
 	tcp->tcp_timer_backoff = 0;
 	tcp->tcp_ms_we_have_waited = 0;
@@ -2659,7 +2682,7 @@
 	}
 
 	sqp = IP_SQUEUE_GET((uint_t)gethrtime());
-	connp = (conn_t *)tcp_get_conn(sqp, tcps);
+	connp = tcp_get_conn(sqp, tcps);
 	/*
 	 * Both tcp_get_conn and netstack_find_by_cred incremented refcnt,
 	 * so we drop it by one.
@@ -3847,6 +3870,9 @@
 	list_create(&tcps->tcps_listener_conf, sizeof (tcp_listener_t),
 	    offsetof(tcp_listener_t, tl_link));
 
+	tcps->tcps_default_cc_algo = cc_load_algo(CC_DEFAULT_ALGO_NAME);
+	ASSERT3P(tcps->tcps_default_cc_algo, !=, NULL);
+
 	return (tcps);
 }
 
