xref: /titanic_51/usr/src/uts/common/inet/tcp/tcp_stats.c (revision 4a0bd0711d2aa8c9386d9c275964fd49a79f7ea5)
1721fffe3SKacheong Poon /*
2721fffe3SKacheong Poon  * CDDL HEADER START
3721fffe3SKacheong Poon  *
4721fffe3SKacheong Poon  * The contents of this file are subject to the terms of the
5721fffe3SKacheong Poon  * Common Development and Distribution License (the "License").
6721fffe3SKacheong Poon  * You may not use this file except in compliance with the License.
7721fffe3SKacheong Poon  *
8721fffe3SKacheong Poon  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9721fffe3SKacheong Poon  * or http://www.opensolaris.org/os/licensing.
10721fffe3SKacheong Poon  * See the License for the specific language governing permissions
11721fffe3SKacheong Poon  * and limitations under the License.
12721fffe3SKacheong Poon  *
13721fffe3SKacheong Poon  * When distributing Covered Code, include this CDDL HEADER in each
14721fffe3SKacheong Poon  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15721fffe3SKacheong Poon  * If applicable, add the following below this CDDL HEADER, with the
16721fffe3SKacheong Poon  * fields enclosed by brackets "[]" replaced with your own identifying
17721fffe3SKacheong Poon  * information: Portions Copyright [yyyy] [name of copyright owner]
18721fffe3SKacheong Poon  *
19721fffe3SKacheong Poon  * CDDL HEADER END
20721fffe3SKacheong Poon  */
21721fffe3SKacheong Poon 
22721fffe3SKacheong Poon /*
235dd46ab5SKacheong Poon  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*4a0bd071SBill Pijewski  * Copyright (c) 2011, Joyent Inc. All rights reserved.
25721fffe3SKacheong Poon  */
26721fffe3SKacheong Poon 
27721fffe3SKacheong Poon #include <sys/types.h>
28721fffe3SKacheong Poon #include <sys/tihdr.h>
29721fffe3SKacheong Poon #include <sys/policy.h>
30721fffe3SKacheong Poon #include <sys/tsol/tnet.h>
31*4a0bd071SBill Pijewski #include <sys/kstat.h>
32721fffe3SKacheong Poon 
33721fffe3SKacheong Poon #include <inet/common.h>
34721fffe3SKacheong Poon #include <inet/ip.h>
35721fffe3SKacheong Poon #include <inet/tcp.h>
36721fffe3SKacheong Poon #include <inet/tcp_impl.h>
37721fffe3SKacheong Poon #include <inet/tcp_stats.h>
38721fffe3SKacheong Poon #include <inet/kstatcom.h>
39721fffe3SKacheong Poon #include <inet/snmpcom.h>
40721fffe3SKacheong Poon 
41ca3c8f41SDavid Höppner static int	tcp_kstat_update(kstat_t *, int);
42ca3c8f41SDavid Höppner static int	tcp_kstat2_update(kstat_t *, int);
43721fffe3SKacheong Poon static void	tcp_sum_mib(tcp_stack_t *, mib2_tcp_t *);
44721fffe3SKacheong Poon 
455dd46ab5SKacheong Poon static void	tcp_add_mib(mib2_tcp_t *, mib2_tcp_t *);
465dd46ab5SKacheong Poon static void	tcp_add_stats(tcp_stat_counter_t *, tcp_stat_t *);
47721fffe3SKacheong Poon static void	tcp_clr_stats(tcp_stat_t *);
48721fffe3SKacheong Poon 
49721fffe3SKacheong Poon tcp_g_stat_t	tcp_g_statistics;
50721fffe3SKacheong Poon kstat_t		*tcp_g_kstat;
51721fffe3SKacheong Poon 
52721fffe3SKacheong Poon /* Translate TCP state to MIB2 TCP state. */
53721fffe3SKacheong Poon static int
54721fffe3SKacheong Poon tcp_snmp_state(tcp_t *tcp)
55721fffe3SKacheong Poon {
56721fffe3SKacheong Poon 	if (tcp == NULL)
57721fffe3SKacheong Poon 		return (0);
58721fffe3SKacheong Poon 
59721fffe3SKacheong Poon 	switch (tcp->tcp_state) {
60721fffe3SKacheong Poon 	case TCPS_CLOSED:
61721fffe3SKacheong Poon 	case TCPS_IDLE:	/* RFC1213 doesn't have analogue for IDLE & BOUND */
62721fffe3SKacheong Poon 	case TCPS_BOUND:
63721fffe3SKacheong Poon 		return (MIB2_TCP_closed);
64721fffe3SKacheong Poon 	case TCPS_LISTEN:
65721fffe3SKacheong Poon 		return (MIB2_TCP_listen);
66721fffe3SKacheong Poon 	case TCPS_SYN_SENT:
67721fffe3SKacheong Poon 		return (MIB2_TCP_synSent);
68721fffe3SKacheong Poon 	case TCPS_SYN_RCVD:
69721fffe3SKacheong Poon 		return (MIB2_TCP_synReceived);
70721fffe3SKacheong Poon 	case TCPS_ESTABLISHED:
71721fffe3SKacheong Poon 		return (MIB2_TCP_established);
72721fffe3SKacheong Poon 	case TCPS_CLOSE_WAIT:
73721fffe3SKacheong Poon 		return (MIB2_TCP_closeWait);
74721fffe3SKacheong Poon 	case TCPS_FIN_WAIT_1:
75721fffe3SKacheong Poon 		return (MIB2_TCP_finWait1);
76721fffe3SKacheong Poon 	case TCPS_CLOSING:
77721fffe3SKacheong Poon 		return (MIB2_TCP_closing);
78721fffe3SKacheong Poon 	case TCPS_LAST_ACK:
79721fffe3SKacheong Poon 		return (MIB2_TCP_lastAck);
80721fffe3SKacheong Poon 	case TCPS_FIN_WAIT_2:
81721fffe3SKacheong Poon 		return (MIB2_TCP_finWait2);
82721fffe3SKacheong Poon 	case TCPS_TIME_WAIT:
83721fffe3SKacheong Poon 		return (MIB2_TCP_timeWait);
84721fffe3SKacheong Poon 	default:
85721fffe3SKacheong Poon 		return (0);
86721fffe3SKacheong Poon 	}
87721fffe3SKacheong Poon }
88721fffe3SKacheong Poon 
89721fffe3SKacheong Poon /*
90721fffe3SKacheong Poon  * Return SNMP stuff in buffer in mpdata.
91721fffe3SKacheong Poon  */
92721fffe3SKacheong Poon mblk_t *
936f773e29SBaban Kenkre tcp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
94721fffe3SKacheong Poon {
95721fffe3SKacheong Poon 	mblk_t			*mpdata;
96721fffe3SKacheong Poon 	mblk_t			*mp_conn_ctl = NULL;
97721fffe3SKacheong Poon 	mblk_t			*mp_conn_tail;
98721fffe3SKacheong Poon 	mblk_t			*mp_attr_ctl = NULL;
99721fffe3SKacheong Poon 	mblk_t			*mp_attr_tail;
100721fffe3SKacheong Poon 	mblk_t			*mp6_conn_ctl = NULL;
101721fffe3SKacheong Poon 	mblk_t			*mp6_conn_tail;
102721fffe3SKacheong Poon 	mblk_t			*mp6_attr_ctl = NULL;
103721fffe3SKacheong Poon 	mblk_t			*mp6_attr_tail;
104721fffe3SKacheong Poon 	struct opthdr		*optp;
105721fffe3SKacheong Poon 	mib2_tcpConnEntry_t	tce;
106721fffe3SKacheong Poon 	mib2_tcp6ConnEntry_t	tce6;
107721fffe3SKacheong Poon 	mib2_transportMLPEntry_t mlp;
108721fffe3SKacheong Poon 	connf_t			*connfp;
109721fffe3SKacheong Poon 	int			i;
110721fffe3SKacheong Poon 	boolean_t 		ispriv;
111721fffe3SKacheong Poon 	zoneid_t 		zoneid;
112721fffe3SKacheong Poon 	int			v4_conn_idx;
113721fffe3SKacheong Poon 	int			v6_conn_idx;
114721fffe3SKacheong Poon 	conn_t			*connp = Q_TO_CONN(q);
115721fffe3SKacheong Poon 	tcp_stack_t		*tcps;
116721fffe3SKacheong Poon 	ip_stack_t		*ipst;
117721fffe3SKacheong Poon 	mblk_t			*mp2ctl;
118721fffe3SKacheong Poon 	mib2_tcp_t		tcp_mib;
1196f773e29SBaban Kenkre 	size_t			tcp_mib_size, tce_size, tce6_size;
120721fffe3SKacheong Poon 
121721fffe3SKacheong Poon 	/*
122721fffe3SKacheong Poon 	 * make a copy of the original message
123721fffe3SKacheong Poon 	 */
124721fffe3SKacheong Poon 	mp2ctl = copymsg(mpctl);
125721fffe3SKacheong Poon 
126721fffe3SKacheong Poon 	if (mpctl == NULL ||
127721fffe3SKacheong Poon 	    (mpdata = mpctl->b_cont) == NULL ||
128721fffe3SKacheong Poon 	    (mp_conn_ctl = copymsg(mpctl)) == NULL ||
129721fffe3SKacheong Poon 	    (mp_attr_ctl = copymsg(mpctl)) == NULL ||
130721fffe3SKacheong Poon 	    (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
131721fffe3SKacheong Poon 	    (mp6_attr_ctl = copymsg(mpctl)) == NULL) {
132721fffe3SKacheong Poon 		freemsg(mp_conn_ctl);
133721fffe3SKacheong Poon 		freemsg(mp_attr_ctl);
134721fffe3SKacheong Poon 		freemsg(mp6_conn_ctl);
135721fffe3SKacheong Poon 		freemsg(mp6_attr_ctl);
136721fffe3SKacheong Poon 		freemsg(mpctl);
137721fffe3SKacheong Poon 		freemsg(mp2ctl);
138721fffe3SKacheong Poon 		return (NULL);
139721fffe3SKacheong Poon 	}
140721fffe3SKacheong Poon 
141721fffe3SKacheong Poon 	ipst = connp->conn_netstack->netstack_ip;
142721fffe3SKacheong Poon 	tcps = connp->conn_netstack->netstack_tcp;
143721fffe3SKacheong Poon 
1446f773e29SBaban Kenkre 	if (legacy_req) {
1456f773e29SBaban Kenkre 		tcp_mib_size = LEGACY_MIB_SIZE(&tcp_mib, mib2_tcp_t);
1466f773e29SBaban Kenkre 		tce_size = LEGACY_MIB_SIZE(&tce, mib2_tcpConnEntry_t);
1476f773e29SBaban Kenkre 		tce6_size = LEGACY_MIB_SIZE(&tce6, mib2_tcp6ConnEntry_t);
1486f773e29SBaban Kenkre 	} else {
1496f773e29SBaban Kenkre 		tcp_mib_size = sizeof (mib2_tcp_t);
1506f773e29SBaban Kenkre 		tce_size = sizeof (mib2_tcpConnEntry_t);
1516f773e29SBaban Kenkre 		tce6_size = sizeof (mib2_tcp6ConnEntry_t);
1526f773e29SBaban Kenkre 	}
1536f773e29SBaban Kenkre 
154721fffe3SKacheong Poon 	bzero(&tcp_mib, sizeof (tcp_mib));
155721fffe3SKacheong Poon 
156721fffe3SKacheong Poon 	/* build table of connections -- need count in fixed part */
157721fffe3SKacheong Poon 	SET_MIB(tcp_mib.tcpRtoAlgorithm, 4);   /* vanj */
158721fffe3SKacheong Poon 	SET_MIB(tcp_mib.tcpRtoMin, tcps->tcps_rexmit_interval_min);
159721fffe3SKacheong Poon 	SET_MIB(tcp_mib.tcpRtoMax, tcps->tcps_rexmit_interval_max);
160721fffe3SKacheong Poon 	SET_MIB(tcp_mib.tcpMaxConn, -1);
161721fffe3SKacheong Poon 	SET_MIB(tcp_mib.tcpCurrEstab, 0);
162721fffe3SKacheong Poon 
163721fffe3SKacheong Poon 	ispriv =
164721fffe3SKacheong Poon 	    secpolicy_ip_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0;
165721fffe3SKacheong Poon 	zoneid = Q_TO_CONN(q)->conn_zoneid;
166721fffe3SKacheong Poon 
167721fffe3SKacheong Poon 	v4_conn_idx = v6_conn_idx = 0;
168721fffe3SKacheong Poon 	mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
169721fffe3SKacheong Poon 
170721fffe3SKacheong Poon 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
171721fffe3SKacheong Poon 		ipst = tcps->tcps_netstack->netstack_ip;
172721fffe3SKacheong Poon 
173721fffe3SKacheong Poon 		connfp = &ipst->ips_ipcl_globalhash_fanout[i];
174721fffe3SKacheong Poon 
175721fffe3SKacheong Poon 		connp = NULL;
176721fffe3SKacheong Poon 
177721fffe3SKacheong Poon 		while ((connp =
178721fffe3SKacheong Poon 		    ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
179721fffe3SKacheong Poon 			tcp_t *tcp;
180721fffe3SKacheong Poon 			boolean_t needattr;
181721fffe3SKacheong Poon 
182721fffe3SKacheong Poon 			if (connp->conn_zoneid != zoneid)
183721fffe3SKacheong Poon 				continue;	/* not in this zone */
184721fffe3SKacheong Poon 
185721fffe3SKacheong Poon 			tcp = connp->conn_tcp;
186721fffe3SKacheong Poon 			TCPS_UPDATE_MIB(tcps, tcpHCInSegs, tcp->tcp_ibsegs);
187721fffe3SKacheong Poon 			tcp->tcp_ibsegs = 0;
188721fffe3SKacheong Poon 			TCPS_UPDATE_MIB(tcps, tcpHCOutSegs, tcp->tcp_obsegs);
189721fffe3SKacheong Poon 			tcp->tcp_obsegs = 0;
190721fffe3SKacheong Poon 
191721fffe3SKacheong Poon 			tce6.tcp6ConnState = tce.tcpConnState =
192721fffe3SKacheong Poon 			    tcp_snmp_state(tcp);
193721fffe3SKacheong Poon 			if (tce.tcpConnState == MIB2_TCP_established ||
194721fffe3SKacheong Poon 			    tce.tcpConnState == MIB2_TCP_closeWait)
19547b75f87SKacheong Poon 				BUMP_MIB(&tcp_mib, tcpCurrEstab);
196721fffe3SKacheong Poon 
197721fffe3SKacheong Poon 			needattr = B_FALSE;
198721fffe3SKacheong Poon 			bzero(&mlp, sizeof (mlp));
199721fffe3SKacheong Poon 			if (connp->conn_mlp_type != mlptSingle) {
200721fffe3SKacheong Poon 				if (connp->conn_mlp_type == mlptShared ||
201721fffe3SKacheong Poon 				    connp->conn_mlp_type == mlptBoth)
202721fffe3SKacheong Poon 					mlp.tme_flags |= MIB2_TMEF_SHARED;
203721fffe3SKacheong Poon 				if (connp->conn_mlp_type == mlptPrivate ||
204721fffe3SKacheong Poon 				    connp->conn_mlp_type == mlptBoth)
205721fffe3SKacheong Poon 					mlp.tme_flags |= MIB2_TMEF_PRIVATE;
206721fffe3SKacheong Poon 				needattr = B_TRUE;
207721fffe3SKacheong Poon 			}
208721fffe3SKacheong Poon 			if (connp->conn_anon_mlp) {
209721fffe3SKacheong Poon 				mlp.tme_flags |= MIB2_TMEF_ANONMLP;
210721fffe3SKacheong Poon 				needattr = B_TRUE;
211721fffe3SKacheong Poon 			}
212721fffe3SKacheong Poon 			switch (connp->conn_mac_mode) {
213721fffe3SKacheong Poon 			case CONN_MAC_DEFAULT:
214721fffe3SKacheong Poon 				break;
215721fffe3SKacheong Poon 			case CONN_MAC_AWARE:
216721fffe3SKacheong Poon 				mlp.tme_flags |= MIB2_TMEF_MACEXEMPT;
217721fffe3SKacheong Poon 				needattr = B_TRUE;
218721fffe3SKacheong Poon 				break;
219721fffe3SKacheong Poon 			case CONN_MAC_IMPLICIT:
220721fffe3SKacheong Poon 				mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT;
221721fffe3SKacheong Poon 				needattr = B_TRUE;
222721fffe3SKacheong Poon 				break;
223721fffe3SKacheong Poon 			}
224721fffe3SKacheong Poon 			if (connp->conn_ixa->ixa_tsl != NULL) {
225721fffe3SKacheong Poon 				ts_label_t *tsl;
226721fffe3SKacheong Poon 
227721fffe3SKacheong Poon 				tsl = connp->conn_ixa->ixa_tsl;
228721fffe3SKacheong Poon 				mlp.tme_flags |= MIB2_TMEF_IS_LABELED;
229721fffe3SKacheong Poon 				mlp.tme_doi = label2doi(tsl);
230721fffe3SKacheong Poon 				mlp.tme_label = *label2bslabel(tsl);
231721fffe3SKacheong Poon 				needattr = B_TRUE;
232721fffe3SKacheong Poon 			}
233721fffe3SKacheong Poon 
234721fffe3SKacheong Poon 			/* Create a message to report on IPv6 entries */
235721fffe3SKacheong Poon 			if (connp->conn_ipversion == IPV6_VERSION) {
236721fffe3SKacheong Poon 			tce6.tcp6ConnLocalAddress = connp->conn_laddr_v6;
237721fffe3SKacheong Poon 			tce6.tcp6ConnRemAddress = connp->conn_faddr_v6;
238721fffe3SKacheong Poon 			tce6.tcp6ConnLocalPort = ntohs(connp->conn_lport);
239721fffe3SKacheong Poon 			tce6.tcp6ConnRemPort = ntohs(connp->conn_fport);
240721fffe3SKacheong Poon 			if (connp->conn_ixa->ixa_flags & IXAF_SCOPEID_SET) {
241721fffe3SKacheong Poon 				tce6.tcp6ConnIfIndex =
242721fffe3SKacheong Poon 				    connp->conn_ixa->ixa_scopeid;
243721fffe3SKacheong Poon 			} else {
244721fffe3SKacheong Poon 				tce6.tcp6ConnIfIndex = connp->conn_bound_if;
245721fffe3SKacheong Poon 			}
246721fffe3SKacheong Poon 			/* Don't want just anybody seeing these... */
247721fffe3SKacheong Poon 			if (ispriv) {
248721fffe3SKacheong Poon 				tce6.tcp6ConnEntryInfo.ce_snxt =
249721fffe3SKacheong Poon 				    tcp->tcp_snxt;
250721fffe3SKacheong Poon 				tce6.tcp6ConnEntryInfo.ce_suna =
251721fffe3SKacheong Poon 				    tcp->tcp_suna;
252721fffe3SKacheong Poon 				tce6.tcp6ConnEntryInfo.ce_rnxt =
253721fffe3SKacheong Poon 				    tcp->tcp_rnxt;
254721fffe3SKacheong Poon 				tce6.tcp6ConnEntryInfo.ce_rack =
255721fffe3SKacheong Poon 				    tcp->tcp_rack;
256721fffe3SKacheong Poon 			} else {
257721fffe3SKacheong Poon 				/*
258721fffe3SKacheong Poon 				 * Netstat, unfortunately, uses this to
259721fffe3SKacheong Poon 				 * get send/receive queue sizes.  How to fix?
260721fffe3SKacheong Poon 				 * Why not compute the difference only?
261721fffe3SKacheong Poon 				 */
262721fffe3SKacheong Poon 				tce6.tcp6ConnEntryInfo.ce_snxt =
263721fffe3SKacheong Poon 				    tcp->tcp_snxt - tcp->tcp_suna;
264721fffe3SKacheong Poon 				tce6.tcp6ConnEntryInfo.ce_suna = 0;
265721fffe3SKacheong Poon 				tce6.tcp6ConnEntryInfo.ce_rnxt =
266721fffe3SKacheong Poon 				    tcp->tcp_rnxt - tcp->tcp_rack;
267721fffe3SKacheong Poon 				tce6.tcp6ConnEntryInfo.ce_rack = 0;
268721fffe3SKacheong Poon 			}
269721fffe3SKacheong Poon 
270721fffe3SKacheong Poon 			tce6.tcp6ConnEntryInfo.ce_swnd = tcp->tcp_swnd;
271721fffe3SKacheong Poon 			tce6.tcp6ConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
272721fffe3SKacheong Poon 			tce6.tcp6ConnEntryInfo.ce_rto =  tcp->tcp_rto;
273721fffe3SKacheong Poon 			tce6.tcp6ConnEntryInfo.ce_mss =  tcp->tcp_mss;
274721fffe3SKacheong Poon 			tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state;
275721fffe3SKacheong Poon 
276721fffe3SKacheong Poon 			tce6.tcp6ConnCreationProcess =
277721fffe3SKacheong Poon 			    (connp->conn_cpid < 0) ? MIB2_UNKNOWN_PROCESS :
278721fffe3SKacheong Poon 			    connp->conn_cpid;
279721fffe3SKacheong Poon 			tce6.tcp6ConnCreationTime = connp->conn_open_time;
280721fffe3SKacheong Poon 
281721fffe3SKacheong Poon 			(void) snmp_append_data2(mp6_conn_ctl->b_cont,
2826f773e29SBaban Kenkre 			    &mp6_conn_tail, (char *)&tce6, tce6_size);
283721fffe3SKacheong Poon 
284721fffe3SKacheong Poon 			mlp.tme_connidx = v6_conn_idx++;
285721fffe3SKacheong Poon 			if (needattr)
286721fffe3SKacheong Poon 				(void) snmp_append_data2(mp6_attr_ctl->b_cont,
287721fffe3SKacheong Poon 				    &mp6_attr_tail, (char *)&mlp, sizeof (mlp));
288721fffe3SKacheong Poon 			}
289721fffe3SKacheong Poon 			/*
290721fffe3SKacheong Poon 			 * Create an IPv4 table entry for IPv4 entries and also
291721fffe3SKacheong Poon 			 * for IPv6 entries which are bound to in6addr_any
292721fffe3SKacheong Poon 			 * but don't have IPV6_V6ONLY set.
293721fffe3SKacheong Poon 			 * (i.e. anything an IPv4 peer could connect to)
294721fffe3SKacheong Poon 			 */
295721fffe3SKacheong Poon 			if (connp->conn_ipversion == IPV4_VERSION ||
296721fffe3SKacheong Poon 			    (tcp->tcp_state <= TCPS_LISTEN &&
297721fffe3SKacheong Poon 			    !connp->conn_ipv6_v6only &&
298721fffe3SKacheong Poon 			    IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) {
299721fffe3SKacheong Poon 				if (connp->conn_ipversion == IPV6_VERSION) {
300721fffe3SKacheong Poon 					tce.tcpConnRemAddress = INADDR_ANY;
301721fffe3SKacheong Poon 					tce.tcpConnLocalAddress = INADDR_ANY;
302721fffe3SKacheong Poon 				} else {
303721fffe3SKacheong Poon 					tce.tcpConnRemAddress =
304721fffe3SKacheong Poon 					    connp->conn_faddr_v4;
305721fffe3SKacheong Poon 					tce.tcpConnLocalAddress =
306721fffe3SKacheong Poon 					    connp->conn_laddr_v4;
307721fffe3SKacheong Poon 				}
308721fffe3SKacheong Poon 				tce.tcpConnLocalPort = ntohs(connp->conn_lport);
309721fffe3SKacheong Poon 				tce.tcpConnRemPort = ntohs(connp->conn_fport);
310721fffe3SKacheong Poon 				/* Don't want just anybody seeing these... */
311721fffe3SKacheong Poon 				if (ispriv) {
312721fffe3SKacheong Poon 					tce.tcpConnEntryInfo.ce_snxt =
313721fffe3SKacheong Poon 					    tcp->tcp_snxt;
314721fffe3SKacheong Poon 					tce.tcpConnEntryInfo.ce_suna =
315721fffe3SKacheong Poon 					    tcp->tcp_suna;
316721fffe3SKacheong Poon 					tce.tcpConnEntryInfo.ce_rnxt =
317721fffe3SKacheong Poon 					    tcp->tcp_rnxt;
318721fffe3SKacheong Poon 					tce.tcpConnEntryInfo.ce_rack =
319721fffe3SKacheong Poon 					    tcp->tcp_rack;
320721fffe3SKacheong Poon 				} else {
321721fffe3SKacheong Poon 					/*
322721fffe3SKacheong Poon 					 * Netstat, unfortunately, uses this to
323721fffe3SKacheong Poon 					 * get send/receive queue sizes.  How
324721fffe3SKacheong Poon 					 * to fix?
325721fffe3SKacheong Poon 					 * Why not compute the difference only?
326721fffe3SKacheong Poon 					 */
327721fffe3SKacheong Poon 					tce.tcpConnEntryInfo.ce_snxt =
328721fffe3SKacheong Poon 					    tcp->tcp_snxt - tcp->tcp_suna;
329721fffe3SKacheong Poon 					tce.tcpConnEntryInfo.ce_suna = 0;
330721fffe3SKacheong Poon 					tce.tcpConnEntryInfo.ce_rnxt =
331721fffe3SKacheong Poon 					    tcp->tcp_rnxt - tcp->tcp_rack;
332721fffe3SKacheong Poon 					tce.tcpConnEntryInfo.ce_rack = 0;
333721fffe3SKacheong Poon 				}
334721fffe3SKacheong Poon 
335721fffe3SKacheong Poon 				tce.tcpConnEntryInfo.ce_swnd = tcp->tcp_swnd;
336721fffe3SKacheong Poon 				tce.tcpConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
337721fffe3SKacheong Poon 				tce.tcpConnEntryInfo.ce_rto =  tcp->tcp_rto;
338721fffe3SKacheong Poon 				tce.tcpConnEntryInfo.ce_mss =  tcp->tcp_mss;
339721fffe3SKacheong Poon 				tce.tcpConnEntryInfo.ce_state =
340721fffe3SKacheong Poon 				    tcp->tcp_state;
341721fffe3SKacheong Poon 
342721fffe3SKacheong Poon 				tce.tcpConnCreationProcess =
343721fffe3SKacheong Poon 				    (connp->conn_cpid < 0) ?
344721fffe3SKacheong Poon 				    MIB2_UNKNOWN_PROCESS :
345721fffe3SKacheong Poon 				    connp->conn_cpid;
346721fffe3SKacheong Poon 				tce.tcpConnCreationTime = connp->conn_open_time;
347721fffe3SKacheong Poon 
348721fffe3SKacheong Poon 				(void) snmp_append_data2(mp_conn_ctl->b_cont,
3496f773e29SBaban Kenkre 				    &mp_conn_tail, (char *)&tce, tce_size);
350721fffe3SKacheong Poon 
351721fffe3SKacheong Poon 				mlp.tme_connidx = v4_conn_idx++;
352721fffe3SKacheong Poon 				if (needattr)
353721fffe3SKacheong Poon 					(void) snmp_append_data2(
354721fffe3SKacheong Poon 					    mp_attr_ctl->b_cont,
355721fffe3SKacheong Poon 					    &mp_attr_tail, (char *)&mlp,
356721fffe3SKacheong Poon 					    sizeof (mlp));
357721fffe3SKacheong Poon 			}
358721fffe3SKacheong Poon 		}
359721fffe3SKacheong Poon 	}
360721fffe3SKacheong Poon 
36147b75f87SKacheong Poon 	tcp_sum_mib(tcps, &tcp_mib);
362721fffe3SKacheong Poon 
3636f773e29SBaban Kenkre 	/* Fixed length structure for IPv4 and IPv6 counters */
3646f773e29SBaban Kenkre 	SET_MIB(tcp_mib.tcpConnTableSize, tce_size);
3656f773e29SBaban Kenkre 	SET_MIB(tcp_mib.tcp6ConnTableSize, tce6_size);
3666f773e29SBaban Kenkre 
36747b75f87SKacheong Poon 	/*
36847b75f87SKacheong Poon 	 * Synchronize 32- and 64-bit counters.  Note that tcpInSegs and
36947b75f87SKacheong Poon 	 * tcpOutSegs are not updated anywhere in TCP.  The new 64 bits
37047b75f87SKacheong Poon 	 * counters are used.  Hence the old counters' values in tcp_sc_mib
37147b75f87SKacheong Poon 	 * are always 0.
37247b75f87SKacheong Poon 	 */
373721fffe3SKacheong Poon 	SYNC32_MIB(&tcp_mib, tcpInSegs, tcpHCInSegs);
374721fffe3SKacheong Poon 	SYNC32_MIB(&tcp_mib, tcpOutSegs, tcpHCOutSegs);
375721fffe3SKacheong Poon 
376721fffe3SKacheong Poon 	optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
377721fffe3SKacheong Poon 	optp->level = MIB2_TCP;
378721fffe3SKacheong Poon 	optp->name = 0;
3796f773e29SBaban Kenkre 	(void) snmp_append_data(mpdata, (char *)&tcp_mib, tcp_mib_size);
380721fffe3SKacheong Poon 	optp->len = msgdsize(mpdata);
381721fffe3SKacheong Poon 	qreply(q, mpctl);
382721fffe3SKacheong Poon 
383721fffe3SKacheong Poon 	/* table of connections... */
384721fffe3SKacheong Poon 	optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
385721fffe3SKacheong Poon 	    sizeof (struct T_optmgmt_ack)];
386721fffe3SKacheong Poon 	optp->level = MIB2_TCP;
387721fffe3SKacheong Poon 	optp->name = MIB2_TCP_CONN;
388721fffe3SKacheong Poon 	optp->len = msgdsize(mp_conn_ctl->b_cont);
389721fffe3SKacheong Poon 	qreply(q, mp_conn_ctl);
390721fffe3SKacheong Poon 
391721fffe3SKacheong Poon 	/* table of MLP attributes... */
392721fffe3SKacheong Poon 	optp = (struct opthdr *)&mp_attr_ctl->b_rptr[
393721fffe3SKacheong Poon 	    sizeof (struct T_optmgmt_ack)];
394721fffe3SKacheong Poon 	optp->level = MIB2_TCP;
395721fffe3SKacheong Poon 	optp->name = EXPER_XPORT_MLP;
396721fffe3SKacheong Poon 	optp->len = msgdsize(mp_attr_ctl->b_cont);
397721fffe3SKacheong Poon 	if (optp->len == 0)
398721fffe3SKacheong Poon 		freemsg(mp_attr_ctl);
399721fffe3SKacheong Poon 	else
400721fffe3SKacheong Poon 		qreply(q, mp_attr_ctl);
401721fffe3SKacheong Poon 
402721fffe3SKacheong Poon 	/* table of IPv6 connections... */
403721fffe3SKacheong Poon 	optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
404721fffe3SKacheong Poon 	    sizeof (struct T_optmgmt_ack)];
405721fffe3SKacheong Poon 	optp->level = MIB2_TCP6;
406721fffe3SKacheong Poon 	optp->name = MIB2_TCP6_CONN;
407721fffe3SKacheong Poon 	optp->len = msgdsize(mp6_conn_ctl->b_cont);
408721fffe3SKacheong Poon 	qreply(q, mp6_conn_ctl);
409721fffe3SKacheong Poon 
410721fffe3SKacheong Poon 	/* table of IPv6 MLP attributes... */
411721fffe3SKacheong Poon 	optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[
412721fffe3SKacheong Poon 	    sizeof (struct T_optmgmt_ack)];
413721fffe3SKacheong Poon 	optp->level = MIB2_TCP6;
414721fffe3SKacheong Poon 	optp->name = EXPER_XPORT_MLP;
415721fffe3SKacheong Poon 	optp->len = msgdsize(mp6_attr_ctl->b_cont);
416721fffe3SKacheong Poon 	if (optp->len == 0)
417721fffe3SKacheong Poon 		freemsg(mp6_attr_ctl);
418721fffe3SKacheong Poon 	else
419721fffe3SKacheong Poon 		qreply(q, mp6_attr_ctl);
420721fffe3SKacheong Poon 	return (mp2ctl);
421721fffe3SKacheong Poon }
422721fffe3SKacheong Poon 
423721fffe3SKacheong Poon /* Return 0 if invalid set request, 1 otherwise, including non-tcp requests  */
424721fffe3SKacheong Poon /* ARGSUSED */
425721fffe3SKacheong Poon int
426721fffe3SKacheong Poon tcp_snmp_set(queue_t *q, int level, int name, uchar_t *ptr, int len)
427721fffe3SKacheong Poon {
428721fffe3SKacheong Poon 	mib2_tcpConnEntry_t	*tce = (mib2_tcpConnEntry_t *)ptr;
429721fffe3SKacheong Poon 
430721fffe3SKacheong Poon 	switch (level) {
431721fffe3SKacheong Poon 	case MIB2_TCP:
432721fffe3SKacheong Poon 		switch (name) {
433721fffe3SKacheong Poon 		case 13:
434721fffe3SKacheong Poon 			if (tce->tcpConnState != MIB2_TCP_deleteTCB)
435721fffe3SKacheong Poon 				return (0);
436721fffe3SKacheong Poon 			/* TODO: delete entry defined by tce */
437721fffe3SKacheong Poon 			return (1);
438721fffe3SKacheong Poon 		default:
439721fffe3SKacheong Poon 			return (0);
440721fffe3SKacheong Poon 		}
441721fffe3SKacheong Poon 	default:
442721fffe3SKacheong Poon 		return (1);
443721fffe3SKacheong Poon 	}
444721fffe3SKacheong Poon }
445721fffe3SKacheong Poon 
446721fffe3SKacheong Poon /*
447721fffe3SKacheong Poon  * TCP Kstats implementation
448721fffe3SKacheong Poon  */
449721fffe3SKacheong Poon void *
450721fffe3SKacheong Poon tcp_kstat_init(netstackid_t stackid)
451721fffe3SKacheong Poon {
452721fffe3SKacheong Poon 	kstat_t	*ksp;
453721fffe3SKacheong Poon 
454721fffe3SKacheong Poon 	tcp_named_kstat_t template = {
455721fffe3SKacheong Poon 		{ "rtoAlgorithm",	KSTAT_DATA_INT32, 0 },
456721fffe3SKacheong Poon 		{ "rtoMin",		KSTAT_DATA_INT32, 0 },
457721fffe3SKacheong Poon 		{ "rtoMax",		KSTAT_DATA_INT32, 0 },
458721fffe3SKacheong Poon 		{ "maxConn",		KSTAT_DATA_INT32, 0 },
459721fffe3SKacheong Poon 		{ "activeOpens",	KSTAT_DATA_UINT32, 0 },
460721fffe3SKacheong Poon 		{ "passiveOpens",	KSTAT_DATA_UINT32, 0 },
461721fffe3SKacheong Poon 		{ "attemptFails",	KSTAT_DATA_UINT32, 0 },
462721fffe3SKacheong Poon 		{ "estabResets",	KSTAT_DATA_UINT32, 0 },
463721fffe3SKacheong Poon 		{ "currEstab",		KSTAT_DATA_UINT32, 0 },
464721fffe3SKacheong Poon 		{ "inSegs",		KSTAT_DATA_UINT64, 0 },
465721fffe3SKacheong Poon 		{ "outSegs",		KSTAT_DATA_UINT64, 0 },
466721fffe3SKacheong Poon 		{ "retransSegs",	KSTAT_DATA_UINT32, 0 },
467721fffe3SKacheong Poon 		{ "connTableSize",	KSTAT_DATA_INT32, 0 },
468721fffe3SKacheong Poon 		{ "outRsts",		KSTAT_DATA_UINT32, 0 },
469721fffe3SKacheong Poon 		{ "outDataSegs",	KSTAT_DATA_UINT32, 0 },
470721fffe3SKacheong Poon 		{ "outDataBytes",	KSTAT_DATA_UINT32, 0 },
471721fffe3SKacheong Poon 		{ "retransBytes",	KSTAT_DATA_UINT32, 0 },
472721fffe3SKacheong Poon 		{ "outAck",		KSTAT_DATA_UINT32, 0 },
473721fffe3SKacheong Poon 		{ "outAckDelayed",	KSTAT_DATA_UINT32, 0 },
474721fffe3SKacheong Poon 		{ "outUrg",		KSTAT_DATA_UINT32, 0 },
475721fffe3SKacheong Poon 		{ "outWinUpdate",	KSTAT_DATA_UINT32, 0 },
476721fffe3SKacheong Poon 		{ "outWinProbe",	KSTAT_DATA_UINT32, 0 },
477721fffe3SKacheong Poon 		{ "outControl",		KSTAT_DATA_UINT32, 0 },
478721fffe3SKacheong Poon 		{ "outFastRetrans",	KSTAT_DATA_UINT32, 0 },
479721fffe3SKacheong Poon 		{ "inAckSegs",		KSTAT_DATA_UINT32, 0 },
480721fffe3SKacheong Poon 		{ "inAckBytes",		KSTAT_DATA_UINT32, 0 },
481721fffe3SKacheong Poon 		{ "inDupAck",		KSTAT_DATA_UINT32, 0 },
482721fffe3SKacheong Poon 		{ "inAckUnsent",	KSTAT_DATA_UINT32, 0 },
483721fffe3SKacheong Poon 		{ "inDataInorderSegs",	KSTAT_DATA_UINT32, 0 },
484721fffe3SKacheong Poon 		{ "inDataInorderBytes",	KSTAT_DATA_UINT32, 0 },
485721fffe3SKacheong Poon 		{ "inDataUnorderSegs",	KSTAT_DATA_UINT32, 0 },
486721fffe3SKacheong Poon 		{ "inDataUnorderBytes",	KSTAT_DATA_UINT32, 0 },
487721fffe3SKacheong Poon 		{ "inDataDupSegs",	KSTAT_DATA_UINT32, 0 },
488721fffe3SKacheong Poon 		{ "inDataDupBytes",	KSTAT_DATA_UINT32, 0 },
489721fffe3SKacheong Poon 		{ "inDataPartDupSegs",	KSTAT_DATA_UINT32, 0 },
490721fffe3SKacheong Poon 		{ "inDataPartDupBytes",	KSTAT_DATA_UINT32, 0 },
491721fffe3SKacheong Poon 		{ "inDataPastWinSegs",	KSTAT_DATA_UINT32, 0 },
492721fffe3SKacheong Poon 		{ "inDataPastWinBytes",	KSTAT_DATA_UINT32, 0 },
493721fffe3SKacheong Poon 		{ "inWinProbe",		KSTAT_DATA_UINT32, 0 },
494721fffe3SKacheong Poon 		{ "inWinUpdate",	KSTAT_DATA_UINT32, 0 },
495721fffe3SKacheong Poon 		{ "inClosed",		KSTAT_DATA_UINT32, 0 },
496721fffe3SKacheong Poon 		{ "rttUpdate",		KSTAT_DATA_UINT32, 0 },
497721fffe3SKacheong Poon 		{ "rttNoUpdate",	KSTAT_DATA_UINT32, 0 },
498721fffe3SKacheong Poon 		{ "timRetrans",		KSTAT_DATA_UINT32, 0 },
499721fffe3SKacheong Poon 		{ "timRetransDrop",	KSTAT_DATA_UINT32, 0 },
500721fffe3SKacheong Poon 		{ "timKeepalive",	KSTAT_DATA_UINT32, 0 },
501721fffe3SKacheong Poon 		{ "timKeepaliveProbe",	KSTAT_DATA_UINT32, 0 },
502721fffe3SKacheong Poon 		{ "timKeepaliveDrop",	KSTAT_DATA_UINT32, 0 },
503721fffe3SKacheong Poon 		{ "listenDrop",		KSTAT_DATA_UINT32, 0 },
504721fffe3SKacheong Poon 		{ "listenDropQ0",	KSTAT_DATA_UINT32, 0 },
505721fffe3SKacheong Poon 		{ "halfOpenDrop",	KSTAT_DATA_UINT32, 0 },
506721fffe3SKacheong Poon 		{ "outSackRetransSegs",	KSTAT_DATA_UINT32, 0 },
507721fffe3SKacheong Poon 		{ "connTableSize6",	KSTAT_DATA_INT32, 0 }
508721fffe3SKacheong Poon 	};
509721fffe3SKacheong Poon 
510*4a0bd071SBill Pijewski 	ksp = kstat_create_netstack(TCP_MOD_NAME, stackid, TCP_MOD_NAME, "mib2",
511721fffe3SKacheong Poon 	    KSTAT_TYPE_NAMED, NUM_OF_FIELDS(tcp_named_kstat_t), 0, stackid);
512721fffe3SKacheong Poon 
513721fffe3SKacheong Poon 	if (ksp == NULL)
514721fffe3SKacheong Poon 		return (NULL);
515721fffe3SKacheong Poon 
516721fffe3SKacheong Poon 	template.rtoAlgorithm.value.ui32 = 4;
517721fffe3SKacheong Poon 	template.maxConn.value.i32 = -1;
518721fffe3SKacheong Poon 
519721fffe3SKacheong Poon 	bcopy(&template, ksp->ks_data, sizeof (template));
520721fffe3SKacheong Poon 	ksp->ks_update = tcp_kstat_update;
521721fffe3SKacheong Poon 	ksp->ks_private = (void *)(uintptr_t)stackid;
522721fffe3SKacheong Poon 
523*4a0bd071SBill Pijewski 	/*
524*4a0bd071SBill Pijewski 	 * If this is an exclusive netstack for a local zone, the global zone
525*4a0bd071SBill Pijewski 	 * should still be able to read the kstat.
526*4a0bd071SBill Pijewski 	 */
527*4a0bd071SBill Pijewski 	if (stackid != GLOBAL_NETSTACKID)
528*4a0bd071SBill Pijewski 		kstat_zone_add(ksp, GLOBAL_ZONEID);
529*4a0bd071SBill Pijewski 
530721fffe3SKacheong Poon 	kstat_install(ksp);
531721fffe3SKacheong Poon 	return (ksp);
532721fffe3SKacheong Poon }
533721fffe3SKacheong Poon 
534721fffe3SKacheong Poon void
535721fffe3SKacheong Poon tcp_kstat_fini(netstackid_t stackid, kstat_t *ksp)
536721fffe3SKacheong Poon {
537721fffe3SKacheong Poon 	if (ksp != NULL) {
538721fffe3SKacheong Poon 		ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
539721fffe3SKacheong Poon 		kstat_delete_netstack(ksp, stackid);
540721fffe3SKacheong Poon 	}
541721fffe3SKacheong Poon }
542721fffe3SKacheong Poon 
543721fffe3SKacheong Poon static int
544721fffe3SKacheong Poon tcp_kstat_update(kstat_t *kp, int rw)
545721fffe3SKacheong Poon {
546721fffe3SKacheong Poon 	tcp_named_kstat_t *tcpkp;
547721fffe3SKacheong Poon 	tcp_t		*tcp;
548721fffe3SKacheong Poon 	connf_t		*connfp;
549721fffe3SKacheong Poon 	conn_t		*connp;
550721fffe3SKacheong Poon 	int 		i;
551721fffe3SKacheong Poon 	netstackid_t	stackid = (netstackid_t)(uintptr_t)kp->ks_private;
552721fffe3SKacheong Poon 	netstack_t	*ns;
553721fffe3SKacheong Poon 	tcp_stack_t	*tcps;
554721fffe3SKacheong Poon 	ip_stack_t	*ipst;
555721fffe3SKacheong Poon 	mib2_tcp_t	tcp_mib;
556721fffe3SKacheong Poon 
557721fffe3SKacheong Poon 	if (rw == KSTAT_WRITE)
558721fffe3SKacheong Poon 		return (EACCES);
559721fffe3SKacheong Poon 
560721fffe3SKacheong Poon 	ns = netstack_find_by_stackid(stackid);
561721fffe3SKacheong Poon 	if (ns == NULL)
562721fffe3SKacheong Poon 		return (-1);
563721fffe3SKacheong Poon 	tcps = ns->netstack_tcp;
564721fffe3SKacheong Poon 	if (tcps == NULL) {
565721fffe3SKacheong Poon 		netstack_rele(ns);
566721fffe3SKacheong Poon 		return (-1);
567721fffe3SKacheong Poon 	}
568721fffe3SKacheong Poon 
569721fffe3SKacheong Poon 	tcpkp = (tcp_named_kstat_t *)kp->ks_data;
570721fffe3SKacheong Poon 
571721fffe3SKacheong Poon 	tcpkp->currEstab.value.ui32 = 0;
572721fffe3SKacheong Poon 	tcpkp->rtoMin.value.ui32 = tcps->tcps_rexmit_interval_min;
573721fffe3SKacheong Poon 	tcpkp->rtoMax.value.ui32 = tcps->tcps_rexmit_interval_max;
574721fffe3SKacheong Poon 
575721fffe3SKacheong Poon 	ipst = ns->netstack_ip;
576721fffe3SKacheong Poon 
577721fffe3SKacheong Poon 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
578721fffe3SKacheong Poon 		connfp = &ipst->ips_ipcl_globalhash_fanout[i];
579721fffe3SKacheong Poon 		connp = NULL;
580721fffe3SKacheong Poon 		while ((connp =
581721fffe3SKacheong Poon 		    ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
582721fffe3SKacheong Poon 			tcp = connp->conn_tcp;
583721fffe3SKacheong Poon 			switch (tcp_snmp_state(tcp)) {
584721fffe3SKacheong Poon 			case MIB2_TCP_established:
585721fffe3SKacheong Poon 			case MIB2_TCP_closeWait:
586721fffe3SKacheong Poon 				tcpkp->currEstab.value.ui32++;
587721fffe3SKacheong Poon 				break;
588721fffe3SKacheong Poon 			}
589721fffe3SKacheong Poon 		}
590721fffe3SKacheong Poon 	}
591721fffe3SKacheong Poon 	bzero(&tcp_mib, sizeof (tcp_mib));
592721fffe3SKacheong Poon 	tcp_sum_mib(tcps, &tcp_mib);
593721fffe3SKacheong Poon 
5946f773e29SBaban Kenkre 	/* Fixed length structure for IPv4 and IPv6 counters */
5956f773e29SBaban Kenkre 	SET_MIB(tcp_mib.tcpConnTableSize, sizeof (mib2_tcpConnEntry_t));
5966f773e29SBaban Kenkre 	SET_MIB(tcp_mib.tcp6ConnTableSize, sizeof (mib2_tcp6ConnEntry_t));
5976f773e29SBaban Kenkre 
598721fffe3SKacheong Poon 	tcpkp->activeOpens.value.ui32 = tcp_mib.tcpActiveOpens;
599721fffe3SKacheong Poon 	tcpkp->passiveOpens.value.ui32 = tcp_mib.tcpPassiveOpens;
600721fffe3SKacheong Poon 	tcpkp->attemptFails.value.ui32 = tcp_mib.tcpAttemptFails;
601721fffe3SKacheong Poon 	tcpkp->estabResets.value.ui32 = tcp_mib.tcpEstabResets;
602721fffe3SKacheong Poon 	tcpkp->inSegs.value.ui64 = tcp_mib.tcpHCInSegs;
603721fffe3SKacheong Poon 	tcpkp->outSegs.value.ui64 = tcp_mib.tcpHCOutSegs;
604721fffe3SKacheong Poon 	tcpkp->retransSegs.value.ui32 =	tcp_mib.tcpRetransSegs;
605721fffe3SKacheong Poon 	tcpkp->connTableSize.value.i32 = tcp_mib.tcpConnTableSize;
606721fffe3SKacheong Poon 	tcpkp->outRsts.value.ui32 = tcp_mib.tcpOutRsts;
607721fffe3SKacheong Poon 	tcpkp->outDataSegs.value.ui32 = tcp_mib.tcpOutDataSegs;
608721fffe3SKacheong Poon 	tcpkp->outDataBytes.value.ui32 = tcp_mib.tcpOutDataBytes;
609721fffe3SKacheong Poon 	tcpkp->retransBytes.value.ui32 = tcp_mib.tcpRetransBytes;
610721fffe3SKacheong Poon 	tcpkp->outAck.value.ui32 = tcp_mib.tcpOutAck;
611721fffe3SKacheong Poon 	tcpkp->outAckDelayed.value.ui32 = tcp_mib.tcpOutAckDelayed;
612721fffe3SKacheong Poon 	tcpkp->outUrg.value.ui32 = tcp_mib.tcpOutUrg;
613721fffe3SKacheong Poon 	tcpkp->outWinUpdate.value.ui32 = tcp_mib.tcpOutWinUpdate;
614721fffe3SKacheong Poon 	tcpkp->outWinProbe.value.ui32 = tcp_mib.tcpOutWinProbe;
615721fffe3SKacheong Poon 	tcpkp->outControl.value.ui32 = tcp_mib.tcpOutControl;
616721fffe3SKacheong Poon 	tcpkp->outFastRetrans.value.ui32 = tcp_mib.tcpOutFastRetrans;
617721fffe3SKacheong Poon 	tcpkp->inAckSegs.value.ui32 = tcp_mib.tcpInAckSegs;
618721fffe3SKacheong Poon 	tcpkp->inAckBytes.value.ui32 = tcp_mib.tcpInAckBytes;
619721fffe3SKacheong Poon 	tcpkp->inDupAck.value.ui32 = tcp_mib.tcpInDupAck;
620721fffe3SKacheong Poon 	tcpkp->inAckUnsent.value.ui32 = tcp_mib.tcpInAckUnsent;
621721fffe3SKacheong Poon 	tcpkp->inDataInorderSegs.value.ui32 = tcp_mib.tcpInDataInorderSegs;
622721fffe3SKacheong Poon 	tcpkp->inDataInorderBytes.value.ui32 = tcp_mib.tcpInDataInorderBytes;
623721fffe3SKacheong Poon 	tcpkp->inDataUnorderSegs.value.ui32 = tcp_mib.tcpInDataUnorderSegs;
624721fffe3SKacheong Poon 	tcpkp->inDataUnorderBytes.value.ui32 = tcp_mib.tcpInDataUnorderBytes;
625721fffe3SKacheong Poon 	tcpkp->inDataDupSegs.value.ui32 = tcp_mib.tcpInDataDupSegs;
626721fffe3SKacheong Poon 	tcpkp->inDataDupBytes.value.ui32 = tcp_mib.tcpInDataDupBytes;
627721fffe3SKacheong Poon 	tcpkp->inDataPartDupSegs.value.ui32 = tcp_mib.tcpInDataPartDupSegs;
628721fffe3SKacheong Poon 	tcpkp->inDataPartDupBytes.value.ui32 = tcp_mib.tcpInDataPartDupBytes;
629721fffe3SKacheong Poon 	tcpkp->inDataPastWinSegs.value.ui32 = tcp_mib.tcpInDataPastWinSegs;
630721fffe3SKacheong Poon 	tcpkp->inDataPastWinBytes.value.ui32 = tcp_mib.tcpInDataPastWinBytes;
631721fffe3SKacheong Poon 	tcpkp->inWinProbe.value.ui32 = tcp_mib.tcpInWinProbe;
632721fffe3SKacheong Poon 	tcpkp->inWinUpdate.value.ui32 = tcp_mib.tcpInWinUpdate;
633721fffe3SKacheong Poon 	tcpkp->inClosed.value.ui32 = tcp_mib.tcpInClosed;
634721fffe3SKacheong Poon 	tcpkp->rttNoUpdate.value.ui32 = tcp_mib.tcpRttNoUpdate;
635721fffe3SKacheong Poon 	tcpkp->rttUpdate.value.ui32 = tcp_mib.tcpRttUpdate;
636721fffe3SKacheong Poon 	tcpkp->timRetrans.value.ui32 = tcp_mib.tcpTimRetrans;
637721fffe3SKacheong Poon 	tcpkp->timRetransDrop.value.ui32 = tcp_mib.tcpTimRetransDrop;
638721fffe3SKacheong Poon 	tcpkp->timKeepalive.value.ui32 = tcp_mib.tcpTimKeepalive;
639721fffe3SKacheong Poon 	tcpkp->timKeepaliveProbe.value.ui32 = tcp_mib.tcpTimKeepaliveProbe;
640721fffe3SKacheong Poon 	tcpkp->timKeepaliveDrop.value.ui32 = tcp_mib.tcpTimKeepaliveDrop;
641721fffe3SKacheong Poon 	tcpkp->listenDrop.value.ui32 = tcp_mib.tcpListenDrop;
642721fffe3SKacheong Poon 	tcpkp->listenDropQ0.value.ui32 = tcp_mib.tcpListenDropQ0;
643721fffe3SKacheong Poon 	tcpkp->halfOpenDrop.value.ui32 = tcp_mib.tcpHalfOpenDrop;
644721fffe3SKacheong Poon 	tcpkp->outSackRetransSegs.value.ui32 = tcp_mib.tcpOutSackRetransSegs;
645721fffe3SKacheong Poon 	tcpkp->connTableSize6.value.i32 = tcp_mib.tcp6ConnTableSize;
646721fffe3SKacheong Poon 
647721fffe3SKacheong Poon 	netstack_rele(ns);
648721fffe3SKacheong Poon 	return (0);
649721fffe3SKacheong Poon }
650721fffe3SKacheong Poon 
651721fffe3SKacheong Poon /*
652721fffe3SKacheong Poon  * kstats related to squeues i.e. not per IP instance
653721fffe3SKacheong Poon  */
654721fffe3SKacheong Poon void *
655721fffe3SKacheong Poon tcp_g_kstat_init(tcp_g_stat_t *tcp_g_statp)
656721fffe3SKacheong Poon {
657721fffe3SKacheong Poon 	kstat_t *ksp;
658721fffe3SKacheong Poon 
659721fffe3SKacheong Poon 	tcp_g_stat_t template = {
660721fffe3SKacheong Poon 		{ "tcp_timermp_alloced",	KSTAT_DATA_UINT64 },
661721fffe3SKacheong Poon 		{ "tcp_timermp_allocfail",	KSTAT_DATA_UINT64 },
662721fffe3SKacheong Poon 		{ "tcp_timermp_allocdblfail",	KSTAT_DATA_UINT64 },
663721fffe3SKacheong Poon 		{ "tcp_freelist_cleanup",	KSTAT_DATA_UINT64 },
664721fffe3SKacheong Poon 	};
665721fffe3SKacheong Poon 
666721fffe3SKacheong Poon 	ksp = kstat_create(TCP_MOD_NAME, 0, "tcpstat_g", "net",
667721fffe3SKacheong Poon 	    KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t),
668721fffe3SKacheong Poon 	    KSTAT_FLAG_VIRTUAL);
669721fffe3SKacheong Poon 
670721fffe3SKacheong Poon 	if (ksp == NULL)
671721fffe3SKacheong Poon 		return (NULL);
672721fffe3SKacheong Poon 
673721fffe3SKacheong Poon 	bcopy(&template, tcp_g_statp, sizeof (template));
674721fffe3SKacheong Poon 	ksp->ks_data = (void *)tcp_g_statp;
675721fffe3SKacheong Poon 
676721fffe3SKacheong Poon 	kstat_install(ksp);
677721fffe3SKacheong Poon 	return (ksp);
678721fffe3SKacheong Poon }
679721fffe3SKacheong Poon 
680721fffe3SKacheong Poon void
681721fffe3SKacheong Poon tcp_g_kstat_fini(kstat_t *ksp)
682721fffe3SKacheong Poon {
683721fffe3SKacheong Poon 	if (ksp != NULL) {
684721fffe3SKacheong Poon 		kstat_delete(ksp);
685721fffe3SKacheong Poon 	}
686721fffe3SKacheong Poon }
687721fffe3SKacheong Poon 
688721fffe3SKacheong Poon void *
689721fffe3SKacheong Poon tcp_kstat2_init(netstackid_t stackid)
690721fffe3SKacheong Poon {
691721fffe3SKacheong Poon 	kstat_t *ksp;
692721fffe3SKacheong Poon 
693721fffe3SKacheong Poon 	tcp_stat_t template = {
694721fffe3SKacheong Poon 		{ "tcp_time_wait_syn_success",	KSTAT_DATA_UINT64, 0 },
695721fffe3SKacheong Poon 		{ "tcp_clean_death_nondetached",	KSTAT_DATA_UINT64, 0 },
696721fffe3SKacheong Poon 		{ "tcp_eager_blowoff_q",	KSTAT_DATA_UINT64, 0 },
697721fffe3SKacheong Poon 		{ "tcp_eager_blowoff_q0",	KSTAT_DATA_UINT64, 0 },
698721fffe3SKacheong Poon 		{ "tcp_no_listener",		KSTAT_DATA_UINT64, 0 },
699721fffe3SKacheong Poon 		{ "tcp_listendrop",		KSTAT_DATA_UINT64, 0 },
700721fffe3SKacheong Poon 		{ "tcp_listendropq0",		KSTAT_DATA_UINT64, 0 },
701721fffe3SKacheong Poon 		{ "tcp_wsrv_called",		KSTAT_DATA_UINT64, 0 },
702721fffe3SKacheong Poon 		{ "tcp_flwctl_on",		KSTAT_DATA_UINT64, 0 },
703721fffe3SKacheong Poon 		{ "tcp_timer_fire_early",	KSTAT_DATA_UINT64, 0 },
704721fffe3SKacheong Poon 		{ "tcp_timer_fire_miss",	KSTAT_DATA_UINT64, 0 },
705721fffe3SKacheong Poon 		{ "tcp_zcopy_on",		KSTAT_DATA_UINT64, 0 },
706721fffe3SKacheong Poon 		{ "tcp_zcopy_off",		KSTAT_DATA_UINT64, 0 },
707721fffe3SKacheong Poon 		{ "tcp_zcopy_backoff",		KSTAT_DATA_UINT64, 0 },
708721fffe3SKacheong Poon 		{ "tcp_fusion_flowctl",		KSTAT_DATA_UINT64, 0 },
709721fffe3SKacheong Poon 		{ "tcp_fusion_backenabled",	KSTAT_DATA_UINT64, 0 },
710721fffe3SKacheong Poon 		{ "tcp_fusion_urg",		KSTAT_DATA_UINT64, 0 },
711721fffe3SKacheong Poon 		{ "tcp_fusion_putnext",		KSTAT_DATA_UINT64, 0 },
712721fffe3SKacheong Poon 		{ "tcp_fusion_unfusable",	KSTAT_DATA_UINT64, 0 },
713721fffe3SKacheong Poon 		{ "tcp_fusion_aborted",		KSTAT_DATA_UINT64, 0 },
714721fffe3SKacheong Poon 		{ "tcp_fusion_unqualified",	KSTAT_DATA_UINT64, 0 },
715721fffe3SKacheong Poon 		{ "tcp_fusion_rrw_busy",	KSTAT_DATA_UINT64, 0 },
716721fffe3SKacheong Poon 		{ "tcp_fusion_rrw_msgcnt",	KSTAT_DATA_UINT64, 0 },
717721fffe3SKacheong Poon 		{ "tcp_fusion_rrw_plugged",	KSTAT_DATA_UINT64, 0 },
718721fffe3SKacheong Poon 		{ "tcp_in_ack_unsent_drop",	KSTAT_DATA_UINT64, 0 },
719721fffe3SKacheong Poon 		{ "tcp_sock_fallback",		KSTAT_DATA_UINT64, 0 },
720721fffe3SKacheong Poon 		{ "tcp_lso_enabled",		KSTAT_DATA_UINT64, 0 },
721721fffe3SKacheong Poon 		{ "tcp_lso_disabled",		KSTAT_DATA_UINT64, 0 },
722721fffe3SKacheong Poon 		{ "tcp_lso_times",		KSTAT_DATA_UINT64, 0 },
723721fffe3SKacheong Poon 		{ "tcp_lso_pkt_out",		KSTAT_DATA_UINT64, 0 },
724721fffe3SKacheong Poon 		{ "tcp_listen_cnt_drop",	KSTAT_DATA_UINT64, 0 },
725721fffe3SKacheong Poon 		{ "tcp_listen_mem_drop",	KSTAT_DATA_UINT64, 0 },
726721fffe3SKacheong Poon 		{ "tcp_zwin_mem_drop",		KSTAT_DATA_UINT64, 0 },
727721fffe3SKacheong Poon 		{ "tcp_zwin_ack_syn",		KSTAT_DATA_UINT64, 0 },
728721fffe3SKacheong Poon 		{ "tcp_rst_unsent",		KSTAT_DATA_UINT64, 0 },
729721fffe3SKacheong Poon 		{ "tcp_reclaim_cnt",		KSTAT_DATA_UINT64, 0 },
730721fffe3SKacheong Poon 		{ "tcp_reass_timeout",		KSTAT_DATA_UINT64, 0 },
731721fffe3SKacheong Poon #ifdef TCP_DEBUG_COUNTER
732721fffe3SKacheong Poon 		{ "tcp_time_wait",		KSTAT_DATA_UINT64, 0 },
733721fffe3SKacheong Poon 		{ "tcp_rput_time_wait",		KSTAT_DATA_UINT64, 0 },
734721fffe3SKacheong Poon 		{ "tcp_detach_time_wait",	KSTAT_DATA_UINT64, 0 },
735721fffe3SKacheong Poon 		{ "tcp_timeout_calls",		KSTAT_DATA_UINT64, 0 },
736721fffe3SKacheong Poon 		{ "tcp_timeout_cached_alloc",	KSTAT_DATA_UINT64, 0 },
737721fffe3SKacheong Poon 		{ "tcp_timeout_cancel_reqs",	KSTAT_DATA_UINT64, 0 },
738721fffe3SKacheong Poon 		{ "tcp_timeout_canceled",	KSTAT_DATA_UINT64, 0 },
739721fffe3SKacheong Poon 		{ "tcp_timermp_freed",		KSTAT_DATA_UINT64, 0 },
740721fffe3SKacheong Poon 		{ "tcp_push_timer_cnt",		KSTAT_DATA_UINT64, 0 },
741721fffe3SKacheong Poon 		{ "tcp_ack_timer_cnt",		KSTAT_DATA_UINT64, 0 },
742721fffe3SKacheong Poon #endif
743721fffe3SKacheong Poon 	};
744721fffe3SKacheong Poon 
745*4a0bd071SBill Pijewski 	ksp = kstat_create_netstack(TCP_MOD_NAME, stackid, "tcpstat", "net",
746721fffe3SKacheong Poon 	    KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t), 0,
747721fffe3SKacheong Poon 	    stackid);
748721fffe3SKacheong Poon 
749721fffe3SKacheong Poon 	if (ksp == NULL)
750721fffe3SKacheong Poon 		return (NULL);
751721fffe3SKacheong Poon 
752721fffe3SKacheong Poon 	bcopy(&template, ksp->ks_data, sizeof (template));
753721fffe3SKacheong Poon 	ksp->ks_private = (void *)(uintptr_t)stackid;
754721fffe3SKacheong Poon 	ksp->ks_update = tcp_kstat2_update;
755721fffe3SKacheong Poon 
756*4a0bd071SBill Pijewski 	/*
757*4a0bd071SBill Pijewski 	 * If this is an exclusive netstack for a local zone, the global zone
758*4a0bd071SBill Pijewski 	 * should still be able to read the kstat.
759*4a0bd071SBill Pijewski 	 */
760*4a0bd071SBill Pijewski 	if (stackid != GLOBAL_NETSTACKID)
761*4a0bd071SBill Pijewski 		kstat_zone_add(ksp, GLOBAL_ZONEID);
762*4a0bd071SBill Pijewski 
763721fffe3SKacheong Poon 	kstat_install(ksp);
764721fffe3SKacheong Poon 	return (ksp);
765721fffe3SKacheong Poon }
766721fffe3SKacheong Poon 
767721fffe3SKacheong Poon void
768721fffe3SKacheong Poon tcp_kstat2_fini(netstackid_t stackid, kstat_t *ksp)
769721fffe3SKacheong Poon {
770721fffe3SKacheong Poon 	if (ksp != NULL) {
771721fffe3SKacheong Poon 		ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
772721fffe3SKacheong Poon 		kstat_delete_netstack(ksp, stackid);
773721fffe3SKacheong Poon 	}
774721fffe3SKacheong Poon }
775721fffe3SKacheong Poon 
776721fffe3SKacheong Poon /*
777721fffe3SKacheong Poon  * Sum up all per CPU tcp_stat_t kstat counters.
778721fffe3SKacheong Poon  */
779721fffe3SKacheong Poon static int
780721fffe3SKacheong Poon tcp_kstat2_update(kstat_t *kp, int rw)
781721fffe3SKacheong Poon {
782721fffe3SKacheong Poon 	netstackid_t	stackid = (netstackid_t)(uintptr_t)kp->ks_private;
783721fffe3SKacheong Poon 	netstack_t	*ns;
784721fffe3SKacheong Poon 	tcp_stack_t	*tcps;
785721fffe3SKacheong Poon 	tcp_stat_t	*stats;
786721fffe3SKacheong Poon 	int		i;
787721fffe3SKacheong Poon 	int		cnt;
788721fffe3SKacheong Poon 
789721fffe3SKacheong Poon 	if (rw == KSTAT_WRITE)
790721fffe3SKacheong Poon 		return (EACCES);
791721fffe3SKacheong Poon 
792721fffe3SKacheong Poon 	ns = netstack_find_by_stackid(stackid);
793721fffe3SKacheong Poon 	if (ns == NULL)
794721fffe3SKacheong Poon 		return (-1);
795721fffe3SKacheong Poon 	tcps = ns->netstack_tcp;
796721fffe3SKacheong Poon 	if (tcps == NULL) {
797721fffe3SKacheong Poon 		netstack_rele(ns);
798721fffe3SKacheong Poon 		return (-1);
799721fffe3SKacheong Poon 	}
800721fffe3SKacheong Poon 
801721fffe3SKacheong Poon 	stats = (tcp_stat_t *)kp->ks_data;
802721fffe3SKacheong Poon 	tcp_clr_stats(stats);
803721fffe3SKacheong Poon 
804721fffe3SKacheong Poon 	/*
805721fffe3SKacheong Poon 	 * tcps_sc_cnt may change in the middle of the loop.  It is better
806721fffe3SKacheong Poon 	 * to get its value first.
807721fffe3SKacheong Poon 	 */
808721fffe3SKacheong Poon 	cnt = tcps->tcps_sc_cnt;
809721fffe3SKacheong Poon 	for (i = 0; i < cnt; i++)
8105dd46ab5SKacheong Poon 		tcp_add_stats(&tcps->tcps_sc[i]->tcp_sc_stats, stats);
811721fffe3SKacheong Poon 
812721fffe3SKacheong Poon 	netstack_rele(ns);
813721fffe3SKacheong Poon 	return (0);
814721fffe3SKacheong Poon }
815721fffe3SKacheong Poon 
816721fffe3SKacheong Poon /*
8175dd46ab5SKacheong Poon  * To add stats from one mib2_tcp_t to another.  Static fields are not added.
818721fffe3SKacheong Poon  * The caller should set them up propertly.
819721fffe3SKacheong Poon  */
820ca3c8f41SDavid Höppner static void
8215dd46ab5SKacheong Poon tcp_add_mib(mib2_tcp_t *from, mib2_tcp_t *to)
822721fffe3SKacheong Poon {
823721fffe3SKacheong Poon 	to->tcpActiveOpens += from->tcpActiveOpens;
824721fffe3SKacheong Poon 	to->tcpPassiveOpens += from->tcpPassiveOpens;
825721fffe3SKacheong Poon 	to->tcpAttemptFails += from->tcpAttemptFails;
826721fffe3SKacheong Poon 	to->tcpEstabResets += from->tcpEstabResets;
827721fffe3SKacheong Poon 	to->tcpInSegs += from->tcpInSegs;
828721fffe3SKacheong Poon 	to->tcpOutSegs += from->tcpOutSegs;
829721fffe3SKacheong Poon 	to->tcpRetransSegs += from->tcpRetransSegs;
830721fffe3SKacheong Poon 	to->tcpOutRsts += from->tcpOutRsts;
831721fffe3SKacheong Poon 
832721fffe3SKacheong Poon 	to->tcpOutDataSegs += from->tcpOutDataSegs;
833721fffe3SKacheong Poon 	to->tcpOutDataBytes += from->tcpOutDataBytes;
834721fffe3SKacheong Poon 	to->tcpRetransBytes += from->tcpRetransBytes;
835721fffe3SKacheong Poon 	to->tcpOutAck += from->tcpOutAck;
836721fffe3SKacheong Poon 	to->tcpOutAckDelayed += from->tcpOutAckDelayed;
837721fffe3SKacheong Poon 	to->tcpOutUrg += from->tcpOutUrg;
838721fffe3SKacheong Poon 	to->tcpOutWinUpdate += from->tcpOutWinUpdate;
839721fffe3SKacheong Poon 	to->tcpOutWinProbe += from->tcpOutWinProbe;
840721fffe3SKacheong Poon 	to->tcpOutControl += from->tcpOutControl;
841721fffe3SKacheong Poon 	to->tcpOutFastRetrans += from->tcpOutFastRetrans;
842721fffe3SKacheong Poon 
843721fffe3SKacheong Poon 	to->tcpInAckBytes += from->tcpInAckBytes;
844721fffe3SKacheong Poon 	to->tcpInDupAck += from->tcpInDupAck;
845721fffe3SKacheong Poon 	to->tcpInAckUnsent += from->tcpInAckUnsent;
846721fffe3SKacheong Poon 	to->tcpInDataInorderSegs += from->tcpInDataInorderSegs;
847721fffe3SKacheong Poon 	to->tcpInDataInorderBytes += from->tcpInDataInorderBytes;
848721fffe3SKacheong Poon 	to->tcpInDataUnorderSegs += from->tcpInDataUnorderSegs;
849721fffe3SKacheong Poon 	to->tcpInDataUnorderBytes += from->tcpInDataUnorderBytes;
850721fffe3SKacheong Poon 	to->tcpInDataDupSegs += from->tcpInDataDupSegs;
851721fffe3SKacheong Poon 	to->tcpInDataDupBytes += from->tcpInDataDupBytes;
852721fffe3SKacheong Poon 	to->tcpInDataPartDupSegs += from->tcpInDataPartDupSegs;
853721fffe3SKacheong Poon 	to->tcpInDataPartDupBytes += from->tcpInDataPartDupBytes;
854721fffe3SKacheong Poon 	to->tcpInDataPastWinSegs += from->tcpInDataPastWinSegs;
855721fffe3SKacheong Poon 	to->tcpInDataPastWinBytes += from->tcpInDataPastWinBytes;
856721fffe3SKacheong Poon 	to->tcpInWinProbe += from->tcpInWinProbe;
857721fffe3SKacheong Poon 	to->tcpInWinUpdate += from->tcpInWinUpdate;
858721fffe3SKacheong Poon 	to->tcpInClosed += from->tcpInClosed;
859721fffe3SKacheong Poon 
860721fffe3SKacheong Poon 	to->tcpRttNoUpdate += from->tcpRttNoUpdate;
861721fffe3SKacheong Poon 	to->tcpRttUpdate += from->tcpRttUpdate;
862721fffe3SKacheong Poon 	to->tcpTimRetrans += from->tcpTimRetrans;
863721fffe3SKacheong Poon 	to->tcpTimRetransDrop += from->tcpTimRetransDrop;
864721fffe3SKacheong Poon 	to->tcpTimKeepalive += from->tcpTimKeepalive;
865721fffe3SKacheong Poon 	to->tcpTimKeepaliveProbe += from->tcpTimKeepaliveProbe;
866721fffe3SKacheong Poon 	to->tcpTimKeepaliveDrop += from->tcpTimKeepaliveDrop;
867721fffe3SKacheong Poon 	to->tcpListenDrop += from->tcpListenDrop;
868721fffe3SKacheong Poon 	to->tcpListenDropQ0 += from->tcpListenDropQ0;
869721fffe3SKacheong Poon 	to->tcpHalfOpenDrop += from->tcpHalfOpenDrop;
870721fffe3SKacheong Poon 	to->tcpOutSackRetransSegs += from->tcpOutSackRetransSegs;
871721fffe3SKacheong Poon 	to->tcpHCInSegs += from->tcpHCInSegs;
872721fffe3SKacheong Poon 	to->tcpHCOutSegs += from->tcpHCOutSegs;
873721fffe3SKacheong Poon }
874721fffe3SKacheong Poon 
875721fffe3SKacheong Poon /*
876721fffe3SKacheong Poon  * To sum up all MIB2 stats for a tcp_stack_t from all per CPU stats.  The
877721fffe3SKacheong Poon  * caller should initialize the target mib2_tcp_t properly as this function
878721fffe3SKacheong Poon  * just adds up all the per CPU stats.
879721fffe3SKacheong Poon  */
880721fffe3SKacheong Poon static void
881721fffe3SKacheong Poon tcp_sum_mib(tcp_stack_t *tcps, mib2_tcp_t *tcp_mib)
882721fffe3SKacheong Poon {
883721fffe3SKacheong Poon 	int i;
884721fffe3SKacheong Poon 	int cnt;
885721fffe3SKacheong Poon 
886721fffe3SKacheong Poon 	/*
887721fffe3SKacheong Poon 	 * tcps_sc_cnt may change in the middle of the loop.  It is better
888721fffe3SKacheong Poon 	 * to get its value first.
889721fffe3SKacheong Poon 	 */
890721fffe3SKacheong Poon 	cnt = tcps->tcps_sc_cnt;
891721fffe3SKacheong Poon 	for (i = 0; i < cnt; i++)
8925dd46ab5SKacheong Poon 		tcp_add_mib(&tcps->tcps_sc[i]->tcp_sc_mib, tcp_mib);
893721fffe3SKacheong Poon }
894721fffe3SKacheong Poon 
895721fffe3SKacheong Poon /*
896721fffe3SKacheong Poon  * To set all tcp_stat_t counters to 0.
897721fffe3SKacheong Poon  */
8985dd46ab5SKacheong Poon static void
899721fffe3SKacheong Poon tcp_clr_stats(tcp_stat_t *stats)
900721fffe3SKacheong Poon {
901721fffe3SKacheong Poon 	stats->tcp_time_wait_syn_success.value.ui64 = 0;
902721fffe3SKacheong Poon 	stats->tcp_clean_death_nondetached.value.ui64 = 0;
903721fffe3SKacheong Poon 	stats->tcp_eager_blowoff_q.value.ui64 = 0;
904721fffe3SKacheong Poon 	stats->tcp_eager_blowoff_q0.value.ui64 = 0;
905721fffe3SKacheong Poon 	stats->tcp_no_listener.value.ui64 = 0;
906721fffe3SKacheong Poon 	stats->tcp_listendrop.value.ui64 = 0;
907721fffe3SKacheong Poon 	stats->tcp_listendropq0.value.ui64 = 0;
908721fffe3SKacheong Poon 	stats->tcp_wsrv_called.value.ui64 = 0;
909721fffe3SKacheong Poon 	stats->tcp_flwctl_on.value.ui64 = 0;
910721fffe3SKacheong Poon 	stats->tcp_timer_fire_early.value.ui64 = 0;
911721fffe3SKacheong Poon 	stats->tcp_timer_fire_miss.value.ui64 = 0;
912721fffe3SKacheong Poon 	stats->tcp_zcopy_on.value.ui64 = 0;
913721fffe3SKacheong Poon 	stats->tcp_zcopy_off.value.ui64 = 0;
914721fffe3SKacheong Poon 	stats->tcp_zcopy_backoff.value.ui64 = 0;
915721fffe3SKacheong Poon 	stats->tcp_fusion_flowctl.value.ui64 = 0;
916721fffe3SKacheong Poon 	stats->tcp_fusion_backenabled.value.ui64 = 0;
917721fffe3SKacheong Poon 	stats->tcp_fusion_urg.value.ui64 = 0;
918721fffe3SKacheong Poon 	stats->tcp_fusion_putnext.value.ui64 = 0;
919721fffe3SKacheong Poon 	stats->tcp_fusion_unfusable.value.ui64 = 0;
920721fffe3SKacheong Poon 	stats->tcp_fusion_aborted.value.ui64 = 0;
921721fffe3SKacheong Poon 	stats->tcp_fusion_unqualified.value.ui64 = 0;
922721fffe3SKacheong Poon 	stats->tcp_fusion_rrw_busy.value.ui64 = 0;
923721fffe3SKacheong Poon 	stats->tcp_fusion_rrw_msgcnt.value.ui64 = 0;
924721fffe3SKacheong Poon 	stats->tcp_fusion_rrw_plugged.value.ui64 = 0;
925721fffe3SKacheong Poon 	stats->tcp_in_ack_unsent_drop.value.ui64 = 0;
926721fffe3SKacheong Poon 	stats->tcp_sock_fallback.value.ui64 = 0;
927721fffe3SKacheong Poon 	stats->tcp_lso_enabled.value.ui64 = 0;
928721fffe3SKacheong Poon 	stats->tcp_lso_disabled.value.ui64 = 0;
929721fffe3SKacheong Poon 	stats->tcp_lso_times.value.ui64 = 0;
930721fffe3SKacheong Poon 	stats->tcp_lso_pkt_out.value.ui64 = 0;
931721fffe3SKacheong Poon 	stats->tcp_listen_cnt_drop.value.ui64 = 0;
932721fffe3SKacheong Poon 	stats->tcp_listen_mem_drop.value.ui64 = 0;
933721fffe3SKacheong Poon 	stats->tcp_zwin_mem_drop.value.ui64 = 0;
934721fffe3SKacheong Poon 	stats->tcp_zwin_ack_syn.value.ui64 = 0;
935721fffe3SKacheong Poon 	stats->tcp_rst_unsent.value.ui64 = 0;
936721fffe3SKacheong Poon 	stats->tcp_reclaim_cnt.value.ui64 = 0;
937721fffe3SKacheong Poon 	stats->tcp_reass_timeout.value.ui64 = 0;
938721fffe3SKacheong Poon 
939721fffe3SKacheong Poon #ifdef TCP_DEBUG_COUNTER
940721fffe3SKacheong Poon 	stats->tcp_time_wait.value.ui64 = 0;
941721fffe3SKacheong Poon 	stats->tcp_rput_time_wait.value.ui64 = 0;
942721fffe3SKacheong Poon 	stats->tcp_detach_time_wait.value.ui64 = 0;
943721fffe3SKacheong Poon 	stats->tcp_timeout_calls.value.ui64 = 0;
944721fffe3SKacheong Poon 	stats->tcp_timeout_cached_alloc.value.ui64 = 0;
945721fffe3SKacheong Poon 	stats->tcp_timeout_cancel_reqs.value.ui64 = 0;
946721fffe3SKacheong Poon 	stats->tcp_timeout_canceled.value.ui64 = 0;
947721fffe3SKacheong Poon 	stats->tcp_timermp_freed.value.ui64 = 0;
948721fffe3SKacheong Poon 	stats->tcp_push_timer_cnt.value.ui64 = 0;
949721fffe3SKacheong Poon 	stats->tcp_ack_timer_cnt.value.ui64 = 0;
950721fffe3SKacheong Poon #endif
951721fffe3SKacheong Poon }
952721fffe3SKacheong Poon 
953721fffe3SKacheong Poon /*
9545dd46ab5SKacheong Poon  * To add counters from the per CPU tcp_stat_counter_t to the stack
9555dd46ab5SKacheong Poon  * tcp_stat_t.
956721fffe3SKacheong Poon  */
9575dd46ab5SKacheong Poon static void
9585dd46ab5SKacheong Poon tcp_add_stats(tcp_stat_counter_t *from, tcp_stat_t *to)
959721fffe3SKacheong Poon {
960721fffe3SKacheong Poon 	to->tcp_time_wait_syn_success.value.ui64 +=
9615dd46ab5SKacheong Poon 	    from->tcp_time_wait_syn_success;
962721fffe3SKacheong Poon 	to->tcp_clean_death_nondetached.value.ui64 +=
9635dd46ab5SKacheong Poon 	    from->tcp_clean_death_nondetached;
964721fffe3SKacheong Poon 	to->tcp_eager_blowoff_q.value.ui64 +=
9655dd46ab5SKacheong Poon 	    from->tcp_eager_blowoff_q;
966721fffe3SKacheong Poon 	to->tcp_eager_blowoff_q0.value.ui64 +=
9675dd46ab5SKacheong Poon 	    from->tcp_eager_blowoff_q0;
968721fffe3SKacheong Poon 	to->tcp_no_listener.value.ui64 +=
9695dd46ab5SKacheong Poon 	    from->tcp_no_listener;
970721fffe3SKacheong Poon 	to->tcp_listendrop.value.ui64 +=
9715dd46ab5SKacheong Poon 	    from->tcp_listendrop;
972721fffe3SKacheong Poon 	to->tcp_listendropq0.value.ui64 +=
9735dd46ab5SKacheong Poon 	    from->tcp_listendropq0;
974721fffe3SKacheong Poon 	to->tcp_wsrv_called.value.ui64 +=
9755dd46ab5SKacheong Poon 	    from->tcp_wsrv_called;
976721fffe3SKacheong Poon 	to->tcp_flwctl_on.value.ui64 +=
9775dd46ab5SKacheong Poon 	    from->tcp_flwctl_on;
978721fffe3SKacheong Poon 	to->tcp_timer_fire_early.value.ui64 +=
9795dd46ab5SKacheong Poon 	    from->tcp_timer_fire_early;
980721fffe3SKacheong Poon 	to->tcp_timer_fire_miss.value.ui64 +=
9815dd46ab5SKacheong Poon 	    from->tcp_timer_fire_miss;
982721fffe3SKacheong Poon 	to->tcp_zcopy_on.value.ui64 +=
9835dd46ab5SKacheong Poon 	    from->tcp_zcopy_on;
984721fffe3SKacheong Poon 	to->tcp_zcopy_off.value.ui64 +=
9855dd46ab5SKacheong Poon 	    from->tcp_zcopy_off;
986721fffe3SKacheong Poon 	to->tcp_zcopy_backoff.value.ui64 +=
9875dd46ab5SKacheong Poon 	    from->tcp_zcopy_backoff;
988721fffe3SKacheong Poon 	to->tcp_fusion_flowctl.value.ui64 +=
9895dd46ab5SKacheong Poon 	    from->tcp_fusion_flowctl;
990721fffe3SKacheong Poon 	to->tcp_fusion_backenabled.value.ui64 +=
9915dd46ab5SKacheong Poon 	    from->tcp_fusion_backenabled;
992721fffe3SKacheong Poon 	to->tcp_fusion_urg.value.ui64 +=
9935dd46ab5SKacheong Poon 	    from->tcp_fusion_urg;
994721fffe3SKacheong Poon 	to->tcp_fusion_putnext.value.ui64 +=
9955dd46ab5SKacheong Poon 	    from->tcp_fusion_putnext;
996721fffe3SKacheong Poon 	to->tcp_fusion_unfusable.value.ui64 +=
9975dd46ab5SKacheong Poon 	    from->tcp_fusion_unfusable;
998721fffe3SKacheong Poon 	to->tcp_fusion_aborted.value.ui64 +=
9995dd46ab5SKacheong Poon 	    from->tcp_fusion_aborted;
1000721fffe3SKacheong Poon 	to->tcp_fusion_unqualified.value.ui64 +=
10015dd46ab5SKacheong Poon 	    from->tcp_fusion_unqualified;
1002721fffe3SKacheong Poon 	to->tcp_fusion_rrw_busy.value.ui64 +=
10035dd46ab5SKacheong Poon 	    from->tcp_fusion_rrw_busy;
1004721fffe3SKacheong Poon 	to->tcp_fusion_rrw_msgcnt.value.ui64 +=
10055dd46ab5SKacheong Poon 	    from->tcp_fusion_rrw_msgcnt;
1006721fffe3SKacheong Poon 	to->tcp_fusion_rrw_plugged.value.ui64 +=
10075dd46ab5SKacheong Poon 	    from->tcp_fusion_rrw_plugged;
1008721fffe3SKacheong Poon 	to->tcp_in_ack_unsent_drop.value.ui64 +=
10095dd46ab5SKacheong Poon 	    from->tcp_in_ack_unsent_drop;
1010721fffe3SKacheong Poon 	to->tcp_sock_fallback.value.ui64 +=
10115dd46ab5SKacheong Poon 	    from->tcp_sock_fallback;
1012721fffe3SKacheong Poon 	to->tcp_lso_enabled.value.ui64 +=
10135dd46ab5SKacheong Poon 	    from->tcp_lso_enabled;
1014721fffe3SKacheong Poon 	to->tcp_lso_disabled.value.ui64 +=
10155dd46ab5SKacheong Poon 	    from->tcp_lso_disabled;
1016721fffe3SKacheong Poon 	to->tcp_lso_times.value.ui64 +=
10175dd46ab5SKacheong Poon 	    from->tcp_lso_times;
1018721fffe3SKacheong Poon 	to->tcp_lso_pkt_out.value.ui64 +=
10195dd46ab5SKacheong Poon 	    from->tcp_lso_pkt_out;
1020721fffe3SKacheong Poon 	to->tcp_listen_cnt_drop.value.ui64 +=
10215dd46ab5SKacheong Poon 	    from->tcp_listen_cnt_drop;
1022721fffe3SKacheong Poon 	to->tcp_listen_mem_drop.value.ui64 +=
10235dd46ab5SKacheong Poon 	    from->tcp_listen_mem_drop;
1024721fffe3SKacheong Poon 	to->tcp_zwin_mem_drop.value.ui64 +=
10255dd46ab5SKacheong Poon 	    from->tcp_zwin_mem_drop;
1026721fffe3SKacheong Poon 	to->tcp_zwin_ack_syn.value.ui64 +=
10275dd46ab5SKacheong Poon 	    from->tcp_zwin_ack_syn;
1028721fffe3SKacheong Poon 	to->tcp_rst_unsent.value.ui64 +=
10295dd46ab5SKacheong Poon 	    from->tcp_rst_unsent;
1030721fffe3SKacheong Poon 	to->tcp_reclaim_cnt.value.ui64 +=
10315dd46ab5SKacheong Poon 	    from->tcp_reclaim_cnt;
1032721fffe3SKacheong Poon 	to->tcp_reass_timeout.value.ui64 +=
10335dd46ab5SKacheong Poon 	    from->tcp_reass_timeout;
1034721fffe3SKacheong Poon 
1035721fffe3SKacheong Poon #ifdef TCP_DEBUG_COUNTER
1036721fffe3SKacheong Poon 	to->tcp_time_wait.value.ui64 +=
10375dd46ab5SKacheong Poon 	    from->tcp_time_wait;
1038721fffe3SKacheong Poon 	to->tcp_rput_time_wait.value.ui64 +=
10395dd46ab5SKacheong Poon 	    from->tcp_rput_time_wait;
1040721fffe3SKacheong Poon 	to->tcp_detach_time_wait.value.ui64 +=
10415dd46ab5SKacheong Poon 	    from->tcp_detach_time_wait;
1042721fffe3SKacheong Poon 	to->tcp_timeout_calls.value.ui64 +=
10435dd46ab5SKacheong Poon 	    from->tcp_timeout_calls;
1044721fffe3SKacheong Poon 	to->tcp_timeout_cached_alloc.value.ui64 +=
10455dd46ab5SKacheong Poon 	    from->tcp_timeout_cached_alloc;
1046721fffe3SKacheong Poon 	to->tcp_timeout_cancel_reqs.value.ui64 +=
10475dd46ab5SKacheong Poon 	    from->tcp_timeout_cancel_reqs;
1048721fffe3SKacheong Poon 	to->tcp_timeout_canceled.value.ui64 +=
10495dd46ab5SKacheong Poon 	    from->tcp_timeout_canceled;
1050721fffe3SKacheong Poon 	to->tcp_timermp_freed.value.ui64 +=
10515dd46ab5SKacheong Poon 	    from->tcp_timermp_freed;
1052721fffe3SKacheong Poon 	to->tcp_push_timer_cnt.value.ui64 +=
10535dd46ab5SKacheong Poon 	    from->tcp_push_timer_cnt;
1054721fffe3SKacheong Poon 	to->tcp_ack_timer_cnt.value.ui64 +=
10555dd46ab5SKacheong Poon 	    from->tcp_ack_timer_cnt;
1056721fffe3SKacheong Poon #endif
1057721fffe3SKacheong Poon }
1058