--- old/usr/src/uts/common/inet/tcp/tcp_output.c	Thu Mar  1 14:54:16 2018
+++ new/usr/src/uts/common/inet/tcp/tcp_output.c	Thu Mar  1 14:54:16 2018
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2014, 2017 by Delphix. All rights reserved.
  */
 
 /* This file contains all TCP output processing functions. */
@@ -63,7 +63,7 @@
 		    int, ip_recv_attr_t *, ip_stack_t *, conn_t *);
 static boolean_t	tcp_send_rst_chk(tcp_stack_t *);
 static void	tcp_process_shrunk_swnd(tcp_t *, uint32_t);
-static void	tcp_fill_header(tcp_t *, uchar_t *, clock_t, int);
+static void	tcp_fill_header(tcp_t *, uchar_t *, int);
 
 /*
  * Functions called directly via squeue having a prototype of edesc_t.
@@ -80,6 +80,18 @@
  */
 static int tcp_tx_pull_len = 16;
 
+static void
+cc_after_idle(tcp_t *tcp)
+{
+	uint32_t old_cwnd = tcp->tcp_cwnd;
+
+	if (CC_ALGO(tcp)->after_idle != NULL)
+		CC_ALGO(tcp)->after_idle(&tcp->tcp_ccv);
+
+	DTRACE_PROBE3(cwnd__cc__after__idle, tcp_t *, tcp, uint32_t, old_cwnd,
+	    uint32_t, tcp->tcp_cwnd);
+}
+
 void
 tcp_wput(queue_t *q, mblk_t *mp)
 {
@@ -217,7 +229,6 @@
 	int32_t		total_hdr_len;
 	int32_t		tcp_hdr_len;
 	int		rc;
-	tcp_stack_t	*tcps = tcp->tcp_tcps;
 	conn_t		*connp = tcp->tcp_connp;
 	clock_t		now = LBOLT_FASTPATH;
 
@@ -372,7 +383,7 @@
 
 	if ((tcp->tcp_suna == snxt) && !tcp->tcp_localnet &&
 	    (TICK_TO_MSEC(now - tcp->tcp_last_recv_time) >= tcp->tcp_rto)) {
-		TCP_SET_INIT_CWND(tcp, mss, tcps->tcps_slow_start_after_idle);
+		cc_after_idle(tcp);
 	}
 	if (tcpstate == TCPS_SYN_RCVD) {
 		/*
@@ -453,7 +464,11 @@
 		}
 	}
 
+#ifdef KERNEL_32
 	local_time = (mblk_t *)now;
+#else
+	local_time = (mblk_t *)(intptr_t)gethrtime();
+#endif
 
 	/*
 	 * "Our" Nagle Algorithm.  This is not the same as in the old
@@ -1190,7 +1205,7 @@
 	now = LBOLT_FASTPATH;
 	if ((tcp->tcp_suna == snxt) && !tcp->tcp_localnet &&
 	    (TICK_TO_MSEC(now - tcp->tcp_last_recv_time) >= tcp->tcp_rto)) {
-		TCP_SET_INIT_CWND(tcp, mss, tcps->tcps_slow_start_after_idle);
+		cc_after_idle(tcp);
 	}
 
 	usable = tcp->tcp_swnd;		/* tcp window size */
@@ -1253,7 +1268,11 @@
 
 	if ((mp1 = dupb(mp)) == 0)
 		goto no_memory;
+#ifdef KERNEL_32
 	mp->b_prev = (mblk_t *)(uintptr_t)now;
+#else
+	mp->b_prev = (mblk_t *)(intptr_t)gethrtime();
+#endif
 	mp->b_next = (mblk_t *)(uintptr_t)snxt;
 
 	/* adjust tcp header information */
@@ -1268,7 +1287,9 @@
 
 	TCPS_BUMP_MIB(tcps, tcpOutDataSegs);
 	TCPS_UPDATE_MIB(tcps, tcpOutDataBytes, len);
-	BUMP_LOCAL(tcp->tcp_obsegs);
+	TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
+	tcp->tcp_cs.tcp_out_data_segs++;
+	tcp->tcp_cs.tcp_out_data_bytes += len;
 
 	/* Update the latest receive window size in TCP header. */
 	tcpha->tha_win = htons(tcp->tcp_rwnd >> tcp->tcp_rcv_ws);
@@ -1308,12 +1329,10 @@
 
 	/* Fill in the timestamp option. */
 	if (tcp->tcp_snd_ts_ok) {
-		uint32_t llbolt = (uint32_t)LBOLT_FASTPATH;
-
-		U32_TO_BE32(llbolt,
-		    (char *)tcpha + TCP_MIN_HEADER_LENGTH+4);
+		U32_TO_BE32(now,
+		    (char *)tcpha + TCP_MIN_HEADER_LENGTH + 4);
 		U32_TO_BE32(tcp->tcp_ts_recent,
-		    (char *)tcpha + TCP_MIN_HEADER_LENGTH+8);
+		    (char *)tcpha + TCP_MIN_HEADER_LENGTH + 8);
 	} else {
 		ASSERT(connp->conn_ht_ulp_len == TCP_MIN_HEADER_LENGTH);
 	}
@@ -1957,16 +1976,21 @@
 			}
 			*snxt += len;
 			*tail_unsent = (*xmit_tail)->b_wptr - mp1->b_wptr;
-			BUMP_LOCAL(tcp->tcp_obsegs);
+			TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
 			TCPS_BUMP_MIB(tcps, tcpOutDataSegs);
 			TCPS_UPDATE_MIB(tcps, tcpOutDataBytes, len);
+			tcp->tcp_cs.tcp_out_data_segs++;
+			tcp->tcp_cs.tcp_out_data_bytes += len;
 			tcp_send_data(tcp, mp);
 			continue;
 		}
 
 		*snxt += len;	/* Adjust later if we don't send all of len */
+		TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
 		TCPS_BUMP_MIB(tcps, tcpOutDataSegs);
 		TCPS_UPDATE_MIB(tcps, tcpOutDataBytes, len);
+		tcp->tcp_cs.tcp_out_data_segs++;
+		tcp->tcp_cs.tcp_out_data_bytes += len;
 
 		if (*tail_unsent) {
 			/* Are the bytes above us in flight? */
@@ -2063,7 +2087,7 @@
 		 * Fill in the header using the template header, and add
 		 * options such as time-stamp, ECN and/or SACK, as needed.
 		 */
-		tcp_fill_header(tcp, rptr, (clock_t)local_time, num_sack_blk);
+		tcp_fill_header(tcp, rptr, num_sack_blk);
 
 		mp->b_rptr = rptr;
 
@@ -2142,6 +2166,7 @@
 				*snxt += spill;
 				tcp->tcp_last_sent_len += spill;
 				TCPS_UPDATE_MIB(tcps, tcpOutDataBytes, spill);
+				tcp->tcp_cs.tcp_out_data_bytes += spill;
 				/*
 				 * Adjust the checksum
 				 */
@@ -2190,7 +2215,7 @@
 			 */
 			ixa->ixa_fragsize = ixa->ixa_pmtu;
 			ixa->ixa_extra_ident = 0;
-			tcp->tcp_obsegs += num_lso_seg;
+			TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
 			TCP_STAT(tcps, tcp_lso_times);
 			TCP_STAT_UPDATE(tcps, tcp_lso_pkt_out, num_lso_seg);
 		} else {
@@ -2201,7 +2226,7 @@
 			 */
 			lso_info_cleanup(mp);
 			tcp_send_data(tcp, mp);
-			BUMP_LOCAL(tcp->tcp_obsegs);
+			TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
 		}
 	}
 
@@ -2281,8 +2306,8 @@
 	 * So don't do any update.
 	 */
 	bzero(&uinfo, sizeof (uinfo));
-	uinfo.iulp_rtt = tcp->tcp_rtt_sa;
-	uinfo.iulp_rtt_sd = tcp->tcp_rtt_sd;
+	uinfo.iulp_rtt = NSEC2MSEC(tcp->tcp_rtt_sa);
+	uinfo.iulp_rtt_sd = NSEC2MSEC(tcp->tcp_rtt_sd);
 
 	/*
 	 * Note that uinfo is kept for conn_faddr in the DCE. Could update even
@@ -2417,7 +2442,7 @@
 		tcp->tcp_rack_cnt = 0;
 		TCPS_BUMP_MIB(tcps, tcpOutAck);
 	}
-	BUMP_LOCAL(tcp->tcp_obsegs);
+	TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
 	tcpha->tha_seq = htonl(seq);
 	tcpha->tha_ack = htonl(ack);
 	/*
@@ -3386,11 +3411,17 @@
 		/*
 		 * Update the send timestamp to avoid false retransmission.
 		 */
+#ifdef KERNEL_32
 		snxt_mp->b_prev = (mblk_t *)ddi_get_lbolt();
+#else
+		snxt_mp->b_prev = (mblk_t *)(intptr_t)gethrtime();
+#endif
 
 		TCPS_BUMP_MIB(tcps, tcpRetransSegs);
 		TCPS_UPDATE_MIB(tcps, tcpRetransBytes, seg_len);
 		TCPS_BUMP_MIB(tcps, tcpOutSackRetransSegs);
+		tcp->tcp_cs.tcp_out_retrans_segs++;
+		tcp->tcp_cs.tcp_out_retrans_bytes += seg_len;
 		/*
 		 * Update tcp_rexmit_max to extend this SACK recovery phase.
 		 * This happens when new data sent during fast recovery is
@@ -3458,9 +3489,15 @@
 			 * Update the send timestamp to avoid false
 			 * retransmission.
 			 */
+#ifdef KERNEL_32
 			old_snxt_mp->b_prev = (mblk_t *)ddi_get_lbolt();
+#else
+			old_snxt_mp->b_prev = (mblk_t *)(intptr_t)gethrtime();
+#endif
 			TCPS_BUMP_MIB(tcps, tcpRetransSegs);
 			TCPS_UPDATE_MIB(tcps, tcpRetransBytes, cnt);
+			tcp->tcp_cs.tcp_out_retrans_segs++;
+			tcp->tcp_cs.tcp_out_retrans_bytes += cnt;
 
 			tcp->tcp_rexmit_nxt = snxt;
 		}
@@ -3618,7 +3655,7 @@
  * ECN and/or SACK.
  */
 static void
-tcp_fill_header(tcp_t *tcp, uchar_t *rptr, clock_t now, int num_sack_blk)
+tcp_fill_header(tcp_t *tcp, uchar_t *rptr, int num_sack_blk)
 {
 	tcpha_t *tcp_tmpl, *tcpha;
 	uint32_t *dst, *src;
@@ -3640,7 +3677,7 @@
 
 	/* Fill time-stamp option if needed */
 	if (tcp->tcp_snd_ts_ok) {
-		U32_TO_BE32((uint32_t)now,
+		U32_TO_BE32(LBOLT_FASTPATH,
 		    (char *)tcp_tmpl + TCP_MIN_HEADER_LENGTH + 4);
 		U32_TO_BE32(tcp->tcp_ts_recent,
 		    (char *)tcp_tmpl + TCP_MIN_HEADER_LENGTH + 8);
