xref: /onnv-gate/usr/src/uts/common/inet/tcp/tcp_stats.c (revision 12897:d4754c89220d)
111754SKacheong.Poon@Sun.COM /*
211754SKacheong.Poon@Sun.COM  * CDDL HEADER START
311754SKacheong.Poon@Sun.COM  *
411754SKacheong.Poon@Sun.COM  * The contents of this file are subject to the terms of the
511754SKacheong.Poon@Sun.COM  * Common Development and Distribution License (the "License").
611754SKacheong.Poon@Sun.COM  * You may not use this file except in compliance with the License.
711754SKacheong.Poon@Sun.COM  *
811754SKacheong.Poon@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911754SKacheong.Poon@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011754SKacheong.Poon@Sun.COM  * See the License for the specific language governing permissions
1111754SKacheong.Poon@Sun.COM  * and limitations under the License.
1211754SKacheong.Poon@Sun.COM  *
1311754SKacheong.Poon@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411754SKacheong.Poon@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511754SKacheong.Poon@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611754SKacheong.Poon@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711754SKacheong.Poon@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811754SKacheong.Poon@Sun.COM  *
1911754SKacheong.Poon@Sun.COM  * CDDL HEADER END
2011754SKacheong.Poon@Sun.COM  */
2111754SKacheong.Poon@Sun.COM 
2211754SKacheong.Poon@Sun.COM /*
2312869SKacheong.Poon@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2411754SKacheong.Poon@Sun.COM  */
2511754SKacheong.Poon@Sun.COM 
2611754SKacheong.Poon@Sun.COM #include <sys/types.h>
2711754SKacheong.Poon@Sun.COM #include <sys/tihdr.h>
2811754SKacheong.Poon@Sun.COM #include <sys/policy.h>
2911754SKacheong.Poon@Sun.COM #include <sys/tsol/tnet.h>
3011754SKacheong.Poon@Sun.COM 
3111754SKacheong.Poon@Sun.COM #include <inet/common.h>
3211754SKacheong.Poon@Sun.COM #include <inet/ip.h>
3311754SKacheong.Poon@Sun.COM #include <inet/tcp.h>
3411754SKacheong.Poon@Sun.COM #include <inet/tcp_impl.h>
3511754SKacheong.Poon@Sun.COM #include <inet/tcp_stats.h>
3611754SKacheong.Poon@Sun.COM #include <inet/kstatcom.h>
3711754SKacheong.Poon@Sun.COM #include <inet/snmpcom.h>
3811754SKacheong.Poon@Sun.COM 
3911754SKacheong.Poon@Sun.COM static int	tcp_kstat_update(kstat_t *kp, int rw);
4011754SKacheong.Poon@Sun.COM static int	tcp_kstat2_update(kstat_t *kp, int rw);
4111754SKacheong.Poon@Sun.COM static void	tcp_sum_mib(tcp_stack_t *, mib2_tcp_t *);
4211754SKacheong.Poon@Sun.COM 
4312869SKacheong.Poon@Sun.COM static void	tcp_add_mib(mib2_tcp_t *, mib2_tcp_t *);
4412869SKacheong.Poon@Sun.COM static void	tcp_add_stats(tcp_stat_counter_t *, tcp_stat_t *);
4511754SKacheong.Poon@Sun.COM static void	tcp_clr_stats(tcp_stat_t *);
4611754SKacheong.Poon@Sun.COM 
4711754SKacheong.Poon@Sun.COM tcp_g_stat_t	tcp_g_statistics;
4811754SKacheong.Poon@Sun.COM kstat_t		*tcp_g_kstat;
4911754SKacheong.Poon@Sun.COM 
5011754SKacheong.Poon@Sun.COM /* Translate TCP state to MIB2 TCP state. */
5111754SKacheong.Poon@Sun.COM static int
tcp_snmp_state(tcp_t * tcp)5211754SKacheong.Poon@Sun.COM tcp_snmp_state(tcp_t *tcp)
5311754SKacheong.Poon@Sun.COM {
5411754SKacheong.Poon@Sun.COM 	if (tcp == NULL)
5511754SKacheong.Poon@Sun.COM 		return (0);
5611754SKacheong.Poon@Sun.COM 
5711754SKacheong.Poon@Sun.COM 	switch (tcp->tcp_state) {
5811754SKacheong.Poon@Sun.COM 	case TCPS_CLOSED:
5911754SKacheong.Poon@Sun.COM 	case TCPS_IDLE:	/* RFC1213 doesn't have analogue for IDLE & BOUND */
6011754SKacheong.Poon@Sun.COM 	case TCPS_BOUND:
6111754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_closed);
6211754SKacheong.Poon@Sun.COM 	case TCPS_LISTEN:
6311754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_listen);
6411754SKacheong.Poon@Sun.COM 	case TCPS_SYN_SENT:
6511754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_synSent);
6611754SKacheong.Poon@Sun.COM 	case TCPS_SYN_RCVD:
6711754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_synReceived);
6811754SKacheong.Poon@Sun.COM 	case TCPS_ESTABLISHED:
6911754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_established);
7011754SKacheong.Poon@Sun.COM 	case TCPS_CLOSE_WAIT:
7111754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_closeWait);
7211754SKacheong.Poon@Sun.COM 	case TCPS_FIN_WAIT_1:
7311754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_finWait1);
7411754SKacheong.Poon@Sun.COM 	case TCPS_CLOSING:
7511754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_closing);
7611754SKacheong.Poon@Sun.COM 	case TCPS_LAST_ACK:
7711754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_lastAck);
7811754SKacheong.Poon@Sun.COM 	case TCPS_FIN_WAIT_2:
7911754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_finWait2);
8011754SKacheong.Poon@Sun.COM 	case TCPS_TIME_WAIT:
8111754SKacheong.Poon@Sun.COM 		return (MIB2_TCP_timeWait);
8211754SKacheong.Poon@Sun.COM 	default:
8311754SKacheong.Poon@Sun.COM 		return (0);
8411754SKacheong.Poon@Sun.COM 	}
8511754SKacheong.Poon@Sun.COM }
8611754SKacheong.Poon@Sun.COM 
8711754SKacheong.Poon@Sun.COM /*
8811754SKacheong.Poon@Sun.COM  * Return SNMP stuff in buffer in mpdata.
8911754SKacheong.Poon@Sun.COM  */
9011754SKacheong.Poon@Sun.COM mblk_t *
tcp_snmp_get(queue_t * q,mblk_t * mpctl,boolean_t legacy_req)91*12897SBaban.Kenkre@Sun.COM tcp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
9211754SKacheong.Poon@Sun.COM {
9311754SKacheong.Poon@Sun.COM 	mblk_t			*mpdata;
9411754SKacheong.Poon@Sun.COM 	mblk_t			*mp_conn_ctl = NULL;
9511754SKacheong.Poon@Sun.COM 	mblk_t			*mp_conn_tail;
9611754SKacheong.Poon@Sun.COM 	mblk_t			*mp_attr_ctl = NULL;
9711754SKacheong.Poon@Sun.COM 	mblk_t			*mp_attr_tail;
9811754SKacheong.Poon@Sun.COM 	mblk_t			*mp6_conn_ctl = NULL;
9911754SKacheong.Poon@Sun.COM 	mblk_t			*mp6_conn_tail;
10011754SKacheong.Poon@Sun.COM 	mblk_t			*mp6_attr_ctl = NULL;
10111754SKacheong.Poon@Sun.COM 	mblk_t			*mp6_attr_tail;
10211754SKacheong.Poon@Sun.COM 	struct opthdr		*optp;
10311754SKacheong.Poon@Sun.COM 	mib2_tcpConnEntry_t	tce;
10411754SKacheong.Poon@Sun.COM 	mib2_tcp6ConnEntry_t	tce6;
10511754SKacheong.Poon@Sun.COM 	mib2_transportMLPEntry_t mlp;
10611754SKacheong.Poon@Sun.COM 	connf_t			*connfp;
10711754SKacheong.Poon@Sun.COM 	int			i;
10811754SKacheong.Poon@Sun.COM 	boolean_t 		ispriv;
10911754SKacheong.Poon@Sun.COM 	zoneid_t 		zoneid;
11011754SKacheong.Poon@Sun.COM 	int			v4_conn_idx;
11111754SKacheong.Poon@Sun.COM 	int			v6_conn_idx;
11211754SKacheong.Poon@Sun.COM 	conn_t			*connp = Q_TO_CONN(q);
11311754SKacheong.Poon@Sun.COM 	tcp_stack_t		*tcps;
11411754SKacheong.Poon@Sun.COM 	ip_stack_t		*ipst;
11511754SKacheong.Poon@Sun.COM 	mblk_t			*mp2ctl;
11611754SKacheong.Poon@Sun.COM 	mib2_tcp_t		tcp_mib;
117*12897SBaban.Kenkre@Sun.COM 	size_t			tcp_mib_size, tce_size, tce6_size;
11811754SKacheong.Poon@Sun.COM 
11911754SKacheong.Poon@Sun.COM 	/*
12011754SKacheong.Poon@Sun.COM 	 * make a copy of the original message
12111754SKacheong.Poon@Sun.COM 	 */
12211754SKacheong.Poon@Sun.COM 	mp2ctl = copymsg(mpctl);
12311754SKacheong.Poon@Sun.COM 
12411754SKacheong.Poon@Sun.COM 	if (mpctl == NULL ||
12511754SKacheong.Poon@Sun.COM 	    (mpdata = mpctl->b_cont) == NULL ||
12611754SKacheong.Poon@Sun.COM 	    (mp_conn_ctl = copymsg(mpctl)) == NULL ||
12711754SKacheong.Poon@Sun.COM 	    (mp_attr_ctl = copymsg(mpctl)) == NULL ||
12811754SKacheong.Poon@Sun.COM 	    (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
12911754SKacheong.Poon@Sun.COM 	    (mp6_attr_ctl = copymsg(mpctl)) == NULL) {
13011754SKacheong.Poon@Sun.COM 		freemsg(mp_conn_ctl);
13111754SKacheong.Poon@Sun.COM 		freemsg(mp_attr_ctl);
13211754SKacheong.Poon@Sun.COM 		freemsg(mp6_conn_ctl);
13311754SKacheong.Poon@Sun.COM 		freemsg(mp6_attr_ctl);
13411754SKacheong.Poon@Sun.COM 		freemsg(mpctl);
13511754SKacheong.Poon@Sun.COM 		freemsg(mp2ctl);
13611754SKacheong.Poon@Sun.COM 		return (NULL);
13711754SKacheong.Poon@Sun.COM 	}
13811754SKacheong.Poon@Sun.COM 
13911754SKacheong.Poon@Sun.COM 	ipst = connp->conn_netstack->netstack_ip;
14011754SKacheong.Poon@Sun.COM 	tcps = connp->conn_netstack->netstack_tcp;
14111754SKacheong.Poon@Sun.COM 
142*12897SBaban.Kenkre@Sun.COM 	if (legacy_req) {
143*12897SBaban.Kenkre@Sun.COM 		tcp_mib_size = LEGACY_MIB_SIZE(&tcp_mib, mib2_tcp_t);
144*12897SBaban.Kenkre@Sun.COM 		tce_size = LEGACY_MIB_SIZE(&tce, mib2_tcpConnEntry_t);
145*12897SBaban.Kenkre@Sun.COM 		tce6_size = LEGACY_MIB_SIZE(&tce6, mib2_tcp6ConnEntry_t);
146*12897SBaban.Kenkre@Sun.COM 	} else {
147*12897SBaban.Kenkre@Sun.COM 		tcp_mib_size = sizeof (mib2_tcp_t);
148*12897SBaban.Kenkre@Sun.COM 		tce_size = sizeof (mib2_tcpConnEntry_t);
149*12897SBaban.Kenkre@Sun.COM 		tce6_size = sizeof (mib2_tcp6ConnEntry_t);
150*12897SBaban.Kenkre@Sun.COM 	}
151*12897SBaban.Kenkre@Sun.COM 
15211754SKacheong.Poon@Sun.COM 	bzero(&tcp_mib, sizeof (tcp_mib));
15311754SKacheong.Poon@Sun.COM 
15411754SKacheong.Poon@Sun.COM 	/* build table of connections -- need count in fixed part */
15511754SKacheong.Poon@Sun.COM 	SET_MIB(tcp_mib.tcpRtoAlgorithm, 4);   /* vanj */
15611754SKacheong.Poon@Sun.COM 	SET_MIB(tcp_mib.tcpRtoMin, tcps->tcps_rexmit_interval_min);
15711754SKacheong.Poon@Sun.COM 	SET_MIB(tcp_mib.tcpRtoMax, tcps->tcps_rexmit_interval_max);
15811754SKacheong.Poon@Sun.COM 	SET_MIB(tcp_mib.tcpMaxConn, -1);
15911754SKacheong.Poon@Sun.COM 	SET_MIB(tcp_mib.tcpCurrEstab, 0);
16011754SKacheong.Poon@Sun.COM 
16111754SKacheong.Poon@Sun.COM 	ispriv =
16211754SKacheong.Poon@Sun.COM 	    secpolicy_ip_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0;
16311754SKacheong.Poon@Sun.COM 	zoneid = Q_TO_CONN(q)->conn_zoneid;
16411754SKacheong.Poon@Sun.COM 
16511754SKacheong.Poon@Sun.COM 	v4_conn_idx = v6_conn_idx = 0;
16611754SKacheong.Poon@Sun.COM 	mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
16711754SKacheong.Poon@Sun.COM 
16811754SKacheong.Poon@Sun.COM 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
16911754SKacheong.Poon@Sun.COM 		ipst = tcps->tcps_netstack->netstack_ip;
17011754SKacheong.Poon@Sun.COM 
17111754SKacheong.Poon@Sun.COM 		connfp = &ipst->ips_ipcl_globalhash_fanout[i];
17211754SKacheong.Poon@Sun.COM 
17311754SKacheong.Poon@Sun.COM 		connp = NULL;
17411754SKacheong.Poon@Sun.COM 
17511754SKacheong.Poon@Sun.COM 		while ((connp =
17611754SKacheong.Poon@Sun.COM 		    ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
17711754SKacheong.Poon@Sun.COM 			tcp_t *tcp;
17811754SKacheong.Poon@Sun.COM 			boolean_t needattr;
17911754SKacheong.Poon@Sun.COM 
18011754SKacheong.Poon@Sun.COM 			if (connp->conn_zoneid != zoneid)
18111754SKacheong.Poon@Sun.COM 				continue;	/* not in this zone */
18211754SKacheong.Poon@Sun.COM 
18311754SKacheong.Poon@Sun.COM 			tcp = connp->conn_tcp;
18411754SKacheong.Poon@Sun.COM 			TCPS_UPDATE_MIB(tcps, tcpHCInSegs, tcp->tcp_ibsegs);
18511754SKacheong.Poon@Sun.COM 			tcp->tcp_ibsegs = 0;
18611754SKacheong.Poon@Sun.COM 			TCPS_UPDATE_MIB(tcps, tcpHCOutSegs, tcp->tcp_obsegs);
18711754SKacheong.Poon@Sun.COM 			tcp->tcp_obsegs = 0;
18811754SKacheong.Poon@Sun.COM 
18911754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnState = tce.tcpConnState =
19011754SKacheong.Poon@Sun.COM 			    tcp_snmp_state(tcp);
19111754SKacheong.Poon@Sun.COM 			if (tce.tcpConnState == MIB2_TCP_established ||
19211754SKacheong.Poon@Sun.COM 			    tce.tcpConnState == MIB2_TCP_closeWait)
19311772SKacheong.Poon@Sun.COM 				BUMP_MIB(&tcp_mib, tcpCurrEstab);
19411754SKacheong.Poon@Sun.COM 
19511754SKacheong.Poon@Sun.COM 			needattr = B_FALSE;
19611754SKacheong.Poon@Sun.COM 			bzero(&mlp, sizeof (mlp));
19711754SKacheong.Poon@Sun.COM 			if (connp->conn_mlp_type != mlptSingle) {
19811754SKacheong.Poon@Sun.COM 				if (connp->conn_mlp_type == mlptShared ||
19911754SKacheong.Poon@Sun.COM 				    connp->conn_mlp_type == mlptBoth)
20011754SKacheong.Poon@Sun.COM 					mlp.tme_flags |= MIB2_TMEF_SHARED;
20111754SKacheong.Poon@Sun.COM 				if (connp->conn_mlp_type == mlptPrivate ||
20211754SKacheong.Poon@Sun.COM 				    connp->conn_mlp_type == mlptBoth)
20311754SKacheong.Poon@Sun.COM 					mlp.tme_flags |= MIB2_TMEF_PRIVATE;
20411754SKacheong.Poon@Sun.COM 				needattr = B_TRUE;
20511754SKacheong.Poon@Sun.COM 			}
20611754SKacheong.Poon@Sun.COM 			if (connp->conn_anon_mlp) {
20711754SKacheong.Poon@Sun.COM 				mlp.tme_flags |= MIB2_TMEF_ANONMLP;
20811754SKacheong.Poon@Sun.COM 				needattr = B_TRUE;
20911754SKacheong.Poon@Sun.COM 			}
21011754SKacheong.Poon@Sun.COM 			switch (connp->conn_mac_mode) {
21111754SKacheong.Poon@Sun.COM 			case CONN_MAC_DEFAULT:
21211754SKacheong.Poon@Sun.COM 				break;
21311754SKacheong.Poon@Sun.COM 			case CONN_MAC_AWARE:
21411754SKacheong.Poon@Sun.COM 				mlp.tme_flags |= MIB2_TMEF_MACEXEMPT;
21511754SKacheong.Poon@Sun.COM 				needattr = B_TRUE;
21611754SKacheong.Poon@Sun.COM 				break;
21711754SKacheong.Poon@Sun.COM 			case CONN_MAC_IMPLICIT:
21811754SKacheong.Poon@Sun.COM 				mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT;
21911754SKacheong.Poon@Sun.COM 				needattr = B_TRUE;
22011754SKacheong.Poon@Sun.COM 				break;
22111754SKacheong.Poon@Sun.COM 			}
22211754SKacheong.Poon@Sun.COM 			if (connp->conn_ixa->ixa_tsl != NULL) {
22311754SKacheong.Poon@Sun.COM 				ts_label_t *tsl;
22411754SKacheong.Poon@Sun.COM 
22511754SKacheong.Poon@Sun.COM 				tsl = connp->conn_ixa->ixa_tsl;
22611754SKacheong.Poon@Sun.COM 				mlp.tme_flags |= MIB2_TMEF_IS_LABELED;
22711754SKacheong.Poon@Sun.COM 				mlp.tme_doi = label2doi(tsl);
22811754SKacheong.Poon@Sun.COM 				mlp.tme_label = *label2bslabel(tsl);
22911754SKacheong.Poon@Sun.COM 				needattr = B_TRUE;
23011754SKacheong.Poon@Sun.COM 			}
23111754SKacheong.Poon@Sun.COM 
23211754SKacheong.Poon@Sun.COM 			/* Create a message to report on IPv6 entries */
23311754SKacheong.Poon@Sun.COM 			if (connp->conn_ipversion == IPV6_VERSION) {
23411754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnLocalAddress = connp->conn_laddr_v6;
23511754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnRemAddress = connp->conn_faddr_v6;
23611754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnLocalPort = ntohs(connp->conn_lport);
23711754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnRemPort = ntohs(connp->conn_fport);
23811754SKacheong.Poon@Sun.COM 			if (connp->conn_ixa->ixa_flags & IXAF_SCOPEID_SET) {
23911754SKacheong.Poon@Sun.COM 				tce6.tcp6ConnIfIndex =
24011754SKacheong.Poon@Sun.COM 				    connp->conn_ixa->ixa_scopeid;
24111754SKacheong.Poon@Sun.COM 			} else {
24211754SKacheong.Poon@Sun.COM 				tce6.tcp6ConnIfIndex = connp->conn_bound_if;
24311754SKacheong.Poon@Sun.COM 			}
24411754SKacheong.Poon@Sun.COM 			/* Don't want just anybody seeing these... */
24511754SKacheong.Poon@Sun.COM 			if (ispriv) {
24611754SKacheong.Poon@Sun.COM 				tce6.tcp6ConnEntryInfo.ce_snxt =
24711754SKacheong.Poon@Sun.COM 				    tcp->tcp_snxt;
24811754SKacheong.Poon@Sun.COM 				tce6.tcp6ConnEntryInfo.ce_suna =
24911754SKacheong.Poon@Sun.COM 				    tcp->tcp_suna;
25011754SKacheong.Poon@Sun.COM 				tce6.tcp6ConnEntryInfo.ce_rnxt =
25111754SKacheong.Poon@Sun.COM 				    tcp->tcp_rnxt;
25211754SKacheong.Poon@Sun.COM 				tce6.tcp6ConnEntryInfo.ce_rack =
25311754SKacheong.Poon@Sun.COM 				    tcp->tcp_rack;
25411754SKacheong.Poon@Sun.COM 			} else {
25511754SKacheong.Poon@Sun.COM 				/*
25611754SKacheong.Poon@Sun.COM 				 * Netstat, unfortunately, uses this to
25711754SKacheong.Poon@Sun.COM 				 * get send/receive queue sizes.  How to fix?
25811754SKacheong.Poon@Sun.COM 				 * Why not compute the difference only?
25911754SKacheong.Poon@Sun.COM 				 */
26011754SKacheong.Poon@Sun.COM 				tce6.tcp6ConnEntryInfo.ce_snxt =
26111754SKacheong.Poon@Sun.COM 				    tcp->tcp_snxt - tcp->tcp_suna;
26211754SKacheong.Poon@Sun.COM 				tce6.tcp6ConnEntryInfo.ce_suna = 0;
26311754SKacheong.Poon@Sun.COM 				tce6.tcp6ConnEntryInfo.ce_rnxt =
26411754SKacheong.Poon@Sun.COM 				    tcp->tcp_rnxt - tcp->tcp_rack;
26511754SKacheong.Poon@Sun.COM 				tce6.tcp6ConnEntryInfo.ce_rack = 0;
26611754SKacheong.Poon@Sun.COM 			}
26711754SKacheong.Poon@Sun.COM 
26811754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnEntryInfo.ce_swnd = tcp->tcp_swnd;
26911754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
27011754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnEntryInfo.ce_rto =  tcp->tcp_rto;
27111754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnEntryInfo.ce_mss =  tcp->tcp_mss;
27211754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state;
27311754SKacheong.Poon@Sun.COM 
27411754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnCreationProcess =
27511754SKacheong.Poon@Sun.COM 			    (connp->conn_cpid < 0) ? MIB2_UNKNOWN_PROCESS :
27611754SKacheong.Poon@Sun.COM 			    connp->conn_cpid;
27711754SKacheong.Poon@Sun.COM 			tce6.tcp6ConnCreationTime = connp->conn_open_time;
27811754SKacheong.Poon@Sun.COM 
27911754SKacheong.Poon@Sun.COM 			(void) snmp_append_data2(mp6_conn_ctl->b_cont,
280*12897SBaban.Kenkre@Sun.COM 			    &mp6_conn_tail, (char *)&tce6, tce6_size);
28111754SKacheong.Poon@Sun.COM 
28211754SKacheong.Poon@Sun.COM 			mlp.tme_connidx = v6_conn_idx++;
28311754SKacheong.Poon@Sun.COM 			if (needattr)
28411754SKacheong.Poon@Sun.COM 				(void) snmp_append_data2(mp6_attr_ctl->b_cont,
28511754SKacheong.Poon@Sun.COM 				    &mp6_attr_tail, (char *)&mlp, sizeof (mlp));
28611754SKacheong.Poon@Sun.COM 			}
28711754SKacheong.Poon@Sun.COM 			/*
28811754SKacheong.Poon@Sun.COM 			 * Create an IPv4 table entry for IPv4 entries and also
28911754SKacheong.Poon@Sun.COM 			 * for IPv6 entries which are bound to in6addr_any
29011754SKacheong.Poon@Sun.COM 			 * but don't have IPV6_V6ONLY set.
29111754SKacheong.Poon@Sun.COM 			 * (i.e. anything an IPv4 peer could connect to)
29211754SKacheong.Poon@Sun.COM 			 */
29311754SKacheong.Poon@Sun.COM 			if (connp->conn_ipversion == IPV4_VERSION ||
29411754SKacheong.Poon@Sun.COM 			    (tcp->tcp_state <= TCPS_LISTEN &&
29511754SKacheong.Poon@Sun.COM 			    !connp->conn_ipv6_v6only &&
29611754SKacheong.Poon@Sun.COM 			    IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) {
29711754SKacheong.Poon@Sun.COM 				if (connp->conn_ipversion == IPV6_VERSION) {
29811754SKacheong.Poon@Sun.COM 					tce.tcpConnRemAddress = INADDR_ANY;
29911754SKacheong.Poon@Sun.COM 					tce.tcpConnLocalAddress = INADDR_ANY;
30011754SKacheong.Poon@Sun.COM 				} else {
30111754SKacheong.Poon@Sun.COM 					tce.tcpConnRemAddress =
30211754SKacheong.Poon@Sun.COM 					    connp->conn_faddr_v4;
30311754SKacheong.Poon@Sun.COM 					tce.tcpConnLocalAddress =
30411754SKacheong.Poon@Sun.COM 					    connp->conn_laddr_v4;
30511754SKacheong.Poon@Sun.COM 				}
30611754SKacheong.Poon@Sun.COM 				tce.tcpConnLocalPort = ntohs(connp->conn_lport);
30711754SKacheong.Poon@Sun.COM 				tce.tcpConnRemPort = ntohs(connp->conn_fport);
30811754SKacheong.Poon@Sun.COM 				/* Don't want just anybody seeing these... */
30911754SKacheong.Poon@Sun.COM 				if (ispriv) {
31011754SKacheong.Poon@Sun.COM 					tce.tcpConnEntryInfo.ce_snxt =
31111754SKacheong.Poon@Sun.COM 					    tcp->tcp_snxt;
31211754SKacheong.Poon@Sun.COM 					tce.tcpConnEntryInfo.ce_suna =
31311754SKacheong.Poon@Sun.COM 					    tcp->tcp_suna;
31411754SKacheong.Poon@Sun.COM 					tce.tcpConnEntryInfo.ce_rnxt =
31511754SKacheong.Poon@Sun.COM 					    tcp->tcp_rnxt;
31611754SKacheong.Poon@Sun.COM 					tce.tcpConnEntryInfo.ce_rack =
31711754SKacheong.Poon@Sun.COM 					    tcp->tcp_rack;
31811754SKacheong.Poon@Sun.COM 				} else {
31911754SKacheong.Poon@Sun.COM 					/*
32011754SKacheong.Poon@Sun.COM 					 * Netstat, unfortunately, uses this to
32111754SKacheong.Poon@Sun.COM 					 * get send/receive queue sizes.  How
32211754SKacheong.Poon@Sun.COM 					 * to fix?
32311754SKacheong.Poon@Sun.COM 					 * Why not compute the difference only?
32411754SKacheong.Poon@Sun.COM 					 */
32511754SKacheong.Poon@Sun.COM 					tce.tcpConnEntryInfo.ce_snxt =
32611754SKacheong.Poon@Sun.COM 					    tcp->tcp_snxt - tcp->tcp_suna;
32711754SKacheong.Poon@Sun.COM 					tce.tcpConnEntryInfo.ce_suna = 0;
32811754SKacheong.Poon@Sun.COM 					tce.tcpConnEntryInfo.ce_rnxt =
32911754SKacheong.Poon@Sun.COM 					    tcp->tcp_rnxt - tcp->tcp_rack;
33011754SKacheong.Poon@Sun.COM 					tce.tcpConnEntryInfo.ce_rack = 0;
33111754SKacheong.Poon@Sun.COM 				}
33211754SKacheong.Poon@Sun.COM 
33311754SKacheong.Poon@Sun.COM 				tce.tcpConnEntryInfo.ce_swnd = tcp->tcp_swnd;
33411754SKacheong.Poon@Sun.COM 				tce.tcpConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
33511754SKacheong.Poon@Sun.COM 				tce.tcpConnEntryInfo.ce_rto =  tcp->tcp_rto;
33611754SKacheong.Poon@Sun.COM 				tce.tcpConnEntryInfo.ce_mss =  tcp->tcp_mss;
33711754SKacheong.Poon@Sun.COM 				tce.tcpConnEntryInfo.ce_state =
33811754SKacheong.Poon@Sun.COM 				    tcp->tcp_state;
33911754SKacheong.Poon@Sun.COM 
34011754SKacheong.Poon@Sun.COM 				tce.tcpConnCreationProcess =
34111754SKacheong.Poon@Sun.COM 				    (connp->conn_cpid < 0) ?
34211754SKacheong.Poon@Sun.COM 				    MIB2_UNKNOWN_PROCESS :
34311754SKacheong.Poon@Sun.COM 				    connp->conn_cpid;
34411754SKacheong.Poon@Sun.COM 				tce.tcpConnCreationTime = connp->conn_open_time;
34511754SKacheong.Poon@Sun.COM 
34611754SKacheong.Poon@Sun.COM 				(void) snmp_append_data2(mp_conn_ctl->b_cont,
347*12897SBaban.Kenkre@Sun.COM 				    &mp_conn_tail, (char *)&tce, tce_size);
34811754SKacheong.Poon@Sun.COM 
34911754SKacheong.Poon@Sun.COM 				mlp.tme_connidx = v4_conn_idx++;
35011754SKacheong.Poon@Sun.COM 				if (needattr)
35111754SKacheong.Poon@Sun.COM 					(void) snmp_append_data2(
35211754SKacheong.Poon@Sun.COM 					    mp_attr_ctl->b_cont,
35311754SKacheong.Poon@Sun.COM 					    &mp_attr_tail, (char *)&mlp,
35411754SKacheong.Poon@Sun.COM 					    sizeof (mlp));
35511754SKacheong.Poon@Sun.COM 			}
35611754SKacheong.Poon@Sun.COM 		}
35711754SKacheong.Poon@Sun.COM 	}
35811754SKacheong.Poon@Sun.COM 
35911772SKacheong.Poon@Sun.COM 	tcp_sum_mib(tcps, &tcp_mib);
36011754SKacheong.Poon@Sun.COM 
361*12897SBaban.Kenkre@Sun.COM 	/* Fixed length structure for IPv4 and IPv6 counters */
362*12897SBaban.Kenkre@Sun.COM 	SET_MIB(tcp_mib.tcpConnTableSize, tce_size);
363*12897SBaban.Kenkre@Sun.COM 	SET_MIB(tcp_mib.tcp6ConnTableSize, tce6_size);
364*12897SBaban.Kenkre@Sun.COM 
36511772SKacheong.Poon@Sun.COM 	/*
36611772SKacheong.Poon@Sun.COM 	 * Synchronize 32- and 64-bit counters.  Note that tcpInSegs and
36711772SKacheong.Poon@Sun.COM 	 * tcpOutSegs are not updated anywhere in TCP.  The new 64 bits
36811772SKacheong.Poon@Sun.COM 	 * counters are used.  Hence the old counters' values in tcp_sc_mib
36911772SKacheong.Poon@Sun.COM 	 * are always 0.
37011772SKacheong.Poon@Sun.COM 	 */
37111754SKacheong.Poon@Sun.COM 	SYNC32_MIB(&tcp_mib, tcpInSegs, tcpHCInSegs);
37211754SKacheong.Poon@Sun.COM 	SYNC32_MIB(&tcp_mib, tcpOutSegs, tcpHCOutSegs);
37311754SKacheong.Poon@Sun.COM 
37411754SKacheong.Poon@Sun.COM 	optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
37511754SKacheong.Poon@Sun.COM 	optp->level = MIB2_TCP;
37611754SKacheong.Poon@Sun.COM 	optp->name = 0;
377*12897SBaban.Kenkre@Sun.COM 	(void) snmp_append_data(mpdata, (char *)&tcp_mib, tcp_mib_size);
37811754SKacheong.Poon@Sun.COM 	optp->len = msgdsize(mpdata);
37911754SKacheong.Poon@Sun.COM 	qreply(q, mpctl);
38011754SKacheong.Poon@Sun.COM 
38111754SKacheong.Poon@Sun.COM 	/* table of connections... */
38211754SKacheong.Poon@Sun.COM 	optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
38311754SKacheong.Poon@Sun.COM 	    sizeof (struct T_optmgmt_ack)];
38411754SKacheong.Poon@Sun.COM 	optp->level = MIB2_TCP;
38511754SKacheong.Poon@Sun.COM 	optp->name = MIB2_TCP_CONN;
38611754SKacheong.Poon@Sun.COM 	optp->len = msgdsize(mp_conn_ctl->b_cont);
38711754SKacheong.Poon@Sun.COM 	qreply(q, mp_conn_ctl);
38811754SKacheong.Poon@Sun.COM 
38911754SKacheong.Poon@Sun.COM 	/* table of MLP attributes... */
39011754SKacheong.Poon@Sun.COM 	optp = (struct opthdr *)&mp_attr_ctl->b_rptr[
39111754SKacheong.Poon@Sun.COM 	    sizeof (struct T_optmgmt_ack)];
39211754SKacheong.Poon@Sun.COM 	optp->level = MIB2_TCP;
39311754SKacheong.Poon@Sun.COM 	optp->name = EXPER_XPORT_MLP;
39411754SKacheong.Poon@Sun.COM 	optp->len = msgdsize(mp_attr_ctl->b_cont);
39511754SKacheong.Poon@Sun.COM 	if (optp->len == 0)
39611754SKacheong.Poon@Sun.COM 		freemsg(mp_attr_ctl);
39711754SKacheong.Poon@Sun.COM 	else
39811754SKacheong.Poon@Sun.COM 		qreply(q, mp_attr_ctl);
39911754SKacheong.Poon@Sun.COM 
40011754SKacheong.Poon@Sun.COM 	/* table of IPv6 connections... */
40111754SKacheong.Poon@Sun.COM 	optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
40211754SKacheong.Poon@Sun.COM 	    sizeof (struct T_optmgmt_ack)];
40311754SKacheong.Poon@Sun.COM 	optp->level = MIB2_TCP6;
40411754SKacheong.Poon@Sun.COM 	optp->name = MIB2_TCP6_CONN;
40511754SKacheong.Poon@Sun.COM 	optp->len = msgdsize(mp6_conn_ctl->b_cont);
40611754SKacheong.Poon@Sun.COM 	qreply(q, mp6_conn_ctl);
40711754SKacheong.Poon@Sun.COM 
40811754SKacheong.Poon@Sun.COM 	/* table of IPv6 MLP attributes... */
40911754SKacheong.Poon@Sun.COM 	optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[
41011754SKacheong.Poon@Sun.COM 	    sizeof (struct T_optmgmt_ack)];
41111754SKacheong.Poon@Sun.COM 	optp->level = MIB2_TCP6;
41211754SKacheong.Poon@Sun.COM 	optp->name = EXPER_XPORT_MLP;
41311754SKacheong.Poon@Sun.COM 	optp->len = msgdsize(mp6_attr_ctl->b_cont);
41411754SKacheong.Poon@Sun.COM 	if (optp->len == 0)
41511754SKacheong.Poon@Sun.COM 		freemsg(mp6_attr_ctl);
41611754SKacheong.Poon@Sun.COM 	else
41711754SKacheong.Poon@Sun.COM 		qreply(q, mp6_attr_ctl);
41811754SKacheong.Poon@Sun.COM 	return (mp2ctl);
41911754SKacheong.Poon@Sun.COM }
42011754SKacheong.Poon@Sun.COM 
42111754SKacheong.Poon@Sun.COM /* Return 0 if invalid set request, 1 otherwise, including non-tcp requests  */
42211754SKacheong.Poon@Sun.COM /* ARGSUSED */
42311754SKacheong.Poon@Sun.COM int
tcp_snmp_set(queue_t * q,int level,int name,uchar_t * ptr,int len)42411754SKacheong.Poon@Sun.COM tcp_snmp_set(queue_t *q, int level, int name, uchar_t *ptr, int len)
42511754SKacheong.Poon@Sun.COM {
42611754SKacheong.Poon@Sun.COM 	mib2_tcpConnEntry_t	*tce = (mib2_tcpConnEntry_t *)ptr;
42711754SKacheong.Poon@Sun.COM 
42811754SKacheong.Poon@Sun.COM 	switch (level) {
42911754SKacheong.Poon@Sun.COM 	case MIB2_TCP:
43011754SKacheong.Poon@Sun.COM 		switch (name) {
43111754SKacheong.Poon@Sun.COM 		case 13:
43211754SKacheong.Poon@Sun.COM 			if (tce->tcpConnState != MIB2_TCP_deleteTCB)
43311754SKacheong.Poon@Sun.COM 				return (0);
43411754SKacheong.Poon@Sun.COM 			/* TODO: delete entry defined by tce */
43511754SKacheong.Poon@Sun.COM 			return (1);
43611754SKacheong.Poon@Sun.COM 		default:
43711754SKacheong.Poon@Sun.COM 			return (0);
43811754SKacheong.Poon@Sun.COM 		}
43911754SKacheong.Poon@Sun.COM 	default:
44011754SKacheong.Poon@Sun.COM 		return (1);
44111754SKacheong.Poon@Sun.COM 	}
44211754SKacheong.Poon@Sun.COM }
44311754SKacheong.Poon@Sun.COM 
44411754SKacheong.Poon@Sun.COM /*
44511754SKacheong.Poon@Sun.COM  * TCP Kstats implementation
44611754SKacheong.Poon@Sun.COM  */
44711754SKacheong.Poon@Sun.COM void *
tcp_kstat_init(netstackid_t stackid)44811754SKacheong.Poon@Sun.COM tcp_kstat_init(netstackid_t stackid)
44911754SKacheong.Poon@Sun.COM {
45011754SKacheong.Poon@Sun.COM 	kstat_t	*ksp;
45111754SKacheong.Poon@Sun.COM 
45211754SKacheong.Poon@Sun.COM 	tcp_named_kstat_t template = {
45311754SKacheong.Poon@Sun.COM 		{ "rtoAlgorithm",	KSTAT_DATA_INT32, 0 },
45411754SKacheong.Poon@Sun.COM 		{ "rtoMin",		KSTAT_DATA_INT32, 0 },
45511754SKacheong.Poon@Sun.COM 		{ "rtoMax",		KSTAT_DATA_INT32, 0 },
45611754SKacheong.Poon@Sun.COM 		{ "maxConn",		KSTAT_DATA_INT32, 0 },
45711754SKacheong.Poon@Sun.COM 		{ "activeOpens",	KSTAT_DATA_UINT32, 0 },
45811754SKacheong.Poon@Sun.COM 		{ "passiveOpens",	KSTAT_DATA_UINT32, 0 },
45911754SKacheong.Poon@Sun.COM 		{ "attemptFails",	KSTAT_DATA_UINT32, 0 },
46011754SKacheong.Poon@Sun.COM 		{ "estabResets",	KSTAT_DATA_UINT32, 0 },
46111754SKacheong.Poon@Sun.COM 		{ "currEstab",		KSTAT_DATA_UINT32, 0 },
46211754SKacheong.Poon@Sun.COM 		{ "inSegs",		KSTAT_DATA_UINT64, 0 },
46311754SKacheong.Poon@Sun.COM 		{ "outSegs",		KSTAT_DATA_UINT64, 0 },
46411754SKacheong.Poon@Sun.COM 		{ "retransSegs",	KSTAT_DATA_UINT32, 0 },
46511754SKacheong.Poon@Sun.COM 		{ "connTableSize",	KSTAT_DATA_INT32, 0 },
46611754SKacheong.Poon@Sun.COM 		{ "outRsts",		KSTAT_DATA_UINT32, 0 },
46711754SKacheong.Poon@Sun.COM 		{ "outDataSegs",	KSTAT_DATA_UINT32, 0 },
46811754SKacheong.Poon@Sun.COM 		{ "outDataBytes",	KSTAT_DATA_UINT32, 0 },
46911754SKacheong.Poon@Sun.COM 		{ "retransBytes",	KSTAT_DATA_UINT32, 0 },
47011754SKacheong.Poon@Sun.COM 		{ "outAck",		KSTAT_DATA_UINT32, 0 },
47111754SKacheong.Poon@Sun.COM 		{ "outAckDelayed",	KSTAT_DATA_UINT32, 0 },
47211754SKacheong.Poon@Sun.COM 		{ "outUrg",		KSTAT_DATA_UINT32, 0 },
47311754SKacheong.Poon@Sun.COM 		{ "outWinUpdate",	KSTAT_DATA_UINT32, 0 },
47411754SKacheong.Poon@Sun.COM 		{ "outWinProbe",	KSTAT_DATA_UINT32, 0 },
47511754SKacheong.Poon@Sun.COM 		{ "outControl",		KSTAT_DATA_UINT32, 0 },
47611754SKacheong.Poon@Sun.COM 		{ "outFastRetrans",	KSTAT_DATA_UINT32, 0 },
47711754SKacheong.Poon@Sun.COM 		{ "inAckSegs",		KSTAT_DATA_UINT32, 0 },
47811754SKacheong.Poon@Sun.COM 		{ "inAckBytes",		KSTAT_DATA_UINT32, 0 },
47911754SKacheong.Poon@Sun.COM 		{ "inDupAck",		KSTAT_DATA_UINT32, 0 },
48011754SKacheong.Poon@Sun.COM 		{ "inAckUnsent",	KSTAT_DATA_UINT32, 0 },
48111754SKacheong.Poon@Sun.COM 		{ "inDataInorderSegs",	KSTAT_DATA_UINT32, 0 },
48211754SKacheong.Poon@Sun.COM 		{ "inDataInorderBytes",	KSTAT_DATA_UINT32, 0 },
48311754SKacheong.Poon@Sun.COM 		{ "inDataUnorderSegs",	KSTAT_DATA_UINT32, 0 },
48411754SKacheong.Poon@Sun.COM 		{ "inDataUnorderBytes",	KSTAT_DATA_UINT32, 0 },
48511754SKacheong.Poon@Sun.COM 		{ "inDataDupSegs",	KSTAT_DATA_UINT32, 0 },
48611754SKacheong.Poon@Sun.COM 		{ "inDataDupBytes",	KSTAT_DATA_UINT32, 0 },
48711754SKacheong.Poon@Sun.COM 		{ "inDataPartDupSegs",	KSTAT_DATA_UINT32, 0 },
48811754SKacheong.Poon@Sun.COM 		{ "inDataPartDupBytes",	KSTAT_DATA_UINT32, 0 },
48911754SKacheong.Poon@Sun.COM 		{ "inDataPastWinSegs",	KSTAT_DATA_UINT32, 0 },
49011754SKacheong.Poon@Sun.COM 		{ "inDataPastWinBytes",	KSTAT_DATA_UINT32, 0 },
49111754SKacheong.Poon@Sun.COM 		{ "inWinProbe",		KSTAT_DATA_UINT32, 0 },
49211754SKacheong.Poon@Sun.COM 		{ "inWinUpdate",	KSTAT_DATA_UINT32, 0 },
49311754SKacheong.Poon@Sun.COM 		{ "inClosed",		KSTAT_DATA_UINT32, 0 },
49411754SKacheong.Poon@Sun.COM 		{ "rttUpdate",		KSTAT_DATA_UINT32, 0 },
49511754SKacheong.Poon@Sun.COM 		{ "rttNoUpdate",	KSTAT_DATA_UINT32, 0 },
49611754SKacheong.Poon@Sun.COM 		{ "timRetrans",		KSTAT_DATA_UINT32, 0 },
49711754SKacheong.Poon@Sun.COM 		{ "timRetransDrop",	KSTAT_DATA_UINT32, 0 },
49811754SKacheong.Poon@Sun.COM 		{ "timKeepalive",	KSTAT_DATA_UINT32, 0 },
49911754SKacheong.Poon@Sun.COM 		{ "timKeepaliveProbe",	KSTAT_DATA_UINT32, 0 },
50011754SKacheong.Poon@Sun.COM 		{ "timKeepaliveDrop",	KSTAT_DATA_UINT32, 0 },
50111754SKacheong.Poon@Sun.COM 		{ "listenDrop",		KSTAT_DATA_UINT32, 0 },
50211754SKacheong.Poon@Sun.COM 		{ "listenDropQ0",	KSTAT_DATA_UINT32, 0 },
50311754SKacheong.Poon@Sun.COM 		{ "halfOpenDrop",	KSTAT_DATA_UINT32, 0 },
50411754SKacheong.Poon@Sun.COM 		{ "outSackRetransSegs",	KSTAT_DATA_UINT32, 0 },
50511754SKacheong.Poon@Sun.COM 		{ "connTableSize6",	KSTAT_DATA_INT32, 0 }
50611754SKacheong.Poon@Sun.COM 	};
50711754SKacheong.Poon@Sun.COM 
50811754SKacheong.Poon@Sun.COM 	ksp = kstat_create_netstack(TCP_MOD_NAME, 0, TCP_MOD_NAME, "mib2",
50911754SKacheong.Poon@Sun.COM 	    KSTAT_TYPE_NAMED, NUM_OF_FIELDS(tcp_named_kstat_t), 0, stackid);
51011754SKacheong.Poon@Sun.COM 
51111754SKacheong.Poon@Sun.COM 	if (ksp == NULL)
51211754SKacheong.Poon@Sun.COM 		return (NULL);
51311754SKacheong.Poon@Sun.COM 
51411754SKacheong.Poon@Sun.COM 	template.rtoAlgorithm.value.ui32 = 4;
51511754SKacheong.Poon@Sun.COM 	template.maxConn.value.i32 = -1;
51611754SKacheong.Poon@Sun.COM 
51711754SKacheong.Poon@Sun.COM 	bcopy(&template, ksp->ks_data, sizeof (template));
51811754SKacheong.Poon@Sun.COM 	ksp->ks_update = tcp_kstat_update;
51911754SKacheong.Poon@Sun.COM 	ksp->ks_private = (void *)(uintptr_t)stackid;
52011754SKacheong.Poon@Sun.COM 
52111754SKacheong.Poon@Sun.COM 	kstat_install(ksp);
52211754SKacheong.Poon@Sun.COM 	return (ksp);
52311754SKacheong.Poon@Sun.COM }
52411754SKacheong.Poon@Sun.COM 
52511754SKacheong.Poon@Sun.COM void
tcp_kstat_fini(netstackid_t stackid,kstat_t * ksp)52611754SKacheong.Poon@Sun.COM tcp_kstat_fini(netstackid_t stackid, kstat_t *ksp)
52711754SKacheong.Poon@Sun.COM {
52811754SKacheong.Poon@Sun.COM 	if (ksp != NULL) {
52911754SKacheong.Poon@Sun.COM 		ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
53011754SKacheong.Poon@Sun.COM 		kstat_delete_netstack(ksp, stackid);
53111754SKacheong.Poon@Sun.COM 	}
53211754SKacheong.Poon@Sun.COM }
53311754SKacheong.Poon@Sun.COM 
53411754SKacheong.Poon@Sun.COM static int
tcp_kstat_update(kstat_t * kp,int rw)53511754SKacheong.Poon@Sun.COM tcp_kstat_update(kstat_t *kp, int rw)
53611754SKacheong.Poon@Sun.COM {
53711754SKacheong.Poon@Sun.COM 	tcp_named_kstat_t *tcpkp;
53811754SKacheong.Poon@Sun.COM 	tcp_t		*tcp;
53911754SKacheong.Poon@Sun.COM 	connf_t		*connfp;
54011754SKacheong.Poon@Sun.COM 	conn_t		*connp;
54111754SKacheong.Poon@Sun.COM 	int 		i;
54211754SKacheong.Poon@Sun.COM 	netstackid_t	stackid = (netstackid_t)(uintptr_t)kp->ks_private;
54311754SKacheong.Poon@Sun.COM 	netstack_t	*ns;
54411754SKacheong.Poon@Sun.COM 	tcp_stack_t	*tcps;
54511754SKacheong.Poon@Sun.COM 	ip_stack_t	*ipst;
54611754SKacheong.Poon@Sun.COM 	mib2_tcp_t	tcp_mib;
54711754SKacheong.Poon@Sun.COM 
54811754SKacheong.Poon@Sun.COM 	if (rw == KSTAT_WRITE)
54911754SKacheong.Poon@Sun.COM 		return (EACCES);
55011754SKacheong.Poon@Sun.COM 
55111754SKacheong.Poon@Sun.COM 	ns = netstack_find_by_stackid(stackid);
55211754SKacheong.Poon@Sun.COM 	if (ns == NULL)
55311754SKacheong.Poon@Sun.COM 		return (-1);
55411754SKacheong.Poon@Sun.COM 	tcps = ns->netstack_tcp;
55511754SKacheong.Poon@Sun.COM 	if (tcps == NULL) {
55611754SKacheong.Poon@Sun.COM 		netstack_rele(ns);
55711754SKacheong.Poon@Sun.COM 		return (-1);
55811754SKacheong.Poon@Sun.COM 	}
55911754SKacheong.Poon@Sun.COM 
56011754SKacheong.Poon@Sun.COM 	tcpkp = (tcp_named_kstat_t *)kp->ks_data;
56111754SKacheong.Poon@Sun.COM 
56211754SKacheong.Poon@Sun.COM 	tcpkp->currEstab.value.ui32 = 0;
56311754SKacheong.Poon@Sun.COM 	tcpkp->rtoMin.value.ui32 = tcps->tcps_rexmit_interval_min;
56411754SKacheong.Poon@Sun.COM 	tcpkp->rtoMax.value.ui32 = tcps->tcps_rexmit_interval_max;
56511754SKacheong.Poon@Sun.COM 
56611754SKacheong.Poon@Sun.COM 	ipst = ns->netstack_ip;
56711754SKacheong.Poon@Sun.COM 
56811754SKacheong.Poon@Sun.COM 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
56911754SKacheong.Poon@Sun.COM 		connfp = &ipst->ips_ipcl_globalhash_fanout[i];
57011754SKacheong.Poon@Sun.COM 		connp = NULL;
57111754SKacheong.Poon@Sun.COM 		while ((connp =
57211754SKacheong.Poon@Sun.COM 		    ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
57311754SKacheong.Poon@Sun.COM 			tcp = connp->conn_tcp;
57411754SKacheong.Poon@Sun.COM 			switch (tcp_snmp_state(tcp)) {
57511754SKacheong.Poon@Sun.COM 			case MIB2_TCP_established:
57611754SKacheong.Poon@Sun.COM 			case MIB2_TCP_closeWait:
57711754SKacheong.Poon@Sun.COM 				tcpkp->currEstab.value.ui32++;
57811754SKacheong.Poon@Sun.COM 				break;
57911754SKacheong.Poon@Sun.COM 			}
58011754SKacheong.Poon@Sun.COM 		}
58111754SKacheong.Poon@Sun.COM 	}
58211754SKacheong.Poon@Sun.COM 	bzero(&tcp_mib, sizeof (tcp_mib));
58311754SKacheong.Poon@Sun.COM 	tcp_sum_mib(tcps, &tcp_mib);
58411754SKacheong.Poon@Sun.COM 
585*12897SBaban.Kenkre@Sun.COM 	/* Fixed length structure for IPv4 and IPv6 counters */
586*12897SBaban.Kenkre@Sun.COM 	SET_MIB(tcp_mib.tcpConnTableSize, sizeof (mib2_tcpConnEntry_t));
587*12897SBaban.Kenkre@Sun.COM 	SET_MIB(tcp_mib.tcp6ConnTableSize, sizeof (mib2_tcp6ConnEntry_t));
588*12897SBaban.Kenkre@Sun.COM 
58911754SKacheong.Poon@Sun.COM 	tcpkp->activeOpens.value.ui32 = tcp_mib.tcpActiveOpens;
59011754SKacheong.Poon@Sun.COM 	tcpkp->passiveOpens.value.ui32 = tcp_mib.tcpPassiveOpens;
59111754SKacheong.Poon@Sun.COM 	tcpkp->attemptFails.value.ui32 = tcp_mib.tcpAttemptFails;
59211754SKacheong.Poon@Sun.COM 	tcpkp->estabResets.value.ui32 = tcp_mib.tcpEstabResets;
59311754SKacheong.Poon@Sun.COM 	tcpkp->inSegs.value.ui64 = tcp_mib.tcpHCInSegs;
59411754SKacheong.Poon@Sun.COM 	tcpkp->outSegs.value.ui64 = tcp_mib.tcpHCOutSegs;
59511754SKacheong.Poon@Sun.COM 	tcpkp->retransSegs.value.ui32 =	tcp_mib.tcpRetransSegs;
59611754SKacheong.Poon@Sun.COM 	tcpkp->connTableSize.value.i32 = tcp_mib.tcpConnTableSize;
59711754SKacheong.Poon@Sun.COM 	tcpkp->outRsts.value.ui32 = tcp_mib.tcpOutRsts;
59811754SKacheong.Poon@Sun.COM 	tcpkp->outDataSegs.value.ui32 = tcp_mib.tcpOutDataSegs;
59911754SKacheong.Poon@Sun.COM 	tcpkp->outDataBytes.value.ui32 = tcp_mib.tcpOutDataBytes;
60011754SKacheong.Poon@Sun.COM 	tcpkp->retransBytes.value.ui32 = tcp_mib.tcpRetransBytes;
60111754SKacheong.Poon@Sun.COM 	tcpkp->outAck.value.ui32 = tcp_mib.tcpOutAck;
60211754SKacheong.Poon@Sun.COM 	tcpkp->outAckDelayed.value.ui32 = tcp_mib.tcpOutAckDelayed;
60311754SKacheong.Poon@Sun.COM 	tcpkp->outUrg.value.ui32 = tcp_mib.tcpOutUrg;
60411754SKacheong.Poon@Sun.COM 	tcpkp->outWinUpdate.value.ui32 = tcp_mib.tcpOutWinUpdate;
60511754SKacheong.Poon@Sun.COM 	tcpkp->outWinProbe.value.ui32 = tcp_mib.tcpOutWinProbe;
60611754SKacheong.Poon@Sun.COM 	tcpkp->outControl.value.ui32 = tcp_mib.tcpOutControl;
60711754SKacheong.Poon@Sun.COM 	tcpkp->outFastRetrans.value.ui32 = tcp_mib.tcpOutFastRetrans;
60811754SKacheong.Poon@Sun.COM 	tcpkp->inAckSegs.value.ui32 = tcp_mib.tcpInAckSegs;
60911754SKacheong.Poon@Sun.COM 	tcpkp->inAckBytes.value.ui32 = tcp_mib.tcpInAckBytes;
61011754SKacheong.Poon@Sun.COM 	tcpkp->inDupAck.value.ui32 = tcp_mib.tcpInDupAck;
61111754SKacheong.Poon@Sun.COM 	tcpkp->inAckUnsent.value.ui32 = tcp_mib.tcpInAckUnsent;
61211754SKacheong.Poon@Sun.COM 	tcpkp->inDataInorderSegs.value.ui32 = tcp_mib.tcpInDataInorderSegs;
61311754SKacheong.Poon@Sun.COM 	tcpkp->inDataInorderBytes.value.ui32 = tcp_mib.tcpInDataInorderBytes;
61411754SKacheong.Poon@Sun.COM 	tcpkp->inDataUnorderSegs.value.ui32 = tcp_mib.tcpInDataUnorderSegs;
61511754SKacheong.Poon@Sun.COM 	tcpkp->inDataUnorderBytes.value.ui32 = tcp_mib.tcpInDataUnorderBytes;
61611754SKacheong.Poon@Sun.COM 	tcpkp->inDataDupSegs.value.ui32 = tcp_mib.tcpInDataDupSegs;
61711754SKacheong.Poon@Sun.COM 	tcpkp->inDataDupBytes.value.ui32 = tcp_mib.tcpInDataDupBytes;
61811754SKacheong.Poon@Sun.COM 	tcpkp->inDataPartDupSegs.value.ui32 = tcp_mib.tcpInDataPartDupSegs;
61911754SKacheong.Poon@Sun.COM 	tcpkp->inDataPartDupBytes.value.ui32 = tcp_mib.tcpInDataPartDupBytes;
62011754SKacheong.Poon@Sun.COM 	tcpkp->inDataPastWinSegs.value.ui32 = tcp_mib.tcpInDataPastWinSegs;
62111754SKacheong.Poon@Sun.COM 	tcpkp->inDataPastWinBytes.value.ui32 = tcp_mib.tcpInDataPastWinBytes;
62211754SKacheong.Poon@Sun.COM 	tcpkp->inWinProbe.value.ui32 = tcp_mib.tcpInWinProbe;
62311754SKacheong.Poon@Sun.COM 	tcpkp->inWinUpdate.value.ui32 = tcp_mib.tcpInWinUpdate;
62411754SKacheong.Poon@Sun.COM 	tcpkp->inClosed.value.ui32 = tcp_mib.tcpInClosed;
62511754SKacheong.Poon@Sun.COM 	tcpkp->rttNoUpdate.value.ui32 = tcp_mib.tcpRttNoUpdate;
62611754SKacheong.Poon@Sun.COM 	tcpkp->rttUpdate.value.ui32 = tcp_mib.tcpRttUpdate;
62711754SKacheong.Poon@Sun.COM 	tcpkp->timRetrans.value.ui32 = tcp_mib.tcpTimRetrans;
62811754SKacheong.Poon@Sun.COM 	tcpkp->timRetransDrop.value.ui32 = tcp_mib.tcpTimRetransDrop;
62911754SKacheong.Poon@Sun.COM 	tcpkp->timKeepalive.value.ui32 = tcp_mib.tcpTimKeepalive;
63011754SKacheong.Poon@Sun.COM 	tcpkp->timKeepaliveProbe.value.ui32 = tcp_mib.tcpTimKeepaliveProbe;
63111754SKacheong.Poon@Sun.COM 	tcpkp->timKeepaliveDrop.value.ui32 = tcp_mib.tcpTimKeepaliveDrop;
63211754SKacheong.Poon@Sun.COM 	tcpkp->listenDrop.value.ui32 = tcp_mib.tcpListenDrop;
63311754SKacheong.Poon@Sun.COM 	tcpkp->listenDropQ0.value.ui32 = tcp_mib.tcpListenDropQ0;
63411754SKacheong.Poon@Sun.COM 	tcpkp->halfOpenDrop.value.ui32 = tcp_mib.tcpHalfOpenDrop;
63511754SKacheong.Poon@Sun.COM 	tcpkp->outSackRetransSegs.value.ui32 = tcp_mib.tcpOutSackRetransSegs;
63611754SKacheong.Poon@Sun.COM 	tcpkp->connTableSize6.value.i32 = tcp_mib.tcp6ConnTableSize;
63711754SKacheong.Poon@Sun.COM 
63811754SKacheong.Poon@Sun.COM 	netstack_rele(ns);
63911754SKacheong.Poon@Sun.COM 	return (0);
64011754SKacheong.Poon@Sun.COM }
64111754SKacheong.Poon@Sun.COM 
64211754SKacheong.Poon@Sun.COM /*
64311754SKacheong.Poon@Sun.COM  * kstats related to squeues i.e. not per IP instance
64411754SKacheong.Poon@Sun.COM  */
64511754SKacheong.Poon@Sun.COM void *
tcp_g_kstat_init(tcp_g_stat_t * tcp_g_statp)64611754SKacheong.Poon@Sun.COM tcp_g_kstat_init(tcp_g_stat_t *tcp_g_statp)
64711754SKacheong.Poon@Sun.COM {
64811754SKacheong.Poon@Sun.COM 	kstat_t *ksp;
64911754SKacheong.Poon@Sun.COM 
65011754SKacheong.Poon@Sun.COM 	tcp_g_stat_t template = {
65111754SKacheong.Poon@Sun.COM 		{ "tcp_timermp_alloced",	KSTAT_DATA_UINT64 },
65211754SKacheong.Poon@Sun.COM 		{ "tcp_timermp_allocfail",	KSTAT_DATA_UINT64 },
65311754SKacheong.Poon@Sun.COM 		{ "tcp_timermp_allocdblfail",	KSTAT_DATA_UINT64 },
65411754SKacheong.Poon@Sun.COM 		{ "tcp_freelist_cleanup",	KSTAT_DATA_UINT64 },
65511754SKacheong.Poon@Sun.COM 	};
65611754SKacheong.Poon@Sun.COM 
65711754SKacheong.Poon@Sun.COM 	ksp = kstat_create(TCP_MOD_NAME, 0, "tcpstat_g", "net",
65811754SKacheong.Poon@Sun.COM 	    KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t),
65911754SKacheong.Poon@Sun.COM 	    KSTAT_FLAG_VIRTUAL);
66011754SKacheong.Poon@Sun.COM 
66111754SKacheong.Poon@Sun.COM 	if (ksp == NULL)
66211754SKacheong.Poon@Sun.COM 		return (NULL);
66311754SKacheong.Poon@Sun.COM 
66411754SKacheong.Poon@Sun.COM 	bcopy(&template, tcp_g_statp, sizeof (template));
66511754SKacheong.Poon@Sun.COM 	ksp->ks_data = (void *)tcp_g_statp;
66611754SKacheong.Poon@Sun.COM 
66711754SKacheong.Poon@Sun.COM 	kstat_install(ksp);
66811754SKacheong.Poon@Sun.COM 	return (ksp);
66911754SKacheong.Poon@Sun.COM }
67011754SKacheong.Poon@Sun.COM 
67111754SKacheong.Poon@Sun.COM void
tcp_g_kstat_fini(kstat_t * ksp)67211754SKacheong.Poon@Sun.COM tcp_g_kstat_fini(kstat_t *ksp)
67311754SKacheong.Poon@Sun.COM {
67411754SKacheong.Poon@Sun.COM 	if (ksp != NULL) {
67511754SKacheong.Poon@Sun.COM 		kstat_delete(ksp);
67611754SKacheong.Poon@Sun.COM 	}
67711754SKacheong.Poon@Sun.COM }
67811754SKacheong.Poon@Sun.COM 
67911754SKacheong.Poon@Sun.COM void *
tcp_kstat2_init(netstackid_t stackid)68011754SKacheong.Poon@Sun.COM tcp_kstat2_init(netstackid_t stackid)
68111754SKacheong.Poon@Sun.COM {
68211754SKacheong.Poon@Sun.COM 	kstat_t *ksp;
68311754SKacheong.Poon@Sun.COM 
68411754SKacheong.Poon@Sun.COM 	tcp_stat_t template = {
68511754SKacheong.Poon@Sun.COM 		{ "tcp_time_wait_syn_success",	KSTAT_DATA_UINT64, 0 },
68611754SKacheong.Poon@Sun.COM 		{ "tcp_clean_death_nondetached",	KSTAT_DATA_UINT64, 0 },
68711754SKacheong.Poon@Sun.COM 		{ "tcp_eager_blowoff_q",	KSTAT_DATA_UINT64, 0 },
68811754SKacheong.Poon@Sun.COM 		{ "tcp_eager_blowoff_q0",	KSTAT_DATA_UINT64, 0 },
68911754SKacheong.Poon@Sun.COM 		{ "tcp_no_listener",		KSTAT_DATA_UINT64, 0 },
69011754SKacheong.Poon@Sun.COM 		{ "tcp_listendrop",		KSTAT_DATA_UINT64, 0 },
69111754SKacheong.Poon@Sun.COM 		{ "tcp_listendropq0",		KSTAT_DATA_UINT64, 0 },
69211754SKacheong.Poon@Sun.COM 		{ "tcp_wsrv_called",		KSTAT_DATA_UINT64, 0 },
69311754SKacheong.Poon@Sun.COM 		{ "tcp_flwctl_on",		KSTAT_DATA_UINT64, 0 },
69411754SKacheong.Poon@Sun.COM 		{ "tcp_timer_fire_early",	KSTAT_DATA_UINT64, 0 },
69511754SKacheong.Poon@Sun.COM 		{ "tcp_timer_fire_miss",	KSTAT_DATA_UINT64, 0 },
69611754SKacheong.Poon@Sun.COM 		{ "tcp_zcopy_on",		KSTAT_DATA_UINT64, 0 },
69711754SKacheong.Poon@Sun.COM 		{ "tcp_zcopy_off",		KSTAT_DATA_UINT64, 0 },
69811754SKacheong.Poon@Sun.COM 		{ "tcp_zcopy_backoff",		KSTAT_DATA_UINT64, 0 },
69911754SKacheong.Poon@Sun.COM 		{ "tcp_fusion_flowctl",		KSTAT_DATA_UINT64, 0 },
70011754SKacheong.Poon@Sun.COM 		{ "tcp_fusion_backenabled",	KSTAT_DATA_UINT64, 0 },
70111754SKacheong.Poon@Sun.COM 		{ "tcp_fusion_urg",		KSTAT_DATA_UINT64, 0 },
70211754SKacheong.Poon@Sun.COM 		{ "tcp_fusion_putnext",		KSTAT_DATA_UINT64, 0 },
70311754SKacheong.Poon@Sun.COM 		{ "tcp_fusion_unfusable",	KSTAT_DATA_UINT64, 0 },
70411754SKacheong.Poon@Sun.COM 		{ "tcp_fusion_aborted",		KSTAT_DATA_UINT64, 0 },
70511754SKacheong.Poon@Sun.COM 		{ "tcp_fusion_unqualified",	KSTAT_DATA_UINT64, 0 },
70611754SKacheong.Poon@Sun.COM 		{ "tcp_fusion_rrw_busy",	KSTAT_DATA_UINT64, 0 },
70711754SKacheong.Poon@Sun.COM 		{ "tcp_fusion_rrw_msgcnt",	KSTAT_DATA_UINT64, 0 },
70811754SKacheong.Poon@Sun.COM 		{ "tcp_fusion_rrw_plugged",	KSTAT_DATA_UINT64, 0 },
70911754SKacheong.Poon@Sun.COM 		{ "tcp_in_ack_unsent_drop",	KSTAT_DATA_UINT64, 0 },
71011754SKacheong.Poon@Sun.COM 		{ "tcp_sock_fallback",		KSTAT_DATA_UINT64, 0 },
71111754SKacheong.Poon@Sun.COM 		{ "tcp_lso_enabled",		KSTAT_DATA_UINT64, 0 },
71211754SKacheong.Poon@Sun.COM 		{ "tcp_lso_disabled",		KSTAT_DATA_UINT64, 0 },
71311754SKacheong.Poon@Sun.COM 		{ "tcp_lso_times",		KSTAT_DATA_UINT64, 0 },
71411754SKacheong.Poon@Sun.COM 		{ "tcp_lso_pkt_out",		KSTAT_DATA_UINT64, 0 },
71511754SKacheong.Poon@Sun.COM 		{ "tcp_listen_cnt_drop",	KSTAT_DATA_UINT64, 0 },
71611754SKacheong.Poon@Sun.COM 		{ "tcp_listen_mem_drop",	KSTAT_DATA_UINT64, 0 },
71711754SKacheong.Poon@Sun.COM 		{ "tcp_zwin_mem_drop",		KSTAT_DATA_UINT64, 0 },
71811754SKacheong.Poon@Sun.COM 		{ "tcp_zwin_ack_syn",		KSTAT_DATA_UINT64, 0 },
71911754SKacheong.Poon@Sun.COM 		{ "tcp_rst_unsent",		KSTAT_DATA_UINT64, 0 },
72011754SKacheong.Poon@Sun.COM 		{ "tcp_reclaim_cnt",		KSTAT_DATA_UINT64, 0 },
72111754SKacheong.Poon@Sun.COM 		{ "tcp_reass_timeout",		KSTAT_DATA_UINT64, 0 },
72211754SKacheong.Poon@Sun.COM #ifdef TCP_DEBUG_COUNTER
72311754SKacheong.Poon@Sun.COM 		{ "tcp_time_wait",		KSTAT_DATA_UINT64, 0 },
72411754SKacheong.Poon@Sun.COM 		{ "tcp_rput_time_wait",		KSTAT_DATA_UINT64, 0 },
72511754SKacheong.Poon@Sun.COM 		{ "tcp_detach_time_wait",	KSTAT_DATA_UINT64, 0 },
72611754SKacheong.Poon@Sun.COM 		{ "tcp_timeout_calls",		KSTAT_DATA_UINT64, 0 },
72711754SKacheong.Poon@Sun.COM 		{ "tcp_timeout_cached_alloc",	KSTAT_DATA_UINT64, 0 },
72811754SKacheong.Poon@Sun.COM 		{ "tcp_timeout_cancel_reqs",	KSTAT_DATA_UINT64, 0 },
72911754SKacheong.Poon@Sun.COM 		{ "tcp_timeout_canceled",	KSTAT_DATA_UINT64, 0 },
73011754SKacheong.Poon@Sun.COM 		{ "tcp_timermp_freed",		KSTAT_DATA_UINT64, 0 },
73111754SKacheong.Poon@Sun.COM 		{ "tcp_push_timer_cnt",		KSTAT_DATA_UINT64, 0 },
73211754SKacheong.Poon@Sun.COM 		{ "tcp_ack_timer_cnt",		KSTAT_DATA_UINT64, 0 },
73311754SKacheong.Poon@Sun.COM #endif
73411754SKacheong.Poon@Sun.COM 	};
73511754SKacheong.Poon@Sun.COM 
73611754SKacheong.Poon@Sun.COM 	ksp = kstat_create_netstack(TCP_MOD_NAME, 0, "tcpstat", "net",
73711754SKacheong.Poon@Sun.COM 	    KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t), 0,
73811754SKacheong.Poon@Sun.COM 	    stackid);
73911754SKacheong.Poon@Sun.COM 
74011754SKacheong.Poon@Sun.COM 	if (ksp == NULL)
74111754SKacheong.Poon@Sun.COM 		return (NULL);
74211754SKacheong.Poon@Sun.COM 
74311754SKacheong.Poon@Sun.COM 	bcopy(&template, ksp->ks_data, sizeof (template));
74411754SKacheong.Poon@Sun.COM 	ksp->ks_private = (void *)(uintptr_t)stackid;
74511754SKacheong.Poon@Sun.COM 	ksp->ks_update = tcp_kstat2_update;
74611754SKacheong.Poon@Sun.COM 
74711754SKacheong.Poon@Sun.COM 	kstat_install(ksp);
74811754SKacheong.Poon@Sun.COM 	return (ksp);
74911754SKacheong.Poon@Sun.COM }
75011754SKacheong.Poon@Sun.COM 
75111754SKacheong.Poon@Sun.COM void
tcp_kstat2_fini(netstackid_t stackid,kstat_t * ksp)75211754SKacheong.Poon@Sun.COM tcp_kstat2_fini(netstackid_t stackid, kstat_t *ksp)
75311754SKacheong.Poon@Sun.COM {
75411754SKacheong.Poon@Sun.COM 	if (ksp != NULL) {
75511754SKacheong.Poon@Sun.COM 		ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
75611754SKacheong.Poon@Sun.COM 		kstat_delete_netstack(ksp, stackid);
75711754SKacheong.Poon@Sun.COM 	}
75811754SKacheong.Poon@Sun.COM }
75911754SKacheong.Poon@Sun.COM 
76011754SKacheong.Poon@Sun.COM /*
76111754SKacheong.Poon@Sun.COM  * Sum up all per CPU tcp_stat_t kstat counters.
76211754SKacheong.Poon@Sun.COM  */
76311754SKacheong.Poon@Sun.COM static int
tcp_kstat2_update(kstat_t * kp,int rw)76411754SKacheong.Poon@Sun.COM tcp_kstat2_update(kstat_t *kp, int rw)
76511754SKacheong.Poon@Sun.COM {
76611754SKacheong.Poon@Sun.COM 	netstackid_t	stackid = (netstackid_t)(uintptr_t)kp->ks_private;
76711754SKacheong.Poon@Sun.COM 	netstack_t	*ns;
76811754SKacheong.Poon@Sun.COM 	tcp_stack_t	*tcps;
76911754SKacheong.Poon@Sun.COM 	tcp_stat_t	*stats;
77011754SKacheong.Poon@Sun.COM 	int		i;
77111754SKacheong.Poon@Sun.COM 	int		cnt;
77211754SKacheong.Poon@Sun.COM 
77311754SKacheong.Poon@Sun.COM 	if (rw == KSTAT_WRITE)
77411754SKacheong.Poon@Sun.COM 		return (EACCES);
77511754SKacheong.Poon@Sun.COM 
77611754SKacheong.Poon@Sun.COM 	ns = netstack_find_by_stackid(stackid);
77711754SKacheong.Poon@Sun.COM 	if (ns == NULL)
77811754SKacheong.Poon@Sun.COM 		return (-1);
77911754SKacheong.Poon@Sun.COM 	tcps = ns->netstack_tcp;
78011754SKacheong.Poon@Sun.COM 	if (tcps == NULL) {
78111754SKacheong.Poon@Sun.COM 		netstack_rele(ns);
78211754SKacheong.Poon@Sun.COM 		return (-1);
78311754SKacheong.Poon@Sun.COM 	}
78411754SKacheong.Poon@Sun.COM 
78511754SKacheong.Poon@Sun.COM 	stats = (tcp_stat_t *)kp->ks_data;
78611754SKacheong.Poon@Sun.COM 	tcp_clr_stats(stats);
78711754SKacheong.Poon@Sun.COM 
78811754SKacheong.Poon@Sun.COM 	/*
78911754SKacheong.Poon@Sun.COM 	 * tcps_sc_cnt may change in the middle of the loop.  It is better
79011754SKacheong.Poon@Sun.COM 	 * to get its value first.
79111754SKacheong.Poon@Sun.COM 	 */
79211754SKacheong.Poon@Sun.COM 	cnt = tcps->tcps_sc_cnt;
79311754SKacheong.Poon@Sun.COM 	for (i = 0; i < cnt; i++)
79412869SKacheong.Poon@Sun.COM 		tcp_add_stats(&tcps->tcps_sc[i]->tcp_sc_stats, stats);
79511754SKacheong.Poon@Sun.COM 
79611754SKacheong.Poon@Sun.COM 	netstack_rele(ns);
79711754SKacheong.Poon@Sun.COM 	return (0);
79811754SKacheong.Poon@Sun.COM }
79911754SKacheong.Poon@Sun.COM 
80011754SKacheong.Poon@Sun.COM /*
80112869SKacheong.Poon@Sun.COM  * To add stats from one mib2_tcp_t to another.  Static fields are not added.
80211754SKacheong.Poon@Sun.COM  * The caller should set them up propertly.
80311754SKacheong.Poon@Sun.COM  */
80411754SKacheong.Poon@Sun.COM void
tcp_add_mib(mib2_tcp_t * from,mib2_tcp_t * to)80512869SKacheong.Poon@Sun.COM tcp_add_mib(mib2_tcp_t *from, mib2_tcp_t *to)
80611754SKacheong.Poon@Sun.COM {
80711754SKacheong.Poon@Sun.COM 	to->tcpActiveOpens += from->tcpActiveOpens;
80811754SKacheong.Poon@Sun.COM 	to->tcpPassiveOpens += from->tcpPassiveOpens;
80911754SKacheong.Poon@Sun.COM 	to->tcpAttemptFails += from->tcpAttemptFails;
81011754SKacheong.Poon@Sun.COM 	to->tcpEstabResets += from->tcpEstabResets;
81111754SKacheong.Poon@Sun.COM 	to->tcpInSegs += from->tcpInSegs;
81211754SKacheong.Poon@Sun.COM 	to->tcpOutSegs += from->tcpOutSegs;
81311754SKacheong.Poon@Sun.COM 	to->tcpRetransSegs += from->tcpRetransSegs;
81411754SKacheong.Poon@Sun.COM 	to->tcpOutRsts += from->tcpOutRsts;
81511754SKacheong.Poon@Sun.COM 
81611754SKacheong.Poon@Sun.COM 	to->tcpOutDataSegs += from->tcpOutDataSegs;
81711754SKacheong.Poon@Sun.COM 	to->tcpOutDataBytes += from->tcpOutDataBytes;
81811754SKacheong.Poon@Sun.COM 	to->tcpRetransBytes += from->tcpRetransBytes;
81911754SKacheong.Poon@Sun.COM 	to->tcpOutAck += from->tcpOutAck;
82011754SKacheong.Poon@Sun.COM 	to->tcpOutAckDelayed += from->tcpOutAckDelayed;
82111754SKacheong.Poon@Sun.COM 	to->tcpOutUrg += from->tcpOutUrg;
82211754SKacheong.Poon@Sun.COM 	to->tcpOutWinUpdate += from->tcpOutWinUpdate;
82311754SKacheong.Poon@Sun.COM 	to->tcpOutWinProbe += from->tcpOutWinProbe;
82411754SKacheong.Poon@Sun.COM 	to->tcpOutControl += from->tcpOutControl;
82511754SKacheong.Poon@Sun.COM 	to->tcpOutFastRetrans += from->tcpOutFastRetrans;
82611754SKacheong.Poon@Sun.COM 
82711754SKacheong.Poon@Sun.COM 	to->tcpInAckBytes += from->tcpInAckBytes;
82811754SKacheong.Poon@Sun.COM 	to->tcpInDupAck += from->tcpInDupAck;
82911754SKacheong.Poon@Sun.COM 	to->tcpInAckUnsent += from->tcpInAckUnsent;
83011754SKacheong.Poon@Sun.COM 	to->tcpInDataInorderSegs += from->tcpInDataInorderSegs;
83111754SKacheong.Poon@Sun.COM 	to->tcpInDataInorderBytes += from->tcpInDataInorderBytes;
83211754SKacheong.Poon@Sun.COM 	to->tcpInDataUnorderSegs += from->tcpInDataUnorderSegs;
83311754SKacheong.Poon@Sun.COM 	to->tcpInDataUnorderBytes += from->tcpInDataUnorderBytes;
83411754SKacheong.Poon@Sun.COM 	to->tcpInDataDupSegs += from->tcpInDataDupSegs;
83511754SKacheong.Poon@Sun.COM 	to->tcpInDataDupBytes += from->tcpInDataDupBytes;
83611754SKacheong.Poon@Sun.COM 	to->tcpInDataPartDupSegs += from->tcpInDataPartDupSegs;
83711754SKacheong.Poon@Sun.COM 	to->tcpInDataPartDupBytes += from->tcpInDataPartDupBytes;
83811754SKacheong.Poon@Sun.COM 	to->tcpInDataPastWinSegs += from->tcpInDataPastWinSegs;
83911754SKacheong.Poon@Sun.COM 	to->tcpInDataPastWinBytes += from->tcpInDataPastWinBytes;
84011754SKacheong.Poon@Sun.COM 	to->tcpInWinProbe += from->tcpInWinProbe;
84111754SKacheong.Poon@Sun.COM 	to->tcpInWinUpdate += from->tcpInWinUpdate;
84211754SKacheong.Poon@Sun.COM 	to->tcpInClosed += from->tcpInClosed;
84311754SKacheong.Poon@Sun.COM 
84411754SKacheong.Poon@Sun.COM 	to->tcpRttNoUpdate += from->tcpRttNoUpdate;
84511754SKacheong.Poon@Sun.COM 	to->tcpRttUpdate += from->tcpRttUpdate;
84611754SKacheong.Poon@Sun.COM 	to->tcpTimRetrans += from->tcpTimRetrans;
84711754SKacheong.Poon@Sun.COM 	to->tcpTimRetransDrop += from->tcpTimRetransDrop;
84811754SKacheong.Poon@Sun.COM 	to->tcpTimKeepalive += from->tcpTimKeepalive;
84911754SKacheong.Poon@Sun.COM 	to->tcpTimKeepaliveProbe += from->tcpTimKeepaliveProbe;
85011754SKacheong.Poon@Sun.COM 	to->tcpTimKeepaliveDrop += from->tcpTimKeepaliveDrop;
85111754SKacheong.Poon@Sun.COM 	to->tcpListenDrop += from->tcpListenDrop;
85211754SKacheong.Poon@Sun.COM 	to->tcpListenDropQ0 += from->tcpListenDropQ0;
85311754SKacheong.Poon@Sun.COM 	to->tcpHalfOpenDrop += from->tcpHalfOpenDrop;
85411754SKacheong.Poon@Sun.COM 	to->tcpOutSackRetransSegs += from->tcpOutSackRetransSegs;
85511754SKacheong.Poon@Sun.COM 	to->tcpHCInSegs += from->tcpHCInSegs;
85611754SKacheong.Poon@Sun.COM 	to->tcpHCOutSegs += from->tcpHCOutSegs;
85711754SKacheong.Poon@Sun.COM }
85811754SKacheong.Poon@Sun.COM 
85911754SKacheong.Poon@Sun.COM /*
86011754SKacheong.Poon@Sun.COM  * To sum up all MIB2 stats for a tcp_stack_t from all per CPU stats.  The
86111754SKacheong.Poon@Sun.COM  * caller should initialize the target mib2_tcp_t properly as this function
86211754SKacheong.Poon@Sun.COM  * just adds up all the per CPU stats.
86311754SKacheong.Poon@Sun.COM  */
86411754SKacheong.Poon@Sun.COM static void
tcp_sum_mib(tcp_stack_t * tcps,mib2_tcp_t * tcp_mib)86511754SKacheong.Poon@Sun.COM tcp_sum_mib(tcp_stack_t *tcps, mib2_tcp_t *tcp_mib)
86611754SKacheong.Poon@Sun.COM {
86711754SKacheong.Poon@Sun.COM 	int i;
86811754SKacheong.Poon@Sun.COM 	int cnt;
86911754SKacheong.Poon@Sun.COM 
87011754SKacheong.Poon@Sun.COM 	/*
87111754SKacheong.Poon@Sun.COM 	 * tcps_sc_cnt may change in the middle of the loop.  It is better
87211754SKacheong.Poon@Sun.COM 	 * to get its value first.
87311754SKacheong.Poon@Sun.COM 	 */
87411754SKacheong.Poon@Sun.COM 	cnt = tcps->tcps_sc_cnt;
87511754SKacheong.Poon@Sun.COM 	for (i = 0; i < cnt; i++)
87612869SKacheong.Poon@Sun.COM 		tcp_add_mib(&tcps->tcps_sc[i]->tcp_sc_mib, tcp_mib);
87711754SKacheong.Poon@Sun.COM }
87811754SKacheong.Poon@Sun.COM 
87911754SKacheong.Poon@Sun.COM /*
88011754SKacheong.Poon@Sun.COM  * To set all tcp_stat_t counters to 0.
88111754SKacheong.Poon@Sun.COM  */
88212869SKacheong.Poon@Sun.COM static void
tcp_clr_stats(tcp_stat_t * stats)88311754SKacheong.Poon@Sun.COM tcp_clr_stats(tcp_stat_t *stats)
88411754SKacheong.Poon@Sun.COM {
88511754SKacheong.Poon@Sun.COM 	stats->tcp_time_wait_syn_success.value.ui64 = 0;
88611754SKacheong.Poon@Sun.COM 	stats->tcp_clean_death_nondetached.value.ui64 = 0;
88711754SKacheong.Poon@Sun.COM 	stats->tcp_eager_blowoff_q.value.ui64 = 0;
88811754SKacheong.Poon@Sun.COM 	stats->tcp_eager_blowoff_q0.value.ui64 = 0;
88911754SKacheong.Poon@Sun.COM 	stats->tcp_no_listener.value.ui64 = 0;
89011754SKacheong.Poon@Sun.COM 	stats->tcp_listendrop.value.ui64 = 0;
89111754SKacheong.Poon@Sun.COM 	stats->tcp_listendropq0.value.ui64 = 0;
89211754SKacheong.Poon@Sun.COM 	stats->tcp_wsrv_called.value.ui64 = 0;
89311754SKacheong.Poon@Sun.COM 	stats->tcp_flwctl_on.value.ui64 = 0;
89411754SKacheong.Poon@Sun.COM 	stats->tcp_timer_fire_early.value.ui64 = 0;
89511754SKacheong.Poon@Sun.COM 	stats->tcp_timer_fire_miss.value.ui64 = 0;
89611754SKacheong.Poon@Sun.COM 	stats->tcp_zcopy_on.value.ui64 = 0;
89711754SKacheong.Poon@Sun.COM 	stats->tcp_zcopy_off.value.ui64 = 0;
89811754SKacheong.Poon@Sun.COM 	stats->tcp_zcopy_backoff.value.ui64 = 0;
89911754SKacheong.Poon@Sun.COM 	stats->tcp_fusion_flowctl.value.ui64 = 0;
90011754SKacheong.Poon@Sun.COM 	stats->tcp_fusion_backenabled.value.ui64 = 0;
90111754SKacheong.Poon@Sun.COM 	stats->tcp_fusion_urg.value.ui64 = 0;
90211754SKacheong.Poon@Sun.COM 	stats->tcp_fusion_putnext.value.ui64 = 0;
90311754SKacheong.Poon@Sun.COM 	stats->tcp_fusion_unfusable.value.ui64 = 0;
90411754SKacheong.Poon@Sun.COM 	stats->tcp_fusion_aborted.value.ui64 = 0;
90511754SKacheong.Poon@Sun.COM 	stats->tcp_fusion_unqualified.value.ui64 = 0;
90611754SKacheong.Poon@Sun.COM 	stats->tcp_fusion_rrw_busy.value.ui64 = 0;
90711754SKacheong.Poon@Sun.COM 	stats->tcp_fusion_rrw_msgcnt.value.ui64 = 0;
90811754SKacheong.Poon@Sun.COM 	stats->tcp_fusion_rrw_plugged.value.ui64 = 0;
90911754SKacheong.Poon@Sun.COM 	stats->tcp_in_ack_unsent_drop.value.ui64 = 0;
91011754SKacheong.Poon@Sun.COM 	stats->tcp_sock_fallback.value.ui64 = 0;
91111754SKacheong.Poon@Sun.COM 	stats->tcp_lso_enabled.value.ui64 = 0;
91211754SKacheong.Poon@Sun.COM 	stats->tcp_lso_disabled.value.ui64 = 0;
91311754SKacheong.Poon@Sun.COM 	stats->tcp_lso_times.value.ui64 = 0;
91411754SKacheong.Poon@Sun.COM 	stats->tcp_lso_pkt_out.value.ui64 = 0;
91511754SKacheong.Poon@Sun.COM 	stats->tcp_listen_cnt_drop.value.ui64 = 0;
91611754SKacheong.Poon@Sun.COM 	stats->tcp_listen_mem_drop.value.ui64 = 0;
91711754SKacheong.Poon@Sun.COM 	stats->tcp_zwin_mem_drop.value.ui64 = 0;
91811754SKacheong.Poon@Sun.COM 	stats->tcp_zwin_ack_syn.value.ui64 = 0;
91911754SKacheong.Poon@Sun.COM 	stats->tcp_rst_unsent.value.ui64 = 0;
92011754SKacheong.Poon@Sun.COM 	stats->tcp_reclaim_cnt.value.ui64 = 0;
92111754SKacheong.Poon@Sun.COM 	stats->tcp_reass_timeout.value.ui64 = 0;
92211754SKacheong.Poon@Sun.COM 
92311754SKacheong.Poon@Sun.COM #ifdef TCP_DEBUG_COUNTER
92411754SKacheong.Poon@Sun.COM 	stats->tcp_time_wait.value.ui64 = 0;
92511754SKacheong.Poon@Sun.COM 	stats->tcp_rput_time_wait.value.ui64 = 0;
92611754SKacheong.Poon@Sun.COM 	stats->tcp_detach_time_wait.value.ui64 = 0;
92711754SKacheong.Poon@Sun.COM 	stats->tcp_timeout_calls.value.ui64 = 0;
92811754SKacheong.Poon@Sun.COM 	stats->tcp_timeout_cached_alloc.value.ui64 = 0;
92911754SKacheong.Poon@Sun.COM 	stats->tcp_timeout_cancel_reqs.value.ui64 = 0;
93011754SKacheong.Poon@Sun.COM 	stats->tcp_timeout_canceled.value.ui64 = 0;
93111754SKacheong.Poon@Sun.COM 	stats->tcp_timermp_freed.value.ui64 = 0;
93211754SKacheong.Poon@Sun.COM 	stats->tcp_push_timer_cnt.value.ui64 = 0;
93311754SKacheong.Poon@Sun.COM 	stats->tcp_ack_timer_cnt.value.ui64 = 0;
93411754SKacheong.Poon@Sun.COM #endif
93511754SKacheong.Poon@Sun.COM }
93611754SKacheong.Poon@Sun.COM 
93711754SKacheong.Poon@Sun.COM /*
93812869SKacheong.Poon@Sun.COM  * To add counters from the per CPU tcp_stat_counter_t to the stack
93912869SKacheong.Poon@Sun.COM  * tcp_stat_t.
94011754SKacheong.Poon@Sun.COM  */
94112869SKacheong.Poon@Sun.COM static void
tcp_add_stats(tcp_stat_counter_t * from,tcp_stat_t * to)94212869SKacheong.Poon@Sun.COM tcp_add_stats(tcp_stat_counter_t *from, tcp_stat_t *to)
94311754SKacheong.Poon@Sun.COM {
94411754SKacheong.Poon@Sun.COM 	to->tcp_time_wait_syn_success.value.ui64 +=
94512869SKacheong.Poon@Sun.COM 	    from->tcp_time_wait_syn_success;
94611754SKacheong.Poon@Sun.COM 	to->tcp_clean_death_nondetached.value.ui64 +=
94712869SKacheong.Poon@Sun.COM 	    from->tcp_clean_death_nondetached;
94811754SKacheong.Poon@Sun.COM 	to->tcp_eager_blowoff_q.value.ui64 +=
94912869SKacheong.Poon@Sun.COM 	    from->tcp_eager_blowoff_q;
95011754SKacheong.Poon@Sun.COM 	to->tcp_eager_blowoff_q0.value.ui64 +=
95112869SKacheong.Poon@Sun.COM 	    from->tcp_eager_blowoff_q0;
95211754SKacheong.Poon@Sun.COM 	to->tcp_no_listener.value.ui64 +=
95312869SKacheong.Poon@Sun.COM 	    from->tcp_no_listener;
95411754SKacheong.Poon@Sun.COM 	to->tcp_listendrop.value.ui64 +=
95512869SKacheong.Poon@Sun.COM 	    from->tcp_listendrop;
95611754SKacheong.Poon@Sun.COM 	to->tcp_listendropq0.value.ui64 +=
95712869SKacheong.Poon@Sun.COM 	    from->tcp_listendropq0;
95811754SKacheong.Poon@Sun.COM 	to->tcp_wsrv_called.value.ui64 +=
95912869SKacheong.Poon@Sun.COM 	    from->tcp_wsrv_called;
96011754SKacheong.Poon@Sun.COM 	to->tcp_flwctl_on.value.ui64 +=
96112869SKacheong.Poon@Sun.COM 	    from->tcp_flwctl_on;
96211754SKacheong.Poon@Sun.COM 	to->tcp_timer_fire_early.value.ui64 +=
96312869SKacheong.Poon@Sun.COM 	    from->tcp_timer_fire_early;
96411754SKacheong.Poon@Sun.COM 	to->tcp_timer_fire_miss.value.ui64 +=
96512869SKacheong.Poon@Sun.COM 	    from->tcp_timer_fire_miss;
96611754SKacheong.Poon@Sun.COM 	to->tcp_zcopy_on.value.ui64 +=
96712869SKacheong.Poon@Sun.COM 	    from->tcp_zcopy_on;
96811754SKacheong.Poon@Sun.COM 	to->tcp_zcopy_off.value.ui64 +=
96912869SKacheong.Poon@Sun.COM 	    from->tcp_zcopy_off;
97011754SKacheong.Poon@Sun.COM 	to->tcp_zcopy_backoff.value.ui64 +=
97112869SKacheong.Poon@Sun.COM 	    from->tcp_zcopy_backoff;
97211754SKacheong.Poon@Sun.COM 	to->tcp_fusion_flowctl.value.ui64 +=
97312869SKacheong.Poon@Sun.COM 	    from->tcp_fusion_flowctl;
97411754SKacheong.Poon@Sun.COM 	to->tcp_fusion_backenabled.value.ui64 +=
97512869SKacheong.Poon@Sun.COM 	    from->tcp_fusion_backenabled;
97611754SKacheong.Poon@Sun.COM 	to->tcp_fusion_urg.value.ui64 +=
97712869SKacheong.Poon@Sun.COM 	    from->tcp_fusion_urg;
97811754SKacheong.Poon@Sun.COM 	to->tcp_fusion_putnext.value.ui64 +=
97912869SKacheong.Poon@Sun.COM 	    from->tcp_fusion_putnext;
98011754SKacheong.Poon@Sun.COM 	to->tcp_fusion_unfusable.value.ui64 +=
98112869SKacheong.Poon@Sun.COM 	    from->tcp_fusion_unfusable;
98211754SKacheong.Poon@Sun.COM 	to->tcp_fusion_aborted.value.ui64 +=
98312869SKacheong.Poon@Sun.COM 	    from->tcp_fusion_aborted;
98411754SKacheong.Poon@Sun.COM 	to->tcp_fusion_unqualified.value.ui64 +=
98512869SKacheong.Poon@Sun.COM 	    from->tcp_fusion_unqualified;
98611754SKacheong.Poon@Sun.COM 	to->tcp_fusion_rrw_busy.value.ui64 +=
98712869SKacheong.Poon@Sun.COM 	    from->tcp_fusion_rrw_busy;
98811754SKacheong.Poon@Sun.COM 	to->tcp_fusion_rrw_msgcnt.value.ui64 +=
98912869SKacheong.Poon@Sun.COM 	    from->tcp_fusion_rrw_msgcnt;
99011754SKacheong.Poon@Sun.COM 	to->tcp_fusion_rrw_plugged.value.ui64 +=
99112869SKacheong.Poon@Sun.COM 	    from->tcp_fusion_rrw_plugged;
99211754SKacheong.Poon@Sun.COM 	to->tcp_in_ack_unsent_drop.value.ui64 +=
99312869SKacheong.Poon@Sun.COM 	    from->tcp_in_ack_unsent_drop;
99411754SKacheong.Poon@Sun.COM 	to->tcp_sock_fallback.value.ui64 +=
99512869SKacheong.Poon@Sun.COM 	    from->tcp_sock_fallback;
99611754SKacheong.Poon@Sun.COM 	to->tcp_lso_enabled.value.ui64 +=
99712869SKacheong.Poon@Sun.COM 	    from->tcp_lso_enabled;
99811754SKacheong.Poon@Sun.COM 	to->tcp_lso_disabled.value.ui64 +=
99912869SKacheong.Poon@Sun.COM 	    from->tcp_lso_disabled;
100011754SKacheong.Poon@Sun.COM 	to->tcp_lso_times.value.ui64 +=
100112869SKacheong.Poon@Sun.COM 	    from->tcp_lso_times;
100211754SKacheong.Poon@Sun.COM 	to->tcp_lso_pkt_out.value.ui64 +=
100312869SKacheong.Poon@Sun.COM 	    from->tcp_lso_pkt_out;
100411754SKacheong.Poon@Sun.COM 	to->tcp_listen_cnt_drop.value.ui64 +=
100512869SKacheong.Poon@Sun.COM 	    from->tcp_listen_cnt_drop;
100611754SKacheong.Poon@Sun.COM 	to->tcp_listen_mem_drop.value.ui64 +=
100712869SKacheong.Poon@Sun.COM 	    from->tcp_listen_mem_drop;
100811754SKacheong.Poon@Sun.COM 	to->tcp_zwin_mem_drop.value.ui64 +=
100912869SKacheong.Poon@Sun.COM 	    from->tcp_zwin_mem_drop;
101011754SKacheong.Poon@Sun.COM 	to->tcp_zwin_ack_syn.value.ui64 +=
101112869SKacheong.Poon@Sun.COM 	    from->tcp_zwin_ack_syn;
101211754SKacheong.Poon@Sun.COM 	to->tcp_rst_unsent.value.ui64 +=
101312869SKacheong.Poon@Sun.COM 	    from->tcp_rst_unsent;
101411754SKacheong.Poon@Sun.COM 	to->tcp_reclaim_cnt.value.ui64 +=
101512869SKacheong.Poon@Sun.COM 	    from->tcp_reclaim_cnt;
101611754SKacheong.Poon@Sun.COM 	to->tcp_reass_timeout.value.ui64 +=
101712869SKacheong.Poon@Sun.COM 	    from->tcp_reass_timeout;
101811754SKacheong.Poon@Sun.COM 
101911754SKacheong.Poon@Sun.COM #ifdef TCP_DEBUG_COUNTER
102011754SKacheong.Poon@Sun.COM 	to->tcp_time_wait.value.ui64 +=
102112869SKacheong.Poon@Sun.COM 	    from->tcp_time_wait;
102211754SKacheong.Poon@Sun.COM 	to->tcp_rput_time_wait.value.ui64 +=
102312869SKacheong.Poon@Sun.COM 	    from->tcp_rput_time_wait;
102411754SKacheong.Poon@Sun.COM 	to->tcp_detach_time_wait.value.ui64 +=
102512869SKacheong.Poon@Sun.COM 	    from->tcp_detach_time_wait;
102611754SKacheong.Poon@Sun.COM 	to->tcp_timeout_calls.value.ui64 +=
102712869SKacheong.Poon@Sun.COM 	    from->tcp_timeout_calls;
102811754SKacheong.Poon@Sun.COM 	to->tcp_timeout_cached_alloc.value.ui64 +=
102912869SKacheong.Poon@Sun.COM 	    from->tcp_timeout_cached_alloc;
103011754SKacheong.Poon@Sun.COM 	to->tcp_timeout_cancel_reqs.value.ui64 +=
103112869SKacheong.Poon@Sun.COM 	    from->tcp_timeout_cancel_reqs;
103211754SKacheong.Poon@Sun.COM 	to->tcp_timeout_canceled.value.ui64 +=
103312869SKacheong.Poon@Sun.COM 	    from->tcp_timeout_canceled;
103411754SKacheong.Poon@Sun.COM 	to->tcp_timermp_freed.value.ui64 +=
103512869SKacheong.Poon@Sun.COM 	    from->tcp_timermp_freed;
103611754SKacheong.Poon@Sun.COM 	to->tcp_push_timer_cnt.value.ui64 +=
103712869SKacheong.Poon@Sun.COM 	    from->tcp_push_timer_cnt;
103811754SKacheong.Poon@Sun.COM 	to->tcp_ack_timer_cnt.value.ui64 +=
103912869SKacheong.Poon@Sun.COM 	    from->tcp_ack_timer_cnt;
104011754SKacheong.Poon@Sun.COM #endif
104111754SKacheong.Poon@Sun.COM }
1042